[
  {
    "path": ".clang-format",
    "content": "## This config file is only relevant for clang-format version 19.1.4\n##\n## Examples of each format style can be found on the in the clang-format documentation\n## See: https://clang.llvm.org/docs/ClangFormatStyleOptions.html for details of each option\n##\n## The clang-format binaries can be downloaded as part of the clang binary distributions\n## from https://releases.llvm.org/download.html\n##\n## Use the script Utilities/Maintenance/clang-format.bash to faciliate\n## maintaining a consistent code style.\n##\n## EXAMPLE apply code style enforcement before commit:\n#     Utilities/Maintenance/clang-format.bash --clang ${PATH_TO_CLANG_FORMAT_19.1.4} --modified\n## EXAMPLE apply code style enforcement after commit:\n#     Utilities/Maintenance/clang-format.bash --clang ${PATH_TO_CLANG_FORMAT_19.1.4} --last\n---\n# This configuration requires clang-format version 19.1.4 exactly.\nLanguage:        Cpp\nAccessModifierOffset: -2\nAlignAfterOpenBracket: Align\nAlignArrayOfStructures: None\nAlignConsecutiveAssignments:\n  Enabled:         false\n  AcrossEmptyLines: false\n  AcrossComments:  false\n  AlignCompound:   false\n  AlignFunctionPointers: false\n  PadOperators:    true\nAlignConsecutiveBitFields:\n  Enabled:         false\n  AcrossEmptyLines: false\n  AcrossComments:  false\n  AlignCompound:   false\n  AlignFunctionPointers: false\n  PadOperators:    false\nAlignConsecutiveDeclarations:\n  Enabled:         true\n  AcrossEmptyLines: false\n  AcrossComments:  false\n  AlignCompound:   false\n  AlignFunctionPointers: false\n  PadOperators:    true\nAlignConsecutiveMacros:\n  Enabled:         false\n  AcrossEmptyLines: false\n  AcrossComments:  false\n  AlignCompound:   false\n  AlignFunctionPointers: false\n  PadOperators:    false\nAlignConsecutiveShortCaseStatements:\n  Enabled:         false\n  AcrossEmptyLines: false\n  AcrossComments:  false\n  AlignCaseArrows: false\n  AlignCaseColons: false\nAlignConsecutiveTableGenBreakingDAGArgColons:\n  Enabled:         false\n  AcrossEmptyLines: false\n  AcrossComments:  false\n  AlignCompound:   false\n  AlignFunctionPointers: false\n  PadOperators:    false\nAlignConsecutiveTableGenCondOperatorColons:\n  Enabled:         false\n  AcrossEmptyLines: false\n  AcrossComments:  false\n  AlignCompound:   false\n  AlignFunctionPointers: false\n  PadOperators:    false\nAlignConsecutiveTableGenDefinitionColons:\n  Enabled:         false\n  AcrossEmptyLines: false\n  AcrossComments:  false\n  AlignCompound:   false\n  AlignFunctionPointers: false\n  PadOperators:    false\nAlignEscapedNewlines: Left\nAlignOperands:   Align\nAlignTrailingComments:\n  Kind:            Always\n  OverEmptyLines:  0\nAllowAllArgumentsOnNextLine: true\nAllowAllParametersOfDeclarationOnNextLine: false\nAllowBreakBeforeNoexceptSpecifier: Never\nAllowShortBlocksOnASingleLine: Never\nAllowShortCaseExpressionOnASingleLine: true\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortCompoundRequirementOnASingleLine: true\nAllowShortEnumsOnASingleLine: true\n#AllowShortFunctionsOnASingleLine: Inline Only merge functions defined inside a class. Implies empty.\n#AllowShortFunctionsOnASingleLine: None (in configuration: None) Never merge functions into a single line.\nAllowShortFunctionsOnASingleLine: All\nAllowShortIfStatementsOnASingleLine: Never\nAllowShortLambdasOnASingleLine: All\nAllowShortLoopsOnASingleLine: false\nAlwaysBreakAfterDefinitionReturnType: None\nAlwaysBreakBeforeMultilineStrings: false\nAttributeMacros:\n  - __capability\nBinPackArguments: false\nBinPackParameters: false\nBitFieldColonSpacing: Both\nBraceWrapping:\n  AfterCaseLabel:  true\n  AfterClass:      true\n  AfterControlStatement: Always\n  AfterEnum:       true\n  AfterExternBlock: true\n  AfterFunction:   true\n  AfterNamespace:  true\n  AfterObjCDeclaration: true\n  AfterStruct:     true\n  AfterUnion:      true\n  BeforeCatch:     true\n  BeforeElse:      true\n  BeforeLambdaBody: false\n  BeforeWhile:     false\n  IndentBraces:    false\n  SplitEmptyFunction: false\n  SplitEmptyRecord: false\n  SplitEmptyNamespace: false\nBreakAdjacentStringLiterals: true\nBreakAfterAttributes: Leave\nBreakAfterJavaFieldAnnotations: false\nBreakAfterReturnType: All\nBreakArrays:     true\nBreakBeforeBinaryOperators: None\nBreakBeforeConceptDeclarations: Always\nBreakBeforeBraces: Custom\nBreakBeforeInlineASMColon: OnlyMultiline\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializers: BeforeComma\nBreakFunctionDefinitionParameters: false\nBreakInheritanceList: BeforeComma\nBreakStringLiterals: true\nBreakTemplateDeclarations: Yes\n## The following line allows larger lines in non-documentation code\nColumnLimit:     120\nCommentPragmas:  '^ IWYU pragma:'\nCompactNamespaces: false\nConstructorInitializerIndentWidth: 2\nContinuationIndentWidth: 2\nCpp11BracedListStyle: false\nDerivePointerAlignment: false\nDisableFormat:   false\nEmptyLineAfterAccessModifier: Never\nEmptyLineBeforeAccessModifier: LogicalBlock\nExperimentalAutoDetectBinPacking: false\nFixNamespaceComments: true\nForEachMacros:\n  - foreach\n  - Q_FOREACH\n  - BOOST_FOREACH\nIfMacros:\n  - KJ_IF_MAYBE\nIncludeBlocks:   Preserve\nIncludeCategories:\n  - Regex:           '^\"(llvm|llvm-c|clang|clang-c)/'\n    Priority:        2\n    SortPriority:    0\n    CaseSensitive:   false\n  - Regex:           '^(<|\"(gtest|gmock|isl|json)/)'\n    Priority:        3\n    SortPriority:    0\n    CaseSensitive:   false\n  - Regex:           '.*'\n    Priority:        1\n    SortPriority:    0\n    CaseSensitive:   false\nIncludeIsMainRegex: '(Test)?$'\nIncludeIsMainSourceRegex: ''\nIndentAccessModifiers: false\nIndentCaseBlocks: false\nIndentCaseLabels: true\nIndentExternBlock: AfterExternBlock\nIndentGotoLabels: true\nIndentPPDirectives: AfterHash\nIndentRequiresClause: true\nIndentWidth:     2\nIndentWrappedFunctionNames: false\nInsertBraces:    false\nInsertNewlineAtEOF: false\nInsertTrailingCommas: None\nIntegerLiteralSeparator:\n  Binary:          0\n  BinaryMinDigits: 0\n  Decimal:         0\n  DecimalMinDigits: 0\n  Hex:             0\n  HexMinDigits:    0\nJavaScriptQuotes: Leave\nJavaScriptWrapImports: true\nKeepEmptyLines:\n  AtEndOfFile:     false\n  AtStartOfBlock:  true\n  AtStartOfFile:   true\nLambdaBodyIndentation: Signature\nLineEnding:      DeriveLF\nMacroBlockBegin: ''\nMacroBlockEnd:   ''\nMainIncludeChar: Quote\nMaxEmptyLinesToKeep: 2\nNamespaceIndentation: None\nObjCBinPackProtocolList: Auto\nObjCBlockIndentWidth: 2\nObjCBreakBeforeNestedBlockParam: true\nObjCSpaceAfterProperty: true\nObjCSpaceBeforeProtocolList: false\nPackConstructorInitializers: BinPack\nPenaltyBreakAssignment: 2\nPenaltyBreakBeforeFirstCallParameter: 19\nPenaltyBreakComment: 300\n## The following line allows larger lines in non-documentation code\nPenaltyBreakFirstLessLess: 120\nPenaltyBreakOpenParenthesis: 0\nPenaltyBreakScopeResolution: 500\nPenaltyBreakString: 1000\nPenaltyBreakTemplateDeclaration: 10\nPenaltyExcessCharacter: 1000000\nPenaltyIndentedWhitespace: 0\nPenaltyReturnTypeOnItsOwnLine: 200\nPointerAlignment: Middle\nPPIndentWidth:   -1\nQualifierAlignment: Custom\nQualifierOrder:\n  - friend\n  - static\n  - inline\n  - constexpr\n  - const\n  - type\nReferenceAlignment: Pointer\nReflowComments:  true\nRemoveBracesLLVM: false\nRemoveParentheses: Leave\nRemoveSemicolon: false\nRequiresClausePosition: OwnLine\nRequiresExpressionIndentation: OuterScope\nSeparateDefinitionBlocks: Leave\nShortNamespaceLines: 1\nSkipMacroDefinitionBody: false\n# We may want to sort the includes as a separate pass\nSortIncludes:    Never\nSortJavaStaticImport: Before\n# We may want to revisit this later\nSortUsingDeclarations: Never\nSpaceAfterCStyleCast: false\nSpaceAfterLogicalNot: false\nSpaceAfterTemplateKeyword: true\nSpaceAroundPointerQualifiers: Default\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeCaseColon: false\nSpaceBeforeCpp11BracedList: false\nSpaceBeforeCtorInitializerColon: true\nSpaceBeforeInheritanceColon: true\nSpaceBeforeJsonColon: false\nSpaceBeforeParens: ControlStatements\nSpaceBeforeParensOptions:\n  AfterControlStatements: true\n  AfterForeachMacros: true\n  AfterFunctionDefinitionName: false\n  AfterFunctionDeclarationName: false\n  AfterIfMacros:   true\n  AfterOverloadedOperator: false\n  AfterPlacementOperator: true\n  AfterRequiresInClause: false\n  AfterRequiresInExpression: false\n  BeforeNonEmptyParentheses: false\nSpaceBeforeRangeBasedForLoopColon: true\nSpaceBeforeSquareBrackets: false\nSpaceInEmptyBlock: false\nSpacesBeforeTrailingComments: 1\nSpacesInAngles:  Never\nSpacesInContainerLiterals: false\nSpacesInLineCommentPrefix:\n  Minimum:         1\n  Maximum:         -1\nSpacesInParens:  Never\nSpacesInParensOptions:\n  ExceptDoubleParentheses: false\n  InCStyleCasts:   false\n  InConditionalStatements: false\n  InEmptyParentheses: false\n  Other:           false\nSpacesInSquareBrackets: false\nStandard:        Latest\nStatementAttributeLikeMacros:\n  - Q_EMIT\nStatementMacros:\n  - Q_UNUSED\n  - QT_REQUIRE_VERSION\n  - ITK_GCC_PRAGMA_PUSH\n  - ITK_GCC_PRAGMA_POP\n  - ITK_GCC_SUPPRESS_Wfloat_equal\n  - ITK_GCC_SUPPRESS_Wformat_nonliteral\n  - ITK_GCC_SUPPRESS_Warray_bounds\n  - ITK_CLANG_PRAGMA_PUSH\n  - ITK_CLANG_PRAGMA_POP\n  - ITK_CLANG_SUPPRESS_Wzero_as_null_pointer_constant\n  - CLANG_PRAGMA_PUSH\n  - CLANG_PRAGMA_POP\n  - CLANG_SUPPRESS_Wfloat_equal\n  - INTEL_PRAGMA_WARN_PUSH\n  - INTEL_PRAGMA_WARN_POP\n  - INTEL_SUPPRESS_warning_1292\n  - itkTemplateFloatingToIntegerMacro\n  - itkLegacyMacro\nTableGenBreakInsideDAGArg: DontBreak\nTabWidth:        2\nUseTab:          Never\nVerilogBreakBetweenInstancePorts: true\nWhitespaceSensitiveMacros:\n  - BOOST_PP_STRINGIZE\n  - CF_SWIFT_NAME\n  - NS_SWIFT_NAME\n  - PP_STRINGIZE\n  - STRINGIZE\n...\n"
  },
  {
    "path": ".gitattributes",
    "content": ".git*                                   export-ignore\n# Custom attribute to mark sources as using our C++/C code style.\n[attr]our-c-style  whitespace=tab-in-indent,no-lf-at-eof  hooks.style=KWStyle,clangformat,uncrustify\n\ncmake/*.cxx                             our-c-style\ninclude/*.h*                            our-c-style\nsrc/*.c*                                our-c-style\napplications/**/*.h                     our-c-style\napplications/**/*.cxx                   our-c-style\napplications/**/*.hxx                   our-c-style\nexamples/**/*.cxx                       our-c-style\nutilities/ITKCudaCommon/include/*.h*    our-c-style\nutilities/ITKCudaCommon/src/*.cxx       our-c-style\ntest/*h                                 our-c-style\ntest/*cxx                               our-c-style\n*.txt                                   whitespace=tab-in-indent,no-lf-at-eof\n*.cmake                                 whitespace=tab-in-indent,no-lf-at-eof\n\n# ExternalData content links must have LF newlines\n*.md5                                   crlf=input\n"
  },
  {
    "path": ".github/workflows/build-test-cxx-cuda.yml",
    "content": "name: 'Build, Test RTK with CUDA'\n\non: [push,pull_request]\n\nenv:\n  itk-git-tag: \"v5.4.3\"\n  itk-module-deps: \"CudaCommon@8baef219d19d8f320898c3c649539bbb5ba3f509\"\n\nconcurrency:\n  group: '${{ github.workflow }}@${{ github.head_ref || github.run_id }}'\n  cancel-in-progress: ${{ github.event_name == 'pull_request' }}\n\njobs:\n  build-test-cxx:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      max-parallel: 3\n      matrix:\n        os: [self-hosted-linux, self-hosted-windows]\n        include:\n          - os: self-hosted-linux\n            c-compiler: \"gcc\"\n            cxx-compiler: \"g++\"\n            cmake-build-type: \"MinSizeRel\"\n          - os: self-hosted-windows\n            c-compiler: \"cl.exe\"\n            cxx-compiler: \"cl.exe\"\n            cmake-build-type: \"Release\"\n\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: Install build dependencies\n      run: |\n        python -m pip install --upgrade pip\n        python -m pip install ninja\n\n    - name: self-hosted cleanup\n      shell: bash\n      run: |\n        rm -fr ../ITK\n        rm -fr ../ITK-build\n        rm -fr ../build\n\n    - name: Download ITK\n      run: |\n        cd ..\n        git clone https://github.com/InsightSoftwareConsortium/ITK.git\n        cd ITK\n        git checkout ${{ env.itk-git-tag }}\n\n    - name: Build ITK\n      if: matrix.os != 'self-hosted-windows'\n      shell: bash\n      run: |\n        cd ..\n        mkdir ITK-build\n        cd ITK-build\n        MODULE_ARGS=\"\"\n        MODULE_DEPS=${{ env.itk-module-deps }}\n        for MODULE_INFO in ${MODULE_DEPS//:/ }; do\n          MODULE_NAME=`(echo ${MODULE_INFO} | cut -d'@' -f 1)`\n          MODULE_ARGS=\"${MODULE_ARGS} -DModule_${MODULE_NAME}:BOOL=ON\"\n          MODULE_TAG=`(echo ${MODULE_INFO} | cut -d'@' -f 2)`\n          if [[ -n ${MODULE_TAG} ]]; then\n            MODULE_ARGS+=\" -DModule_${MODULE_NAME}_GIT_TAG:STRING=${MODULE_TAG}\"\n          fi\n        done\n        if [[ -n $MODULE_ARGS ]]; then\n          echo \"Building with modules: $MODULE_ARGS\"\n        fi\n\n        cmake -DCMAKE_C_COMPILER:FILEPATH=\"${{ matrix.c-compiler }}\" -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_CXX_COMPILER=\"${{ matrix.cxx-compiler }}\" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.cmake-build-type }} -DBUILD_TESTING:BOOL=OFF ${{ env.itk-cmake-options }} ${MODULE_ARGS} -GNinja ../ITK\n        ninja\n\n    - name: Build ITK\n      if: matrix.os == 'self-hosted-windows'\n      shell: pwsh\n      run: |\n        Set-PSDebug -Trace 1\n        cd ..\n        & \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\Tools\\Launch-VsDevShell.ps1\" -Arch amd64 -SkipAutomaticLocation\n        mkdir ITK-build\n        cd ITK-build\n\n        $MODULE_ARGS=\"\"\n        $MODULE_DEPS=\"${{ env.itk-module-deps }}\"\n        $MODULES_LIST = $MODULE_DEPS.split(\":\")\n        foreach($MODULE_INFO in $MODULES_LIST) {\n          if($MODULE_ARGS) { $MODULE_ARGS += \" \" }\n          $MODULE_NAME = $MODULE_INFO.split(\"@\")[0]\n          $MODULE_ARGS += \"-DModule_$MODULE_NAME`:BOOL=ON\"\n          $MODULE_TAG = $MODULE_INFO.split(\"@\")[1]\n          if($MODULE_TAG) {\n            $MODULE_ARGS += \" -DModule_$MODULE_NAME`_GIT_TAG:STRING=$MODULE_TAG\"\n          }\n        }\n\n        if($MODULE_ARGS) {\n          echo \"Building with parameters: ${{ env.itk-cmake-options }} $MODULE_ARGS\"\n        }\n\n        cmake -DCMAKE_C_COMPILER:FILEPATH=\"${{ matrix.c-compiler }}\" -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_CXX_COMPILER=\"${{ matrix.cxx-compiler }}\" -DCMAKE_BUILD_TYPE:STRING=${{ matrix.cmake-build-type }} -DBUILD_TESTING:BOOL=OFF ${{ env.itk-cmake-options }} $MODULE_ARGS.split(\" \") -GNinja ../ITK\n        ninja\n\n    - name: Fetch CTest driver script\n      run: |\n        curl -L https://raw.githubusercontent.com/InsightSoftwareConsortium/ITK/dashboard/itk_common.cmake -O\n\n    - name: Configure CTest script\n      shell: bash\n      run: |\n        operating_system=\"${{ matrix.os }}\"\n        cat > dashboard.cmake << EOF\n        set(CTEST_SITE \"GitHubActions\")\n        file(TO_CMAKE_PATH \"\\$ENV{GITHUB_WORKSPACE}/..\" CTEST_DASHBOARD_ROOT)\n        file(TO_CMAKE_PATH \"\\$ENV{GITHUB_WORKSPACE}/\" CTEST_SOURCE_DIRECTORY)\n        file(TO_CMAKE_PATH \"\\$ENV{GITHUB_WORKSPACE}/../build\" CTEST_BINARY_DIRECTORY)\n        set(dashboard_source_name \"${GITHUB_REPOSITORY}\")\n        if(ENV{GITHUB_REF_NAME} MATCHES \"main\")\n          set(branch \"-main\")\n          set(dashboard_model \"Continuous\")\n        else()\n          set(branch \"-${GITHUB_REF}\")\n          set(dashboard_model \"Experimental\")\n        endif()\n        set(CTEST_BUILD_NAME \"${GITHUB_REPOSITORY}-${operating_system}-\\${branch}\")\n        set(CTEST_UPDATE_VERSION_ONLY 1)\n        set(CTEST_TEST_ARGS \\${CTEST_TEST_ARGS} PARALLEL_LEVEL \\${PARALLEL_LEVEL})\n        set(CTEST_BUILD_CONFIGURATION \"Release\")\n        set(CTEST_CMAKE_GENERATOR \"Ninja\")\n        set(CTEST_CUSTOM_WARNING_EXCEPTION\n          \\${CTEST_CUSTOM_WARNING_EXCEPTION}\n          # macOS Azure VM Warning\n          \"ld: warning: text-based stub file\"\n          ${{ env.warnings-to-ignore }}\n          )\n        set(dashboard_no_clean 1)\n        set(ENV{CC} ${{ matrix.c-compiler }})\n        set(ENV{CXX} ${{ matrix.cxx-compiler }})\n        if(WIN32)\n          set(ENV{PATH} \"\\${CTEST_DASHBOARD_ROOT}/ITK-build/bin;\\$ENV{PATH}\")\n        endif()\n        set(dashboard_cache \"\n        ITK_DIR:PATH=\\${CTEST_DASHBOARD_ROOT}/ITK-build\n        BUILD_TESTING:BOOL=ON\n        ${{ env.cmake-options }}\n        \")\n        string(TIMESTAMP build_date \"%Y-%m-%d\")\n        message(\"CDash Build Identifier: \\${build_date} \\${CTEST_BUILD_NAME}\")\n        message(\"CTEST_SITE = \\${CTEST_SITE}\")\n        include(\\${CTEST_SCRIPT_DIRECTORY}/itk_common.cmake)\n        EOF\n        cat dashboard.cmake\n\n    - name: Build and test\n      if: matrix.os != 'self-hosted-windows'\n      run: |\n        ctest --output-on-failure -j 2 -VV -S dashboard.cmake ${{ env.ctest-options }}\n\n    - name: Build and test\n      if: matrix.os == 'self-hosted-windows'\n      shell: pwsh\n      run: |\n        & \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\Tools\\Launch-VsDevShell.ps1\" -Arch amd64 -SkipAutomaticLocation\n        ctest --output-on-failure -j 2 -VV -S dashboard.cmake ${{ env.ctest-options }}\n"
  },
  {
    "path": ".github/workflows/build-test-package-python-cuda.yml",
    "content": "name: 'Package RTK with CUDA'\n\non: [push,pull_request]\n\nenv:\n  itk-wheel-tag: 'v5.4.3'\n  itk-python-package-tag: 'release'\n  itk-python-package-org: 'InsightSoftwareConsortium'\n  itk-module-deps: \"RTKConsortium/ITKCudaCommon@8baef219d19d8f320898c3c649539bbb5ba3f509\"\n\nconcurrency:\n  group: '${{ github.workflow }}@${{ github.head_ref || github.run_id }}'\n  cancel-in-progress: ${{ github.event_name == 'pull_request' }}\n\njobs:\n  build-linux-cuda-python-packages:\n    runs-on: self-hosted-linux\n    strategy:\n      max-parallel: 2\n      matrix:\n        python3-minor-version: ${{ github.event_name == 'pull_request' && fromJSON('[\"11\"]') || fromJSON('[\"9\",\"10\",\"11\"]') }}\n        manylinux-platform: [\"_2_28-x64\",\"2014-x64\"]\n        cuda-version: [\"116\",\"121\",\"124\"]\n\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: 'Fetch build script'\n      run: |\n        IPP_DOWNLOAD_GIT_TAG=${{ env.itk-python-package-tag }}\n        IPP_DOWNLOAD_ORG=${{ env.itk-python-package-org }}\n        curl -L https://raw.githubusercontent.com/${IPP_DOWNLOAD_ORG:=InsightSoftwareConsortium}/ITKPythonPackage/${IPP_DOWNLOAD_GIT_TAG:=master}/scripts/dockcross-manylinux-download-cache-and-build-module-wheels.sh -O\n        chmod u+x dockcross-manylinux-download-cache-and-build-module-wheels.sh\n\n    - name: 'Build 🐍 Python 📦 package'\n      shell: bash\n      run: |\n        rm -rf dist\n        export ITK_PACKAGE_VERSION=${{ env.itk-wheel-tag }}\n        export ITKPYTHONPACKAGE_TAG=${{ env.itk-python-package-tag }}\n        export ITKPYTHONPACKAGE_ORG=${{ env.itk-python-package-org }}\n        export ITK_MODULE_PREQ=${{ env.itk-module-deps }}\n        export CUDA_VERSION=${{ matrix.cuda-version }}\n        export CUDA_VERSION_MAJOR=`(echo ${CUDA_VERSION} | cut -b1-2)`\n        export CUDA_VERSION_MINOR=`(echo ${CUDA_VERSION} | cut -b3-)`\n        CMAKE_OPTIONS=\"-DRTK_CUDA_VERSION=${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}\"\n        CMAKE_OPTIONS=\"${CMAKE_OPTIONS} -DRTK_BUILD_APPLICATIONS:BOOL=OFF\"\n        CMAKE_OPTIONS=\"${CMAKE_OPTIONS} -DCUDAToolkit_ROOT=/usr/lib64/cuda${CUDA_VERSION}\"\n        CMAKE_OPTIONS=\"${CMAKE_OPTIONS} -DCMAKE_CUDA_COMPILER=/usr/lib64/cuda${CUDA_VERSION}/bin/nvcc\"\n        CMAKE_OPTIONS=\"${CMAKE_OPTIONS} --config-setting=build.tool-args=-j16\"\n\n        # The first two are not library paths but are included to be mounted in the\n        # docker by dockcross-manylinux-build-module-wheels.sh\n        export LD_LIBRARY_PATH=\"/home/srit/Downloads/cuda${CUDA_VERSION}\"\n        export LD_LIBRARY_PATH=\"/usr/lib64/libcuda.so.1:$LD_LIBRARY_PATH\"\n        export LD_LIBRARY_PATH=\"/home/srit/Downloads/cuda${CUDA_VERSION}/targets/x86_64-linux/lib:$LD_LIBRARY_PATH\"\n        if test -e ../../ITKPythonBuilds-linux-manylinux2014.tar.zst ; then\n           mv ../../*zst .\n        fi\n\n        MANYLINUX_PLATFORM=${{ matrix.manylinux-platform }}\n        if test ${MANYLINUX_PLATFORM} == \"_2_28-x64\" && test ${CUDA_VERSION} -lt 120; then\n          export IMAGE_TAG=20230106-1aeaea0\n          CMAKE_OPTIONS=\"${CMAKE_OPTIONS} -DITK_USE_PYTHON_LIMITED_API=FALSE\"\n        fi\n        CMAKE_OPTIONS=(--cmake_options \"${CMAKE_OPTIONS}\")\n        echo \"Manylinux platform ${MANYLINUX_PLATFORM}\"\n        rm -rf ITKPythonPackage\n        export MANYLINUX_VERSION=`(echo ${MANYLINUX_PLATFORM} | cut -d '-' -f 1)`\n        export TARGET_ARCH=`(echo ${MANYLINUX_PLATFORM} | cut -d '-' -f 2)`\n        export ITK_MODULE_NO_CLEANUP=TRUE\n        echo \"Building for manylinux specialization ${MANYLINUX_VERSION} and target architecture ${TARGET_ARCH}\"\n        LIBCUDART=`basename /home/srit/Downloads/cuda${CUDA_VERSION}/targets/x86_64-linux/lib/libcudart.so.${CUDA_VERSION_MAJOR}*`\n        LIBCUBLAS=`basename /home/srit/Downloads/cuda${CUDA_VERSION}/targets/x86_64-linux/lib/libcublas.so.${CUDA_VERSION_MAJOR}*`\n        LIBCUBLASLT=`basename /home/srit/Downloads/cuda${CUDA_VERSION}/targets/x86_64-linux/lib/libcublasLt.so.${CUDA_VERSION_MAJOR}*`\n        LIBCUFFT=`basename /home/srit/Downloads/cuda${CUDA_VERSION}/targets/x86_64-linux/lib/libcufft.so.$((${CUDA_VERSION_MAJOR}-1))*`\n        sed -i \"s/dependencies = \\[/dependencies = [ \\\"itk-cudacommon-cuda${CUDA_VERSION}  == 1.1.*\\\",/g\" pyproject.toml\n        sed -i \"s/itk-rtk/itk-rtk-cuda${CUDA_VERSION}/g\" pyproject.toml\n\n        ./dockcross-manylinux-download-cache-and-build-module-wheels.sh \"${CMAKE_OPTIONS[@]}\" -x \"libcuda.so.1;${LIBCUDART};${LIBCUBLAS};${LIBCUBLASLT};${LIBCUFFT}\" cp3${{ matrix.python3-minor-version }}\n        mv *zst ../..\n\n    - name: Validate build output\n      shell: bash\n      run: |\n        python -m pip install twine\n        ls dist/\n\n        MANYLINUX_PLATFORM=${{ matrix.manylinux-platform }}\n        MANYLINUX_VERSION=`(echo ${MANYLINUX_PLATFORM} | cut -d '-' -f 1)`\n        TARGET_ARCH_NAME=`(echo ${MANYLINUX_PLATFORM} | cut -d '-' -f 2)`\n        if [[ ${TARGET_ARCH_NAME} == \"x64\" ]]; then\n          TARGET_ARCH_NAME=\"x86_64\" # Match auditwheel naming convention\n        fi\n        WHEEL_PATTERN=\"dist/itk_*cp3${{ matrix.python3-minor-version }}*manylinux${MANYLINUX_VERSION}*${TARGET_ARCH_NAME}.whl\"\n\n        echo \"Searching for wheels matching pattern ${WHEEL_PATTERN}\"\n        python -m twine check ${WHEEL_PATTERN}\n\n    - name: Publish Python package as GitHub Artifact\n      uses: actions/upload-artifact@v4\n      with:\n        name: LinuxWheel3${{ matrix.python3-minor-version }}${{ matrix.manylinux-platform }}-cuda${{ matrix.cuda-version }}\n        path: dist/*.whl\n\n  build-windows-cuda-python-packages:\n    runs-on: self-hosted-windows\n    strategy:\n      max-parallel: 2\n      matrix:\n        python3-minor-version: ${{ github.event_name == 'pull_request' && fromJSON('[\"11\"]') || fromJSON('[\"9\",\"10\",\"11\"]') }}\n        cuda-version: [\"124\"]\n\n    steps:\n    - uses: actions/checkout@v4\n      with:\n        path: \"im\"\n\n    - name: 'Reduce source path length'\n      shell: bash\n      run: |\n        # Move ITKPythonBuilds archive to the checked-out source\n        if test -f ../../im/ITKPythonBuilds-windows.zip; then\n           mv ../../im/*.zip im\n        fi\n        rm -fr ../../im\n\n        # Move checked-out source to a shorter path to avoid Windows path length issues\n        mv im ../../\n\n    - name: 'Fetch build script'\n      shell: pwsh\n      run: |\n        cd ../../im\n        $ITKPYTHONPACKAGE_TAG = \"${{ env.itk-python-package-tag }}\"\n        $ITKPYTHONPACKAGE_ORG = \"${{ env.itk-python-package-org }}\"\n        $SCRIPT_UPSTREAM = \"https://raw.githubusercontent.com/$ITKPYTHONPACKAGE_ORG/ITKPythonPackage/$ITKPYTHONPACKAGE_TAG/scripts/windows-download-cache-and-build-module-wheels.ps1\"\n        echo \"Fetching $SCRIPT_UPSTREAM\"\n        (new-object net.webclient).DownloadString($SCRIPT_UPSTREAM) > windows-download-cache-and-build-module-wheels.ps1\n\n    - name: 'Build 🐍 Python 📦 package'\n      shell: pwsh\n      run: |\n        if (Test-Path dist) { rm dist -r -fo }\n\n        cd ../../im\n        & \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\Tools\\Launch-VsDevShell.ps1\" -Arch amd64 -SkipAutomaticLocation\n        $env:CC=\"cl.exe\"\n        $env:CXX=\"cl.exe\"\n        $env:ITK_PACKAGE_VERSION = \"${{ env.itk-wheel-tag }}\"\n        $env:ITKPYTHONPACKAGE_TAG = \"${{ env.itk-python-package-tag }}\"\n        $env:ITKPYTHONPACKAGE_ORG = \"${{ env.itk-python-package-org }}\"\n        $env:ITK_MODULE_PREQ = \"${{ env.itk-module-deps }}\"\n        $CUDA_VERSION = \"${{ matrix.cuda-version }}\"\n        $CUDA_VERSION_MAJOR=$CUDA_VERSION.substring(0,2)\n        $CUDA_VERSION_MINOR=$CUDA_VERSION.substring(2,$CUDA_VERSION.Length-2)\n        $env:CUDA_PATH = \"C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}\"\n        $env:CUDACXX = \"$env:CUDA_PATH\\bin\\nvcc.exe\"\n        $env:Path = \"C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}\\bin;\" + $env:Path\n        $LIBCUDART= (Get-Item \"C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}\\bin\\cudart64*dll\" ).Name\n        $LIBCUBLAS= (Get-Item \"C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}\\bin\\cublas64*dll\" ).Name\n        $LIBCUBLASLT= (Get-Item \"C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}\\bin\\cublasLt64*dll\" ).Name\n        $LIBCUFFT= (Get-Item \"C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}\\bin\\cufft64*dll\" ).Name\n        ((Get-Content -Path pyproject.toml) -replace \"itk-rtk\",\"itk-rtk-cuda${CUDA_VERSION}\") | Set-Content -Path pyproject.toml\n        ((Get-Content -Path pyproject.toml) -replace \"dependencies = \\[\",\"dependencies = [\"\"itk-cudacommon-cuda${CUDA_VERSION}  == 1.1.*\"\",\") | Set-Content -Path pyproject.toml\n        ./windows-download-cache-and-build-module-wheels.ps1 \"${{ matrix.python3-minor-version }}\" -setup_options \"--lib-paths \"\"C:/Program\\ Files/NVIDIA\\ GPU\\ Computing\\ Toolkit/CUDA/v${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}/bin\"\" --exclude-libs \"\"nvcuda.dll;concrt140.dll;${LIBCUDART};${LIBCUBLAS};${LIBCUBLASLT};${LIBCUFFT}\"\"\" -cmake_options \"\"\"-DRTK_CUDA_VERSION=${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}\"\" \"\"-DCMAKE_CUDA_COMPILER=$env:CUDACXX\"\" \"\"-DRTK_BUILD_APPLICATIONS:BOOL=OFF\"\"\"\n\n        mkdir -p '${{ github.workspace }}\\dist'\n        cp 'dist\\*.whl' '${{ github.workspace }}\\dist'\n\n    - name: Validate build output\n      shell: pwsh\n      run: |\n        python -m pip install twine\n        ls dist/\n\n        $WHEEL_PATTERN = \"dist/itk_*cp3${{ matrix.python3-minor-version }}*win*.whl\"\n        echo \"Searching for wheels matching pattern ${WHEEL_PATTERN}\"\n\n        python -m twine check ${WHEEL_PATTERN}\n\n    - name: Publish Python package as GitHub Artifact\n      uses: actions/upload-artifact@v4\n      with:\n        name: WindowsWheel3${{ matrix.python3-minor-version }}-cuda${{ matrix.cuda-version }}\n        path: dist/*.whl\n\n  publish-python-packages-to-pypi:\n    needs:\n      - build-linux-cuda-python-packages\n      - build-windows-cuda-python-packages\n    runs-on: ubuntu-22.04\n\n    steps:\n    - name: Download Python Packages\n      uses: actions/download-artifact@v4\n\n    - name: Prepare packages for upload\n      run: |\n        ls -R\n        for d in */; do\n          mv ${d}/*.whl .\n        done\n        mkdir dist\n        mv *.whl dist/\n        ls dist\n\n    - name: Publish 🐍 Python 📦 package to PyPI\n      if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')\n      uses: pypa/gh-action-pypi-publish@v1.5.1\n      with:\n        skip_existing: true\n        user: __token__\n        password: ${{ secrets.pypi_password }}\n\n  test-python-wheel:\n    needs:\n      - build-linux-cuda-python-packages\n    runs-on: self-hosted-linux\n\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: Download all wheel artifacts\n      uses: actions/download-artifact@v4\n      with:\n        path: wheels\n\n    - name: Set up Python 3.11\n      uses: actions/setup-python@v4\n      with:\n        python-version: '3.11'\n\n    - name: Test python wheel\n      run: |\n        # Find the CUDA 124 wheel for Python 3.11 dynamically\n        wheel=$(find wheels -name \"*cuda124*cp311*manylinux_2_28_x86_64.whl\" -type f | head -1)\n\n        pip uninstall -y $(pip list |  grep -E '^itk-')\n        echo \"Installing wheel: $wheel\"\n        pip install $wheel\n\n        pip install pytest matplotlib\n        pytest $GITHUB_WORKSPACE/test/*.py -vv -W \"ignore:builtin type swig\""
  },
  {
    "path": ".github/workflows/build-test-package.yml",
    "content": "name: Build, test, package\n\non: [push,pull_request]\n\nconcurrency:\n  group: '${{ github.workflow }}@${{ github.head_ref || github.run_id }}'\n  cancel-in-progress: ${{ github.event_name == 'pull_request' }}\n\njobs:\n  cxx-build-workflow:\n    uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@v5.4.3\n\n  python-build-workflow:\n    uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@v5.4.3\n    with:\n      cmake-options: '-DRTK_BUILD_APPLICATIONS:BOOL=OFF'\n      python3-minor-versions: ${{ github.event_name == 'pull_request' && '[\"11\"]' || '[\"9\",\"10\",\"11\"]' }}\n      itk-python-package-tag: 'release'\n    secrets:\n      pypi_password: ${{ secrets.pypi_password }}\n\n  test-python-wheel:\n    needs:\n      - python-build-workflow\n    runs-on: self-hosted-linux\n\n    steps:\n    - uses: actions/checkout@v4\n\n    - name: Download all wheel artifacts\n      uses: actions/download-artifact@v4\n      with:\n        path: wheels\n\n    - name: Set up Python 3.11\n      uses: actions/setup-python@v4\n      with:\n        python-version: '3.11'\n\n    - name: Test python wheel\n      run: |\n        # Find wheel for Python 3.11 dynamically\n        wheel=$(find wheels -name \"*cp311*manylinux_2_28_x86_64.whl\" -type f | head -1)\n\n        pip uninstall -y $(pip list |  grep -E '^itk-')\n        echo \"Installing wheel: $wheel\"\n        pip install $wheel\n\n        pip install pytest matplotlib\n        pytest $GITHUB_WORKSPACE/test/*.py -vv -W \"ignore:builtin type swig\""
  },
  {
    "path": ".github/workflows/clang-format-linter.yml",
    "content": "name: clang-format linter\n\non: [push,pull_request]\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v4\n\n    - uses: InsightSoftwareConsortium/ITKClangFormatLinterAction@master\n      with:\n        itk-branch: main\n"
  },
  {
    "path": ".gitignore",
    "content": "# Do not add ExternalData module staging files\n.ExternalData*\n\n# back-up files\n*~\n*.bak\n# vim swp files\n*.swp\n## Ignore files that are used for auto_completion with clang\n*.clang_complete\n## YouCompleteMe vim plugin configuration file\n.ycm_extra_conf.py\n\n\n# KWStyle hook output\n*.kws\n\n# compiled python files\n*.pyc\n\n# qtcreator\nCMakeLists.txt.user*\n\n# kdevelop\n*.kdev*\n.kdev*\n\n# back-up files when conflicts occur\n*.orig\n\n# Clion editor internal project information\n.idea\n\n# Mac System File\n.DS_Store\n"
  },
  {
    "path": ".readthedocs.yml",
    "content": "# .readthedocs.yml\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details\n\n# Required\nversion: 2\n\nbuild:\n  os: ubuntu-22.04\n  tools:\n    python: \"3.11\"\n  apt_packages:\n    - fonts-roboto\n    - graphviz\n\nsphinx:\n  configuration: conf.py\n\npython:\n   install:\n   - requirements: documentation/docs/requirements.txt\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "#=========================================================\n# RTK : Reconstruction Toolkit\n#=========================================================\n# Respect the CMAKE_CXX_STANDARD flags when building for\n# ITKv5 or C++11.\ncmake_minimum_required(VERSION 3.16.3 FATAL_ERROR)\n\n## Only policies introduced after the cmake_minimum_required\n## version need to explicitly be set to NEW.\n## Refer to https://cmake.org/cmake/help/v3.11/manual/cmake-policies.7.html\nset(CMAKE_POLICIES\n  CMP0135)\n\nforeach(p ${CMAKE_POLICIES})\n  if(POLICY ${p})\n    cmake_policy(SET ${p} NEW)\n  endif()\nendforeach()\n\n#=========================================================\n# Help function to debug CMake\nmacro (DD in)\n  message(${in}=[${${in}}])\nendmacro()\n#=========================================================\n\nproject(RTK)\n\n## RTK Version\nset(RTK_VERSION_MAJOR \"2\")\nset(RTK_VERSION_MINOR \"7\")\nset(RTK_VERSION_PATCH \"0\")\nset(RTK_VERSION_STRING \"${RTK_VERSION_MAJOR}.${RTK_VERSION_MINOR}\")\n\nset(RTK_LIBRARIES RTK)\n\n#=========================================================\n# Installation variables\n#=========================================================\nif(NOT CMAKE_INSTALL_LIBDIR)\n  set(CMAKE_INSTALL_LIBDIR lib)\nendif()\nif(NOT RTK_INSTALL_RUNTIME_DIR)\n  set(RTK_INSTALL_RUNTIME_DIR bin)\nendif()\nif(NOT RTK_INSTALL_LIB_DIR)\n  set(RTK_INSTALL_LIB_DIR ${CMAKE_INSTALL_LIBDIR})\nendif()\nif(NOT RTK_INSTALL_ARCHIVE_DIR)\n  set(RTK_INSTALL_ARCHIVE_DIR ${CMAKE_INSTALL_LIBDIR})\nendif()\nif(NOT RTK_INSTALL_INCLUDE_DIR)\n  set(RTK_INSTALL_INCLUDE_DIR include/RTK)\nendif()\nif(NOT RTK_INSTALL_PACKAGE_DIR)\n  set(RTK_INSTALL_PACKAGE_DIR \"${CMAKE_INSTALL_LIBDIR}/cmake/RTK\")\nendif()\n\n#Set position independent code for Unix (-fPIC)\nset(CMAKE_POSITION_INDEPENDENT_CODE ON)\n\n#=========================================================\n# Remove some MS Visual c++ flags\nif(MSVC)\n  add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS)\nendif()\n\n#=========================================================\n# Remove some Intel compiler warnings\nif(\"${CMAKE_CXX_COMPILER_ID}\" STREQUAL \"Intel\")\n  string(REPLACE \"-Wno-unused-parameter\" \"\" CMAKE_C_FLAGS \"${CMAKE_C_FLAGS}\")\n  if(WIN32)\n    set (CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Qwd1268\")\n  else()\n    set (CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -wd1268\")\n  endif()\nendif()\n\ninclude(cmake/rtkCompilerFlags.cmake)\n\n# --------------------------------------------------------\n# Find ITK (required)\nif(NOT ITK_SOURCE_DIR)\n  find_package(ITK 5.1 REQUIRED)\nendif()\n\n# --------------------------------------------------------\n# Shared libraries option\nif(NOT ITK_SOURCE_DIR)\n  set(RTK_BUILD_SHARED_LIBS ${ITK_BUILD_SHARED})\nelse()\n  set(RTK_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})\nendif()\n\n# ----------------------------------------------------------------------------\n# Set RTK_DATA_ROOT\n# Internally used by XRadRawToAttenuationImageFilter to set the path for its\n# flat and dark headers.\nif(NOT ITK_SOURCE_DIR)\n  set(RTK_DATA_ROOT ${CMAKE_BINARY_DIR}/ExternalData/test CACHE PATH \"Path of the data root\" FORCE)\nelse()\n  file(RELATIVE_PATH RTK_RELATIVE_PATH ${ITK_SOURCE_DIR} ${RTK_SOURCE_DIR})\n  set(RTK_DATA_ROOT ${ExternalData_BINARY_ROOT}/${RTK_RELATIVE_PATH}/test CACHE PATH \"Path of the data root\" FORCE)\nendif()\nmark_as_advanced(RTK_DATA_ROOT)\n\n# --------------------------------------------------------\n# Initialization\nif(NOT ITK_SOURCE_DIR)\n  include(itk-module-init.cmake)\n\n  if(RTK_BUILD_SHARED_LIBS)\n    set(ITK_LIBRARY_BUILD_TYPE \"SHARED\")\n  else()\n    set(ITK_LIBRARY_BUILD_TYPE \"STATIC\")\n  endif()\nendif()\n\n#=========================================================\n# If choose to build documentation, then search for Doxygen/Sphinx executables.\noption(RTK_BUILD_DOXYGEN \"Build Doxygen Documentation\" OFF)\nif(RTK_BUILD_DOXYGEN)\n  add_subdirectory(documentation/Doxygen)\nendif()\n\noption(RTK_BUILD_SPHINX \"Build Sphinx Documentation\" OFF)\nif(RTK_BUILD_SPHINX)\n  add_subdirectory(documentation/docs)\nendif()\n\n# Setup build locations.\nif(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)\n  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${RTK_BINARY_DIR}/bin)\nendif()\nif(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)\n  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${RTK_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})\nendif()\nif(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)\n  # Python builds CI workflows expects archives to be placed in the ITK lib\n  # directory. This makes sure that other remote modules that depends on RTK\n  # can link against the RTK libraries.\n  if (WRAP_ITK_INSTALL_COMPONENT_IDENTIFIER STREQUAL \"PythonWheel\")\n    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ITK_DIR}/${CMAKE_INSTALL_LIBDIR})\n  else()\n    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${RTK_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})\n  endif()\nendif()\n\n#=========================================================\n# lp_solve library\n#=========================================================\nadd_subdirectory(utilities/lp_solve)\n\nset(LPSOLVE_INCLUDE_DIRS\n  ${PROJECT_SOURCE_DIR}/utilities/lp_solve\n  ${PROJECT_SOURCE_DIR}/utilities/lp_solve/shared\n  ${PROJECT_SOURCE_DIR}/utilities/lp_solve/bfp\n  ${PROJECT_SOURCE_DIR}/utilities/lp_solve/bfp/bfp_LUSOL\n  ${PROJECT_SOURCE_DIR}/utilities/lp_solve/bfp/bfp_LUSOL/LUSOL\n  ${PROJECT_SOURCE_DIR}/utilities/lp_solve/colamd\n  )\n\nlist(APPEND RTK_INCLUDE_DIRS\n  \"${LPSOLVE_INCLUDE_DIRS}\")\n\n#=========================================================\n# Include directories\n#=========================================================\nlist(APPEND RTK_INCLUDE_DIRS\n  ${RTK_BINARY_DIR}/include)\n\n#=========================================================\n# Generate RTKConfig.cmake for the build tree.\nset(RTK_MODULE_PATH_CONFIG ${CMAKE_MODULE_PATH})\n\n# Add option to control the generation of RTK applications\noption(RTK_BUILD_APPLICATIONS \"Build RTK applications\" ON)\n\n#-----------------------------------------------------------------------------\n# Common revision info between applications\ninclude(GetGitRevisionDescription)\nget_git_head_revision(GIT_REFSPEC GIT_SHA1)\nif(GIT_SHA1 MATCHES \".*NOTFOUND\")\n  set(RTK_VERSION_HASH \"\")\nelse()\n  set(RTK_VERSION_HASH \", git hash ${GIT_SHA1}\")\nendif()\n\nset(RTK_EXPORT_CODE_BUILD \"\n# The RTK version number\nset(RTK_VERSION_MAJOR ${RTK_VERSION_MAJOR})\nset(RTK_VERSION_MINOR ${RTK_VERSION_MINOR})\nset(RTK_VERSION_PATCH ${RTK_VERSION_PATCH})\n\n# Whether the compiled version of RTK uses CUDA\nset(RTK_USE_CUDA ${RTK_USE_CUDA})\n\n# Whether RTK applications were built\nset(RTK_BUILD_APPLICATIONS ${RTK_BUILD_APPLICATIONS})\n\nif(RTK_USE_CUDA)\n  find_package(CUDAToolkit)\n  set(RTK_CUDA_PROJECTIONS_SLAB_SIZE \\\"16\\\" CACHE STRING \\\"Number of projections processed simultaneously in CUDA forward and back projections\\\")\nendif()\n\")\n\nset(RTK_EXPORT_CODE_INSTALL \"\n# The RTK version number\nset(RTK_VERSION_MAJOR ${RTK_VERSION_MAJOR})\nset(RTK_VERSION_MINOR ${RTK_VERSION_MINOR})\nset(RTK_VERSION_PATCH ${RTK_VERSION_PATCH})\n\n# Whether the compiled version of RTK uses CUDA\nset(RTK_USE_CUDA ${RTK_USE_CUDA})\n\n# Whether RTK applications were built\nset(RTK_BUILD_APPLICATIONS ${RTK_BUILD_APPLICATIONS})\n\nif(RTK_USE_CUDA)\n  find_package(CUDAToolkit)\n  set(RTK_CUDA_PROJECTIONS_SLAB_SIZE \\\"16\\\" CACHE STRING \\\"Number of projections processed simultaneously in CUDA forward and back projections\\\")\nendif()\n\")\n\n#=========================================================\n# Configure and build ITK external module\n#=========================================================\nif(NOT ITK_SOURCE_DIR)\n  if(NOT EXISTS ${ITK_CMAKE_DIR}/ITKModuleMacros.cmake)\n    message(FATAL_ERROR \"Modules can only be built against an ITK build tree; they cannot be built against an ITK install tree.\")\n  endif()\n\n  list(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR})\n  include(ITKModuleExternal)\n\n  # Add third party to RTK build targets.\n  # This must be done after RTK has been loaded by ITK to make sure\n  # ${itk-module} variables are defined for RTK.\n  itk_module_target(lpsolve55)\n\n  if(${ITK_VERSION} VERSION_LESS 5.3)\n    ## Set the default target properties for RTK\n    if(NOT CMAKE_CXX_STANDARD)\n      set(CMAKE_CXX_STANDARD 14) # Supported values are ``11``, ``14``, and ``17``.\n    endif()\n    if(NOT CMAKE_CXX_STANDARD_REQUIRED)\n      set(CMAKE_CXX_STANDARD_REQUIRED ON)\n    endif()\n    if(NOT CMAKE_CXX_EXTENSIONS)\n      set(CMAKE_CXX_EXTENSIONS OFF)\n    endif()\n\n    ## Default to release\n    if (NOT CMAKE_BUILD_TYPE)\n      set(CMAKE_BUILD_TYPE Release)\n    endif()\n  endif()\nelse()\n  itk_module_impl()\nendif()\n\n# Propagate cmake options in a header file\n# Must be done after the external module configuration to make sure CudaCommon_VERSION is defined\nconfigure_file(${RTK_SOURCE_DIR}/rtkConfiguration.h.in\n  ${RTK_BINARY_DIR}/include/rtkConfiguration.h)\n\n# Install lpsolve headers\ninstall(FILES ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_bit.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_crash.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_explicit.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_fortify.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_Hash.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_lib.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_matrix.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_MDO.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_mipbb.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_MPS.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_presolve.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_price.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_pricePSE.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_report.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_rlp.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_scale.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_simplex.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_solveDLL.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_SOS.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_types.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_utils.h\n              ${RTK_SOURCE_DIR}/utilities/lp_solve/lp_wlp.h\n        DESTINATION ${RTK_INSTALL_INCLUDE_DIR}/lpsolve\n        COMPONENT Development)\ntarget_include_directories(lpsolve55 PUBLIC $<INSTALL_INTERFACE:${RTK_INSTALL_INCLUDE_DIR}/lpsolve>)\n\n# Install configuration file\ninstall(FILES ${RTK_BINARY_DIR}/include/rtkConfiguration.h DESTINATION ${RTK_INSTALL_INCLUDE_DIR})\ninstall(FILES ${RTK_SOURCE_DIR}/cmake/FindGengetopt.cmake\n              ${RTK_SOURCE_DIR}/cmake/GetGitRevisionDescription.cmake\n              ${RTK_SOURCE_DIR}/cmake/GetGitRevisionDescription.cmake.in\n        DESTINATION ${ITK_INSTALL_PACKAGE_DIR})\nif(NOT ITK_SOURCE_DIR)\n  install(CODE \"MESSAGE(FATAL_ERROR \\\"Cannot install, RTK is compiled separately from ITK. Installation is only functional if RTK is compiled within ITK.\\\")\")\nendif()\n\n#=========================================================\n# Build applications\n#=========================================================\noption(RTK_PROBE_EACH_FILTER \"Probe each RTK filter in a global object and report times and memory used in RTK applications\" OFF)\n\nif(RTK_BUILD_APPLICATIONS)\n  add_subdirectory(applications)\nendif()\n\n# --------------------------------------------------------\n# Setup KWStyle from ITK\nif(ITK_USE_KWSTYLE)\n  find_package( Git )\n  if(GIT_FOUND AND EXISTS \"${RTK_SOURCE_DIR}/.git/config\")\n    execute_process( COMMAND ${GIT_EXECUTABLE} config hooks.KWStyle.path\n      \"${KWSTYLE_EXECUTABLE}\"\n      WORKING_DIRECTORY ${RTK_SOURCE_DIR} )\n  endif()\nendif()\n\n# --------------------------------------------------------\n# Setup ClangFormat from ITK\nif(ITK_USE_CLANGFORMAT)\n  find_package( Git )\n  if(GIT_FOUND AND EXISTS \"${RTK_SOURCE_DIR}/.git/config\")\n    execute_process(COMMAND ${GIT_EXECUTABLE} config clangFormat.binary\n      \"${CLANG_FORMAT_EXECUTABLE}\"\n      WORKING_DIRECTORY ${RTK_SOURCE_DIR})\n  endif()\nendif()\n\n#=========================================================\n# Install pre-commit hook\n#=========================================================\nif(EXISTS \"${RTK_SOURCE_DIR}/.git/config\" AND\n    NOT EXISTS \"${RTK_SOURCE_DIR}/.git/hooks/pre-commit\")\n  # Silently ignore the error if the hooks directory is read-only.\n  execute_process(\n    COMMAND ${CMAKE_COMMAND} -E copy ${RTK_SOURCE_DIR}/cmake/Hooks/pre-commit\n                                     ${RTK_SOURCE_DIR}/.git/hooks/pre-commit\n    OUTPUT_VARIABLE _output\n    ERROR_VARIABLE  _output\n    RESULT_VARIABLE _result\n    )\n  if(_result AND NOT \"${_output}\" MATCHES \"Error copying file\")\n    message(\"${_output}\")\n  endif()\nendif()\n"
  },
  {
    "path": "COPYRIGHT.TXT",
    "content": "RTK is copyrighted software.\n\n  Copyright (c) 2010-2012 RTK consortium\n  All rights reserved\n\n  You can freely use and distribute RTK under an Apache 2.0 license.\n  See LICENSE.TXT for details\n\n------------------------------------------------------------------------\nSome code is modified from plastimatch.org:\n- hnd_io.c in itkHndImageIO.cxx\n- fdk_cuda.cu in itkCudaFDKBackProjectionImageFilter.cu\n\nPlastimatch Software License (\"Software License\") Version 1.0\n\nThis Software License covers downloads from the Plastimatch project\n(\"Plastimatch\") maintained by The General Hospital Corporation\nInc. (\"MGH\").\n\nYour downloading, copying, modifying, displaying, distributing or use\nof any software and/or data from Plastimatch (collectively, the\n\"Software\") constitutes acceptance of all of the terms and conditions\nof this Software License.  If you do not agree to such terms and\nconditions, you have no right to download, copy, modify, display,\ndistribute or use the Software.\n\n\n1. As used in this Software License, \"you\" means the individual\n   downloading and/or using, reproducing, modifying, displaying and/or\n   distributing the Software and the institution or entity which\n   employs or is otherwise affiliated with such individual in\n   connection therewith.  The MGH hereby grants you, with right to\n   sublicense, with respect to MGH's rights in the software, and data,\n   if any, which is the subject of this Software License\n   (collectively, the \"Software\"), a royalty-free, non-exclusive\n   license to use, reproduce, make derivative works of, display and\n   distribute the Software, provided that:\n\n   (a) you accept and adhere to all of the terms and conditions of\n   this Software License;\n\n   (b) in connection with any copy of or sublicense of all or any\n   portion of the Software, all of the terms and conditions in this\n   Software License shall appear in and shall apply to such copy and\n   such sublicense, including without limitation all source and\n   executable forms and on any user documentation, prefaced with the\n   following words: \"All or portions of this licensed product (such\n   portions are the \"Software\") have been obtained under license from\n   MGH and are subject to the following terms and conditions:\"\n\n   (c) you preserve and maintain all applicable attributions,\n   copyright notices and licenses included in or applicable to the\n   Software;\n\n   (d) modified versions of the Software must be clearly identified\n   and marked as such, and must not be misrepresented as being the\n   original Software; and\n\n   (e) you consider making, but are under no obligation to make, the\n   source code of any of your modifications to the Software freely\n   available to others on an open source basis.\n\n2. The license granted under this Software License includes without\n   limitation the right to (i) incorporate the Software into\n   proprietary programs (subject to any restrictions applicable to\n   such programs), (ii) add your own copyright statement to your\n   modifications of the Software, and (iii) provide additional or\n   different license terms and conditions in your sublicenses of\n   modifications of the Software; provided that in each case your use,\n   reproduction or distribution of such modifications otherwise\n   complies with the conditions stated in this Software License.\n\n3. This Software License does not grant any rights with respect to\n   third party software, except those rights that MGH has been\n   authorized by a third party to grant to you, and accordingly you\n   are solely responsible for (i) obtaining any permissions from third\n   parties that you need to use, reproduce, make derivative works of,\n   display and distribute the Software, and (ii) informing your\n   sublicensees, including without limitation your end-users, of their\n   obligations to secure any such required permissions.\n\n4. The Software has been designed for research purposes only and has\n   not been reviewed or approved by the Food and Drug Administration\n   or by any other agency.  YOU ACKNOWLEDGE AND AGREE THAT CLINICAL\n   APPLICATIONS ARE NEITHER RECOMMENDED NOR ADVISED.  Any\n   commercialization of the Software is at the sole risk of the party\n   or parties engaged in such commercialization.  You further agree to\n   use, reproduce, make derivative works of, display and distribute\n   the Software in compliance with all applicable governmental laws,\n   regulations and orders, including without limitation those relating\n   to export and import control.\n\n5. The Software is provided \"AS IS\" and neither MGH nor any\n   contributor to the software (each a \"Contributor\") shall have any\n   obligation to provide maintenance, support, updates, enhancements\n   or modifications thereto.  MGH AND ALL CONTRIBUTORS SPECIFICALLY\n   DISCLAIM ALL EXPRESS AND IMPLIED WARRANTIES OF ANY KIND INCLUDING,\n   BUT NOT LIMITED TO, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR\n   A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL MGH\n   OR ANY CONTRIBUTOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,\n   SPECIAL, INCIDENTAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES HOWEVER\n   CAUSED AND ON ANY THEORY OF LIABILITY ARISING IN ANY WAY RELATED TO\n   THE SOFTWARE, EVEN IF MGH OR ANY CONTRIBUTOR HAS BEEN ADVISED OF\n   THE POSSIBILITY OF SUCH DAMAGES.  TO THE MAXIMUM EXTENT NOT\n   PROHIBITED BY LAW OR REGULATION, YOU FURTHER ASSUME ALL LIABILITY\n   FOR YOUR USE, REPRODUCTION, MAKING OF DERIVATIVE WORKS, DISPLAY,\n   LICENSE OR DISTRIBUTION OF THE SOFTWARE AND AGREE TO INDEMNIFY AND\n   HOLD HARMLESS MGH AND ALL CONTRIBUTORS FROM AND AGAINST ANY AND ALL\n   CLAIMS, SUITS, ACTIONS, DEMANDS AND JUDGMENTS ARISING THEREFROM.\n\n6. None of the names, logos or trademarks of MGH or any of MGH's\n   affiliates or any of the Contributors, or any funding agency, may\n   be used to endorse or promote products produced in whole or in part\n   by operation of the Software or derived from or based on the\n   Software without specific prior written permission from the\n   applicable party.\n\n7. Any use, reproduction or distribution of the Software which is not\n   in accordance with this Software License shall automatically revoke\n   all rights granted to you under this Software License and render\n   Paragraphs 1 and 2 of this Software License null and void.\n\n8. This Software License does not grant any rights in or to any\n   intellectual property owned by MGH or any Contributor except those\n   rights expressly granted hereunder.\n\n------------------------------------------------------------------------\ngengetopt code has been taken from git://git.sv.gnu.org/gengetopt.git\ntag rel_2_22_4\n\n\ngengetopt - generate a C function that uses getopt_long\nto parse command line arguments\n\nCopyright (C) 1999, 2011, 2012, 2013-2007, Free Software Foundation, Inc.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 3 of the License, or\n(at your option) any later version.\n\nUse of gengetopt does not impose any particular license on the\ngenerated code.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\nThe included file 'COPYING' is a copy of the GNU General Public License.\n\n------------------------------------------------------------------------\nitkBinShrinkImageFilter has been taken from https://hdl.handle.net/10380/3450\nIt uses the same Apache 2.0 license as RTK\n\n------------------------------------------------------------------------\nitkImageScanlineConstIterator has been taken from ITK 4.5.0\nIt uses the same Apache 2.0 license as RTK\n\n------------------------------------------------------------------------\nSome code is modified (a lot) from GIFT, the Generalized Image Fusion Toolkit\n(https://hdl.handle.net/1926/216)\n- rtkDaubechiesWaveletsKernelSource.h\n- rtkDaubechiesWaveletsKernelSource.hxx\n- rtkDeconstructImageFilter.h\n- rtkDeconstructImageFilter.hxx\n- rtkReconstructImageFilter.h\n- rtkReconstructImageFilter.hxx\n- rtkDownsampleImageFilter.h\n- rtkDownsampleImageFilter.hxx\n- rtkUpsampleImageFilter.h\n- rtkUpsampleImageFilter.hxx\n\n------------------------------------------------------------------------\nSome code is modified from https://sourceforge.net/projects/niftyrec/:\n- tt_project_ray_gpu_kernels.cu in rtkCudaForwardProjectionImageFilter.h\n\n                      NIFTYREC TOMOGRAPHY TOOLBOX\n\nCopyright (c) 2009-2013, University College London, United-Kingdom.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice,\nthis list of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n\nNeither the name of the University College London nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\nTHE POSSIBILITY OF SUCH DAMAGE.\n\n------------------------------------------------------------------------\nutilities/lpsolve has been taken from\nhttps://sourceforge.net/projects/lpsolve/files/lpsolve/5.5.2.0/lp_solve_5.5.2.0_source.tar.gz/download\nand is distributed under the following license GNU lesser general public\nlicense.\n\n------------------------------------------------------------------------\nThe CMakeLists.txt file for lpsolve has been taken from\nhttps://github.com/PADrend/ThirdParty. There is no license specified on this\nrepository, https://github.com/PADrend/Rendering is distributed under the\nMozilla Public License Version 2.0.\n\n------------------------------------------------------------------------\nGetGitRevisionDescription.cmake and GetGitRevisionDescription.cmake.in have\nbeen taken from https://github.com/rpavlik/cmake-modules with the following\nlicense:\n\nBoost Software License - Version 1.0 - August 17th, 2003\n\nPermission is hereby granted, free of charge, to any person or organization\nobtaining a copy of the software and accompanying documentation covered by\nthis license (the \"Software\") to use, reproduce, display, distribute,\nexecute, and transmit the Software, and to prepare derivative works of the\nSoftware, and to permit third-parties to whom the Software is furnished to\ndo so, all subject to the following:\n\nThe copyright notices in the Software and this entire statement, including\nthe above license grant, this restriction and the following disclaimer,\nmust be included in all copies of the Software, in whole or in part, and\nall derivative works of the Software, unless such copies or derivative\nworks are solely in the form of machine-executable object code generated by\na source language processor.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\nSHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\nFOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "CTestConfig.cmake",
    "content": "set(CTEST_PROJECT_NAME \"RTK\")\nset(CTEST_NIGHTLY_START_TIME \"1:00:00 UTC\")\n\nset(CTEST_DROP_METHOD \"https\")\nset(CTEST_DROP_SITE \"my.cdash.org\")\nset(CTEST_DROP_LOCATION \"/submit.php?project=RTK\")\nset(CTEST_DROP_SITE_CDASH TRUE)\n"
  },
  {
    "path": "CodeContribution.md",
    "content": "# Code contribution\n\n## Coding style\n\nRTK is based on ITK and aims at following its coding conventions. Any developer should follow these conventions when submitting new code or contributions to the existing one. We strongly recommend you to read thoroughly [ITK's style guide](http://www.itk.org/Wiki/ITK/Coding_Style_Guide).\n\n## Testing\n\nThis section describes how to add/edit datasets for testing purposes for RTK. Datasets are not stored in the GIT repository for efficiency and also to avoid having large history due to binary files. Instead the files are stored on a [Girder](http://data.kitware.com) instance. Here's the recipe to add new datasets:\n\n1.  Register/Login to Girder hosted at Kitware: [http://data.kitware.com](http://data.kitware.com)\n2.  Locate the RTK collection: [https://data.kitware.com/#collection/5a7706878d777f0649e04776](https://data.kitware.com/#collection/5a7706878d777f0649e04776)\n3.  Upload the new datasets in the appropriate folder. If you don't have the necessary privileges please email the mailing list\n4.  In the GIT repository, add in testing/Data a file with the exact filename of the original file **but with the .md5 extension**. Inside that file put the md5sum of the file on Girder.\n5.  When adding a test use the new macro 'RTK_ADD_TEST' instead of 'ADD_TEST' and specify the datasets you want CTest to download by appending the data to 'DATA{}'. For example:\n\n```\nRTK_ADD_TEST(NAME rtkimagxtest\n    COMMAND ${EXECUTABLE\\_OUTPUT\\_PATH}/rtkimagxtest\n    DATA{Data/Input/ImagX/raw.xml,raw.raw}\n    DATA{Data/Baseline/ImagX/attenuation.mha})\n```\n## Dashboard\n\n*   The RTK dashboard is available at [RTK Dashboard](http://my.cdash.org/index.php?project=RTK)"
  },
  {
    "path": "GettingStarted.md",
    "content": "Getting started\n===============\n\nHere are suggested steps for the RTK beginner.\n\n  1. Install the software following [INSTALLATION.md](INSTALLATION.md).\n\n  2. If you are not already familiar with ITK, [get started with ITK](https://github.com/InsightSoftwareConsortium/ITK/blob/master/GettingStarted.md).\n\n  3. Check out the [First reconstruction](examples/FirstReconstruction/README.md) example (both the [CMake](https://github.com/RTKConsortium/RTK/blob/master/examples/FirstReconstruction/CMakeLists.txt) and the [C++](https://github.com/RTKConsortium/RTK/blob/master/examples/FirstReconstruction/FirstReconstruction.cxx) codes). Many other examples are in the [documentation](https://docs.openrtk.org/).\n\n  4. Ask questions to the [user mailing list](https://www.creatis.insa-lyon.fr/mailman/listinfo/rtk-users).\n"
  },
  {
    "path": "HEADER.TXT",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n"
  },
  {
    "path": "INSTALLATION.md",
    "content": "RTK installation\n================\n\nConfiguration, compilation and installation with ITK\n----------------------------------------------------\nRTK is a module of [ITK](https://www.itk.org), the Insight Toolkit. Follow the instructions of the [ITK software guide](https://itk.org/ITKSoftwareGuide/html) ([chapter 2](https://itk.org/ITKSoftwareGuide/html/Book1/ITKSoftwareGuide-Book1ch2.html) mainly) for configuring and compiling ITK. The following CMake options are RTK specific:\n\n* `Module_RTK`: Activates RTK download and compilation. Default is `OFF`. Turn it `ON` to activate RTK or compile RTK independently (see below).\n* `Module_RTK_GIT_TAG`: Git tag for the RTK download. By default, the RTK version which is downloaded and compiled is the one given in the [RTK.remote.cmake](https://github.com/InsightSoftwareConsortium/ITK/blob/main/Modules/Remote/RTK.remote.cmake). Change this option to build another version. For example, you can change it to `main` to build the latest RTK version. RTK is only maintained to be backward compatible with the latest ITK release and ITK main branch.\n* `RTK_BUILD_APPLICATIONS`: Activates the compilation of RTK's command line tools. Although RTK is mainly a toolkit, we also provide several command line tools for doing most of the available processing. These command line tools use [gengetopt](https://www.gnu.org/software/gengetopt/gengetopt.html). Several examples are available in the [documentation](http://docs.openrtk.org).\n* `RTK_USE_CUDA`: Activates CUDA computation. Default is `ON` if CMake has automatically found the CUDA package and a CUDA-compatible GPU, and `OFF` otherwise.\n* `RTK_CUDA_VERSION`: Specifies an exact version of the CUDA toolkit which must be used. If unspecified, RTK only checks if the found version is recent enough.\n* `RTK_CUDA_PROJECTIONS_SLAB_SIZE`: Set the number of projections processed at once in CUDA processing. Default is 16.\n* `RTK_PROBE_EACH_FILTER`: Activates the timing, CPU and CUDA memory consumption of each filter. Defaults is `OFF`. When activated, each filter processing is probed and a summary can be displayed. All command line applications display the result with `--verbose`.\n\nRTK will automatically be installed when installing ITK.\n\nIndependent configuration and compilation\n-----------------------------------------\nFor RTK developpers, it may be useful to compile RTK independently from ITK. This is possible, simply:\n* Compile ITK with `Module_RTK=OFF`.\n* If you want to use CUDA, also activate `Module_CudaCommon` or compile it separately as RTK in the following two bullet points (cloning its [GitHub repository](https://github.com/RTKConsortium/ITKCudaCommon) or downloading it as a [zip package](https://codeload.github.com/RTKConsortium/ITKCudaCommon/zip/main)).\n* Manually download RTK's source repository from [GitHub](https://github.com/RTKConsortium/RTK) with `git` (recommended) or as a [zip package](https://codeload.github.com/RTKConsortium/RTK/zip/main).\n* Configure the project with CMake pointing to RTK's source directory and setting the CMake option `ITK_DIR` to ITK's compilation directory. All CMake options above can be set except `Module_RTK`.\n\nInstallation is currently not supported for independent RTK compilations.\n\nPre-compiled binaries\n---------------------\nWe only provide pre-compiled binaries for the Python package which depends on ITK. Use the following commands to install the RTK module with `pip`.\n```\npython -m pip install --upgrade pip\npython -m pip install itk-rtk\n```\nThe same operating systems and Python versions are supported as ITK's packages, see the list on [Pypi](https://pypi.org/project/itk-rtk).\n\nWe also provide pre-compiled [CUDA](https://developer.nvidia.com/cuda-toolkit) packages for Windows and Linux. They require an installed version of CUDA compatible with the package. Currently, RTK is available for CUDA 12.4 on Windows and Linux via:\n```\npython -m pip install itk-rtk-cuda124\n```\n```\npython -m pip install itk-rtk-cuda124\n```\n\nGetting started\n---------------\nSee [GettingStarted.md](GettingStarted.md). Your `CMakeLists.txt` can now use RTK when importing ITK as shown in the [FirstReconstruction's CMakeLists.txt](https://github.com/RTKConsortium/RTK/blob/main/examples/FirstReconstruction/CMakeLists.txt#L7).\n"
  },
  {
    "path": "ITKKWStyleFiles.txt.in",
    "content": "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<Description>\n<LineLength>200</LineLength>\n<DeclarationOrder>0,1,2</DeclarationOrder>\n<Typedefs>[A-Z]</Typedefs>\n<InternalVariables>m_[A-Z]</InternalVariables>\n<SemicolonSpace>0</SemicolonSpace>\n<EndOfFileNewLine>1</EndOfFileNewLine>\n<Tabs>1</Tabs>\n<Spaces>3</Spaces>\n<Comments>/**, *, */,true</Comments>\n<Namespace>rtk</Namespace>\n<NameOfClass>[NameOfClass],itk</NameOfClass>\n<IfNDefDefine>[NameOfClass]_[Extension]</IfNDefDefine>\n<EmptyLines>2</EmptyLines>\n<Template>[TNV]</Template>\n<Operator>1,1</Operator>\n<Header>@RTK_SOURCE_DIR@/cmake/KWStyle/RTKHeader.h,false,true</Header>\n</Description>\n"
  },
  {
    "path": "LICENSE.TXT",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        https://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [2010-2012] [RTK Consortium]\n\n   The RTK consortium comprises:\n     - CREATIS CNRS laboratory             https://www.creatis.insa-lyon.fr/\n     - Massachusetts General Hospital      https://www.mgh.harvard.edu/\n     - Université Catholique de Louvain    https://www.uclouvain.be/\n     - IBA                                 https://www.iba-protontherapy.com/\n     - Kitware                             https://www.kitware.com/\n     - medPhoton                           https://www.medphoton.at/\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       https://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "ORGANIZATION.TXT",
    "content": "The software system known as the Reconstruction Toolkit, hereafter referred to as RTK, is an open-source platform for tomographic reconstruction. RTK consists of source code, data, tests, examples and documentation.\n\nMembers of the RTK collaboration are bound by a gentleman's agreement. In this agreement, all partners agree to work together to the development, validation and support of RTK. A member can either be a person or an institute.\n\nEach RTK member provides an on-going contribution to the development, validation and support of RTK as approved by the Steering Committee of the collaboration. Examples of contributions are the design of the software architecture, the development of new features, the writing of the documentation, and so on.\n\nEach RTK member also agrees upon a common review process of any presentation and publication related to the development of new RTK features. Any RTK presentation and publication must circulate through the mailing list of the steering committee for approval.\n\nEvery member should identify one technical contact person the technical coordinator of the RTK collaboration can address specific requests to. An elected technical coordinator organizes technical meetings, and attends the meetings of the Steering Committee. The technical coordinator is in charge of the smoothness of the collaborative developments, i.e., good communication between contributors to ensure that RTK is consistent.\n\nEvery member must also be represented by one representative in the Steering Committee of the collaboration at least once a year. This Steering Committee decides the development strategy of RTK. The elected spokesman of the collaboration chairs this Steering Committee. The elected spokesperson and the elected technical coordinator will be confirmed in their functions or elected every other year by a simple majority of votes cast by the members of the Steering Committee.\n\nThe RTK collaboration is open to new memberships. If you wish to join the collaboration, please contact Simon RIT, CREATIS CNRS UMR 5220 - INSERM U1044 - Universit Lyon 1 - INSA Lyon, France. Membership is confirmed or granted by the Steering Committe every other year by a simple majority of votes cast by the members of the Steering Committee.\n"
  },
  {
    "path": "README.md",
    "content": "RTK: The Reconstruction ToolKit\n===============================\n\n[![GitHub release](https://img.shields.io/github/release/RTKConsortium/RTK.svg)](https://github.com/RTKConsortium/RTK/releases/latest)\n[![PyPI](https://img.shields.io/pypi/v/itk-rtk.svg)](https://pypi.python.org/pypi/itk-rtk)\n[![Wheels](https://img.shields.io/pypi/wheel/itk-rtk.svg)](https://pypi.org/project/itk-rtk)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/RTKConsortium/RTK/blob/master/LICENSE.TXT)\n[![][gha-img]][gha-link]\n\n[gha-img]: https://github.com/RTKConsortium/RTK/actions/workflows/build-test-package.yml/badge.svg\n[gha-link]: https://github.com/RTKConsortium/RTK/actions/workflows/build-test-package.yml\n\n\nLinks\n-----\n\n* [Homepage](https://www.openrtk.org)\n* [Download](https://www.openrtk.org/RTK/resources/software.html)\n* [Mailing List](https://www.creatis.insa-lyon.fr/mailman/listinfo/rtk-users)\n* [Getting Started](GettingStarted.md)\n* [Help](https://docs.openrtk.org)\n* [Issue tracking](https://github.com/RTKConsortium/RTK/issues)\n\n\nCopyright RTK Consortium\n------------------------\n\n  Licensed under the Apache License, Version 2.0 (the\n  \"[License](https://www.apache.org/licenses/LICENSE-2.0.txt)\"); you may not use\n  this file except in compliance with the\n  [License](https://www.apache.org/licenses/LICENSE-2.0.txt).\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the\n  [License](https://www.apache.org/licenses/LICENSE-2.0.txt) is distributed on\n  an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either\n  express or implied. See the\n  [License](https://www.apache.org/licenses/LICENSE-2.0.txt) for the specific\n  language governing permissions and limitations under the\n  [License](https://www.apache.org/licenses/LICENSE-2.0.txt).\n"
  },
  {
    "path": "applications/CMakeLists.txt",
    "content": "find_package(Gengetopt)\n\nconfigure_file (${CMAKE_CURRENT_SOURCE_DIR}/rtkVersion.ggo.in ${RTK_BINARY_DIR}/rtkVersion.ggo)\n\n#-----------------------------------------------------------------------------\n# Setup RPATH :\n#\n# add the automatically determined parts of the RPATH\n# which point to directories outside the build tree to the install RPATH\nset(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)\n\n# add path to RTK libraries to the install path\nset(CMAKE_INSTALL_RPATH \"${CMAKE_INSTALL_PREFIX}/${RTK_INSTALL_LIB_DIR}\")\n\n#-----------------------------------------------------------------------------\n# Find ITK.\n# Required to include ITK_USE_FILE in order to Register IO factories\n# Force requested modules to be RTK dependencies only, otherwise all\n# available factories will try to register themselves.\nif (NOT ITK_DIR)\n  set(ITK_DIR ${ITK_BINARY_DIR}/CMakeTmp)\nendif()\nfind_package(ITK REQUIRED COMPONENTS ${ITK_MODULE_RTK_DEPENDS})\ninclude(${ITK_USE_FILE})\n\n#-----------------------------------------------------------------------------\n# Executables\nadd_subdirectory(rtkamsterdamshroud)\nadd_subdirectory(rtkbackprojections)\nadd_subdirectory(rtkfdk)\nadd_subdirectory(rtkfieldofview)\nadd_subdirectory(rtkforwardprojections)\nadd_subdirectory(rtkfourdfdk)\nadd_subdirectory(rtkfourdsart)\nadd_subdirectory(rtkiterativefdk)\nadd_subdirectory(rtkosem)\nadd_subdirectory(rtkprojectgeometricphantom)\nadd_subdirectory(rtkprojections)\nadd_subdirectory(rtkprojectshepploganphantom)\nadd_subdirectory(rtksart)\nadd_subdirectory(rtksubselect)\n\nadd_subdirectory(rtkdrawgeometricphantom)\nadd_subdirectory(rtkdrawshepploganphantom)\nadd_subdirectory(rtkextractshroudsignal)\nadd_subdirectory(rtkextractphasesignal)\nadd_subdirectory(rtkoverlayphaseandshroud)\nadd_subdirectory(rtktotalvariationdenoising)\nadd_subdirectory(rtktotalnuclearvariationdenoising)\nadd_subdirectory(rtkadmmwavelets)\nadd_subdirectory(rtkadmmtotalvariation)\nadd_subdirectory(rtkfourdrooster)\nadd_subdirectory(rtkmcrooster)\nadd_subdirectory(rtkfourdconjugategradient)\nadd_subdirectory(rtkspectralonestep)\nadd_subdirectory(rtkconjugategradient)\nadd_subdirectory(rtkregularizedconjugategradient)\nadd_subdirectory(rtkwaveletsdenoising)\nadd_subdirectory(rtki0estimation)\nadd_subdirectory(rtktutorialapplication)\nadd_subdirectory(rtkscatterglarecorrection)\nadd_subdirectory(rtkmotioncompensatedfourdconjugategradient)\nadd_subdirectory(rtklagcorrection)\nadd_subdirectory(rtkgaincorrection)\nadd_subdirectory(rtkspectralsimplexdecomposition)\nadd_subdirectory(rtkdualenergysimplexdecomposition)\nadd_subdirectory(rtkspectralrooster)\nadd_subdirectory(rtkspectralforwardmodel)\nadd_subdirectory(rtkmaskcollimation)\nadd_subdirectory(rtkspectraldenoiseprojections)\nadd_subdirectory(rtkprojectionmatrix)\nadd_subdirectory(rtkvectorconjugategradient)\nadd_subdirectory(rtkdualenergyforwardmodel)\n\nadd_subdirectory(rtkcheckimagequality)\n\n#All the executables below are meant to create RTK ThreeDCircularProjectionGeometry files\nadd_subdirectory(rtkvarianobigeometry)\nadd_subdirectory(rtkvarianprobeamgeometry)\nadd_subdirectory(rtksimulatedgeometry)\nadd_subdirectory(rtkelektasynergygeometry)\nadd_subdirectory(rtkdigisensgeometry)\nadd_subdirectory(rtkxradgeometry)\nadd_subdirectory(rtkimagxgeometry)\nadd_subdirectory(rtkorageometry)\nadd_subdirectory(rtkbioscangeometry)\n#=========================================================\n\n#-----------------------------------------------------------------------------\n# Testing of the applications\nif(BUILD_TESTING)\n  # Reference data (geometry, reference Shepp Logan and corresponding projections)\n  add_test(rtkappsimulatedgeometrytest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rtksimulatedgeometry -n 45 --sid 1000 --sdd 1500 -o geo)\n\n  add_test(rtkappdrawshepploganphantomtest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rtkdrawshepploganphantom -o reference.mha --size 21 --phantomscale 10)\n\n  add_test(rtkappprojectshepploganphantomtest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rtkprojectshepploganphantom  -o sheppy.mha -g geo --phantomscale 10 --size 32)\n  set_tests_properties(rtkappprojectshepploganphantomtest PROPERTIES DEPENDS rtkappsimulatedgeometrytest)\n\n  # FDK test\n  if(RTK_USE_CUDA)\n    add_test(rtkappfdktest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rtkfdk -g geo -p . -r sheppy.mha -o fdk.mha --hardware cuda --size 21)\n  else()\n    add_test(rtkappfdktest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rtkfdk -g geo -p . -r sheppy.mha -o fdk.mha --size 21)\n  endif()\n  set_tests_properties(rtkappfdktest PROPERTIES DEPENDS rtkappprojectshepploganphantomtest)\n\n  add_test(rtkappfdkchecktest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rtkcheckimagequality -i reference.mha -j fdk.mha -t 400)\n  set_tests_properties(rtkappfdkchecktest PROPERTIES DEPENDS \"rtkappdrawshepploganphantomtest;rtkappfdktest\")\n\n  # Iteration reporting testing\n  add_test(rtkapposemtest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rtkosem -g geo -p . -r sheppy.mha -o osem.mha -n 3 --size 21 --output-every 1 --nprojpersubset 15 --iteration-file-name osem%d.mha)\n  set_tests_properties(rtkapposemtest PROPERTIES DEPENDS rtkappprojectshepploganphantomtest)\n\n  add_test(rtkapposemchecktest ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/rtkcheckimagequality -i reference.mha -j osem1.mha,osem2.mha,osem3.mha -t 800,550,455)\n  set_tests_properties(rtkapposemchecktest PROPERTIES DEPENDS \"rtkapposemtest;rtkappdrawshepploganphantomtest\")\nendif()\n"
  },
  {
    "path": "applications/README.md",
    "content": "# Command-line applications\n\nRTK provides command line applications which can be built from the C++ code by turning `ON` the `RTK_BUILD_APPLICATIONS` CMake option. A few of these applications have also been translated to Python and integrated in the [Pypi package](https://pypi.org/project/itk-rtk/). The options of each command line application can be listed with the `--help option`.\n\nThe following are examples using RTK applications:\n\n```{toctree}\n:maxdepth: 1\n\n./rtkfdk/README.md\n./rtkconjugategradient/README.md\n./rtkforwardprojections/README.md\n./rtkdrawgeometricphantom/README.md\n./rtkamsterdamshroud/README.md\n./rtkelektasynergygeometry/README.md\n./rtkvarianobigeometry/README.md\n./rtkadmmtotalvariation/README.md\n./rtkadmmwavelets/README.md\n./rtkfourdrooster/README.md\n./rtkshowgeometry/README.md\n```\n\nIn [applications/rtktutorialapplication/](https://github.com/RTKConsortium/RTK/blob/main/applications/rtktutorialapplication), you will find a very basic RTK application that can be used as a starting point for building your own new application.\n\n## Using RTK applications in Python\n\nRTK applications which have been translated to Python can also be called from Python in addition to the command line, thus avoiding reloading the RTK package (which is slow) and enabling the flexibility of Python scripting. The Python interface dynamically maps the RTK applications to Python functions. You can use `help(rtk.<application_name>)` to see all required and optional arguments. Note that only file paths are supported as input, ITK images or RTK geometry objects cannot be passed directly.\n\nEach Python application accepts either:\n\n1. **A single positional string argument**: This mimics the command-line usage.\n2. **A list of keyword arguments**: This provides a more Pythonic interface.\n\n```python\nrtk.<application_name>(<arguments>)\n```\n\nFor example,\n\n```bash\nrtkfdk -p . -r projections.mha -o fdk.mha -g geometry.xml --spacing 2 --dimension 256\n```\n\nis equivalent to execute from Python\n\n```python\nfrom itk import RTK as rtk\n\nrtk.rtkfdk(\n    \"-p . -r projections.mha -o fdk.mha -g geometry.xml --spacing 2 --dimension 256\"\n)\n```\n\nor\n\n```python\nfrom itk import RTK as rtk\n\nrtk.rtkfdk(\n    path=\".\",\n    regexp=\"projections.mha\",\n    output=\"fdk.mha\",\n    geometry=\"geometry.xml\",\n    spacing=\"2,2,2\",\n    dimension=[256,256,256] # You can use a string or a list\n)\n```\n"
  },
  {
    "path": "applications/rtk3Doutputimage_group.py",
    "content": "import itk\nfrom itk import RTK as rtk\n\n__all__ = [\n    \"add_rtk3Doutputimage_group\",\n    \"SetConstantImageSourceFromArgParse\",\n]\n\n\n# Mimicks rtk3Doutputimage_section.ggo\ndef add_rtk3Doutputimage_group(parser):\n    rtk3Doutputimage_group = parser.add_argument_group(\"Output 3D image properties\")\n    rtk3Doutputimage_group.add_argument(\n        \"--origin\",\n        help=\"Origin (default=centered)\",\n        type=float,\n        nargs='+',\n    )\n    rtk3Doutputimage_group.add_argument(\n        \"--size\",\n        help=\"Size\",\n        type=int,\n        nargs='+',\n        default=[256],\n    )\n    rtk3Doutputimage_group.add_argument(\n        \"--dimension\",\n        help=\"Dimension\",\n        type=int,\n        nargs='+',\n    )\n    rtk3Doutputimage_group.add_argument(\n        \"--spacing\", help=\"Spacing\", type=float, nargs='+', default=[1]\n    )\n    rtk3Doutputimage_group.add_argument(\n        \"--direction\", help=\"Direction\", type=float, nargs='+'\n    )\n    rtk3Doutputimage_group.add_argument(\n        \"--like\",\n        help=\"Copy information from this image (origin, size, spacing, direction)\",\n    )\n\n\n# Mimicks SetConstantImageSourceFromGgo\ndef SetConstantImageSourceFromArgParse(source, args_info):\n    ImageType = type(source.GetOutput())\n\n    # Handle deprecated --dimension argument\n    if args_info.dimension is not None:\n        print(\n            \"Warning: '--dimension' is deprecated and will be removed in a future release. \"\n            \"Please use '--size' instead.\"\n        )\n        args_info.size = args_info.dimension\n\n    Dimension = ImageType.GetImageDimension()\n\n    imageDimension = itk.Size[Dimension]()\n    imageDimension.Fill(args_info.size[0])\n    for i in range(min(len(args_info.size), Dimension)):\n        imageDimension[i] = args_info.size[i]\n\n    imageSpacing = itk.Vector[itk.D, Dimension]()\n    imageSpacing.Fill(args_info.spacing[0])\n    for i in range(min(len(args_info.spacing), Dimension)):\n        imageSpacing[i] = args_info.spacing[i]\n\n    imageOrigin = itk.Point[itk.D, Dimension]()\n    for i in range(Dimension):\n        imageOrigin[i] = imageSpacing[i] * (imageDimension[i] - 1) * -0.5\n    if args_info.origin is not None:\n        for i in range(min(len(args_info.origin), Dimension)):\n            imageOrigin[i] = args_info.origin[i]\n\n    imageDirection = source.GetOutput().GetDirection()\n    if args_info.direction is not None:\n        for i in range(Dimension):\n            for j in range(Dimension):\n                imageDirection[i][j] = args_info.direction[i * Dimension + j]\n\n    source.SetOrigin(imageOrigin)\n    source.SetSpacing(imageSpacing)\n    source.SetDirection(imageDirection)\n    source.SetSize(imageDimension)\n    source.SetConstant(0.0)\n\n    # Copy output image information from an existing file, if requested\n    # Overwrites parameters given in command line, if any\n    if args_info.like is not None:\n        LikeReaderType = itk.ImageFileReader[ImageType]\n        likeReader = LikeReaderType.New()\n        likeReader.SetFileName(args_info.like)\n        likeReader.UpdateOutputInformation()\n        source.SetInformationFromImage(likeReader.GetOutput())\n\n    source.UpdateOutputInformation()\n"
  },
  {
    "path": "applications/rtk3Doutputimage_section.ggo",
    "content": "section \"Output 3D image properties\"\noption \"origin\"    - \"Origin (default=centered)\" double multiple no\noption \"dimension\" - \"Dimension(Deprecated) Use --size instead.\" int multiple no  default=\"256\"\noption \"size\"      - \"Size\"                      int multiple no default=\"256\"\noption \"spacing\"   - \"Spacing\"                   double multiple no  default=\"1\"\noption \"direction\" - \"Direction\"                 double multiple no\noption \"like\"      - \"Copy information from this image (origin, size, spacing, direction)\"  string no\n"
  },
  {
    "path": "applications/rtk4Doutputimage_section.ggo",
    "content": "section \"Output 4D image properties\"\noption \"origin\"    - \"Origin (default=centered)\"                       double multiple no\noption \"dimension\" - \"Dimension(Deprecated) Use --size instead.\"       int multiple no  default=\"256\"\noption \"size\"      - \"Size\"                                            int multiple no default=\"256\"\noption \"spacing\"   - \"Spacing\"                                         double multiple no  default=\"1\"\noption \"direction\" - \"Direction\"                                       double multiple no\noption \"frames\"    - \"Number of time frames in the 4D reconstruction\"  int             no  default=\"10\"\noption \"like\"      - \"Copy information from this image (origin, size, spacing, direction, frames)\"  string no\n"
  },
  {
    "path": "applications/rtkVersion.ggo.in",
    "content": "version \"@RTK_VERSION_MAJOR@.@RTK_VERSION_MINOR@.@RTK_VERSION_PATCH@@RTK_VERSION_HASH@\"\n\n"
  },
  {
    "path": "applications/rtkadmmtotalvariation/CMakeLists.txt",
    "content": "WRAP_GGO(rtkadmmtotalvariation_GGO_C rtkadmmtotalvariation.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkadmmtotalvariation rtkadmmtotalvariation.cxx ${rtkadmmtotalvariation_GGO_C})\ntarget_link_libraries(rtkadmmtotalvariation RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkadmmtotalvariation)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkadmmtotalvariation/README.md",
    "content": "# Total Variation Regularized Reconstruction\n\n![sin](../../documentation/docs/ExternalData/SheppLogan-Sinogram-3D.png){w=300px alt=\"SheppLogan sinogram 3D\"}\n![img](../../documentation/docs/ExternalData/Admmtv.png){w=300px alt=\"Admmtv reconstruction\"}\n\nThis script uses the SheppLogan phantom\n\n```{literalinclude} TotalVariationRegularizedReconstruction.sh\n```"
  },
  {
    "path": "applications/rtkadmmtotalvariation/TotalVariationRegularizedReconstruction.sh",
    "content": " # Create a simulated geometry\n rtksimulatedgeometry -n 180 -o geometry.xml\n # You may add \"--arc 200\" to make the scan short or \"--proj_iso_x 200\" to offset the detector\n\n # Create projections of the phantom file\n rtkprojectshepploganphantom -g geometry.xml -o projections.mha --spacing 2 --size 256\n\n # Reconstruct\n rtkadmmtotalvariation -p . -r projections.mha -o admmtv.mha -g geometry.xml --spacing 2 --size 256 --alpha 1 --beta 1000 -n 3\n\n # Create a reference volume for comparison\n rtkdrawshepploganphantom --spacing 2 --size 256 -o ref.mha"
  },
  {
    "path": "applications/rtkadmmtotalvariation/rtkadmmtotalvariation.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkadmmtotalvariation_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\n#include \"rtkProjectionsReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkADMMTotalVariationConeBeamReconstructionFilter.h\"\n#include \"rtkPhaseGatingImageFilter.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkadmmtotalvariation, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  //////////////////////////////////////////////////////////////////////////////////////////\n  // Read all the inputs\n  //////////////////////////////////////////////////////////////////////////////////////////\n\n  // Projections reader\n  using projectionsReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto projectionsReader = projectionsReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<projectionsReaderType, args_info_rtkadmmtotalvariation>(projectionsReader,\n                                                                                           args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Phase gating weights reader\n  auto phaseGating = rtk::PhaseGatingImageFilter<OutputImageType>::New();\n  if (args_info.phases_given)\n  {\n    phaseGating->SetPhasesFileName(args_info.phases_arg);\n    phaseGating->SetGatingWindowWidth(args_info.windowwidth_arg);\n    phaseGating->SetGatingWindowCenter(args_info.windowcenter_arg);\n    phaseGating->SetGatingWindowShape(args_info.windowshape_arg);\n    phaseGating->SetInputProjectionStack(projectionsReader->GetOutput());\n    phaseGating->SetInputGeometry(geometry);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(phaseGating->Update())\n  }\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<OutputImageType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<OutputImageType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkadmmtotalvariation>(constantImageSource,\n                                                                                                 args_info);\n    inputFilter = constantImageSource;\n  }\n\n  //////////////////////////////////////////////////////////////////////////////////////////\n  // Setup the ADMM filter and run it\n  //////////////////////////////////////////////////////////////////////////////////////////\n\n  // Set the reconstruction filter\n  using ADMM_TV_FilterType = rtk::ADMMTotalVariationConeBeamReconstructionFilter<OutputImageType>;\n  auto admmFilter = ADMM_TV_FilterType::New();\n\n  // Set the forward and back projection filters to be used inside admmFilter\n  SetForwardProjectionFromGgo(args_info, admmFilter.GetPointer());\n  SetBackProjectionFromGgo(args_info, admmFilter.GetPointer());\n\n  // Set all four numerical parameters\n  admmFilter->SetCG_iterations(args_info.CGiter_arg);\n  admmFilter->SetAL_iterations(args_info.niterations_arg);\n  admmFilter->SetAlpha(args_info.alpha_arg);\n  admmFilter->SetBeta(args_info.beta_arg);\n\n  // Set the inputs of the ADMM filter\n  admmFilter->SetInput(0, inputFilter->GetOutput());\n  if (args_info.phases_given)\n  {\n    admmFilter->SetInput(1, phaseGating->GetOutput());\n    admmFilter->SetGeometry(phaseGating->GetOutputGeometry());\n    admmFilter->SetGatingWeights(phaseGating->GetGatingWeightsOnSelectedProjections());\n  }\n  else\n  {\n    admmFilter->SetInput(1, projectionsReader->GetOutput());\n    admmFilter->SetGeometry(geometry);\n  }\n  admmFilter->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  REPORT_ITERATIONS(admmFilter, ADMM_TV_FilterType, OutputImageType)\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmFilter->Update())\n\n  // Write the output\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(admmFilter->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkadmmtotalvariation/rtkadmmtotalvariation.ggo",
    "content": "purpose \"Performs an iterative 3D reconstruction with 3D TV regularization\"\n\noption \"verbose\"   v \"Verbose execution\"                                         flag                         off\noption \"geometry\"  g  \"XML geometry file name\"                                   string                       yes\noption \"output\"    o \"Output file name\"                                          string                       yes\noption \"niterations\" n \"Number of iterations\"         \t\t\t\t int                          no   default=\"1\"\noption \"alpha\"     - \"Regularization parameter\"         \t\t\t float                        no   default=\"0.1\"\noption \"beta\"      - \"Augmented Lagrangian constraint multiplier\"         \t float                        no   default=\"1\"\noption \"CGiter\"     - \"Number of nested iterations of conjugate gradient\"       int                       no      default=\"5\"\noption \"input\"     i \"Input volume\"                     string                       no\noption \"nodisplaced\"  - \"Disable the displaced detector filter\"                  flag                     off\n\nsection \"Phase gating\"\noption \"phases\"       - \"File containing the phase of each projection\"                                              string              no\noption \"windowcenter\" c \"Target reconstruction phase\"                                                               float   no default=\"0\"\noption \"windowwidth\"  w \"Tolerance around the target phase to determine in-phase and out-of-phase projections\"      float   no default=\"1\"\noption \"windowshape\"  s \"Shape of the gating window\"     values=\"Rectangular\",\"Triangular\"                          enum    no default=\"Rectangular\"\n\n"
  },
  {
    "path": "applications/rtkadmmtotalvariation/rtkadmmtotalvariation.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport sys\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Perform ADMM total variation reconstruction on cone-beam projections.\"\n    )\n\n    # General options\n    parser.add_argument(\n        \"-v\", \"--verbose\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"-g\", \"--geometry\", help=\"XML geometry file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"-o\", \"--output\", help=\"Output file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"-n\", \"--niterations\", help=\"Number of iterations\", type=int, default=1\n    )\n    parser.add_argument(\n        \"--alpha\", help=\"Regularization parameter\", type=float, default=0.1\n    )\n    parser.add_argument(\n        \"--beta\",\n        help=\"Augmented Lagrangian constraint multiplier\",\n        type=float,\n        default=1.0,\n    )\n    parser.add_argument(\n        \"--CGiter\",\n        help=\"Number of nested iterations of conjugate gradient\",\n        type=int,\n        default=5,\n    )\n    parser.add_argument(\"-i\", \"--input\", help=\"Input volume\", type=str)\n    parser.add_argument(\n        \"--nodisplaced\",\n        help=\"Disable the displaced detector filter\",\n        action=\"store_true\",\n    )\n\n    # Phase gating options\n    parser.add_argument(\n        \"--phases\", help=\"File containing the phase of each projection\", type=str\n    )\n    parser.add_argument(\n        \"-c\",\n        \"--windowcenter\",\n        help=\"Target reconstruction phase\",\n        type=float,\n        default=0.0,\n    )\n    parser.add_argument(\n        \"-w\",\n        \"--windowwidth\",\n        help=\"Tolerance around the target phase\",\n        type=float,\n        default=1.0,\n    )\n    parser.add_argument(\n        \"-s\",\n        \"--windowshape\",\n        help=\"Shape of the gating window\",\n        type=str,\n        choices=[\"Rectangular\", \"Triangular\"],\n        default=\"Rectangular\",\n    )\n\n    # RTK specific groups\n    rtk.add_rtkprojectors_group(parser)\n    rtk.add_rtkiterations_group(parser)\n    rtk.add_rtkinputprojections_group(parser)\n    rtk.add_rtk3Doutputimage_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n\n    # Define output pixel type and dimension\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Projections reader\n    projectionsReader = rtk.ProjectionsReader[OutputImageType].New()\n    rtk.SetProjectionsReaderFromArgParse(projectionsReader, args_info)\n\n    # Geometry\n    if args_info.verbose:\n        print(f\"Reading geometry from {args_info.geometry}...\")\n\n    geometry = rtk.read_geometry(args_info.geometry)\n\n    # Phase gating weights reader\n    phaseGating = rtk.PhaseGatingImageFilter[OutputImageType].New()\n    if args_info.phases:\n        phaseGating.SetPhasesFileName(args_info.phases)\n        phaseGating.SetGatingWindowWidth(args_info.windowwidth)\n        phaseGating.SetGatingWindowCenter(args_info.windowcenter)\n        # Rectangular=0, Triangular=1\n        if args_info.windowshape == \"Triangular\":\n            phaseGating.SetGatingWindowShape(1)\n        else:\n            phaseGating.SetGatingWindowShape(0)\n        phaseGating.SetInputProjectionStack(projectionsReader.GetOutput())\n        phaseGating.SetInputGeometry(geometry)\n\n        phaseGating.Update()\n\n    # Create input: either an existing volume read from a file or a blank image\n    if args_info.input:\n        # Read an existing image to initialize the volume\n        inputFilter = itk.imread(args_info.input)\n    else:\n        # Create new empty volume\n        constantImageSource = rtk.ConstantImageSource[OutputImageType].New()\n        rtk.SetConstantImageSourceFromArgParse(constantImageSource, args_info)\n        constantImageSource.Update()\n        inputFilter = constantImageSource\n\n    # Set the reconstruction filter\n    if hasattr(itk, \"CudaImage\"):\n        CudaOutputImageType = itk.CudaImage[OutputPixelType, Dimension]\n        admmFilter = rtk.ADMMTotalVariationConeBeamReconstructionFilter[CudaOutputImageType].New()\n        admmFilter.SetInput(0, itk.cuda_image_from_image(inputFilter.GetOutput()))\n        if args_info.phases:\n            admmFilter.SetInput(1, itk.cuda_image_from_image(phaseGating.GetOutput()))\n        else:\n            admmFilter.SetInput(\n                1, itk.cuda_image_from_image(projectionsReader.GetOutput())\n            )\n    else:\n        admmFilter = rtk.ADMMTotalVariationConeBeamReconstructionFilter[\n            OutputImageType\n        ].New()\n        admmFilter.SetInput(0, inputFilter.GetOutput())\n        if args_info.phases:\n            admmFilter.SetInput(1, phaseGating.GetOutput())\n        else:\n            admmFilter.SetInput(1, projectionsReader.GetOutput())\n\n    # Set the forward and back projection filters to be used inside admmFilter\n    rtk.SetForwardProjectionFromArgParse(args_info, admmFilter)\n    rtk.SetBackProjectionFromArgParse(args_info, admmFilter)\n\n    # Set all four numerical parameters\n    admmFilter.SetCG_iterations(args_info.CGiter)\n    admmFilter.SetAL_iterations(args_info.niterations)\n    admmFilter.SetAlpha(args_info.alpha)\n    admmFilter.SetBeta(args_info.beta)\n\n    admmFilter.SetDisableDisplacedDetectorFilter(args_info.nodisplaced)\n\n    # Set the inputs of the ADMM filter\n    if args_info.phases:\n        admmFilter.SetGeometry(phaseGating.GetOutputGeometry())\n        admmFilter.SetGatingWeights(phaseGating.GetGatingWeightsOnSelectedProjections())\n    else:\n        admmFilter.SetGeometry(geometry)\n\n    rtk.SetIterationsReportFromArgParse(args_info, admmFilter)\n\n    admmFilter.Update()\n\n    writer = itk.ImageFileWriter[OutputImageType].New()\n    writer.SetFileName(args_info.output)\n    writer.SetInput(admmFilter.GetOutput())\n    writer.Update()\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkadmmwavelets/CMakeLists.txt",
    "content": "WRAP_GGO(rtkadmmwavelets_GGO_C rtkadmmwavelets.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkadmmwavelets rtkadmmwavelets.cxx ${rtkadmmwavelets_GGO_C})\ntarget_link_libraries(rtkadmmwavelets RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkadmmwavelets)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkadmmwavelets/DaubechiesWavelets.sh",
    "content": " # Create a simulated geometry\n rtksimulatedgeometry -n 180 -o geometry.xml\n # You may add \"--arc 200\" to make the scan short or \"--proj_iso_x 200\" to offset the detector\n\n # Create projections of the phantom file\n rtkprojectshepploganphantom -g geometry.xml -o projections.mha --spacing 2 --size 256\n\n # Reconstruct\n rtkadmmwavelets -p . -r projections.mha -o admmwavelets.mha -g geometry.xml --spacing 2 --size 256 --alpha 1 --beta 1000 -n 3\n\n # Create a reference volume for comparison\n rtkdrawshepploganphantom --spacing 2 --size 256 -o ref.mha"
  },
  {
    "path": "applications/rtkadmmwavelets/README.md",
    "content": "# Daubechies Wavelets Regularized Reconstruction\n\n![sin](../../documentation/docs/ExternalData/SheppLogan-Sinogram-3D.png){w=300px alt=\"SheppLogan sinogram 3D\"}\n![img](../../documentation/docs/ExternalData/AdmmWavelets.png){w=300px alt=\"AdmmWavelets reconstruction\"}\n\nThis script uses the SheppLogan phantom\n\n```{literalinclude} DaubechiesWavelets.sh\n```"
  },
  {
    "path": "applications/rtkadmmwavelets/rtkadmmwavelets.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkadmmwavelets_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\n#include \"rtkProjectionsReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n#include \"rtkADMMWaveletsConeBeamReconstructionFilter.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkadmmwavelets, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  //////////////////////////////////////////////////////////////////////////////////////////\n  // Read all the inputs\n  //////////////////////////////////////////////////////////////////////////////////////////\n\n  // Projections reader\n  using projectionsReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto projectionsReader = projectionsReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<projectionsReaderType, args_info_rtkadmmwavelets>(projectionsReader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Displaced detector weighting\n  auto ddf = rtk::DisplacedDetectorImageFilter<OutputImageType>::New();\n  ddf->SetInput(projectionsReader->GetOutput());\n  ddf->SetGeometry(geometry);\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<OutputImageType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<OutputImageType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkadmmwavelets>(constantImageSource,\n                                                                                           args_info);\n    inputFilter = constantImageSource;\n  }\n\n  //////////////////////////////////////////////////////////////////////////////////////////\n  // Setup the ADMM filter and run it\n  //////////////////////////////////////////////////////////////////////////////////////////\n\n  // Set the reconstruction filter\n  using ADMM_Wavelets_FilterType = rtk::ADMMWaveletsConeBeamReconstructionFilter<OutputImageType>;\n  auto admmFilter = ADMM_Wavelets_FilterType::New();\n\n  // Set the forward and back projection filters to be used inside admmFilter\n  SetForwardProjectionFromGgo(args_info, admmFilter.GetPointer());\n  SetBackProjectionFromGgo(args_info, admmFilter.GetPointer());\n\n  // Set the geometry and interpolation weights\n  admmFilter->SetGeometry(geometry);\n\n  // Set all numerical parameters\n  admmFilter->SetCG_iterations(args_info.CGiter_arg);\n  admmFilter->SetAL_iterations(args_info.niterations_arg);\n  admmFilter->SetAlpha(args_info.alpha_arg);\n  admmFilter->SetBeta(args_info.beta_arg);\n  admmFilter->SetNumberOfLevels(args_info.levels_arg);\n  admmFilter->SetOrder(args_info.order_arg);\n\n  // Set the inputs of the ADMM filter\n  admmFilter->SetInput(0, inputFilter->GetOutput());\n  admmFilter->SetInput(1, projectionsReader->GetOutput());\n\n  admmFilter->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  REPORT_ITERATIONS(admmFilter, ADMM_Wavelets_FilterType, OutputImageType);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmFilter->Update())\n\n  // Write the output\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(admmFilter->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkadmmwavelets/rtkadmmwavelets.ggo",
    "content": "purpose \"Performs an iterative 3D reconstruction with Daubechies wavelets regularization\"\n\noption \"verbose\"   v \"Verbose execution\"                                         flag                         off\noption \"geometry\"  g  \"XML geometry file name\"                                   string                       yes\noption \"output\"    o \"Output file name\"                                          string                       yes\noption \"niterations\" n \"Number of iterations\"         \t\t\t\t int                          no   default=\"1\"\noption \"alpha\"     - \"Regularization parameter\"         \t\t\t float                        no   default=\"0.1\"\noption \"beta\"      - \"Augmented Lagrangian constraint multiplier\"         \t float                        no   default=\"1\"\noption \"CGiter\"     - \"Number of nested iterations of conjugate gradient\"       int                       no      default=\"5\"\noption \"order\"      - \"The order of the Daubechies wavelets\"                    int                       no default=\"3\"\noption \"levels\"     - \"The number of decomposition levels in the wavelets transform\" int                  no default=\"5\"\noption \"input\"     i \"Input volume\"                     string                       no\noption \"nodisplaced\" - \"Disable the displaced detector filter\"                  flag                      off\n\n"
  },
  {
    "path": "applications/rtkamsterdamshroud/CMakeLists.txt",
    "content": "WRAP_GGO(rtkamsterdamshroud_GGO_C rtkamsterdamshroud.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkamsterdamshroud rtkamsterdamshroud.cxx ${rtkamsterdamshroud_GGO_C})\ntarget_link_libraries(rtkamsterdamshroud RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkamsterdamshroud)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkamsterdamshroud/README.md",
    "content": "# Amsterdam Shroud\n\n![sin](../../documentation/docs/ExternalData/Moving-Phantom-Sinogram.png){w=400px alt=\"Moving phantom sinogram\"}\n![img](../../documentation/docs/ExternalData/Amsterdam.png){w=400px alt=\"Amsterdam image\"}\n\nPicture 1 shows the sinogram of the input and picture 2 the shroud image that was created using the command line below.\n\nThe script uses the file [movingPhantom.mha](https://data.kitware.com/api/v1/file/5be99c428d777f2179a2e537/download) as input:\n\n```\n# Creating an Amsterdam Shroud image from a set of projections\nrtkamsterdamshroud -p . -r movingPhantom.mha -o Amsterdam.mha\n ```"
  },
  {
    "path": "applications/rtkamsterdamshroud/rtkamsterdamshroud.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkamsterdamshroud_ggo.h\"\n#include \"rtkMacro.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkAmsterdamShroudImageFilter.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkamsterdamshroud, args_info);\n\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<double, Dimension>;\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkamsterdamshroud>(reader, args_info);\n\n  // Amsterdam shroud\n  using ShroudFilterType = rtk::AmsterdamShroudImageFilter<OutputImageType>;\n  auto shroudFilter = ShroudFilterType::New();\n  shroudFilter->SetInput(reader->GetOutput());\n  shroudFilter->SetUnsharpMaskSize(args_info.unsharp_arg);\n\n  // Corners (if given)\n  if (args_info.clipbox_given)\n  {\n    if (args_info.clipbox_given != 6)\n    {\n      std::cerr << \"--clipbox requires 6 values, only\" << args_info.clipbox_given << \" given.\" << std::endl;\n      return EXIT_FAILURE;\n    }\n    if (!args_info.geometry_given)\n    {\n      std::cerr << \"You must provide the geometry to use --clipbox.\" << std::endl;\n      return EXIT_FAILURE;\n    }\n    ShroudFilterType::PointType c1, c2;\n    for (int i = 0; i < 3; i++)\n    {\n      c1[i] = args_info.clipbox_arg[i * 2];\n      c2[i] = args_info.clipbox_arg[i * 2 + 1];\n    }\n    shroudFilter->SetCorner1(c1);\n    shroudFilter->SetCorner2(c2);\n\n    // Geometry\n    rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n    if (args_info.geometry_given)\n    {\n      TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n      shroudFilter->SetGeometry(geometry);\n    }\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(shroudFilter->UpdateOutputInformation())\n\n  // Write\n  auto writer = itk::ImageFileWriter<ShroudFilterType::OutputImageType>::New();\n  writer->SetFileName(args_info.output_arg);\n  writer->SetInput(shroudFilter->GetOutput());\n  writer->SetNumberOfStreamDivisions(shroudFilter->GetOutput()->GetLargestPossibleRegion().GetSize(1));\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(writer->Update())\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkamsterdamshroud/rtkamsterdamshroud.ggo",
    "content": "purpose \"Creates an Amsterdam Shroud image from a sequence of projections [Zijp et al, ICCR, 2004].\"\n\noption \"verbose\"  v \"Verbose execution\"                                          flag            off\noption \"output\"   o \"Output file name\"                                           string          yes\noption \"unsharp\"  u \"Unsharp mask size\"                                          int             no  default=\"17\"\noption \"clipbox\"  c \"3D clipbox for cropping projections (x1,x2,y1,y2,z1,z2) mm\" double multiple no\noption \"geometry\" g \"XML geometry file name\"                                     string          no\n"
  },
  {
    "path": "applications/rtkamsterdamshroud/rtkamsterdamshroud.py",
    "content": "#!/usr/bin/env python\nimport sys\nimport argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Creates an Amsterdam Shroud image from a sequence of projections [Zijp et al, ICCR, 2004].\"\n    )\n\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--unsharp\", \"-u\", help=\"Unsharp mask size\", type=int, default=17\n    )\n    parser.add_argument(\n        \"--clipbox\",\n        \"-c\",\n        help=\"3D clipbox for cropping projections (x1, x2, y1, y2, z1, z2) in mm\",\n        type=float,\n        nargs=\"+\"\n    )\n    parser.add_argument(\"--geometry\", \"-g\", help=\"XML geometry file name\", type=str)\n\n    rtk.add_rtkinputprojections_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n\n    if args_info.verbose:\n        print(\"Running Amsterdam Shroud computation...\")\n\n    # Define output image type\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Projections reader\n    reader = rtk.ProjectionsReader[OutputImageType].New()\n    rtk.SetProjectionsReaderFromArgParse(reader, args_info)\n\n    # Amsterdam Shroud\n    shroudFilter = rtk.AmsterdamShroudImageFilter[OutputImageType].New()\n    shroudFilter.SetInput(reader.GetOutput())\n    shroudFilter.SetUnsharpMaskSize(args_info.unsharp)\n\n    # Corners (if given)\n    if args_info.clipbox:\n        if len(args_info.clipbox) != 6:\n            print(\n                \"--clipbox requires exactly 6 values, only \",\n                args_info.clipbox,\n                \" given.\",\n            )\n            sys.exit(1)\n        if not args_info.geometry:\n            print(\"You must provide the geometry to use --clipbox.\")\n            sys.exit(1)\n\n        c1 = itk.Point[itk.F, Dimension](args_info.clipbox[0:6:2])\n        c2 = itk.Point[itk.F, Dimension](args_info.clipbox[1:6:2])\n        shroudFilter.SetCorner1(c1)\n        shroudFilter.SetCorner2(c2)\n\n        # Geometry\n        if args_info.geometry:\n            geometry = rtk.read_geometry(args_info.geometry)\n            shroudFilter.SetGeometry(geometry)\n\n    shroudFilter.UpdateOutputInformation()\n\n    # Write output\n    writer = itk.ImageFileWriter[itk.Image[itk.D, 2]].New()\n    writer.SetFileName(args_info.output)\n    writer.SetInput(shroudFilter.GetOutput())\n    writer.SetNumberOfStreamDivisions(\n        shroudFilter.GetOutput().GetLargestPossibleRegion().GetSize()[1]\n    )\n\n    writer.Update()\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkargumentparser.py",
    "content": "import re\nimport argparse\nfrom itk import RTK as rtk\nimport difflib\nimport inspect\n\n__all__ = [\n    \"RTKArgumentParser\"\n]\n\nclass RTKHelpFormatter(argparse.ArgumentDefaultsHelpFormatter):\n    def _format_usage(self, usage, actions, groups, prefix=None):\n        if prefix is None:\n            prefix = rtk.version() + \"\\n\\nusage: \"\n        return super()._format_usage(usage, actions, groups, prefix)\n\nclass RTKArgumentParser(argparse.ArgumentParser):\n    def __init__(self, description=None, **kwargs):\n        super().__init__(description=description, **kwargs)\n        self.formatter_class = RTKHelpFormatter\n        # allow negative numeric tokens to be treated as values, not options. This mirrors CPython behavior in python 3.14\n        self._negative_number_matcher = re.compile(r'-\\.?\\d')\n        self.add_argument('-V', '--version', action='version', version=rtk.version())\n\n    def build_signature(self) -> inspect.Signature:\n        \"\"\"Build a compact Python signature: only required kwargs + **kwargs.\"\"\"\n        required_params = []\n        for action in self._actions:\n            name = getattr(action, 'dest', None)\n            if not name or name in (\"help\", \"version\"):\n                continue\n            if getattr(action, 'required', False):\n                required_params.append(\n                    inspect.Parameter(name=name, kind=inspect.Parameter.KEYWORD_ONLY)\n                )\n        # Add catch-all for the many optional CLI options to keep help inline\n        var_kw = inspect.Parameter('kwargs', kind=inspect.Parameter.VAR_KEYWORD)\n        return inspect.Signature(required_params + [var_kw])\n\n    def build_usage_examples(self, app_name: str | None = None) -> str:\n        \"\"\"Return a Usage examples block for Python help().\"\"\"\n        name = app_name or self.prog\n        # Collect required destinations\n        req = [a.dest for a in self._actions\n               if getattr(a, 'required', False) and a.dest and a.dest not in (\"help\", \"version\")]\n        shell = f\"{name}(\\\"{' '.join([f'--{d} {d.upper()}' for d in req])}\\\")\"\n        py = f\"{name}({', '.join([f'{d}={d.upper()}' for d in req])})\"\n        return (\n            \"Usage:\\n\"\n            f\"    • Shell-style: {shell}\\n\"\n            f\"    • Python API:  {py}\\n\\n\"\n        )\n\n    def apply_signature(self, func):\n        \"\"\"Apply the built signature to a callable and return it.\"\"\"\n        func.__signature__ = self.build_signature()\n        return func\n\n    def parse_args(self, args=None, namespace=None):\n        \"\"\"Parse args with optional single-token comma list support for multi-value options.\n        Supported forms:\n          --opt A B C      (space separated)\n          --opt A,B,C      (single token, comma separated)\n        \"\"\"\n        neutralized = {}\n        for action in self._actions:\n            dest = getattr(action, 'dest', None)\n            if not dest or dest in (\"help\", \"version\"):\n                continue\n            nargs = getattr(action, 'nargs', None)\n            if nargs != '+':\n                continue\n            t = getattr(action, 'type', None)\n            if t and t is not str:\n                neutralized[dest] = t\n                action.type = str\n        namespace = super().parse_args(args, namespace)\n        for action in self._actions:\n            dest = getattr(action, 'dest', None)\n            if dest not in neutralized:\n                continue\n            caster = neutralized[dest]\n            val = getattr(namespace, dest, None)\n            if isinstance(val, list):\n                # Case 1: user supplied a single token containing commas (e.g. \"1,2,3\").\n                # Split on commas, strip whitespace, drop empty pieces, then cast each element.\n                if len(val) == 1 and isinstance(val[0], str) and ',' in val[0]:\n                    pieces = [s for s in (p.strip() for p in val[0].split(',')) if s]\n                    setattr(namespace, dest, [caster(p) for p in pieces])\n                else:\n                    # Case 2: normal space-separated form (e.g. \"1 2 3\"). Just cast every token.\n                    setattr(namespace, dest, [caster(tk) for tk in val])\n            action.type = neutralized[dest]\n        return namespace\n\n    def parse_kwargs(self, func_name: str | None = None, **kwargs):\n        \"\"\"Convert Python kwargs to argv and parse them.\n        Lists/tuples for multi-value options are serialized as a single comma token.\"\"\"\n        actions = {a.dest: a for a in self._actions if a.dest and a.dest not in (\"help\", \"version\")}\n        for key in kwargs:\n            if key not in actions:\n                matches = difflib.get_close_matches(key, actions.keys(), n=3, cutoff=0.5)\n                name = func_name or self.prog or \"function\"\n                msg = f\"{name}() got an unexpected keyword argument '{key}'\"\n                if matches:\n                    msg += f\"\\nDid you mean: {', '.join(matches)}?\"\n                else:\n                    msg += f\"\\nValid arguments are: {', '.join(sorted(actions.keys()))}\"\n                raise TypeError(msg)\n        argv = []\n        for key, val in kwargs.items():\n            action = actions[key]\n            opt_strings = list(action.option_strings)\n            flag = next((o for o in opt_strings if o.startswith('--')), opt_strings[0])\n            if isinstance(val, bool):\n                if val:\n                    argv.append(flag)\n            elif isinstance(val, (list, tuple)):\n                argv += [flag, \",\".join(map(str, val))]\n            else:\n                argv += [flag, str(val)]\n        return self.parse_args(argv)\n"
  },
  {
    "path": "applications/rtkbackprojections/CMakeLists.txt",
    "content": "WRAP_GGO(rtkbackprojections_GGO_C rtkbackprojections.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkbackprojections rtkbackprojections.cxx ${rtkbackprojections_GGO_C})\ntarget_link_libraries(rtkbackprojections RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkbackprojections)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkbackprojections/rtkbackprojections.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkbackprojections_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkFDKBackProjectionImageFilter.h\"\n#include \"rtkFDKWarpBackProjectionImageFilter.h\"\n#include \"rtkJosephBackProjectionImageFilter.h\"\n#include \"rtkJosephBackAttenuatedProjectionImageFilter.h\"\n#include \"rtkZengBackProjectionImageFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaFDKBackProjectionImageFilter.h\"\n#  include \"rtkCudaBackProjectionImageFilter.h\"\n#  include \"rtkCudaRayCastBackProjectionImageFilter.h\"\n#endif\n#include \"rtkCyclicDeformationImageFilter.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkbackprojections, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::flush;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n  if (args_info.verbose_flag)\n    std::cout << \" done.\" << std::endl;\n\n  // Create an empty volume\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkbackprojections>(constantImageSource,\n                                                                                            args_info);\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkbackprojections>(reader, args_info);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update())\n\n  OutputImageType::Pointer attenuationMap;\n  if (args_info.attenuationmap_given)\n  {\n    if (args_info.verbose_flag)\n      std::cout << \"Reading attenuation map \" << args_info.attenuationmap_arg << \"...\" << std::endl;\n    // Read an existing image to initialize the attenuation map\n    attenuationMap = itk::ReadImage<OutputImageType>(args_info.attenuationmap_arg);\n  }\n\n  // Create back projection image filter\n  if (args_info.verbose_flag)\n    std::cout << \"Backprojecting volume...\" << std::endl;\n  rtk::BackProjectionImageFilter<OutputImageType, OutputImageType>::Pointer bp;\n\n  // In case warp backprojection is used, we create a deformation\n  using DVFPixelType = itk::Vector<float, 3>;\n  using DeformationType = rtk::CyclicDeformationImageFilter<itk::Image<DVFPixelType, 4>, itk::Image<DVFPixelType, 3>>;\n  auto def = DeformationType::New();\n\n  switch (args_info.bp_arg)\n  {\n    case (bp_arg_VoxelBasedBackProjection):\n      bp = rtk::BackProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (bp_arg_FDKBackProjection):\n      bp = rtk::FDKBackProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (bp_arg_FDKWarpBackProjection):\n      if (!args_info.signal_given || !args_info.dvf_given)\n      {\n        std::cerr << \"FDKWarpBackProjection requires input 4D deformation \"\n                  << \"vector field and signal file names\" << std::endl;\n        return EXIT_FAILURE;\n      }\n      def->SetInput(itk::ReadImage<DeformationType::InputImageType>(args_info.dvf_arg));\n      bp = rtk::FDKWarpBackProjectionImageFilter<OutputImageType, OutputImageType, DeformationType>::New();\n      def->SetSignalFilename(args_info.signal_arg);\n      dynamic_cast<rtk::FDKWarpBackProjectionImageFilter<OutputImageType, OutputImageType, DeformationType> *>(\n        bp.GetPointer())\n        ->SetDeformation(def);\n      break;\n    case (bp_arg_Joseph):\n      bp = rtk::JosephBackProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (bp_arg_JosephAttenuated):\n      bp = rtk::JosephBackAttenuatedProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (bp_arg_Zeng):\n      bp = rtk::ZengBackProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (bp_arg_CudaFDKBackProjection):\n#ifdef RTK_USE_CUDA\n      bp = rtk::CudaFDKBackProjectionImageFilter::New();\n#else\n      std::cerr << \"The program has not been compiled with cuda option\" << std::endl;\n      return EXIT_FAILURE;\n#endif\n      break;\n    case (bp_arg_CudaBackProjection):\n#ifdef RTK_USE_CUDA\n      bp = rtk::CudaBackProjectionImageFilter<OutputImageType>::New();\n#else\n      std::cerr << \"The program has not been compiled with cuda option\" << std::endl;\n      return EXIT_FAILURE;\n#endif\n      break;\n    case (bp_arg_CudaRayCast):\n#ifdef RTK_USE_CUDA\n      bp = rtk::CudaRayCastBackProjectionImageFilter::New();\n#else\n      std::cerr << \"The program has not been compiled with cuda option\" << std::endl;\n      return EXIT_FAILURE;\n#endif\n      break;\n    default:\n      std::cerr << \"Unhandled --method value.\" << std::endl;\n      return EXIT_FAILURE;\n  }\n\n  bp->SetInput(constantImageSource->GetOutput());\n  bp->SetInput(1, reader->GetOutput());\n  if (args_info.attenuationmap_given)\n    bp->SetInput(2, attenuationMap);\n  if (args_info.sigmazero_given && args_info.bp_arg == bp_arg_Zeng)\n    dynamic_cast<rtk::ZengBackProjectionImageFilter<OutputImageType, OutputImageType> *>(bp.GetPointer())\n      ->SetSigmaZero(args_info.sigmazero_arg);\n  if (args_info.alphapsf_given && args_info.bp_arg == bp_arg_Zeng)\n    dynamic_cast<rtk::ZengBackProjectionImageFilter<OutputImageType, OutputImageType> *>(bp.GetPointer())\n      ->SetAlpha(args_info.alphapsf_arg);\n  bp->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(bp->Update())\n\n  // Write\n  if (args_info.verbose_flag)\n    std::cout << \"Writing... \" << std::endl;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(bp->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkbackprojections/rtkbackprojections.ggo",
    "content": "purpose \"Backprojects a volume according to a geometry file.\"\n\noption \"verbose\"   v \"Verbose execution\"                                         flag     off\noption \"geometry\"  g  \"XML geometry file name\"                                   string   yes\noption \"output\"    o \"Output volume file name\"                                   string   yes\n\nsection \"Projectors\"\noption \"bp\"    - \"Backprojection method\" values=\"VoxelBasedBackProjection\",\"FDKBackProjection\",\"FDKWarpBackProjection\",\"Joseph\",\"JosephAttenuated\", \"Zeng\", \"CudaFDKBackProjection\",\"CudaBackProjection\",\"CudaRayCast\"  enum no default=\"VoxelBasedBackProjection\"\noption \"attenuationmap\" - \"Attenuation map relative to the volume to perfom the attenuation correction\"   string  no\noption \"sigmazero\" - \"PSF value at a distance of 0 meter of the detector\"   double  no\noption \"alphapsf\" - \"Slope of the PSF against the detector distance\"   double  no \n\nsection \"Warped backprojection\"\noption \"signal\"    - \"Signal file name\"          string    no\noption \"dvf\"       - \"Input 4D DVF\"              string    no\n\n"
  },
  {
    "path": "applications/rtkbackprojections/rtkbackprojections.py",
    "content": "#!/usr/bin/env python\nimport sys\nimport argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Backprojects a volume according to a geometry file.\"\n    )\n\n    # General arguments\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--geometry\", \"-g\", help=\"XML geometry file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output volume file name\", type=str, required=True\n    )\n\n    # Projectors group\n    rtkprojectors_group = parser.add_argument_group(\"Projectors\")\n    rtkprojectors_group.add_argument(\n        \"--bp\",\n        help=\"Backprojection method\",\n        type=str,\n        choices=[\n            \"VoxelBasedBackProjection\",\n            \"FDKBackProjection\",\n            \"FDKWarpBackProjection\",\n            \"Joseph\",\n            \"JosephAttenuated\",\n            \"Zeng\",\n            \"CudaFDKBackProjection\",\n            \"CudaBackProjection\",\n            \"CudaRayCast\",\n        ],\n        default=\"VoxelBasedBackProjection\",\n    )\n\n    rtkprojectors_group.add_argument(\n        \"--attenuationmap\", help=\"Attenuation map for attenuation correction\", type=str\n    )\n    rtkprojectors_group.add_argument(\n        \"--sigmazero\",\n        help=\"PSF value at a distance of 0 meter of the detector\",\n        type=float,\n    )\n    rtkprojectors_group.add_argument(\n        \"--alphapsf\", help=\"Slope of the PSF against the detector distance\", type=float\n    )\n\n    # Warped backprojections group\n    Warped_backprojection_group = parser.add_argument_group(\n        \"Warped backprojections group\"\n    )\n    Warped_backprojection_group.add_argument(\n        \"--signal\", help=\"Signal file name\", type=str\n    )\n    Warped_backprojection_group.add_argument(\"--dvf\", help=\"Input 4D DVF\", type=str)\n\n    rtk.add_rtk3Doutputimage_group(parser)\n    rtk.add_rtkinputprojections_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n    # Define output pixel type and dimension\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n    if hasattr(itk, \"CudaImage\"):\n        OutputCudaImageType = itk.CudaImage[OutputPixelType, Dimension]\n\n    # Geometry\n    if args_info.verbose:\n        print(f\"Reading geometry from {args_info.geometry}...\")\n    geometry = rtk.read_geometry(args_info.geometry)\n    if args_info.verbose:\n        print(f\"done.\")\n\n    # Create empty volume\n    constantImageSource = rtk.ConstantImageSource[OutputImageType].New()\n    rtk.SetConstantImageSourceFromArgParse(constantImageSource, args_info)\n\n    # Projections reader\n    reader = rtk.ProjectionsReader[itk.Image[itk.F, 3]].New()\n    rtk.SetProjectionsReaderFromArgParse(reader, args_info)\n    reader.Update()\n\n    attenuation_map = None\n    if args_info.attenuationmap:\n        if args_info.verbose:\n            print(f\"Reading attenuation map from {args_info.attenuationmap}...\")\n        # Read an existing image to initialize the attenuation map\n        attenuation_map = itk.imread(args_info.attenuationmap)\n\n    # In case warp backprojection is used, we create a deformation\n    DVFPixelType = itk.Vector[itk.F, 3]\n    DVFImageSequenceType = itk.Image[DVFPixelType, 4]\n    DVFImageType = itk.Image[DVFPixelType, 3]\n    DeformationType = rtk.CyclicDeformationImageFilter[\n        DVFImageSequenceType, DVFImageType\n    ]\n\n    bp = None\n    if args_info.bp == \"VoxelBasedBackProjection\":\n        bp = rtk.BackProjectionImageFilter[OutputImageType, OutputImageType].New()\n    elif args_info.bp == \"FDKBackProjection\":\n        bp = rtk.FDKBackProjectionImageFilter[OutputImageType, OutputImageType].New()\n    elif args_info.bp == \"FDKWarpBackProjection\":\n        if not args_info.dvf or not args_info.signal:\n            raise ValueError(\n                \"FDKWarpBackProjection requires input 4D deformation vector field and signal file names\"\n            )\n        deformation = rtk.CyclicDeformationImageFilter[\n            DVFImageSequenceType, DVFImageType\n        ].New()\n        deformation.SetInput(itk.imread(args_info.dvf))\n        bp = rtk.FDKWarpBackProjectionImageFilter[\n            OutputImageType, OutputImageType, DeformationType\n        ].New()\n        deformation.SetSignalFilename(args_info.signal)\n        bp.SetDeformation(deformation)\n    elif args_info.bp == \"Joseph\":\n        bp = rtk.JosephBackProjectionImageFilter[OutputImageType, OutputImageType].New()\n    elif args_info.bp == \"JosephAttenuated\":\n        bp = rtk.JosephBackAttenuatedProjectionImageFilter[\n            OutputImageType, OutputImageType\n        ].New()\n    elif args_info.bp == \"Zeng\":\n        bp = rtk.ZengBackProjectionImageFilter[OutputImageType, OutputImageType].New()\n        if args_info.sigmazero:\n            bp.SetSigmaZero(args_info.sigmazero)\n        if args_info.alphapsf:\n            bp.SetAlpha(args_info.alphapsf)\n\n    elif args_info.bp == \"CudaFDKBackProjection\":\n        if hasattr(itk, \"CudaImage\"):\n            bp = rtk.CudaFDKBackProjectionImageFilter.New()\n        else:\n            print(\"The program has not been compiled with cuda option\")\n            sys.exit(1)\n    elif args_info.bp == \"CudaBackProjection\":\n        if hasattr(itk, \"CudaImage\"):\n            bp = rtk.CudaBackProjectionImageFilter[OutputCudaImageType].New()\n        else:\n            print(\"The program has not been compiled with cuda option\")\n            sys.exit(1)\n    elif args_info.bp == \"CudaRayCast\":\n        if hasattr(itk, \"CudaImage\"):\n            bp = rtk.CudaRayCastBackProjectionImageFilter.New()\n        else:\n            print(\"The program has not been compiled with cuda option\")\n            sys.exit(1)\n\n    if args_info.bp in [\"CudaFDKBackProjection\", \"CudaBackProjection\", \"CudaRayCast\"]:\n        bp.SetInput(itk.cuda_image_from_image(constantImageSource.GetOutput()))\n        bp.SetInput(1, itk.cuda_image_from_image(reader.GetOutput()))\n        if attenuation_map:\n            bp.SetInput(2, itk.cuda_image_from_image(attenuation_map))\n    else:\n        bp.SetInput(constantImageSource.GetOutput())\n        bp.SetInput(1, reader.GetOutput())\n        if attenuation_map:\n            bp.SetInput(2, attenuation_map)\n\n    bp.SetGeometry(geometry)\n\n    bp.Update()\n\n    # Write\n    if args_info.verbose:\n        print(f\"Writing output to {args_info.output}...\")\n\n    writter = itk.ImageFileWriter[OutputImageType].New()\n    writter.SetFileName(args_info.output)\n    writter.SetInput(bp.GetOutput())\n    writter.Update()\n\n    if args_info.verbose:\n        print(\"Processing completed successfully.\")\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkbioscangeometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtkbioscangeometry_GGO_C rtkbioscangeometry.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkbioscangeometry rtkbioscangeometry.cxx ${rtkbioscangeometry_GGO_C})\ntarget_link_libraries(rtkbioscangeometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkbioscangeometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkbioscangeometry/rtkbioscangeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkbioscangeometry_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkBioscanGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkbioscangeometry, args_info);\n\n  // Create geometry reader\n  auto bioscanReader = rtk::BioscanGeometryReader::New();\n  bioscanReader->SetProjectionsFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(bioscanReader->UpdateOutputData())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(\n    const_cast<rtk::ThreeDCircularProjectionGeometry *>(bioscanReader->GetGeometry()), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkbioscangeometry/rtkbioscangeometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from a sequence of x-ray projections of a Bioscan NanoSPECT/CT scanner.\"\n\noption \"verbose\"     v \"Verbose execution\"                           flag   off\noption \"output\"      o \"Output file name\"                            string yes\n\nsection \"Projections\"\noption \"path\"      p \"Path containing projections\"                             string yes\noption \"regexp\"    r \"Regular expression to select projection files in path\"   string yes\noption \"nsort\"     - \"Numeric sort for regular expression matches\"             flag   off\noption \"submatch\"  - \"Index of the submatch that will be used to sort matches\" int    no   default=\"0\"\n\n"
  },
  {
    "path": "applications/rtkbioscangeometry/rtkbioscangeometry.py",
    "content": "import argparse\nimport sys\nfrom itk import RTK as rtk\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Read Bioscan geometry and write RTK geometry XML file.\"\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", required=True, help=\"Output geometry XML file\"\n    )\n    parser.add_argument(\n        \"--verbose\", \"-v\", action=\"store_true\", help=\"Enable verbose output\"\n    )\n    rtk.add_rtkinputprojections_group(parser)\n    return parser\n\ndef process(args_info: argparse.Namespace):\n    # Create geometry reader\n    bioscanReader = rtk.BioscanGeometryReader.New()\n    bioscanReader.SetProjectionsFileNames(rtk.GetProjectionsFileNamesFromArgParse(args_info))\n    if args_info.verbose:\n        print(\"Reading Bioscan geometry...\")\n    bioscanReader.UpdateOutputData()\n\n    # Write geometry\n    if args_info.verbose:\n        print(f\"Writing geometry to {args_info.output}...\")\n    rtk.write_geometry(bioscanReader.GetGeometry(), args_info.output)\n    if args_info.verbose:\n        print(\"Done.\")\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "applications/rtkcheckimagequality/CMakeLists.txt",
    "content": "WRAP_GGO(rtkcheckimagequality_GGO_C rtkcheckimagequality.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkcheckimagequality rtkcheckimagequality.cxx ${rtkcheckimagequality_GGO_C})\ntarget_link_libraries(rtkcheckimagequality RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkcheckimagequality)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkcheckimagequality/rtkcheckimagequality.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkcheckimagequality_ggo.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n#include \"itkImage.h\"\n#include \"itkImageFileReader.h\"\n#include \"itkImageRegionConstIterator.h\"\n\nnamespace rtk\n{\n/**\n * \\file rtkcheckimagequality.cxx\n *\n * \\brief Checks that an image has a satisfactory MSE against a reference.\n *\n * \\author Aurélien Coussat\n */\n\ntemplate <class TImage>\ndouble\nMSE(typename TImage::Pointer reference, typename TImage::Pointer reconstruction)\n{\n  using ImageIteratorType = itk::ImageRegionConstIterator<TImage>;\n  ImageIteratorType itTest(reconstruction, reconstruction->GetBufferedRegion());\n  ImageIteratorType itRef(reference, reference->GetBufferedRegion());\n\n  using ErrorType = double;\n  ErrorType EnerError = 0.;\n\n  itTest.GoToBegin();\n  itRef.GoToBegin();\n\n  while (!itRef.IsAtEnd())\n  {\n    typename TImage::PixelType TestVal = itTest.Get();\n    typename TImage::PixelType RefVal = itRef.Get();\n    EnerError += std::pow(ErrorType(RefVal - TestVal), 2.);\n    ++itTest;\n    ++itRef;\n  }\n\n  return EnerError;\n}\n} // namespace rtk\n\nint\nmain(int argc, char ** argv)\n{\n  GGO(rtkcheckimagequality, args_info);\n\n  constexpr unsigned int Dimension = 3;\n  using PixelType = float;\n  using ImageType = itk::Image<PixelType, Dimension>;\n\n  // Maximum number of comparisons to perform (depends on the number of inputs)\n  unsigned int n_max =\n    std::max({ args_info.reference_given, args_info.reconstruction_given, args_info.threshold_given });\n\n  for (unsigned int i = 0; i < n_max; i++)\n  {\n    unsigned int reference_index = std::min(args_info.reference_given - 1, i);\n    unsigned int reconstruction_index = std::min(args_info.reconstruction_given - 1, i);\n    unsigned int threshold_index = std::min(args_info.threshold_given - 1, i);\n\n    ImageType::Pointer reference, reconstruction;\n    try\n    {\n      reference = itk::ReadImage<ImageType>(args_info.reference_arg[reference_index]);\n    }\n    catch (::itk::ExceptionObject & e)\n    {\n      std::cerr << e.GetDescription();\n      return EXIT_FAILURE;\n    }\n\n    try\n    {\n      reconstruction = itk::ReadImage<ImageType>(args_info.reconstruction_arg[reconstruction_index]);\n    }\n    catch (::itk::ExceptionObject & e)\n    {\n      std::cerr << e.GetDescription();\n      return EXIT_FAILURE;\n    }\n\n    double mse = rtk::MSE<ImageType>(reference, reconstruction);\n\n    if (mse > args_info.threshold_arg[threshold_index])\n    {\n      std::cerr << \"Error comparing \" << args_info.reference_arg[reference_index] << \" and \"\n                << args_info.reconstruction_arg[reconstruction_index] << \":\" << std::endl\n                << \"MSE \" << mse << \" above given threshold \" << args_info.threshold_arg[threshold_index] << std::endl;\n      return EXIT_FAILURE;\n    }\n  }\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkcheckimagequality/rtkcheckimagequality.ggo",
    "content": "purpose \"Checks the MSE of a reconstructed image against a reference.\"\n\noption \"verbose\" v \"Verbose execution\" flag   off\noption  \"reference\" i \"Reference volume(s)\"  string  multiple  yes\noption  \"reconstruction\"  j \"Reconstructed volume(s)\"  string  multiple  yes\noption  \"threshold\" t \"MSE threshold(s)\" int multiple  yes\n"
  },
  {
    "path": "applications/rtkcheckimagequality/rtkcheckimagequality.py",
    "content": "import argparse\nimport sys\nimport itk\nfrom itk import RTK as rtk\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Checks the MSE of a reconstructed image against a reference.\"\n    )\n    parser.add_argument(\n        \"--reference\",\n        \"-i\",\n        required=True,\n        type=str,\n        nargs=\"+\",\n        help=\"Reference volume(s)\",\n    )\n    parser.add_argument(\n        \"--reconstruction\",\n        \"-j\",\n        required=True,\n        type=str,\n        nargs=\"+\",\n        help=\"Reconstructed volume(s)\",\n    )\n    parser.add_argument(\n        \"--threshold\",\n        \"-t\",\n        required=True,\n        type=float,\n        nargs=\"+\",\n        help=\"MSE threshold(s)\",\n    )\n    parser.add_argument(\n        \"--verbose\", \"-v\", action=\"store_true\", help=\"Enable verbose output\"\n    )\n    return parser\n\ndef mse(reference, reconstruction):\n    arr_ref = itk.array_view_from_image(reference)\n    arr_rec = itk.array_view_from_image(reconstruction)\n    return float(((arr_ref - arr_rec) ** 2).sum())\n\ndef process(args_info: argparse.Namespace):\n    # Maximum number of comparisons to perform (depends on the number of inputs)\n    n_max = max(\n        len(args_info.reference),\n        len(args_info.reconstruction),\n        len(args_info.threshold),\n    )\n\n    for i in range(n_max):\n        reference_index = min(len(args_info.reference) - 1, i)\n        reconstruction_index = min(len(args_info.reconstruction) - 1, i)\n        threshold_index = min(len(args_info.threshold) - 1, i)\n\n        if args_info.verbose:\n            print(f\"Reading reference image: {args_info.reference[reference_index]}\")\n        reference = itk.imread(args_info.reference[reference_index])\n\n        if args_info.verbose:\n            print(f\"Reading reconstruction image: {args_info.reconstruction[reconstruction_index]}\")\n        reconstruction = itk.imread(args_info.reconstruction[reconstruction_index])\n\n        mse_val = mse(reference, reconstruction)\n        if args_info.verbose:\n            print(f\"MSE: {mse_val} (threshold: {args_info.threshold[threshold_index]})\")\n\n        if mse_val > args_info.threshold[threshold_index]:\n            print(\n                f\"Error comparing {args_info.reference[reference_index]} and {args_info.reconstruction[reconstruction_index]}:\\n\"\n                f\"MSE {mse_val} above given threshold {args_info.threshold[threshold_index]}\",\n                file=sys.stderr,\n            )\n            sys.exit(1)\n    if args_info.verbose:\n        print(\"All comparisons passed.\")\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkconjugategradient/CMakeLists.txt",
    "content": "WRAP_GGO(rtkconjugategradient_GGO_C rtkconjugategradient.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkconjugategradient rtkconjugategradient.cxx ${rtkconjugategradient_GGO_C})\ntarget_link_libraries(rtkconjugategradient RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkconjugategradient)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkconjugategradient/ConjugateGradient2D.sh",
    "content": "# Generate geometry for fan-beam setup\nrtksimulatedgeometry -n 720 -o geometry.xml --arc 360\n\n# Create projections of the phantom file\n# Note the sinogram being 3 pixels wide in the y direction to allow back-projection interpolation in a 2D image\nrtkprojectgeometricphantom -g geometry.xml -o projections.mha --spacing 2 --size=512,3,512 --phantomfile SheppLogan-2d.txt --phantomscale=256,1,256\n\n# Perform Conjugate Gradient reconstruction\nrtkconjugategradient -p . -r projections.mha -o cg.mha -g geometry.xml --spacing 2 --size 256 1 256 -n 10\n\n# Create a reference volume for comparison\nrtkdrawgeometricphantom --spacing 2 --size=256,1,256 --phantomfile SheppLogan-2d.txt -o ref.mha --phantomscale=256,1,256"
  },
  {
    "path": "applications/rtkconjugategradient/ConjugateGradient3D.sh",
    "content": " # Create a simulated geometry\n rtksimulatedgeometry -n 180 -o geometry.xml\n # You may add \"--arc 200\" to make the scan short or \"--proj_iso_x 200\" to offset the detector\n\n # Create projections of the phantom file\n rtkprojectshepploganphantom -g geometry.xml -o projections.mha --spacing 2 --size 256\n\n # Reconstruct\n rtkconjugategradient -p . -r projections.mha -o 3dcg.mha -g geometry.xml --spacing 2 --size 256 -n 10\n\n # Create a reference volume for comparison\n rtkdrawshepploganphantom --spacing 2 --size 256 -o ref.mha"
  },
  {
    "path": "applications/rtkconjugategradient/NoisyConjugateGradient.sh",
    "content": "# Create a simulated geometry\nrtksimulatedgeometry -n 180 -o geometry.xml\n# You may add \"--arc 200\" to make the scan short or \"--proj_iso_x 200\" to offset the detector\n\n# Create projections of the phantom file\nrtkprojectshepploganphantom -g geometry.xml -o projections.mha --spacing 2 --size 256\n\n# Perform least squares reconstruction\nrtkconjugategradient -p . -r noisyLineIntegrals.mha -o LeastSquares.mha -g geom.xml -n 20\n\n# Perform weighted least squares reconstruction\nrtkconjugategradient -p . -r noisyLineIntegrals.mha -o WeightedLeastSquares.mha -g geom.xml -w weightsmap.mha -n 10\n\n# Create a reference volume for comparison\n rtkdrawshepploganphantom --spacing 2 --size 256 -o ref.mha"
  },
  {
    "path": "applications/rtkconjugategradient/README.md",
    "content": "# Conjugate gradient\n\n`````{tab-set}\n\n````{tab-item} 3D\n\n## 3D\n\n![sin](../../documentation/docs/ExternalData/SheppLogan-Sinogram-3D.png){w=200px alt=\"SheppLogan sinogram 3D\"}\n![img](../../documentation/docs/ExternalData/ConjugateGradient-3D.png){w=200px alt=\"ConjugateGradient reconstruction\"}\n\nThis script uses the SheppLogan phantom.\n\n```{literalinclude} ConjugateGradient3D.sh\n```\n\n````\n````{tab-item} 2D\n\n## 2D\n\n![sin](../../documentation/docs/ExternalData/ConjugateGradient-Sinogram-2D.png){w=200px alt=\"SHeppLogan sinogram 2D\"}\n![img](../../documentation/docs/ExternalData/ConjugateGradient-2D.png){w=200px alt=\"ConjugateGradient reconstruction\"}\n\nThe same reconstruction can be performed using the original 2D Shepp-Logan phantom.\nRTK can perform 2D reconstructions through images wide of 1 pixel in the y direction.\nThe following script performs the same reconstruction as above in a 2D environment and use the Shepp–Logan phantom (https://data.kitware.com/api/v1/file/67d1ff45c6dec2fc9c534d0d/download).\n\n```{literalinclude} ConjugateGradient2D.sh\n```\n````\n````{tab-item} Noisy Reconstruction\n\n## Noisy Reconstruction\n\nIn the presence of noise, all projection data may not be equally reliable. The conjugate gradient algorithm can be modified to take this into account, and each pixel of the projections can be associated with a weight. The higher the weight, the more reliable the pixel data. Download [noisy projections](https://data.kitware.com/api/v1/item/5be99cdf8d777f2179a2e63d/download) and [the associated weights](https://data.kitware.com/api/v1/item/5be99d268d777f2179a2e6f8/download), as well as [the geometry](https://data.kitware.com/api/v1/item/5be99d268d777f2179a2e700/download), and run the following to compare the regular least squares reconstruction (without weights) and the weighted least squares reconstruction.\n\n```{literalinclude} NoisyConjugateGradient.sh\n```\n````\n`````\n"
  },
  {
    "path": "applications/rtkconjugategradient/rtkconjugategradient.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkconjugategradient_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkConjugateGradientConeBeamReconstructionFilter.h\"\n#include \"rtkIterationCommands.h\"\n\n#include <iostream>\n#include <fstream>\n#include <iterator>\n\n#ifdef RTK_USE_CUDA\n#  include <itkCudaImage.h>\n#endif\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkconjugategradient, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkconjugategradient>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<OutputImageType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<OutputImageType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkconjugategradient>(constantImageSource,\n                                                                                                args_info);\n    inputFilter = constantImageSource;\n  }\n\n  // Read weights if given\n  OutputImageType::Pointer inputWeights;\n  if (args_info.weights_given)\n  {\n    using WeightsReaderType = itk::ImageFileReader<OutputImageType>;\n    auto weightsReader = WeightsReaderType::New();\n    weightsReader->SetFileName(args_info.weights_arg);\n    inputWeights = weightsReader->GetOutput();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(inputWeights->Update())\n  }\n\n  // Read regularization weights if given\n  OutputImageType::Pointer localRegWeights;\n  if (args_info.regweights_given)\n  {\n    using WeightsReaderType = itk::ImageFileReader<OutputImageType>;\n    auto localRegWeightsReader = WeightsReaderType::New();\n    localRegWeightsReader->SetFileName(args_info.regweights_arg);\n    localRegWeights = localRegWeightsReader->GetOutput();\n    localRegWeights->Update();\n  }\n\n  // Read Support Mask if given\n  OutputImageType::Pointer supportmaskSource;\n  if (args_info.mask_given)\n  {\n    supportmaskSource = itk::ReadImage<OutputImageType>(args_info.mask_arg);\n  }\n\n  // Set the forward and back projection filters to be used\n  auto conjugategradient = rtk::ConjugateGradientConeBeamReconstructionFilter<OutputImageType>::New();\n  SetForwardProjectionFromGgo(args_info, conjugategradient.GetPointer());\n  SetBackProjectionFromGgo(args_info, conjugategradient.GetPointer());\n  conjugategradient->SetInputVolume(inputFilter->GetOutput());\n  conjugategradient->SetInputProjectionStack(reader->GetOutput());\n  conjugategradient->SetInputWeights(inputWeights);\n  conjugategradient->SetLocalRegularizationWeights(localRegWeights);\n  conjugategradient->SetCudaConjugateGradient(!args_info.nocudacg_flag);\n  if (args_info.mask_given)\n  {\n    conjugategradient->SetSupportMask(supportmaskSource);\n  }\n\n  if (args_info.gamma_given)\n    conjugategradient->SetGamma(args_info.gamma_arg);\n  if (args_info.tikhonov_given)\n    conjugategradient->SetTikhonov(args_info.tikhonov_arg);\n\n  conjugategradient->SetGeometry(geometry);\n  conjugategradient->SetNumberOfIterations(args_info.niterations_arg);\n  conjugategradient->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  REPORT_ITERATIONS(\n    conjugategradient, rtk::ConjugateGradientConeBeamReconstructionFilter<OutputImageType>, OutputImageType)\n\n  itk::TimeProbe readerProbe;\n  if (args_info.time_flag)\n  {\n    std::cout << \"Recording elapsed time... \" << std::flush;\n    readerProbe.Start();\n  }\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update())\n\n  if (args_info.time_flag)\n  {\n    //    conjugategradient->PrintTiming(std::cout);\n    readerProbe.Stop();\n    std::cout << \"It took...  \" << readerProbe.GetMean() << ' ' << readerProbe.GetUnit() << std::endl;\n  }\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(conjugategradient->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkconjugategradient/rtkconjugategradient.ggo",
    "content": "purpose \"Reconstructs a 3D volume from a sequence of projections with a conjugate gradient technique\"\n\noption \"verbose\"        v \"Verbose execution\"                                                                         flag   off\noption \"geometry\"       g \"XML geometry file name\"                                                                    string yes\noption \"output\"         o \"Output file name\"                                                                          string yes\noption \"niterations\"    n \"Number of iterations\"                                                                      int    no   default=\"5\"\noption \"time\"           t \"Records elapsed time during the process\"                                                   flag   off\noption \"input\"          i \"Input volume\"                                                                              string no\noption \"weights\"        w \"Weights file for Weighted Least Squares (WLS)\"                                             string no\noption \"regweights\"     - \"Local regularization weights file\"                                                         string no\noption \"gamma\"          - \"Laplacian regularization weight\"                                                           float  no   default=\"0\"\noption \"tikhonov\"       - \"Tikhonov regularization weight\"                                                            float  no   default=\"0\"\noption \"nocudacg\"       - \"Do not perform conjugate gradient calculations on GPU\"                                     flag   off\noption \"mask\"           m \"Apply a support binary mask: reconstruction kept null outside the mask)\"                   string no\noption \"nodisplaced\"    - \"Disable the displaced detector filter\"                                                     flag   off\n"
  },
  {
    "path": "applications/rtkconjugategradient/rtkconjugategradient.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    # argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Reconstructs a 3D volume from a sequence of projections with a conjugate gradient technique\"\n    )\n\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\"--geometry\", \"-g\", help=\"Geometry file name\", required=True)\n    parser.add_argument(\"--output\", \"-o\", help=\"Output file name\", required=True)\n    parser.add_argument(\n        \"--niterations\", \"-n\", type=int, default=5, help=\"Number of iterations\"\n    )\n    parser.add_argument(\"--input\", \"-i\", help=\"Input volume\")\n    parser.add_argument(\n        \"--weights\", \"-w\", help=\"Weights file for Weighted Least Squares (WLS)\"\n    )\n    parser.add_argument(\"--gamma\", help=\"Laplacian regularization weight\")\n    parser.add_argument(\"--tikhonov\", help=\"Tikhonov regularization weight\")\n    parser.add_argument(\n        \"--nocudacg\",\n        help=\"Do not perform conjugate gradient calculations on GPU\",\n        action=\"store_true\",\n    )\n    parser.add_argument(\n        \"--mask\",\n        \"-m\",\n        help=\"Apply a support binary mask: reconstruction kept null outside the mask)\",\n    )\n    parser.add_argument(\n        \"--nodisplaced\",\n        help=\"Disable the displaced detector filter\",\n        action=\"store_true\",\n    )\n\n    rtk.add_rtkinputprojections_group(parser)\n    rtk.add_rtk3Doutputimage_group(parser)\n    rtk.add_rtkprojectors_group(parser)\n    rtk.add_rtkiterations_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\ndef process(args_info: argparse.Namespace):\n\n    OutputPixelType = itk.F\n    Dimension = 3\n\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Projections reader\n    reader = rtk.ProjectionsReader[OutputImageType].New()\n    rtk.SetProjectionsReaderFromArgParse(reader, args_info)\n\n    # Geometry\n    if args_info.verbose:\n        print(f\"Reading geometry information from {args_info.geometry}\")\n    geometry = rtk.read_geometry(args_info.geometry)\n\n    # Create input: either an existing volume read from a file or a blank image\n    if args_info.input is not None:\n        # Read an existing image to initialize the volume\n        InputReaderType = itk.ImageFileReader[OutputImageType]\n        inputReader = InputReaderType.New()\n        inputReader.SetFileName(args_info.input)\n        inputFilter = inputReader\n    else:\n        # Create new empty volume\n        ConstantImageSourceType = rtk.ConstantImageSource[OutputImageType]\n        constantImageSource = ConstantImageSourceType.New()\n        rtk.SetConstantImageSourceFromArgParse(constantImageSource, args_info)\n        inputFilter = constantImageSource\n\n    # Read weights if given, otherwise default to weights all equal to one\n    if args_info.weights is not None:\n        WeightsReaderType = itk.ImageFileReader[OutputImageType]\n        weightsReader = WeightsReaderType.New()\n        weightsReader.SetFileName(args_info.weights)\n        weightsSource = weightsReader\n    else:\n        ConstantWeightsSourceType = rtk.ConstantImageSource[OutputImageType]\n        constantWeightsSource = ConstantWeightsSourceType.New()\n\n        # Set the weights to be like the projections\n        reader.UpdateOutputInformation()\n\n        constantWeightsSource.SetInformationFromImage(reader.GetOutput())\n        constantWeightsSource.SetConstant(1.0)\n        weightsSource = constantWeightsSource\n\n    # Read Support Mask if given\n    if args_info.mask is not None:\n        supportmask = itk.imread(args_info.mask)\n\n    # Set the forward and back projection filters to be used\n    if hasattr(itk, \"CudaImage\"):\n        OutputCudaImageType = itk.CudaImage[OutputPixelType, Dimension]\n        ConjugateGradientFilterType = rtk.ConjugateGradientConeBeamReconstructionFilter[\n            OutputCudaImageType\n        ]\n        conjugategradient = ConjugateGradientFilterType.New()\n        conjugategradient.SetInput(itk.cuda_image_from_image(inputFilter.GetOutput()))\n        conjugategradient.SetInput(1, itk.cuda_image_from_image(reader.GetOutput()))\n        conjugategradient.SetInput(\n            2, itk.cuda_image_from_image(weightsSource.GetOutput())\n        )\n        conjugategradient.SetCudaConjugateGradient(not args_info.nocudacg)\n        if args_info.mask is not None:\n            conjugategradient.SetSupportMask(itk.cuda_image_from_image(supportmask))\n    else:\n        ConjugateGradientFilterType = rtk.ConjugateGradientConeBeamReconstructionFilter[\n            OutputImageType\n        ]\n        conjugategradient = ConjugateGradientFilterType.New()\n        conjugategradient.SetInput(inputFilter.GetOutput())\n        conjugategradient.SetInput(1, reader.GetOutput())\n        conjugategradient.SetInput(2, weightsSource.GetOutput())\n        if args_info.mask is not None:\n            conjugategradient.SetSupportMask(supportmask)\n\n    rtk.SetForwardProjectionFromArgParse(args_info, conjugategradient)\n    rtk.SetBackProjectionFromArgParse(args_info, conjugategradient)\n    rtk.SetIterationsReportFromArgParse(args_info, conjugategradient)\n\n    if args_info.gamma is not None:\n        conjugategradient.SetGamma(args_info.gamma)\n    if args_info.tikhonov is not None:\n        conjugategradient.SetTikhonov(args_info.tikhonov)\n\n    conjugategradient.SetGeometry(geometry)\n    conjugategradient.SetNumberOfIterations(args_info.niterations)\n    conjugategradient.SetDisableDisplacedDetectorFilter(args_info.nodisplaced)\n\n    rtk.SetIterationsReportFromArgParse(args_info, conjugategradient)\n\n    conjugategradient.Update()\n\n    # Write\n    writer = itk.ImageFileWriter[OutputImageType].New()\n    writer.SetFileName(args_info.output)\n    writer.SetInput(conjugategradient.GetOutput())\n    writer.Update()\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkdigisensgeometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtkdigisensgeometry_GGO_C rtkdigisensgeometry.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkdigisensgeometry rtkdigisensgeometry.cxx ${rtkdigisensgeometry_GGO_C})\ntarget_link_libraries(rtkdigisensgeometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkdigisensgeometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkdigisensgeometry/rtkdigisensgeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkdigisensgeometry_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkDigisensGeometryReader.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkdigisensgeometry, args_info);\n\n  // Create geometry reader\n  auto reader = rtk::DigisensGeometryReader::New();\n  reader->SetXMLFileName(args_info.xml_file_arg);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputData())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(reader->GetGeometry(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkdigisensgeometry/rtkdigisensgeometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from a Digisens geometry calibration.\"\n\noption \"verbose\"   v \"Verbose execution\"                                     flag            off\noption \"xml_file\"  x \"Digisens XML information file\"                         string          yes\noption \"output\"    o \"Output file name\"                                      string          yes\n"
  },
  {
    "path": "applications/rtkdigisensgeometry/rtkdigisensgeometry.py",
    "content": "import argparse\nfrom itk import RTK as rtk\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Read Digisens geometry XML and write RTK geometry XML file.\"\n    )\n    parser.add_argument(\n        \"--xml_file\", \"-x\", required=True, help=\"Input Digisens XML calibration file\"\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", required=True, help=\"Output geometry XML file\"\n    )\n    parser.add_argument(\n        \"--verbose\", \"-v\", action=\"store_true\", help=\"Enable verbose output\"\n    )\n    return parser\n\ndef process(args_info: argparse.Namespace):\n    # Create geometry reader\n    reader = rtk.DigisensGeometryReader.New()\n    reader.SetXMLFileName(args_info.xml_file)\n    if args_info.verbose:\n        print(f\"Reading Digisens XML: {args_info.xml_file}\")\n    reader.UpdateOutputData()\n\n    # Write geometry\n    if args_info.verbose:\n        print(f\"Writing geometry to {args_info.output}\")\n    rtk.write_geometry(reader.GetGeometry(), args_info.output)\n    if args_info.verbose:\n        print(\"Done.\")\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "applications/rtkdrawgeometricphantom/CMakeLists.txt",
    "content": "WRAP_GGO(rtkdrawgeometricphantom_GGO_C rtkdrawgeometricphantom.ggo ../rtk3Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkdrawgeometricphantom rtkdrawgeometricphantom.cxx ${rtkdrawgeometricphantom_GGO_C})\ntarget_link_libraries(rtkdrawgeometricphantom RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkdrawgeometricphantom)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkdrawgeometricphantom/README.md",
    "content": "# Create gammex phantom\n\n![img](../../documentation/docs/ExternalData/GammexPhantom.png){w=400px alt=\"Gammex\"}\n\nThis script uses the file [Gammex.txt](https://data.kitware.com/api/v1/file/6762da8a290777363f95c293/download) as configuration file which creates a Gammex phantom.\n\n```\n # Create a 3D Gammex phantom\n rtkdrawgeometricphantom --phantomfile Gammex.txt -o gammex.mha\n ```"
  },
  {
    "path": "applications/rtkdrawgeometricphantom/rtkdrawgeometricphantom.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkdrawgeometricphantom_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkDrawGeometricPhantomImageFilter.h\"\n#include \"itkImageFileWriter.h\"\n#include \"rtkAdditiveGaussianNoiseImageFilter.h\"\n\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkdrawgeometricphantom, args_info);\n\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Empty volume image\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkdrawgeometricphantom>(constantImageSource,\n                                                                                                 args_info);\n\n  using DQType = rtk::DrawGeometricPhantomImageFilter<OutputImageType, OutputImageType>;\n\n  // Offset, scale, rotation\n  DQType::VectorType offset(0.);\n  if (args_info.offset_given)\n  {\n    if (args_info.offset_given > 3)\n    {\n      std::cerr << \"--offset needs up to 3 values\" << std::endl;\n      exit(EXIT_FAILURE);\n    }\n    offset[0] = args_info.offset_arg[0];\n    offset[1] = args_info.offset_arg[1];\n    offset[2] = args_info.offset_arg[2];\n  }\n  DQType::VectorType scale;\n  scale.Fill(args_info.phantomscale_arg[0]);\n  if (args_info.phantomscale_given)\n  {\n    if (args_info.phantomscale_given > 3)\n    {\n      std::cerr << \"--phantomscale needs up to 3 values\" << std::endl;\n      exit(EXIT_FAILURE);\n    }\n    for (unsigned int i = 0; i < std::min(args_info.phantomscale_given, Dimension); i++)\n      scale[i] = args_info.phantomscale_arg[i];\n  }\n  DQType::RotationMatrixType rot;\n  rot.SetIdentity();\n  if (args_info.rotation_given)\n  {\n    if (args_info.rotation_given != 9)\n    {\n      std::cerr << \"--rotation needs exactly 9 values\" << std::endl;\n      exit(EXIT_FAILURE);\n    }\n    for (unsigned int i = 0; i < Dimension; i++)\n      for (unsigned int j = 0; j < Dimension; j++)\n        rot[i][j] = args_info.rotation_arg[i * Dimension + j];\n  }\n\n  // Reference\n  if (args_info.verbose_flag)\n    std::cout << \"Creating reference... \" << std::flush;\n  auto dq = DQType::New();\n  dq->SetInput(constantImageSource->GetOutput());\n  dq->SetPhantomScale(scale);\n  dq->SetOriginOffset(offset);\n  dq->SetRotationMatrix(rot);\n  dq->SetConfigFile(args_info.phantomfile_arg);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dq->Update())\n\n  // Add noise\n  OutputImageType::Pointer output = dq->GetOutput();\n  if (args_info.noise_given)\n  {\n    auto noisy = rtk::AdditiveGaussianNoiseImageFilter<OutputImageType>::New();\n    noisy->SetInput(output);\n    noisy->SetMean(0.0);\n    noisy->SetStandardDeviation(args_info.noise_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(noisy->Update())\n    output = noisy->GetOutput();\n  }\n\n  // Write\n  if (args_info.verbose_flag)\n    std::cout << \"Writing reference... \" << std::flush;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(output, args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkdrawgeometricphantom/rtkdrawgeometricphantom.ggo",
    "content": "purpose \"Computes a 3D voxelized phantom from a phantom description file\"\n\noption \"verbose\"      v \"Verbose execution\"                         flag            off\noption \"output\"       o \"Output projections file name\"              string          yes\noption \"phantomfile\"  - \"Parameters of the phantom reference\"       string          yes\noption \"noise\"        - \"Gaussian noise parameter (SD)\"             double          no\noption \"phantomscale\" - \"Scaling factor for the phantom dimensions\" double multiple no default=\"1.\"\noption \"offset\"       - \"3D spatial offset of the phantom center\"   double multiple no\noption \"rotation\"     - \"Rotation matrix for the phantom\"           double multiple no\n\n"
  },
  {
    "path": "applications/rtkdrawgeometricphantom/rtkdrawgeometricphantom.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport sys\nimport itk\nfrom itk import RTK as rtk\nimport numpy as np\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Computes a 3D voxelized phantom from a phantom description file.\"\n    )\n\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output projections file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--phantomfile\",\n        help=\"Parameters of the phantom reference\",\n        type=str,\n        required=True,\n    )\n    parser.add_argument(\"--noise\", help=\"Gaussian noise parameter (SD)\", type=float)\n    parser.add_argument(\n        \"--phantomscale\",\n        help=\"Scaling factor for the phantom dimensions\",\n        type=float,\n        nargs=\"+\",\n        default=[1.0],\n    )\n    parser.add_argument(\n        \"--offset\",\n        help=\"3D spatial offset of the phantom center\",\n        type=float,\n        nargs=\"+\",\n    )\n    parser.add_argument(\n        \"--rotation\",\n        help=\"Rotation matrix for the phantom\",\n        type=float,\n        nargs=\"+\",\n    )\n\n    rtk.add_rtk3Doutputimage_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n    # Define output pixel type and dimension\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Empty volume image\n    constant_image_source = rtk.ConstantImageSource[OutputImageType].New()\n    rtk.SetConstantImageSourceFromArgParse(constant_image_source, args_info)\n\n    # Offset, scale, rotation\n    offset = [0.0] * 3\n    if args_info.offset:\n        if len(args_info.offset) > 3:\n            print(\"--offset needs up to 3 values\", file=sys.stderr)\n            sys.exit(1)\n        offset = args_info.offset\n\n    scale = [args_info.phantomscale[0]] * Dimension\n    if args_info.phantomscale:\n        if len(args_info.phantomscale) > 3:\n            print(\"--phantomscale needs up to 3 values\", file=sys.stderr)\n            sys.exit(1)\n        for i in range(len(args_info.phantomscale)):\n            scale[i] = args_info.phantomscale[i]\n\n    rot = itk.Matrix[itk.D, Dimension, Dimension]()\n    rot.SetIdentity()\n    if args_info.rotation:\n        if len(args_info.rotation) != 9:\n            print(\"--rotation needs exactly 9 values\", file=sys.stderr)\n            sys.exit(1)\n        rot = itk.matrix_from_array(np.array(args_info.rotation).reshape(3, 3))\n\n    # Reference\n    if args_info.verbose:\n        print(\"Creating reference... \", flush=True)\n\n    # DrawGeometricPhantomImageFilter\n    dq = rtk.DrawGeometricPhantomImageFilter[OutputImageType, OutputImageType].New()\n    dq.SetInput(constant_image_source.GetOutput())\n    dq.SetPhantomScale(scale)\n    dq.SetOriginOffset(offset)\n    dq.SetRotationMatrix(rot)\n    dq.SetConfigFile(args_info.phantomfile)\n\n    dq.Update()\n\n    # Add noise\n    output = dq.GetOutput()\n    if args_info.noise:\n        noisy = rtk.AdditiveGaussianNoiseImageFilter[OutputImageType].New()\n        noisy.SetInput(output)\n        noisy.SetMean(0.0)\n        noisy.SetStandardDeviation(args_info.noise)\n\n        noisy.Update()\n\n        output = noisy.GetOutput()\n\n    # Write\n    if args_info.verbose:\n        print(\"Writing reference... \", flush=True)\n\n    itk.imwrite(output, args_info.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkdrawshepploganphantom/CMakeLists.txt",
    "content": "WRAP_GGO(rtkdrawshepploganphantom_GGO_C rtkdrawshepploganphantom.ggo ../rtk3Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkdrawshepploganphantom rtkdrawshepploganphantom.cxx ${rtkdrawshepploganphantom_GGO_C})\ntarget_link_libraries(rtkdrawshepploganphantom RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkdrawshepploganphantom)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkdrawshepploganphantom/rtkdrawshepploganphantom.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkdrawshepploganphantom_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkAdditiveGaussianNoiseImageFilter.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkdrawshepploganphantom, args_info);\n\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Create a stack of empty projection images\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkdrawshepploganphantom>(constantImageSource,\n                                                                                                  args_info);\n\n  // Create a reference object (in this case a 3D phantom reference).\n  using DSLType = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>;\n  DSLType::VectorType offset(0.);\n  DSLType::VectorType scale;\n  for (unsigned int i = 0; i < std::min(args_info.offset_given, Dimension); i++)\n    offset[i] = args_info.offset_arg[i];\n  scale.Fill(args_info.phantomscale_arg[0]);\n  for (unsigned int i = 0; i < std::min(args_info.phantomscale_given, Dimension); i++)\n    scale[i] = args_info.phantomscale_arg[i];\n  auto dsl = DSLType::New();\n  dsl->SetPhantomScale(scale);\n  dsl->SetInput(constantImageSource->GetOutput());\n  dsl->SetOriginOffset(offset);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // Add noise\n  OutputImageType::Pointer output = dsl->GetOutput();\n  if (args_info.noise_given)\n  {\n    auto noisy = rtk::AdditiveGaussianNoiseImageFilter<OutputImageType>::New();\n    noisy->SetInput(output);\n    noisy->SetMean(0.0);\n    noisy->SetStandardDeviation(args_info.noise_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(noisy->Update())\n    output = noisy->GetOutput();\n  }\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(output, args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkdrawshepploganphantom/rtkdrawshepploganphantom.ggo",
    "content": "purpose \"Computes a 3D voxelized Shepp & Logan phantom with noise [https://www.slaney.org/pct/pct-errata.html]\"\n\noption \"verbose\"      v \"Verbose execution\"                         flag            off\noption \"output\"       o \"Output projections file name\"              string          yes\noption \"phantomscale\" - \"Scaling factor for the phantom dimensions\" double multiple no default=\"128\"\noption \"noise\"        - \"Gaussian noise parameter (SD)\"             double          no\noption \"offset\"       - \"3D spatial offset of the phantom center\"   double multiple no\n"
  },
  {
    "path": "applications/rtkdrawshepploganphantom/rtkdrawshepploganphantom.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport sys\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Computes a 3D voxelized Shepp & Logan phantom with noise [https://www.slaney.org/pct/pct-errata.html]\"\n    )\n\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output projections file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--phantomscale\",\n        help=\"Scaling factor for the phantom dimensions\",\n        type=float,\n        nargs=\"+\",\n        default=[128],\n    )\n    parser.add_argument(\"--noise\", help=\"Gaussian noise parameter (SD)\", type=float)\n    parser.add_argument(\n        \"--offset\",\n        help=\"3D spatial offset of the phantom center\",\n        type=float,\n        nargs=\"+\",\n    )\n\n    rtk.add_rtk3Doutputimage_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n    # Define output pixel type and dimension\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Empty volume image\n    constant_image_source = rtk.ConstantImageSource[OutputImageType].New()\n    rtk.SetConstantImageSourceFromArgParse(constant_image_source, args_info)\n\n    # Offset, scale, rotation\n    offset = [0.0] * 3\n    if args_info.offset:\n        if len(args_info.offset) > 3:\n            print(\"--offset needs up to 3 values\", file=sys.stderr)\n            sys.exit(1)\n        offset = args_info.offset\n\n    scale = [args_info.phantomscale[0]] * Dimension\n    if args_info.phantomscale:\n        if len(args_info.phantomscale) > 3:\n            print(\"--phantomscale needs up to 3 values\", file=sys.stderr)\n            sys.exit(1)\n        for i in range(len(args_info.phantomscale)):\n            scale[i] = args_info.phantomscale[i]\n\n    # Reference\n    if args_info.verbose:\n        print(\"Creating reference... \", flush=True)\n\n    # DrawSheppLoganPhantomImageFilter\n    dsl = rtk.DrawSheppLoganFilter[OutputImageType, OutputImageType].New()\n    dsl.SetPhantomScale(scale)\n    dsl.SetInput(constant_image_source.GetOutput())\n    dsl.SetOriginOffset(offset)\n\n    dsl.Update()\n\n    # Add noise\n    output = dsl.GetOutput()\n    if args_info.noise:\n        noisy = rtk.AdditiveGaussianNoiseImageFilter[OutputImageType].New()\n        noisy.SetInput(output)\n        noisy.SetMean(0.0)\n        noisy.SetStandardDeviation(args_info.noise)\n\n        noisy.Update()\n\n        output = noisy.GetOutput()\n\n    # Write\n    if args_info.verbose:\n        print(\"Writing reference... \", flush=True)\n\n    itk.imwrite(output, args_info.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkdualenergyforwardmodel/CMakeLists.txt",
    "content": "WRAP_GGO(rtkdualenergyforwardmodel_GGO_C rtkdualenergyforwardmodel.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkdualenergyforwardmodel rtkdualenergyforwardmodel.cxx ${rtkdualenergyforwardmodel_GGO_C})\ntarget_link_libraries(rtkdualenergyforwardmodel RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkdualenergyforwardmodel)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n"
  },
  {
    "path": "applications/rtkdualenergyforwardmodel/rtkdualenergyforwardmodel.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkdualenergyforwardmodel_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n#include \"rtkSpectralForwardModelImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkdualenergyforwardmodel, args_info);\n\n  using PixelValueType = float;\n  constexpr unsigned int Dimension = 3;\n\n  using DecomposedProjectionType = itk::VectorImage<PixelValueType, Dimension>;\n\n  using DualEnergyProjectionsType = itk::VectorImage<PixelValueType, Dimension>;\n\n  using IncidentSpectrumReaderType = itk::ImageFileReader<itk::Image<PixelValueType, Dimension>>;\n\n  using DetectorResponseImageType = itk::Image<PixelValueType, Dimension - 1>;\n\n\n  // Read all inputs\n  auto decomposedProjectionReader = itk::ImageFileReader<DecomposedProjectionType>::New();\n  decomposedProjectionReader->SetFileName(args_info.input_arg);\n  decomposedProjectionReader->Update();\n\n  auto incidentSpectrumReaderHighEnergy = IncidentSpectrumReaderType::New();\n  incidentSpectrumReaderHighEnergy->SetFileName(args_info.high_arg);\n  incidentSpectrumReaderHighEnergy->Update();\n\n  auto incidentSpectrumReaderLowEnergy = IncidentSpectrumReaderType::New();\n  incidentSpectrumReaderLowEnergy->SetFileName(args_info.low_arg);\n  incidentSpectrumReaderLowEnergy->Update();\n\n  auto materialAttenuationsReader = itk::ImageFileReader<itk::Image<PixelValueType, Dimension - 1>>::New();\n  materialAttenuationsReader->SetFileName(args_info.attenuations_arg);\n  materialAttenuationsReader->Update();\n\n  // Get parameters from the images\n  const unsigned int MaximumEnergy =\n    incidentSpectrumReaderHighEnergy->GetOutput()->GetLargestPossibleRegion().GetSize(0);\n\n  // If the detector response is given by the user, use it. Otherwise, assume it is included in the\n  // incident spectrum, and fill the response with ones\n  auto                               detectorResponseReader = itk::ImageFileReader<DetectorResponseImageType>::New();\n  DetectorResponseImageType::Pointer detectorImage;\n  if (args_info.detector_given)\n  {\n    detectorResponseReader->SetFileName(args_info.detector_arg);\n    detectorResponseReader->Update();\n    detectorImage = detectorResponseReader->GetOutput();\n  }\n  else\n  {\n    auto detectorSource = rtk::ConstantImageSource<DetectorResponseImageType>::New();\n    detectorSource->SetSize(itk::MakeSize(1, MaximumEnergy));\n    detectorSource->SetConstant(1.0);\n    detectorSource->Update();\n    detectorImage = detectorSource->GetOutput();\n  }\n\n  // Generate a set of zero-filled intensity projections\n  auto dualEnergyProjections = DualEnergyProjectionsType::New();\n  dualEnergyProjections->CopyInformation(decomposedProjectionReader->GetOutput());\n  dualEnergyProjections->SetVectorLength(2);\n  dualEnergyProjections->Allocate();\n\n  // Check that the inputs have the expected size\n  DecomposedProjectionType::IndexType indexDecomp;\n  indexDecomp.Fill(0);\n  if (decomposedProjectionReader->GetOutput()->GetVectorLength() != 2)\n    itkGenericExceptionMacro(<< \"Decomposed projections (i.e. initialization data) image has vector length \"\n                             << decomposedProjectionReader->GetOutput()->GetVectorLength() << \", should be 2\");\n\n  if (materialAttenuationsReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] != MaximumEnergy)\n    itkGenericExceptionMacro(<< \"Material attenuations image has \"\n                             << materialAttenuationsReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1]\n                             << \"energies, should have \" << MaximumEnergy);\n\n  // Create and set the filter\n  auto forward = rtk::SpectralForwardModelImageFilter<DecomposedProjectionType, DualEnergyProjectionsType>::New();\n  forward->SetInputDecomposedProjections(decomposedProjectionReader->GetOutput());\n  forward->SetInputMeasuredProjections(dualEnergyProjections);\n  forward->SetInputIncidentSpectrum(incidentSpectrumReaderHighEnergy->GetOutput());\n  forward->SetInputSecondIncidentSpectrum(incidentSpectrumReaderLowEnergy->GetOutput());\n  forward->SetDetectorResponse(detectorImage);\n  forward->SetMaterialAttenuations(materialAttenuationsReader->GetOutput());\n  forward->SetIsSpectralCT(false);\n  forward->SetComputeVariances(args_info.variances_given);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(forward->Update())\n\n  // Write output\n  auto writer = itk::ImageFileWriter<DualEnergyProjectionsType>::New();\n  writer->SetInput(forward->GetOutput());\n  writer->SetFileName(args_info.output_arg);\n  writer->Update();\n\n  // If requested, write the variances\n  if (args_info.variances_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(forward->GetOutputVariances(), args_info.variances_arg))\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkdualenergyforwardmodel/rtkdualenergyforwardmodel.ggo",
    "content": "purpose \"Computes expected photon counts from incident spectrum, material attenuations, detector response and material-decomposed projections\"\n\noption \"verbose\"    v \"Verbose execution\"                                                 flag                         off\noption \"output\"     o \"Output file name (high and low energy projections)\"                string                       yes\noption \"input\"      i \"Material-decomposed projections\"                                   string                       yes\noption \"high\"       - \"Incident spectrum image, high energy\"                              string                       yes\noption \"low\"        - \"Incident spectrum image, low energy\"                               string                       yes\noption \"detector\"   d \"Detector response file\"                                            string                       no\noption \"attenuations\" a \"Material attenuations file\"                                      string                       yes\noption \"variances\"  - \"Output variances of measured energies, file name\"                  string                       no\n"
  },
  {
    "path": "applications/rtkdualenergyforwardmodel/rtkdualenergyforwardmodel.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport sys\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Computes expected photon counts from incident spectrum, material attenuations, detector response and material-decomposed projections\"\n    )\n\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output file name (high and low energy projections)\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--input\", \"-i\", help=\"Material-decomposed projections\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--high\", help=\"Incident spectrum image, high energy\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--low\", help=\"Incident spectrum image, low energy\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--detector\", \"-d\", help=\"Detector response file\", type=str\n    )\n    parser.add_argument(\n        \"--attenuations\", \"-a\", help=\"Material attenuations file\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--variances\", help=\"Output variances of measured energies, file name\", type=str\n    )\n\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n    # Define pixel type and dimension\n    PixelValueType = itk.F\n    Dimension = 3\n\n    DecomposedProjectionType = itk.VectorImage[PixelValueType, Dimension]\n    DualEnergyProjectionsType = itk.VectorImage[PixelValueType, Dimension]\n    IncidentSpectrumImageType = itk.Image[PixelValueType, Dimension]\n    DetectorResponseImageType = itk.Image[PixelValueType, Dimension - 1]\n    MaterialAttenuationsImageType = itk.Image[PixelValueType, Dimension - 1]\n\n    # Read all inputs\n    if args_info.verbose:\n        print(\"Reading material-decomposed projections...\")\n    decomposed_projection_reader = itk.ImageFileReader[DecomposedProjectionType].New()\n    decomposed_projection_reader.SetFileName(args_info.input)\n    decomposed_projection_reader.Update()\n\n    if args_info.verbose:\n        print(\"Reading incident spectrum (high energy)...\")\n    incident_spectrum_reader_high_energy = itk.ImageFileReader[IncidentSpectrumImageType].New()\n    incident_spectrum_reader_high_energy.SetFileName(args_info.high)\n    incident_spectrum_reader_high_energy.Update()\n\n    if args_info.verbose:\n        print(\"Reading incident spectrum (low energy)...\")\n    incident_spectrum_reader_low_energy = itk.ImageFileReader[IncidentSpectrumImageType].New()\n    incident_spectrum_reader_low_energy.SetFileName(args_info.low)\n    incident_spectrum_reader_low_energy.Update()\n\n    if args_info.verbose:\n        print(\"Reading material attenuations...\")\n    material_attenuations_reader = itk.ImageFileReader[MaterialAttenuationsImageType].New()\n    material_attenuations_reader.SetFileName(args_info.attenuations)\n    material_attenuations_reader.Update()\n\n    # Get parameters from the images\n    maximum_energy = incident_spectrum_reader_high_energy.GetOutput().GetLargestPossibleRegion().GetSize(0)\n\n    # If the detector response is given by the user, use it. Otherwise, assume it is included in the\n    # incident spectrum, and fill the response with ones\n    if args_info.detector:\n        if args_info.verbose:\n            print(\"Reading detector response...\")\n        detector_response_reader = itk.ImageFileReader[DetectorResponseImageType].New()\n        detector_response_reader.SetFileName(args_info.detector)\n        detector_response_reader.Update()\n        detector_image = detector_response_reader.GetOutput()\n    else:\n        if args_info.verbose:\n            print(\"No detector response provided, using default (ones)...\")\n        detector_source = rtk.ConstantImageSource[DetectorResponseImageType].New()\n        detector_source.SetSize([1, maximum_energy])\n        detector_source.SetConstant(1.0)\n        detector_source.Update()\n        detector_image = detector_source.GetOutput()\n\n    # Generate a set of zero-filled intensity projections\n    dual_energy_projections = DualEnergyProjectionsType.New()\n    dual_energy_projections.CopyInformation(decomposed_projection_reader.GetOutput())\n    dual_energy_projections.SetVectorLength(2)\n    dual_energy_projections.Allocate()\n\n    # Check that the inputs have the expected size\n    if decomposed_projection_reader.GetOutput().GetVectorLength() != 2:\n        print(f\"Error: Decomposed projections image has vector length {decomposed_projection_reader.GetOutput().GetVectorLength()}, should be 2\")\n        sys.exit(1)\n\n    if material_attenuations_reader.GetOutput().GetLargestPossibleRegion().GetSize()[1] != maximum_energy:\n        print(f\"Error: Material attenuations image has {material_attenuations_reader.GetOutput().GetLargestPossibleRegion().GetSize()[1]} energies, should have {maximum_energy}\")\n        sys.exit(1)\n\n    # Create and set the filter\n    if args_info.verbose:\n        print(\"Setting up spectral forward model filter...\")\n    forward = rtk.SpectralForwardModelImageFilter[DecomposedProjectionType, DualEnergyProjectionsType].New()\n    forward.SetInputDecomposedProjections(decomposed_projection_reader.GetOutput())\n    forward.SetInputMeasuredProjections(dual_energy_projections)\n    forward.SetInputIncidentSpectrum(incident_spectrum_reader_high_energy.GetOutput())\n    forward.SetInputSecondIncidentSpectrum(incident_spectrum_reader_low_energy.GetOutput())\n    forward.SetDetectorResponse(detector_image)\n    forward.SetMaterialAttenuations(material_attenuations_reader.GetOutput())\n    forward.SetIsSpectralCT(False)\n    forward.SetComputeVariances(args_info.variances is not None)\n\n    forward.Update()\n\n    # Write output\n    if args_info.verbose:\n        print(f\"Writing output to {args_info.output}...\")\n    writer = itk.ImageFileWriter[DualEnergyProjectionsType].New()\n    writer.SetInput(forward.GetOutput())\n    writer.SetFileName(args_info.output)\n    writer.Update()\n\n    # If requested, write the variances\n    if args_info.variances:\n        if args_info.verbose:\n            print(f\"Writing variances to {args_info.variances}...\")\n\n        itk.imwrite(forward.GetOutputVariances(), args_info.variances)\n\n    if args_info.verbose:\n        print(\"Processing completed successfully.\")\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkdualenergysimplexdecomposition/CMakeLists.txt",
    "content": "WRAP_GGO(rtkdualenergysimplexdecomposition_GGO_C rtkdualenergysimplexdecomposition.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkdualenergysimplexdecomposition rtkdualenergysimplexdecomposition.cxx ${rtkdualenergysimplexdecomposition_GGO_C})\ntarget_link_libraries(rtkdualenergysimplexdecomposition RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkdualenergysimplexdecomposition)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n"
  },
  {
    "path": "applications/rtkdualenergysimplexdecomposition/rtkdualenergysimplexdecomposition.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkdualenergysimplexdecomposition_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n#include \"rtkSimplexSpectralProjectionsDecompositionImageFilter.h\"\n\n#include <itkImageRegionIterator.h>\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkdualenergysimplexdecomposition, args_info);\n\n  using PixelValueType = float;\n  constexpr unsigned int Dimension = 3;\n\n  using DecomposedProjectionType = itk::VectorImage<PixelValueType, Dimension>;\n\n  using DualEnergyProjectionsType = itk::VectorImage<PixelValueType, Dimension>;\n\n  using IncidentSpectrumImageType = itk::Image<PixelValueType, Dimension>;\n  using IncidentSpectrumReaderType = itk::ImageFileReader<IncidentSpectrumImageType>;\n\n  using DetectorResponseImageType = itk::Image<PixelValueType, Dimension - 1>;\n\n  using MaterialAttenuationsImageType = itk::Image<PixelValueType, Dimension - 1>;\n\n  // Read all inputs\n  auto decomposedProjectionReader = itk::ImageFileReader<DecomposedProjectionType>::New();\n  decomposedProjectionReader->SetFileName(args_info.input_arg);\n  decomposedProjectionReader->Update();\n\n  auto dualEnergyProjectionReader = itk::ImageFileReader<DualEnergyProjectionsType>::New();\n  dualEnergyProjectionReader->SetFileName(args_info.dual_arg);\n  dualEnergyProjectionReader->Update();\n\n  auto incidentSpectrumReaderHighEnergy = IncidentSpectrumReaderType::New();\n  incidentSpectrumReaderHighEnergy->SetFileName(args_info.high_arg);\n  incidentSpectrumReaderHighEnergy->Update();\n\n  auto incidentSpectrumReaderLowEnergy = IncidentSpectrumReaderType::New();\n  incidentSpectrumReaderLowEnergy->SetFileName(args_info.low_arg);\n  incidentSpectrumReaderLowEnergy->Update();\n\n  auto materialAttenuationsReader = itk::ImageFileReader<MaterialAttenuationsImageType>::New();\n  materialAttenuationsReader->SetFileName(args_info.attenuations_arg);\n  materialAttenuationsReader->Update();\n\n  // Get parameters from the images\n  const unsigned int MaximumEnergy =\n    incidentSpectrumReaderHighEnergy->GetOutput()->GetLargestPossibleRegion().GetSize(0);\n\n  // If the detector response is given by the user, use it. Otherwise, assume it is included in the\n  // incident spectrum, and fill the response with ones\n  auto                               detectorResponseReader = itk::ImageFileReader<DetectorResponseImageType>::New();\n  DetectorResponseImageType::Pointer detectorImage;\n  if (args_info.detector_given)\n  {\n    detectorResponseReader->SetFileName(args_info.detector_arg);\n    detectorResponseReader->Update();\n    detectorImage = detectorResponseReader->GetOutput();\n  }\n  else\n  {\n    auto detectorSource = rtk::ConstantImageSource<DetectorResponseImageType>::New();\n    detectorSource->SetSize(itk::MakeSize(1, MaximumEnergy));\n    detectorSource->SetConstant(1.0);\n    detectorSource->Update();\n    detectorImage = detectorSource->GetOutput();\n  }\n\n  if (detectorImage->GetLargestPossibleRegion().GetSize()[1] != MaximumEnergy)\n    itkGenericExceptionMacro(<< \"Detector response image has \" << detectorImage->GetLargestPossibleRegion().GetSize()[1]\n                             << \"energies, should have \" << MaximumEnergy);\n\n  // Create and set the filter\n  auto simplex = rtk::SimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionType,\n                                                                         DualEnergyProjectionsType,\n                                                                         IncidentSpectrumImageType,\n                                                                         DetectorResponseImageType,\n                                                                         MaterialAttenuationsImageType>::New();\n  simplex->SetInputDecomposedProjections(decomposedProjectionReader->GetOutput());\n  simplex->SetGuessInitialization(args_info.guess_flag);\n  simplex->SetInputMeasuredProjections(dualEnergyProjectionReader->GetOutput());\n  simplex->SetInputIncidentSpectrum(incidentSpectrumReaderHighEnergy->GetOutput());\n  simplex->SetInputSecondIncidentSpectrum(incidentSpectrumReaderLowEnergy->GetOutput());\n  simplex->SetDetectorResponse(detectorImage);\n  simplex->SetMaterialAttenuations(materialAttenuationsReader->GetOutput());\n  simplex->SetNumberOfIterations(args_info.niterations_arg);\n  simplex->SetOptimizeWithRestarts(args_info.restarts_flag);\n  simplex->SetIsSpectralCT(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(simplex->Update())\n\n  // Write outputs\n  auto writer = itk::ImageFileWriter<DecomposedProjectionType>::New();\n  writer->SetInput(simplex->GetOutput(0));\n  writer->SetFileName(args_info.output_arg);\n  writer->Update();\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkdualenergysimplexdecomposition/rtkdualenergysimplexdecomposition.ggo",
    "content": "purpose \"Decomposes dual energy projections into materials\"\n\noption \"verbose\"          v \"Verbose execution\"                                                 flag                         off\noption \"input\"            i \"Initial solution for material decomposition, file name\"            string                       yes\noption \"output\"     o \"Output file name (decomposed projections)\"                               string                       yes\noption \"dual\"             - \"Projections to be decomposed, VectorImage file name\"               string                       yes\noption \"detector\"         d \"Detector response file\"                                            string                       no\noption \"high\"             - \"High energy incident spectrum file\"                                string                       yes\noption \"low\"              - \"Low energy incident spectrum file\"                                 string                       yes\noption \"attenuations\"     a \"Material attenuations file\"                                        string                       yes\noption \"niterations\"      n \"Number of iterations\"                                              int                           no   default=\"300\"\noption \"weightsmap\"       w \"File name for the output weights map (inverse noise variance)\"     string                        no\noption \"restarts\"         r \"Allow random restarts during optimization\"                         flag                         off\noption \"guess\"            g \"Ignore values in input and initialize the simplex with a simple heuristic instead\"     flag     off\n"
  },
  {
    "path": "applications/rtkdualenergysimplexdecomposition/rtkdualenergysimplexdecomposition.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport sys\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Decomposes dual energy projections into materials\"\n    )\n\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--input\", \"-i\", help=\"Initial solution for material decomposition, file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output file name (decomposed projections)\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--dual\", help=\"Projections to be decomposed, VectorImage file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--detector\", \"-d\", help=\"Detector response file\", type=str\n    )\n    parser.add_argument(\n        \"--high\", help=\"High energy incident spectrum file\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--low\", help=\"Low energy incident spectrum file\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--attenuations\", \"-a\", help=\"Material attenuations file\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--niterations\", \"-n\", help=\"Number of iterations\", type=int, default=300\n    )\n    parser.add_argument(\n        \"--weightsmap\", \"-w\", help=\"File name for the output weights map (inverse noise variance)\", type=str\n    )\n    parser.add_argument(\n        \"--restarts\", \"-r\", help=\"Allow random restarts during optimization\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--guess\", \"-g\", help=\"Ignore values in input and initialize the simplex with a simple heuristic instead\", action=\"store_true\"\n    )\n\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n    # Define pixel type and dimension\n    PixelValueType = itk.F\n    Dimension = 3\n\n    DecomposedProjectionType = itk.VectorImage[PixelValueType, Dimension]\n    DualEnergyProjectionsType = itk.VectorImage[PixelValueType, Dimension]\n    IncidentSpectrumImageType = itk.Image[PixelValueType, Dimension]\n    DetectorResponseImageType = itk.Image[PixelValueType, Dimension - 1]\n    MaterialAttenuationsImageType = itk.Image[PixelValueType, Dimension - 1]\n\n    # Read all inputs\n    if args_info.verbose:\n        print(\"Reading initial solution for material decomposition...\")\n    decomposed_projection_reader = itk.ImageFileReader[DecomposedProjectionType].New()\n    decomposed_projection_reader.SetFileName(args_info.input)\n    decomposed_projection_reader.Update()\n\n    if args_info.verbose:\n        print(\"Reading dual energy projections...\")\n    dual_energy_projection_reader = itk.ImageFileReader[DualEnergyProjectionsType].New()\n    dual_energy_projection_reader.SetFileName(args_info.dual)\n    dual_energy_projection_reader.Update()\n\n    if args_info.verbose:\n        print(\"Reading incident spectrum (high energy)...\")\n    incident_spectrum_reader_high_energy = itk.ImageFileReader[IncidentSpectrumImageType].New()\n    incident_spectrum_reader_high_energy.SetFileName(args_info.high)\n    incident_spectrum_reader_high_energy.Update()\n\n    if args_info.verbose:\n        print(\"Reading incident spectrum (low energy)...\")\n    incident_spectrum_reader_low_energy = itk.ImageFileReader[IncidentSpectrumImageType].New()\n    incident_spectrum_reader_low_energy.SetFileName(args_info.low)\n    incident_spectrum_reader_low_energy.Update()\n\n    if args_info.verbose:\n        print(\"Reading material attenuations...\")\n    material_attenuations_reader = itk.ImageFileReader[MaterialAttenuationsImageType].New()\n    material_attenuations_reader.SetFileName(args_info.attenuations)\n    material_attenuations_reader.Update()\n\n    # Get parameters from the images\n    maximum_energy = incident_spectrum_reader_high_energy.GetOutput().GetLargestPossibleRegion().GetSize(0)\n\n    # If the detector response is given by the user, use it. Otherwise, assume it is included in the\n    # incident spectrum, and fill the response with ones\n    if args_info.detector:\n        if args_info.verbose:\n            print(\"Reading detector response...\")\n        detector_response_reader = itk.ImageFileReader[DetectorResponseImageType].New()\n        detector_response_reader.SetFileName(args_info.detector)\n        detector_response_reader.Update()\n        detector_image = detector_response_reader.GetOutput()\n    else:\n        if args_info.verbose:\n            print(\"No detector response provided, using default (ones)...\")\n        detector_source = rtk.ConstantImageSource[DetectorResponseImageType].New()\n        detector_source.SetSize([1, maximum_energy])\n        detector_source.SetConstant(1.0)\n        detector_source.Update()\n        detector_image = detector_source.GetOutput()\n\n    # Validate detector response size\n    if detector_image.GetLargestPossibleRegion().GetSize()[1] != maximum_energy:\n        print(f\"Error: Detector response image has {detector_image.GetLargestPossibleRegion().GetSize()[1]} energies, should have {maximum_energy}\")\n        sys.exit(1)\n\n    # Create and set the filter\n    if args_info.verbose:\n        print(\"Setting up simplex spectral projections decomposition filter...\")\n    simplex = rtk.SimplexSpectralProjectionsDecompositionImageFilter[\n        DecomposedProjectionType,\n        DualEnergyProjectionsType,\n        IncidentSpectrumImageType,\n        DetectorResponseImageType,\n        MaterialAttenuationsImageType\n    ].New()\n\n    simplex.SetInputDecomposedProjections(decomposed_projection_reader.GetOutput())\n    simplex.SetGuessInitialization(args_info.guess)\n    simplex.SetInputMeasuredProjections(dual_energy_projection_reader.GetOutput())\n    simplex.SetInputIncidentSpectrum(incident_spectrum_reader_high_energy.GetOutput())\n    simplex.SetInputSecondIncidentSpectrum(incident_spectrum_reader_low_energy.GetOutput())\n    simplex.SetDetectorResponse(detector_image)\n    simplex.SetMaterialAttenuations(material_attenuations_reader.GetOutput())\n    simplex.SetNumberOfIterations(args_info.niterations)\n    simplex.SetOptimizeWithRestarts(args_info.restarts)\n    simplex.SetIsSpectralCT(False)\n\n    simplex.Update()\n\n    # Write output\n    if args_info.verbose:\n        print(f\"Writing decomposed projections to {args_info.output}...\")\n    writer = itk.ImageFileWriter[DecomposedProjectionType].New()\n    writer.SetInput(simplex.GetOutput(0))\n    writer.SetFileName(args_info.output)\n    writer.Update()\n\n    # If requested, write the weights map\n    if args_info.weightsmap:\n        if args_info.verbose:\n            print(f\"Writing weights map to {args_info.weightsmap}...\")\n\n        # Note: The weights map output might need to be accessed differently\n        # depending on the actual filter implementation\n        weights_writer = itk.ImageFileWriter[DecomposedProjectionType].New()\n        weights_writer.SetInput(simplex.GetOutputWeights())\n        weights_writer.SetFileName(args_info.weightsmap)\n        weights_writer.Update()\n\n    if args_info.verbose:\n        print(\"Decomposition completed successfully.\")\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkelektasynergygeometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtkelektasynergygeometry_GGO_C rtkelektasynergygeometry.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkelektasynergygeometry rtkelektasynergygeometry.cxx ${rtkelektasynergygeometry_GGO_C})\ntarget_link_libraries(rtkelektasynergygeometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkelektasynergygeometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkelektasynergygeometry/README.md",
    "content": "# Elekta Reconstruction\n\nElekta provides easy access to raw data. The data and projection images are stored in a single directory which is user-configurable. The default location is `D:\\db`. In this folder, there is a database in DBase format. Each table is contained in a `.DBF` file. RTK needs the `IMAGE.DBF` and `FRAME.DBF` tables.\n\nPatient data are stored in individual folders. By default, the name of each patient folder is `patient_ID` where `ID` is the patient ID. In these folders, one can access the planning CT in the `CT_SET` subfolder and the cone-beam projections in `IMAGES/img_DICOM_UID` subfolders, where `DICOM_UID` is the DICOM UID of the acquisition. The projection images are `.his` files. The reconstructed images are the `IMAGES/img_DICOM_UID/Reconstruction/*SCAN` files.\n\n## Reconstruction Steps\n\nThe first step before proceeding with the reconstruction is to convert Elekta's database information into an RTK geometry file using a command-line tool. Follow these steps:\n\n### 1. Download Elekta Dataset\n\nDownload the dataset from [Elekta-data](https://data.kitware.com/api/v1/item/5be973478d777f2179a26e1c/download).\n\n### 2. Convert Geometry\n\nRun the application to convert Elekta's geometry into RTK's format (DICOM_UID is contained in the subfolder name of the `.his` files):\n\n```bash\nrtkelektasynergygeometry \\\n  --image_db IMAGE.DBF \\\n  --frame_db FRAME.DBF \\\n  --dicom_uid 1.3.46.423632.135428.1351013645.166 \\\n  -o elektaGeometry\n```\n\nSince XVI v5, the geometry is contained in a separate `_Frames.xml` file, which can be used as follows:\n\n```bash\nrtkelektasynergygeometry \\\n  --xml _Frames.xml \\\n  -o elektaGeometry\n```\n\nAn example of such a file is available in the test data [here](https://data.kitware.com/api/v1/item/5b179c898d777f15ebe201fd/download).\n\n### 3. Reconstruct Using RTK Applications\n\nUse the `rtkfdk` algorithm to reconstruct a single axial slice (e.g., slice 29.5) of the volume:\n\n```bash\nrtkfdk \\\n  --lowmem \\\n  --geometry elektaGeometry \\\n  --path img_1.3.46.423632.135428.1351013645.166/ \\\n  --regexp '.*.his' \\\n  --output slice29.5.mha \\\n  --verbose \\\n  --spacing 0.25,0.25,0.25 \\\n  --size 1024,1,1024 \\\n  --origin -127.875,29.5,-127.875\n```\n\n### 4. Apply the FOV Filter\n\nApply the field-of-view (FOV) filter to mask out everything outside the FOV:\n\n```bash\nrtkfieldofview \\\n  --geometry elektaGeometry \\\n  --path img_1.3.46.423632.135428.1351013645.166/ \\\n  --regexp '.*.his' \\\n  --reconstruction slice29.5.mha \\\n  --output slice29.5.mha \\\n  --verbose\n```\n\n### 5. Visualize the Result\n\nYou can visualize the result using a viewer (e.g., VV). The resulting image should look like the following:\n\n![Elekta.jpg](../../documentation/docs/ExternalData/Elekta.png){w=400px alt=\"Elekta snapshot\"}\n"
  },
  {
    "path": "applications/rtkelektasynergygeometry/rtkelektasynergygeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkelektasynergygeometry_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkElektaSynergyGeometryReader.h\"\n#include \"rtkElektaXVI5GeometryXMLFileReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkelektasynergygeometry, args_info);\n\n  if (args_info.image_db_given && args_info.frame_db_given && args_info.dicom_uid_given && !args_info.xml_given)\n  {\n    // Create geometry reader\n    auto reader = rtk::ElektaSynergyGeometryReader::New();\n    reader->SetDicomUID(args_info.dicom_uid_arg);\n    reader->SetImageDbfFileName(args_info.image_db_arg);\n    reader->SetFrameDbfFileName(args_info.frame_db_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputData())\n\n    // Write\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(reader->GetGeometry(), args_info.output_arg))\n\n\n    return EXIT_SUCCESS;\n  }\n  else if (!args_info.image_db_given && !args_info.frame_db_given && !args_info.dicom_uid_given && args_info.xml_given)\n  {\n    // Create geometry reader\n    rtk::ElektaXVI5GeometryXMLFileReader::Pointer geometryReader;\n    geometryReader = rtk::ElektaXVI5GeometryXMLFileReader::New();\n    geometryReader->SetFilename(args_info.xml_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(geometryReader->GenerateOutputInformation());\n\n    // Write\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(geometryReader->GetGeometry(), args_info.output_arg))\n\n    return EXIT_SUCCESS;\n  }\n\n  std::cerr << \"You must either provide image_db, frame_db and dicom_uid\"\n            << \"for versions up to v4 or xml starting with v5.\" << std::endl;\n\n  return EXIT_FAILURE;\n}\n"
  },
  {
    "path": "applications/rtkelektasynergygeometry/rtkelektasynergygeometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from an Elekta Synergy acquisition.\"\n\noption \"verbose\"   v \"Verbose execution\"                    flag   off\noption \"image_db\"  i \"Image table filename (prior to XVI5)\" string no\noption \"frame_db\"  f \"Frame table filename (prior to XVI5)\" string no\noption \"xml\"       x \"XML file name (starting with XVI5)\"   string no\noption \"dicom_uid\" u \"Dicom uid of the acquisition\"         string no\noption \"output\"    o \"Output file name\"                     string yes\n"
  },
  {
    "path": "applications/rtkelektasynergygeometry/rtkelektasynergygeometry.py",
    "content": "#!/usr/bin/env python\nimport argparse\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Creates an RTK geometry file from an Elekta Synergy acquisition.\"\n    )\n\n    parser.add_argument(\"--verbose\", \"-v\", help=\"Verbose execution\", type=bool)\n    parser.add_argument(\n        \"--xml\", \"-x\", help=\"XML file name (starting with XVI5)\", required=True\n    )\n    parser.add_argument(\"--output\", \"-o\", help=\"Output file name\", required=True)\n\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n\n    reader = rtk.ElektaXVI5GeometryXMLFileReader.New()\n    reader.SetFilename(args_info.xml)\n    reader.GenerateOutputInformation()\n\n    rtk.write_geometry(reader.GetGeometry(), args_info.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkextractphasesignal/CMakeLists.txt",
    "content": "WRAP_GGO(rtkextractphasesignal_GGO_C rtkextractphasesignal.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkextractphasesignal rtkextractphasesignal.cxx ${rtkextractphasesignal_GGO_C})\ntarget_link_libraries(rtkextractphasesignal RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkextractphasesignal)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkextractphasesignal/rtkextractphasesignal.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkextractphasesignal_ggo.h\"\n#include \"rtkMacro.h\"\n\n#include \"rtkExtractPhaseImageFilter.h\"\n\n#include <itkImageFileReader.h>\n#include <fstream>\n\nnamespace rtk\n{\ntemplate <class TSignalType>\nvoid\nWriteSignalToTextFile(TSignalType * sig, const std::string & fileName)\n{\n  std::ofstream                              ofs(fileName.c_str());\n  itk::ImageRegionConstIterator<TSignalType> it(sig, sig->GetLargestPossibleRegion());\n  for (it.GoToBegin(); !it.IsAtEnd(); ++it)\n  {\n    ofs << it.Get() << std::endl;\n  }\n  ofs.close();\n}\n} // namespace rtk\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkextractphasesignal, args_info);\n\n  constexpr unsigned int Dimension = 1;\n\n  using ImageType = itk::Image<double, Dimension>;\n\n  // Read\n  ImageType::Pointer signal;\n  signal = itk::ReadImage<ImageType>(args_info.input_arg);\n\n  // Process phase signal if required\n  using PhaseFilter = rtk::ExtractPhaseImageFilter<ImageType>;\n  auto phase = PhaseFilter::New();\n  phase->SetInput(signal);\n  phase->SetMovingAverageSize(args_info.movavg_arg);\n  phase->SetUnsharpMaskSize(args_info.unsharp_arg);\n  phase->SetModel((PhaseFilter::ModelType)args_info.model_arg);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(phase->Update())\n\n  // Write output phase\n  rtk::WriteSignalToTextFile(phase->GetOutput(), args_info.output_arg);\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkextractphasesignal/rtkextractphasesignal.ggo",
    "content": "purpose \"Extracts the phase from a signal.\"\n\noption \"verbose\"    v   \"Verbose execution\"                                   flag                    off\noption \"input\"      i   \"Input signal\"\t\t                                    string                  yes\noption \"output\"     o   \"Output file name for the Hilbert phase signal\"       string                  yes\noption \"movavg\"     -   \"Moving average size applied before phase extraction\" int     default=\"1\"  no\noption \"unsharp\"    -   \"Unsharp mask size applied before phase extraction\"   int     default=\"55\" no\noption \"model\"      -   \"Phase model\" values=\"LOCAL_PHASE\",\"LINEAR_BETWEEN_MINIMA\",\"LINEAR_BETWEEN_MAXIMA\" enum no default=\"LINEAR_BETWEEN_MINIMA\"\n"
  },
  {
    "path": "applications/rtkextractphasesignal/rtkextractphasesignal.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef write_signal_to_text_file(signal_image, filename):\n\n    # Convert ITK image to numpy array\n    signal_array = itk.array_from_image(signal_image)\n\n    # Write to text file\n    with open(filename, 'w') as f:\n        for value in signal_array.flatten():\n            f.write(f\"{value}\\n\")\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Extracts the phase from a signal.\"\n    )\n\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--input\", \"-i\", help=\"Input signal\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output file name for the Hilbert phase signal\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--movavg\", help=\"Moving average size applied before phase extraction\", type=int, default=1\n    )\n    parser.add_argument(\n        \"--unsharp\", help=\"Unsharp mask size applied before phase extraction\", type=int, default=55\n    )\n    parser.add_argument(\n        \"--model\",\n        help=\"Phase model\",\n        choices=[\"LOCAL_PHASE\", \"LINEAR_BETWEEN_MINIMA\", \"LINEAR_BETWEEN_MAXIMA\"],\n        default=\"LINEAR_BETWEEN_MINIMA\"\n    )\n\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n    # Define pixel type and dimension\n    PixelType = itk.D  # double\n    Dimension = 1\n    ImageType = itk.Image[PixelType, Dimension]\n\n    # Read input signal\n    if args_info.verbose:\n        print(f\"Reading input signal from {args_info.input}...\")\n\n    reader = itk.ImageFileReader[ImageType].New()\n    reader.SetFileName(args_info.input)\n    reader.Update()\n    signal = reader.GetOutput()\n\n    # Process phase signal if required\n    PhaseFilter = rtk.ExtractPhaseImageFilter[ImageType]\n    phase = PhaseFilter.New()\n    phase.SetInput(signal)\n    phase.SetMovingAverageSize(args_info.movavg)\n    phase.SetUnsharpMaskSize(args_info.unsharp)\n\n    # Map string to enum integer value\n    model_values = {\n        \"LOCAL_PHASE\": 0,\n        \"LINEAR_BETWEEN_MINIMA\": 1,\n        \"LINEAR_BETWEEN_MAXIMA\": 2\n    }\n    phase.SetModel(model_values[args_info.model])\n\n    # Write output phase signal\n    if args_info.verbose:\n        print(f\"Writing phase signal to {args_info.output}...\")\n\n    write_signal_to_text_file(phase.GetOutput(), args_info.output)\n\n    if args_info.verbose:\n        print(\"Phase extraction completed successfully.\")\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkextractshroudsignal/CMakeLists.txt",
    "content": "WRAP_GGO(rtkextractshroudsignal_GGO_C rtkextractshroudsignal.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkextractshroudsignal rtkextractshroudsignal.cxx ${rtkextractshroudsignal_GGO_C})\ntarget_link_libraries(rtkextractshroudsignal RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkextractshroudsignal)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkextractshroudsignal/rtkextractshroudsignal.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkextractshroudsignal_ggo.h\"\n#include \"rtkMacro.h\"\n\n#include \"rtkDPExtractShroudSignalImageFilter.h\"\n#include \"rtkReg1DExtractShroudSignalImageFilter.h\"\n#include \"rtkExtractPhaseImageFilter.h\"\n\n#include <itkImageFileReader.h>\n#include <fstream>\n\nnamespace rtk\n{\ntemplate <class TSignalType>\nvoid\nWriteSignalToTextFile(TSignalType * sig, const std::string & fileName)\n{\n  std::ofstream                              ofs(fileName.c_str());\n  itk::ImageRegionConstIterator<TSignalType> it(sig, sig->GetLargestPossibleRegion());\n  for (it.GoToBegin(); !it.IsAtEnd(); ++it)\n  {\n    ofs << it.Get() << std::endl;\n  }\n  ofs.close();\n}\n} // namespace rtk\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkextractshroudsignal, args_info);\n\n  using InputPixelType = double;\n  using OutputPixelType = double;\n  constexpr unsigned int Dimension = 2;\n\n  using InputImageType = itk::Image<InputPixelType, Dimension>;\n  using OutputImageType = itk::Image<OutputPixelType, Dimension - 1>;\n\n  // Extract shroud signal\n  OutputImageType::Pointer shroudSignal;\n  if (std::string(args_info.method_arg) == \"DynamicProgramming\")\n  {\n    if (!args_info.amplitude_given)\n    {\n      std::cerr << \"You must supply a maximum amplitude to look for.\" << std::endl;\n      return 1;\n    }\n    using shroudFilterType = rtk::DPExtractShroudSignalImageFilter<InputPixelType, OutputPixelType>;\n    auto shroudFilter = shroudFilterType::New();\n    shroudFilter->SetInput(itk::ReadImage<InputImageType>(args_info.input_arg));\n    shroudFilter->SetAmplitude(args_info.amplitude_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(shroudFilter->Update())\n    shroudSignal = shroudFilter->GetOutput();\n  }\n  else if (std::string(args_info.method_arg) == \"Reg1D\")\n  {\n    using shroudFilterType = rtk::Reg1DExtractShroudSignalImageFilter<InputPixelType, OutputPixelType>;\n    auto shroudFilter = shroudFilterType::New();\n    shroudFilter->SetInput(itk::ReadImage<InputImageType>(args_info.input_arg));\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(shroudFilter->Update())\n    shroudSignal = shroudFilter->GetOutput();\n  }\n  else\n  {\n    std::cerr << \"The specified method does not exist.\" << std::endl;\n    return 1;\n  }\n\n  // Write output signal\n  rtk::WriteSignalToTextFile(shroudSignal.GetPointer(), args_info.output_arg);\n\n  // Process phase signal if required\n  if (args_info.phase_given)\n  {\n    using PhaseFilter = rtk::ExtractPhaseImageFilter<OutputImageType>;\n    auto phase = PhaseFilter::New();\n    phase->SetInput(shroudSignal);\n    phase->SetMovingAverageSize(args_info.movavg_arg);\n    phase->SetUnsharpMaskSize(args_info.unsharp_arg);\n    phase->SetModel((PhaseFilter::ModelType)args_info.model_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(phase->Update())\n\n    rtk::WriteSignalToTextFile(phase->GetOutput(), args_info.phase_arg);\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkextractshroudsignal/rtkextractshroudsignal.ggo",
    "content": "purpose \"Extracts the breathing signal from a shroud image.\"\n\noption \"verbose\"    v   \"Verbose execution\"                           flag                    off\noption \"input\"      i   \"Input shroud image file name\"\t\t            string                  yes\noption \"amplitude\"  a   \"Maximum breathing amplitude explored in mm\"  double                  no\noption \"output\"     o   \"Output file name\"                            string                  yes\noption \"method\"     m   \"Method to use (Reg1D or DynamicProgramming)\" string  default=\"Reg1D\" no\n\nsection \"Phase extraction\"\noption \"phase\"      p   \"Output file name for the Hilbert phase signal\"       string               no\noption \"movavg\"     -   \"Moving average size applied before phase extraction\" int     default=\"1\"  no\noption \"unsharp\"    -   \"Unsharp mask size applied before phase extraction\"   int     default=\"55\" no\noption \"model\"      -   \"Phase model\" values=\"LOCAL_PHASE\",\"LINEAR_BETWEEN_MINIMA\",\"LINEAR_BETWEEN_MAXIMA\" enum no default=\"LINEAR_BETWEEN_MINIMA\"\n"
  },
  {
    "path": "applications/rtkfdk/CMakeLists.txt",
    "content": "WRAP_GGO(rtkfdk_GGO_C rtkfdk.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkfdk rtkfdk.cxx ${rtkfdk_GGO_C})\ntarget_link_libraries(rtkfdk RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkfdk)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkfdk/FDK2D.sh",
    "content": "# Create a simulated geometry\nrtksimulatedgeometry -n 180 -o geometry.xml\n\n# Create projections of the phantom file\n# Note the sinogram being 3 pixels wide in the y direction to allow back-projection interpolation in a 2D image\nrtkprojectgeometricphantom -g geometry.xml -o projections.mha --spacing 2 --size=512,3,512 --phantomfile SheppLogan-2d.txt --phantomscale=256,1,256\n\n# Reconstruct\nrtkfdk -p . -r projections.mha -o fdk.mha -g geometry.xml --spacing 2 --size 256,1,256\n\n# Create a reference volume for comparison\nrtkdrawgeometricphantom --spacing 2 --size=256,1,256 --phantomfile SheppLogan-2d.txt -o ref.mha --phantomscale=256,1,256"
  },
  {
    "path": "applications/rtkfdk/FDK3D.sh",
    "content": "# Create a simulated geometry\nrtksimulatedgeometry -n 180 -o geometry.xml\n# You may add \"--arc 200\" to make the scan short or \"--proj_iso_x 200\" to offset the detector\n\n# Create projections of the phantom file\nrtkprojectshepploganphantom -g geometry.xml -o projections.mha --spacing 2 --size 200\n\n# Reconstruct\nrtkfdk -p . -r projections.mha -o fdk.mha -g geometry.xml --spacing 2 --size 128\n\n# Create a reference volume for comparison\nrtkdrawshepploganphantom --like fdk.mha -o ref.mha\n"
  },
  {
    "path": "applications/rtkfdk/README.md",
    "content": "# 3D, 2D and motion-compensated FDK\n\nThe following exampels illustrates the command line application `rtkfdk` by reconstructing a Shepp Logan phantom with Feldkamp, David and Kress algorithm in 3D (cone-beam) and 2D (fan-beam).\n\n`````{tab-set}\n\n````{tab-item} 3D\n\n## 3D\n\n![sin_3D](../../documentation/docs/ExternalData/SheppLogan-Sinogram-3D.png){w=200px alt=\"SheppLogan sinogram 3D \"}\n![img_3D](../../documentation/docs/ExternalData/Fdk-3D.png){w=200px alt=\"Fdk reconstruction 3D\"}\n\nThis script uses the SheppLogan phantom.\n\n```{literalinclude} FDK3D.sh\n```\n\n````\n````{tab-item} 2D\n\n## 2D\n\n![sin_2D](../../documentation/docs/ExternalData/SheppLogan-Sinogram-2D.png){w=200px alt=\"SheppLogan sinogram 2D\"}\n![img_2D](../../documentation/docs/ExternalData/Fdk-2D.png){w=200px alt=\"Fdk reconstruction 2D\"}\n\nThe same reconstruction can be performed using the original 2D Shepp-Logan phantom.\nRTK can perform 2D reconstructions through images wide of 1 pixel in the y direction.\nThe following script performs the same reconstruction as above in a 2D environment and uses the [2D Shepp-Logan](https://data.kitware.com/api/v1/file/67d1ff45c6dec2fc9c534d0d/download) phantom as input.\n\n```{literalinclude} FDK2D.sh\n```\n````\n\n````{tab-item} Motion compensated\n\n## Motion-compensated reconstruction\n\nRTK provides the necessary tools to reconstruct an image with motion compensation. The implementation is based on two articles that we have published ([article 1](https://hal.archives-ouvertes.fr/hal-00443440) and [article 2](https://hal.archives-ouvertes.fr/hal-01967313)) but only the FDK-based motion-compensated CBCT reconstruction (analytic algorithm in article 1) and without optimization (very slow reconstruction compared to article 2). You should read the articles to understand the basics of the algorithm before trying to use the software.\n\nThe algorithm requires a set of projection images with the associated RTK geometry, the respiratory phase of each projection image and the 4D motion vector field over a respiratory cycle in the cone-beam coordinate system. Each piece of data is described in more details below and can be downloaded using [Girder](https://data.kitware.com/#collection/5a7706878d777f0649e04776). It is assumed that we have a breathing motion that is cyclic and similar to that described by the vector field. Note that you could modify the code and create your own motion model if you want to, in which case you should probably [contact us](http://www.openrtk.org/RTK/project/contactus.html).\n\n### Projection images\n\nThis example is illustrated with a set of projection images of the [POPI patient](https://github.com/open-vv/popi-model/blob/master/popi-model.md). This dataset has been used in the first previously-mentioned article. You can [download the projections](https://data.kitware.com/api/v1/item/5be99af88d777f2179a2e144/download) and the required tables of the Elekta database, [FRAME.DBF](https://data.kitware.com/api/v1/item/5be99a068d777f2179a2cf4f/download) and [IMAGE.DBF](https://data.kitware.com/api/v1/item/5be99a078d777f2179a2cf65/download). The dataset is first used to reconstruct a blurry image:\n\n```bash\n# Convert Elekta database to RTK geometry\nrtkelektasynergygeometry \\\n  -o geometry.rtk \\\n  -f FRAME.DBF \\\n  -i IMAGE.DBF \\\n  -u 1.3.46.423632.141000.1169042526.68\n\n# Reconstruct from all projection images without any motion compensation\nrtkfdk \\\n  -p . \\\n  -r .*.his \\\n  -o fdk.mha \\\n  -g geometry.rtk \\\n  --hann 0.5 \\\n  --pad 1.0\n\n# Keep only the field-of-view of the image\nrtkfieldofview \\\n  --reconstruction fdk.mha \\\n  --output fdk.mha \\\n  --geometry geometry.rtk \\\n  --path . \\\n  --regexp '.*.his'\n```\n\nYou should obtain something like that with [VV](http://vv.creatis.insa-lyon.fr/):\n\n![Blurred](../../documentation/docs/ExternalData/Blurred.jpg){w=600px alt=\"Blurred image\"}\n\n### Deformation vector field\n\nThe next piece of data is a 4D deformation vector field that describes a respiratory cycle. Typically, it can be obtained from the 4D planning CT with deformable image registration. Here, I have used [Elastix](http://elastix.lumc.nl/) with the [sliding module](http://elastix.lumc.nl/modelzoo/par0016) developed by Vivien Delmon. The registration uses a [patient mask](https://data.kitware.com/api/v1/item/5be99a408d777f2179a2dde8/download) (red+green) and a [motion mask](https://data.kitware.com/api/v1/item/5be99a088d777f2179a2cf6f/download) (red) as described in [Jef's publication](http://www.creatis.insa-lyon.fr/site/fr/publications/VAND-12):\n\n![Mm](../../documentation/docs/ExternalData/MotionMask.jpg){w=400px alt=\"Motion mask\"}\n\nThe registration can easily be scripted, here with bash, where each phase image of the POPI 4D CT has been stored in files 00.mhd to 50.mhd:\n\n```bash\nfor i in $(seq -w 0 10 90)\ndo\n  mkdir $i\n  elastix -f 50.mhd \\\n          -m $i.mhd \\\n          -out $i \\\n          -labels mm_50.mha \\\n          -fMask patient_50.mha \\\n          -p Par0016.multibsplines.lung.sliding.txt\ndone\n```\n\nDeformable Image Registration is a complex and long process so you will have to be patient here. Note that the reference frame is phase 50% and it is registered to each phase from 0% to 90%. One subtle step is that the vector field is a displacement vector field, i.e., each vector is the local displacement of the point at its location. Since I ran the registration on the 4D planning CT, the coordinate system is not that of the cone-beam CT. In order to produce the vector field in the cone-beam coordinate system, I have used the following bash script that combines transformix and several \"clitk\" tools that are provided along with VV:\n\n```bash\n# Create 4x4 matrix that describes the CT to CBCT change of coordinate system.\n# This matrix is a combination of the knowledge of the isocenter position / axes orientation\n# and a rigid alignment that has been performed with Elastix\necho \"-0.0220916855767852  0.9996655273534405 -0.0134458487848415 -83.6625731437426197\"  >CT_CBCT.mat\necho \" 0.0150924269790251 -0.0131141301144939 -0.9998000991394341  -4.0763571826687057\" >>CT_CBCT.mat\necho \" 0.9996420239647088  0.0222901999207823  0.0147976657359281  77.8903364738220034\" >>CT_CBCT.mat\necho \" 0.0000000000000000  0.0000000000000000  0.0000000000000000   1.0000000000000000\" >>CT_CBCT.mat\n\n# Transform 4x4 matrix that describes the transformation\n# from planning CT to CBCT to a vector field\nclitkMatrixTransformToVF --like 50.mhd \\\n                         --matrix CT_CBCT.mat \\\n                         --output CT_CBCT.mha\n\n# Inverse transformation. Also remove upper slices that are outside the\n# planning CT CBCT_CT.mat is the inverse of CT_CBCT.mha\nclitkMatrixInverse -i CT_CBCT.mat \\\n                   -o CBCT_CT.mat\nclitkMatrixTransformToVF --origin -127.5,-107.5,-127.5 \\\n                         --spacing 1,1,1 \\\n                         --size 256,236,256 \\\n                         --matrix CBCT_CT.mat \\\n                         --output CBCT_CT.mha\n\n# Go over each elastix output file, generate the vector field with\n# transformix and compose with the two rigid vector fields\nfor i in $(seq -w 0 10 90)\ndo\n  transformix -in 50.mhd \\\n              -out $i \\\n              -tp $i/TransformParameters.0.txt \\\n              -def all -threads 16\n  clitkComposeVF --input1 CBCT_CT.mha \\\n                 --input2 $i/deformationField.mhd \\\n                 --output $i/deformationField.mhd\n  clitkComposeVF --input1 $i/deformationField.mhd \\\n                 --input2 CT_CBCT.mha \\\n                 --output $i/deformationField.mhd\ndone\n```\n\nThis is a bit complicated and there are probably other ways of doing this. For example, Vivien has resampled the planning CT frames on the CBCT coordinate system before doing the registrations, in which case you do not need to do all this. Just pick one of your choice but motion-compensated CBCT reconstruction requires a 4D vector field that is nicely displayed on top of a CBCT image, for example the fdk.mha that has been produced in the first step (the vector field is downsampled and displayed with VV):\n\n![Vf](../../documentation/docs/ExternalData/VectorField.gif){w=400px alt=\"Vector field\"}\n\nThe elastix output files and the transformed 4D DVF are available [here](https://data.kitware.com/api/v1/item/5be99a058d777f2179a2cf42/download).\n\n### Respiratory signal\n\nThe motion model requires that we associate each projection image with one frame of the 4D vector field. We used the Amsterdam shroud solution of Lambert Zijp (described [here](http://www.creatis.insa-lyon.fr/site/fr/publications/RIT-12a)) which is implemented in RTK\n\n```bash\nrtkamsterdamshroud --path . \\\n                   --regexp '.*.his' \\\n                   --output shroud.mha \\\n                   --unsharp 650\nrtkextractshroudsignal --input shroud.mha \\\n                       --output signal.txt\n```\n\nPost-process with Matlab to obtain the phase signal, ensuring the phase ranges from 0 to 1 (e.g., 0.3 corresponds to 30% of the respiratory cycle). The resulting phase is visualized [here](https://data.kitware.com/api/v1/item/5be99af98d777f2179a2e160/download):\n\n![Signal](../../documentation/docs/ExternalData/Signal.jpg){w=800px alt=\"Phase signal\"}\n\n---\n\n### Motion-compensated cone-beam CT reconstruction\n\nGather all the pieces to perform motion-compensated reconstruction. Use the following commands:\n\nReconstruct with Motion Compensation :\n```bash\nrtkfdk \\\n  -p . \\\n  -r .*.his \\\n  -o fdk.mha \\\n  -g geometry.rtk \\\n  --hann 0.5 \\\n  --pad 1.0 \\\n  --signal sphase.txt \\\n  --dvf deformationField_4D.mhd\n```\n\nApply the Field-of-View Filter :\n```bash\nrtkfieldofview \\\n  --reconstruction fdk.mha \\\n  --output fdk.mha \\\n  --geometry geometry.rtk \\\n  --path . \\\n  --regexp '.*.his'\n```\n\nToggle between uncorrected and motion-compensated reconstruction to appreciate the improvement:\n\n![Blurred vs mc.gif](../../documentation/docs/ExternalData/Blurred_vs_mc.gif){w=400 alt=\"blurred vs motion compensation image\"}\n\nThe 4D vector field is constructed with phase 50% as a reference. Modify the reference image to reconstruct other phases, such as the time-average position.\n````\n`````\n"
  },
  {
    "path": "applications/rtkfdk/rtkfdk.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkfdk_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkDisplacedDetectorForOffsetFieldOfViewImageFilter.h\"\n#include \"rtkParkerShortScanImageFilter.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaDisplacedDetectorImageFilter.h\"\n// TODO #  include \"rtkCudaDisplacedDetectorForOffsetFieldOfViewImageFilter.h\"\n#  include \"rtkCudaParkerShortScanImageFilter.h\"\n#  include \"rtkCudaFDKConeBeamReconstructionFilter.h\"\n#endif\n#include \"rtkFDKWarpBackProjectionImageFilter.h\"\n#include \"rtkCyclicDeformationImageFilter.h\"\n#include \"rtkProgressCommands.h\"\n\n#include <itkStreamingImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkfdk, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n  using CPUOutputImageType = itk::Image<OutputPixelType, Dimension>;\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = CPUOutputImageType;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkfdk>(reader, args_info);\n\n  if (!args_info.lowmem_flag)\n  {\n    if (args_info.verbose_flag)\n      std::cout << \"Reading... \" << std::endl;\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update())\n  }\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Check on hardware parameter\n#ifndef RTK_USE_CUDA\n  if (!strcmp(args_info.hardware_arg, \"cuda\"))\n  {\n    std::cerr << \"The program has not been compiled with cuda option\" << std::endl;\n    return EXIT_FAILURE;\n  }\n#endif\n\n  // Displaced detector weighting\n#ifdef RTK_USE_CUDA\n  using DDFType = rtk::CudaDisplacedDetectorImageFilter;\n#else\n  using DDFType = rtk::DisplacedDetectorForOffsetFieldOfViewImageFilter<OutputImageType>;\n#endif\n  rtk::DisplacedDetectorImageFilter<OutputImageType>::Pointer ddf;\n  if (!strcmp(args_info.hardware_arg, \"cuda\"))\n    ddf = DDFType::New();\n  else\n    ddf = rtk::DisplacedDetectorForOffsetFieldOfViewImageFilter<OutputImageType>::New();\n  ddf->SetInput(reader->GetOutput());\n  ddf->SetGeometry(geometry);\n  ddf->SetDisable(args_info.nodisplaced_flag);\n\n  // Short scan image filter\n  using PSSFCPUType = rtk::ParkerShortScanImageFilter<OutputImageType>;\n#ifdef RTK_USE_CUDA\n  using PSSFType = rtk::CudaParkerShortScanImageFilter;\n#else\n  using PSSFType = rtk::ParkerShortScanImageFilter<OutputImageType>;\n#endif\n  PSSFCPUType::Pointer pssf;\n  if (!strcmp(args_info.hardware_arg, \"cuda\"))\n    pssf = PSSFType::New();\n  else\n    pssf = PSSFCPUType::New();\n  pssf->SetInput(ddf->GetOutput());\n  pssf->SetGeometry(geometry);\n  pssf->InPlaceOff();\n  pssf->SetAngularGapThreshold(args_info.short_arg * itk::Math::pi / 180.);\n\n  // Create reconstructed image\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkfdk>(constantImageSource, args_info);\n\n  // Motion-compensated objects for the compensation of a cyclic deformation.\n  // Although these will only be used if the command line options for motion\n  // compensation are set, we still create the object before hand to avoid auto\n  // destruction.\n  using DVFPixelType = itk::Vector<float, 3>;\n  using DeformationType = rtk::CyclicDeformationImageFilter<itk::Image<DVFPixelType, 4>, itk::Image<DVFPixelType, 3>>;\n  auto dvfReader = itk::ImageFileReader<DeformationType::InputImageType>::New();\n  auto def = DeformationType::New();\n  def->SetInput(dvfReader->GetOutput());\n  auto bp = rtk::FDKWarpBackProjectionImageFilter<OutputImageType, OutputImageType, DeformationType>::New();\n  bp->SetDeformation(def);\n  bp->SetGeometry(geometry);\n\n  // This macro sets options for fdk filter which I can not see how to do better\n  // because TFFTPrecision is not the same, e.g. for CPU and CUDA (SR)\n#define SET_FELDKAMP_OPTIONS(f)                                   \\\n  f->SetInput(0, constantImageSource->GetOutput());               \\\n  f->SetInput(1, pssf->GetOutput());                              \\\n  f->SetGeometry(geometry);                                       \\\n  f->GetRampFilter()->SetTruncationCorrection(args_info.pad_arg); \\\n  f->GetRampFilter()->SetHannCutFrequency(args_info.hann_arg);    \\\n  f->GetRampFilter()->SetHannCutFrequencyY(args_info.hannY_arg);  \\\n  f->SetProjectionSubsetSize(args_info.subsetsize_arg);           \\\n  if (args_info.verbose_flag)                                     \\\n  {                                                               \\\n    f->AddObserver(itk::AnyEvent(), progressCommand);             \\\n  }\n\n  // FDK reconstruction filtering\n  using FDKCPUType = rtk::FDKConeBeamReconstructionFilter<OutputImageType>;\n  FDKCPUType::Pointer feldkamp;\n#ifdef RTK_USE_CUDA\n  using FDKCUDAType = rtk::CudaFDKConeBeamReconstructionFilter;\n  FDKCUDAType::Pointer feldkampCUDA;\n#endif\n\n  itk::Image<OutputPixelType, Dimension> * pfeldkamp = nullptr;\n  if (!strcmp(args_info.hardware_arg, \"cpu\"))\n  {\n    // Progress reporting\n    using PercentageProgressCommandType = rtk::PercentageProgressCommand<FDKCPUType>;\n    auto progressCommand = PercentageProgressCommandType::New();\n\n    feldkamp = FDKCPUType::New();\n    SET_FELDKAMP_OPTIONS(feldkamp);\n\n    // Motion compensated CBCT settings\n    if (args_info.signal_given && args_info.dvf_given)\n    {\n      dvfReader->SetFileName(args_info.dvf_arg);\n      def->SetSignalFilename(args_info.signal_arg);\n      feldkamp->SetBackProjectionFilter(bp.GetPointer());\n    }\n    pfeldkamp = feldkamp->GetOutput();\n  }\n#ifdef RTK_USE_CUDA\n  else if (!strcmp(args_info.hardware_arg, \"cuda\"))\n  {\n    // Motion compensation not supported in cuda\n    if (args_info.signal_given && args_info.dvf_given)\n    {\n      std::cerr << \"Motion compensation is not supported in CUDA. Aborting\" << std::endl;\n      return EXIT_FAILURE;\n    }\n\n    // Progress reporting\n    using PercentageProgressCommandType = rtk::PercentageProgressCommand<FDKCUDAType>;\n    auto progressCommand = PercentageProgressCommandType::New();\n\n    feldkampCUDA = FDKCUDAType::New();\n    SET_FELDKAMP_OPTIONS(feldkampCUDA);\n    pfeldkamp = feldkampCUDA->GetOutput();\n  }\n#endif\n\n  // Streaming depending on streaming capability of writer\n  auto streamerBP = itk::StreamingImageFilter<CPUOutputImageType, CPUOutputImageType>::New();\n  streamerBP->SetInput(pfeldkamp);\n  streamerBP->SetNumberOfStreamDivisions(args_info.divisions_arg);\n  auto splitter = itk::ImageRegionSplitterDirection::New();\n  splitter->SetDirection(2); // Prevent splitting along z axis. As a result, splitting will be performed along y axis\n  streamerBP->SetRegionSplitter(splitter);\n\n  // Write\n  if (args_info.verbose_flag)\n    std::cout << \"Reconstructing and writing... \" << std::endl;\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(streamerBP->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkfdk/rtkfdk.ggo",
    "content": "purpose \"Reconstructs a 3D volume from a sequence of projections [Feldkamp, David, Kress, 1984].\"\n\noption \"verbose\"    v \"Verbose execution\"                                           flag                         off\noption \"geometry\"   g \"XML geometry file name\"                                      string                       yes\noption \"output\"     o \"Output file name\"                                            string                       yes\noption \"hardware\"   - \"Hardware used for computation\"                               values=\"cpu\",\"cuda\"          no   default=\"cpu\"\noption \"lowmem\"     l \"Load only one projection per thread in memory\"               flag                         off\noption \"divisions\"  d \"Streaming option: number of stream divisions of the CT\"      int                          no   default=\"1\"\noption \"subsetsize\" - \"Streaming option: number of projections processed at a time\" int                          no   default=\"16\"\noption \"nodisplaced\" - \"Disable the displaced detector filter\"                      flag                         off\noption \"short\"      - \"Minimum angular gap to detect a short scan (in degree).\"     double                       no   default=\"20\"\n\nsection \"Ramp filter\"\noption \"pad\"       - \"Data padding parameter to correct for truncation\"          double                       no   default=\"0.0\"\noption \"hann\"      - \"Cut frequency for hann window in ]0,1] (0.0 disables it)\"  double                       no   default=\"0.0\"\noption \"hannY\"     - \"Cut frequency for hann window in ]0,1] (0.0 disables it)\"  double                       no   default=\"0.0\"\n\nsection \"Motion-compensation described in [Rit et al, TMI, 2009] and [Rit et al, Med Phys, 2009]\"\noption \"signal\"    - \"Signal file name\"          string    no\noption \"dvf\"       - \"Input 4D DVF\"              string    no\n"
  },
  {
    "path": "applications/rtkfdk/rtkfdk.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport sys\nimport math\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Reconstructs a 3D volume from a sequence of projections [Feldkamp, David, Kress, 1984].\"\n    )\n\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--geometry\", \"-g\", help=\"XML geometry file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--hardware\",\n        help=\"Hardware used for computation\",\n        choices=[\"cpu\", \"cuda\"],\n        default=\"cpu\",\n    )\n    parser.add_argument(\n        \"--lowmem\",\n        \"-l\",\n        help=\"Load only one projection per thread in memory\",\n        action=\"store_true\",\n    )\n    parser.add_argument(\n        \"--divisions\",\n        \"-d\",\n        help=\"Streaming option: number of stream divisions of the CT\",\n        type=int,\n        default=1,\n    )\n    parser.add_argument(\n        \"--subsetsize\",\n        help=\"Streaming option: number of projections processed at a time\",\n        type=int,\n        default=16,\n    )\n    parser.add_argument(\n        \"--nodisplaced\",\n        help=\"Disable the displaced detector filter\",\n        action=\"store_true\",\n    )\n    parser.add_argument(\n        \"--short\",\n        help=\"Minimum angular gap to detect a short scan (converted to radians)\",\n        type=float,\n        default=20.0,\n    )\n\n    # Ramp filter options\n    ramp_group = parser.add_argument_group(\"Ramp filter\")\n    ramp_group.add_argument(\n        \"--pad\",\n        help=\"Data padding parameter to correct for truncation\",\n        type=float,\n        default=0.0,\n    )\n    ramp_group.add_argument(\n        \"--hann\",\n        help=\"Cut frequency for Hann window in ]0,1] (0.0 disables it)\",\n        type=float,\n        default=0.0,\n    )\n    ramp_group.add_argument(\n        \"--hannY\",\n        help=\"Cut frequency for Hann window in ]0,1] (0.0 disables it)\",\n        type=float,\n        default=0.0,\n    )\n\n    # Motion compensation options\n    motion_group = parser.add_argument_group(\n        \"Motion compensation described in [Rit et al, TMI, 2009] and [Rit et al, Med Phys, 2009]\"\n    )\n    motion_group.add_argument(\"--signal\", help=\"Signal file name\", type=str)\n    motion_group.add_argument(\"--dvf\", help=\"Input 4D DVF\", type=str)\n\n    # RTK specific groups\n    rtk.add_rtkinputprojections_group(parser)\n    rtk.add_rtk3Doutputimage_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n    # Define pixel type and dimension\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Projections reader\n    reader = rtk.ProjectionsReader[OutputImageType].New()\n    rtk.SetProjectionsReaderFromArgParse(reader, args_info)\n\n    if not args_info.lowmem:\n        if args_info.verbose:\n            print(\"Reading projections...\")\n        reader.Update()\n\n    # Geometry\n    if args_info.verbose:\n        print(f\"Reading geometry information from {args_info.geometry}...\")\n    geometry = rtk.read_geometry(args_info.geometry)\n\n    # Check on hardware parameter\n    if not hasattr(itk, \"CudaImage\") and args_info.hardware == \"cuda\":\n        print(\"The program has not been compiled with CUDA option.\")\n        sys.exit(1)\n\n    # CUDA classes are non-templated, so they do not require a type specification.\n    if args_info.hardware == \"cuda\":\n        ddf = rtk.CudaDisplacedDetectorImageFilter.New()\n        ddf.SetInput(itk.cuda_image_from_image(reader.GetOutput()))\n        pssf = rtk.CudaParkerShortScanImageFilter.New()\n    else:\n        ddf = rtk.DisplacedDetectorForOffsetFieldOfViewImageFilter[\n            OutputImageType\n        ].New()\n        ddf.SetInput(reader.GetOutput())\n        pssf = rtk.ParkerShortScanImageFilter[OutputImageType].New()\n\n    # Displaced detector weighting\n    ddf.SetGeometry(geometry)\n    ddf.SetDisable(args_info.nodisplaced)\n\n    # Short scan image filter\n    pssf.SetInput(ddf.GetOutput())\n    pssf.SetGeometry(geometry)\n    pssf.InPlaceOff()\n    pssf.SetAngularGapThreshold(args_info.short * math.pi / 180.0)\n\n    # Create reconstructed image\n    constantImageSource = rtk.ConstantImageSource[OutputImageType].New()\n    rtk.SetConstantImageSourceFromArgParse(constantImageSource, args_info)\n\n    # Motion-compensated objects for the compensation of a cyclic deformation.\n    # Although these will only be used if the command line options for motion\n    # compensation are set, we still create the object beforehand to avoid auto\n    # destruction.\n    DVFPixelType = itk.Vector[itk.F, 3]\n    DVFImageType = itk.Image[DVFPixelType, 3]\n    DVFImageSequenceType = itk.Image[DVFPixelType, 4]\n\n    # Create the deformation filter and reader for DVF\n    deformation = rtk.CyclicDeformationImageFilter[\n        DVFImageSequenceType, DVFImageType\n    ].New()\n    dvfReader = itk.ImageFileReader[DVFImageSequenceType].New()\n    deformation.SetInput(dvfReader.GetOutput())\n\n    # Set up the back projection filter for motion compensation\n    bp = rtk.FDKWarpBackProjectionImageFilter[\n        OutputImageType, OutputImageType, type(deformation)\n    ].New()\n    bp.SetDeformation(deformation)\n    bp.SetGeometry(geometry)\n\n    # FDK reconstruction filtering\n    if args_info.hardware == \"cuda\":\n        feldkamp = rtk.CudaFDKConeBeamReconstructionFilter.New()\n        feldkamp.SetInput(0, itk.cuda_image_from_image(constantImageSource.GetOutput()))\n    else:\n        feldkamp = rtk.FDKConeBeamReconstructionFilter[OutputImageType].New()\n        feldkamp.SetInput(0, constantImageSource.GetOutput())\n\n    # Set inputs and options for the FDK filter\n    feldkamp.SetInput(1, pssf.GetOutput())\n    feldkamp.SetGeometry(geometry)\n    feldkamp.GetRampFilter().SetTruncationCorrection(args_info.pad)\n    feldkamp.GetRampFilter().SetHannCutFrequency(args_info.hann)\n    feldkamp.GetRampFilter().SetHannCutFrequencyY(args_info.hannY)\n    feldkamp.SetProjectionSubsetSize(args_info.subsetsize)\n\n    # Progress reporting\n    if args_info.verbose:\n        progressCommand = rtk.PercentageProgressCommand(feldkamp)\n        feldkamp.AddObserver(\n            itk.ProgressEvent(), progressCommand.callback\n        )  # Register the callback for progress\n        feldkamp.AddObserver(\n            itk.EndEvent(), progressCommand.End\n        )  # Register end notification\n\n    # Motion compensated CBCT settings\n    if args_info.signal and args_info.dvf:\n        if args_info.hardware == \"cuda\":\n            print(\"Motion compensation is not supported in CUDA. Aborting\")\n            sys.exit(1)  # Exit if CUDA is selected with motion compensation\n        dvfReader.SetFileName(args_info.dvf)\n        deformation.SetSignalFilename(args_info.signal)\n        feldkamp.SetBackProjectionFilter(bp)\n\n    # Streaming depending on streaming capability of writer\n    streamerBP = itk.StreamingImageFilter[OutputImageType, OutputImageType].New()\n    streamerBP.SetInput(feldkamp.GetOutput())\n    streamerBP.SetNumberOfStreamDivisions(args_info.divisions)\n\n    # Create a splitter to control how the image region is divided during streaming\n    splitter = itk.ImageRegionSplitterDirection.New()\n    splitter.SetDirection(2)\n    streamerBP.SetRegionSplitter(splitter)\n\n    if args_info.verbose:\n        print(\"Reconstructing and writing...\")\n\n    itk.imwrite(streamerBP.GetOutput(), args_info.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkfieldofview/CMakeLists.txt",
    "content": "WRAP_GGO(rtkfieldofview_GGO_C rtkfieldofview.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkfieldofview rtkfieldofview.cxx ${rtkfieldofview_GGO_C})\ntarget_link_libraries(rtkfieldofview RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkfieldofview)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkfieldofview/rtkfieldofview.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkfieldofview_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaBackProjectionImageFilter.h\"\n#endif\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n#include <itkThresholdImageFilter.h>\n#include <itkDivideImageFilter.h>\n#include <itkMaskImageFilter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkfieldofview, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n  // Check on hardware parameter\n#ifndef RTK_USE_CUDA\n  if (!strcmp(args_info.hardware_arg, \"cuda\"))\n  {\n    std::cerr << \"The program has not been compiled with cuda option\" << std::endl;\n    return EXIT_FAILURE;\n  }\n#endif\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkfieldofview>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Reconstruction reader\n  OutputImageType::Pointer unmasked_reconstruction;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(unmasked_reconstruction = itk::ReadImage<OutputImageType>(args_info.reconstruction_arg))\n\n  if (!args_info.bp_flag)\n  {\n    // FOV filter\n    auto fieldofview = rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType>::New();\n    fieldofview->SetMask(args_info.mask_flag);\n    fieldofview->SetInput(0, unmasked_reconstruction);\n    fieldofview->SetProjectionsStack(reader->GetOutput());\n    fieldofview->SetGeometry(geometry);\n    fieldofview->SetDisplacedDetector(args_info.displaced_flag);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(fieldofview->Update())\n\n    // Write\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(fieldofview->GetOutput(), args_info.output_arg))\n  }\n  else\n  {\n    if (args_info.displaced_flag)\n    {\n      std::cerr << \"Options --displaced and --bp are not compatible (yet).\" << std::endl;\n      return EXIT_FAILURE;\n    }\n\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputInformation())\n\n#ifdef RTK_USE_CUDA\n    using MaskImgType = itk::CudaImage<float, 3>;\n#else\n    using MaskImgType = itk::Image<unsigned short, 3>;\n#endif\n    using ConstantType = rtk::ConstantImageSource<MaskImgType>;\n    auto ones = ConstantType::New();\n    ones->SetConstant(1);\n    ones->SetInformationFromImage(reader->GetOutput());\n\n    auto zeroVol = ConstantType::New();\n    zeroVol->SetConstant(0.);\n    zeroVol->SetInformationFromImage(unmasked_reconstruction);\n\n    auto bp = rtk::BackProjectionImageFilter<MaskImgType, MaskImgType>::New();\n#ifdef RTK_USE_CUDA\n    if (!strcmp(args_info.hardware_arg, \"cuda\"))\n      bp = rtk::CudaBackProjectionImageFilter<MaskImgType>::New();\n#endif\n    bp->SetInput(zeroVol->GetOutput());\n    bp->SetInput(1, ones->GetOutput());\n    bp->SetGeometry(geometry);\n\n    auto thresh = itk::ThresholdImageFilter<MaskImgType>::New();\n    thresh->SetInput(bp->GetOutput());\n    thresh->ThresholdBelow(geometry->GetGantryAngles().size() - 1);\n    thresh->SetOutsideValue(0.);\n\n    if (args_info.mask_flag)\n    {\n      auto div = itk::DivideImageFilter<MaskImgType, MaskImgType, MaskImgType>::New();\n      div->SetInput(thresh->GetOutput());\n      div->SetConstant2(geometry->GetGantryAngles().size());\n\n      TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(div->GetOutput(), args_info.output_arg))\n    }\n    else\n    {\n      std::cerr << \"Option --bp without --mask is not implemented (yet).\" << std::endl;\n      return EXIT_FAILURE;\n    }\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkfieldofview/rtkfieldofview.ggo",
    "content": "purpose \"Computes the field of view of a reconstruction.\"\n\noption \"verbose\"        v \"Verbose execution\"                                         flag     off\noption \"geometry\"       g  \"XML geometry file name\"                                   string   yes\noption \"output\"         o \"Output projections file name\"                              string   yes\noption \"reconstruction\" - \"Reconstruction file unmasked\"                              string   yes\noption \"mask\"           m \"Output a binary mask instead of a masked image\"            flag     off\noption \"displaced\"      d \"Assume that a displaced detector has been used\"            flag     off\noption \"bp\"             b \"Slow alternative for non cylindrical FOVs:\\\n backproject projections filled with ones and threshold result.\"                      flag     off\noption \"hardware\"       - \"Hardware used for computation (with --bp only)\" values=\"cpu\",\"cuda\" no   default=\"cpu\"\n"
  },
  {
    "path": "applications/rtkfieldofview/rtkfieldofview.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Computes the field of view of a reconstruction.\"\n    )\n    parser.add_argument(\"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\")\n    parser.add_argument(\"--geometry\", \"-g\", help=\"XML geometry file name\", type=str, required=True)\n    parser.add_argument(\"--output\", \"-o\", help=\"Output projections file name\", type=str, required=True)\n    parser.add_argument(\"--reconstruction\", help=\"Reconstruction file unmasked\", type=str, required=True)\n    parser.add_argument(\"--mask\", \"-m\", help=\"Output a binary mask instead of a masked image\", action=\"store_true\")\n    parser.add_argument(\"--displaced\", \"-d\", help=\"Assume that a displaced detector has been used\", action=\"store_true\")\n    parser.add_argument(\"--bp\", \"-b\", help=\"Slow alternative for non cylindrical FOVs: backproject projections filled with ones and threshold result.\", action=\"store_true\")\n    parser.add_argument(\"--hardware\", help=\"Hardware used for computation (with --bp only)\", choices=[\"cpu\", \"cuda\"], default=\"cpu\")\n    rtk.add_rtkinputprojections_group(parser)\n    return parser\n\ndef process(args_info: argparse.Namespace):\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n    use_cuda = args_info.hardware == \"cuda\"\n    if use_cuda:\n        if not hasattr(itk, \"CudaImage\"):\n            raise RuntimeError(\"The program has not been compiled with CUDA option.\")\n\n    # Projections reader\n    reader = rtk.ProjectionsReader[OutputImageType].New()\n    rtk.SetProjectionsReaderFromArgParse(reader, args_info)\n\n    # Geometry\n    if args_info.verbose:\n        print(f\"Reading geometry information from {args_info.geometry}...\")\n    geometry = rtk.read_geometry(args_info.geometry)\n\n    # Reconstruction reader\n    if args_info.verbose:\n        print(f\"Reading reconstruction from {args_info.reconstruction}...\")\n    unmasked_reconstruction = itk.imread(args_info.reconstruction)\n\n    if not args_info.bp:\n        # FOV filter\n        fieldofview = rtk.FieldOfViewImageFilter[OutputImageType, OutputImageType].New()\n        fieldofview.SetMask(args_info.mask)\n        fieldofview.SetInput(0, unmasked_reconstruction)\n        fieldofview.SetProjectionsStack(reader.GetOutput())\n        fieldofview.SetGeometry(geometry)\n        fieldofview.SetDisplacedDetector(args_info.displaced)\n        fieldofview.Update()\n        if args_info.verbose:\n            print(f\"Writing output to {args_info.output}...\")\n        itk.imwrite(fieldofview.GetOutput(), args_info.output)\n    else:\n        if args_info.displaced:\n            raise RuntimeError(\"Options --displaced and --bp are not compatible (yet).\")\n        MaskImgType = itk.image[itk.US, Dimension]\n        reader.UpdateOutputInformation()\n        ones = rtk.ConstantImageSource[MaskImgType].New()\n        ones.SetConstant(1)\n        ones.SetInformationFromImage(reader.GetOutput())\n        zeroVol = rtk.ConstantImageSource[MaskImgType].New()\n        zeroVol.SetConstant(0.)\n        zeroVol.SetInformationFromImage(unmasked_reconstruction)\n\n        if use_cuda:\n            CudaMaskImgType = itk.CudaImage[OutputPixelType, Dimension]\n            bp = rtk.CudaBackProjectionImageFilter[CudaMaskImgType].New()\n            bp.SetInput(itk.cuda_image_from_image(zeroVol.GetOutput()))\n            bp.SetInput(1, itk.cuda_image_from_image(ones.GetOutput()))\n        else:\n            bp = rtk.BackProjectionImageFilter[MaskImgType, MaskImgType].New()\n            bp.SetInput(zeroVol.GetOutput())\n            bp.SetInput(1, ones.GetOutput())\n        bp.SetGeometry(geometry)\n\n        thresh = itk.ThresholdImageFilter[MaskImgType].New()\n        thresh.SetInput(bp.GetOutput())\n        thresh.ThresholdBelow(len(geometry.GetGantryAngles()) - 1)\n        thresh.SetOutsideValue(0.)\n\n        if args_info.mask:\n            div = itk.DivideImageFilter[MaskImgType, MaskImgType, MaskImgType].New()\n            div.SetInput(thresh.GetOutput())\n            div.SetConstant2(len(geometry.GetGantryAngles()))\n            if args_info.verbose:\n                print(f\"Writing mask output to {args_info.output}...\")\n            itk.imwrite(div.GetOutput(), args_info.output)\n        else:\n            raise NotImplementedError(\"Option --bp without --mask is not implemented (yet).\")\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkforwardprojections/CMakeLists.txt",
    "content": "WRAP_GGO(rtkforwardprojections_GGO_C rtkforwardprojections.ggo ../rtk3Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkforwardprojections rtkforwardprojections.cxx ${rtkforwardprojections_GGO_C})\ntarget_link_libraries(rtkforwardprojections RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkforwardprojections)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkforwardprojections/ForwardProjection.sh",
    "content": " # Create a simulated geometry\n rtksimulatedgeometry -n 180 -o geometry.xml\n\n # Forward project\n rtkforwardprojections -g geometry.xml -o projections.mha -i 00.mhd --spacing 2 --size 512\n\n # Reconstruct in the same resolution as the original\n rtkfdk -p . -r projections.mha -o fdk.mha -g geometry.xml --spacing=0.976562,0.976562,2 --origin=-250,-250,-164.5 --size=512,512,141\n"
  },
  {
    "path": "applications/rtkforwardprojections/README.md",
    "content": "# Forward Projection\n\n![sin](../../documentation/docs/ExternalData/POPI-Sinogram.png){w=400px alt=\"POPI sinogram\"}\n![img](../../documentation/docs/ExternalData/POPI-Reconstruction.png){w=400px alt=\"POPI reconstruction\"}\n\nThis script uses the files [00.mhd](http://www.creatis.insa-lyon.fr/~srit/POPI/MedPhys11/bl/mhd/00.mhd) and [00.raw](http://www.creatis.insa-lyon.fr/~srit/POPI/MedPhys11/bl/mhd/00.raw) of the [POPI](https://github.com/open-vv/popi-model/blob/master/popi-model.md) as input.\n\n```{literalinclude} ForwardProjection.sh\n```\n\nNote that the original file is in Hounsfield units which explains the negative values in the projection images since, e.g., the attenuation of air is -1000 HU.\n\nIt is also worth of note that the file is oriented in the DICOM coordinate system although RTK uses the IEC 61217 which results in a rotation around the antero-posterior axis of the patient. This can be easily changed by modifying the TransformMatrix in the 00.mhd file.\n"
  },
  {
    "path": "applications/rtkforwardprojections/rtkforwardprojections.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkforwardprojections_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n#include \"rtkMaximumIntensityProjectionImageFilter.h\"\n#include \"rtkJosephForwardAttenuatedProjectionImageFilter.h\"\n#include \"rtkZengForwardProjectionImageFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaForwardProjectionImageFilter.h\"\n#endif\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkforwardprojections, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::flush;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n  if (args_info.verbose_flag)\n    std::cout << \" done.\" << std::endl;\n\n  // Create a stack of empty projection images\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkforwardprojections>(constantImageSource,\n                                                                                               args_info);\n\n  // Adjust size according to geometry\n  auto sizeOutput = itk::MakeSize(\n    constantImageSource->GetSize()[0], constantImageSource->GetSize()[1], geometry->GetGantryAngles().size());\n  constantImageSource->SetSize(sizeOutput);\n\n  // Input reader\n  if (args_info.verbose_flag)\n    std::cout << \"Reading input volume \" << args_info.input_arg << \"...\" << std::endl;\n  OutputImageType::Pointer inputVolume;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(inputVolume = itk::ReadImage<OutputImageType>(args_info.input_arg))\n\n  OutputImageType::Pointer attenuationMap;\n  if (args_info.attenuationmap_given)\n  {\n    if (args_info.verbose_flag)\n      std::cout << \"Reading attenuation map \" << args_info.attenuationmap_arg << \"...\" << std::endl;\n    // Read an existing image to initialize the attenuation map\n    attenuationMap = itk::ReadImage<OutputImageType>(args_info.attenuationmap_arg);\n  }\n\n  using ClipImageType = itk::Image<double, Dimension>;\n  ClipImageType::Pointer inferiorClipImage, superiorClipImage;\n  if (args_info.inferiorclipimage_given)\n  {\n    if (args_info.verbose_flag)\n      std::cout << \"Reading inferior clip image \" << args_info.inferiorclipimage_arg << \"...\" << std::endl;\n    // Read an existing image to initialize the attenuation map\n    inferiorClipImage = itk::ReadImage<ClipImageType>(args_info.inferiorclipimage_arg);\n  }\n  if (args_info.superiorclipimage_given)\n  {\n    if (args_info.verbose_flag)\n      std::cout << \"Reading superior clip image \" << args_info.superiorclipimage_arg << \"...\" << std::endl;\n    // Read an existing image to initialize the attenuation map\n    superiorClipImage = itk::ReadImage<ClipImageType>(args_info.superiorclipimage_arg);\n  }\n\n  // Create forward projection image filter\n  if (args_info.verbose_flag)\n    std::cout << \"Projecting volume...\" << std::endl;\n\n  rtk::ForwardProjectionImageFilter<OutputImageType, OutputImageType>::Pointer forwardProjection;\n\n  switch (args_info.fp_arg)\n  {\n    case (fp_arg_Joseph):\n      forwardProjection = rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (fp_arg_JosephAttenuated):\n      forwardProjection = rtk::JosephForwardAttenuatedProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (fp_arg_Zeng):\n      forwardProjection = rtk::ZengForwardProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (fp_arg_MIP):\n      forwardProjection = rtk::MaximumIntensityProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      break;\n    case (fp_arg_CudaRayCast):\n#ifdef RTK_USE_CUDA\n      forwardProjection = rtk::CudaForwardProjectionImageFilter<OutputImageType, OutputImageType>::New();\n      dynamic_cast<rtk::CudaForwardProjectionImageFilter<OutputImageType, OutputImageType> *>(\n        forwardProjection.GetPointer())\n        ->SetStepSize(args_info.step_arg);\n#else\n      std::cerr << \"The program has not been compiled with cuda option\" << std::endl;\n      return EXIT_FAILURE;\n#endif\n      break;\n    default:\n      std::cerr << \"Unhandled --method value.\" << std::endl;\n      return EXIT_FAILURE;\n  }\n  forwardProjection->SetInput(constantImageSource->GetOutput());\n  forwardProjection->SetInput(1, inputVolume);\n  if (args_info.attenuationmap_given)\n    forwardProjection->SetInput(2, attenuationMap);\n  if (args_info.inferiorclipimage_given)\n  {\n    if (args_info.fp_arg == fp_arg_Joseph)\n    {\n      dynamic_cast<rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType> *>(\n        forwardProjection.GetPointer())\n        ->SetInferiorClipImage(inferiorClipImage);\n    }\n    else if (args_info.fp_arg == fp_arg_JosephAttenuated)\n    {\n      dynamic_cast<rtk::JosephForwardAttenuatedProjectionImageFilter<OutputImageType, OutputImageType> *>(\n        forwardProjection.GetPointer())\n        ->SetInferiorClipImage(inferiorClipImage);\n    }\n    else if (args_info.fp_arg == fp_arg_MIP)\n    {\n      dynamic_cast<rtk::MaximumIntensityProjectionImageFilter<OutputImageType, OutputImageType> *>(\n        forwardProjection.GetPointer())\n        ->SetInferiorClipImage(inferiorClipImage);\n    }\n  }\n  if (args_info.superiorclipimage_given)\n  {\n    if (args_info.fp_arg == fp_arg_Joseph)\n    {\n      dynamic_cast<rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType> *>(\n        forwardProjection.GetPointer())\n        ->SetSuperiorClipImage(superiorClipImage);\n    }\n    else if (args_info.fp_arg == fp_arg_JosephAttenuated)\n    {\n      dynamic_cast<rtk::JosephForwardAttenuatedProjectionImageFilter<OutputImageType, OutputImageType> *>(\n        forwardProjection.GetPointer())\n        ->SetSuperiorClipImage(superiorClipImage);\n    }\n    else if (args_info.fp_arg == fp_arg_MIP)\n    {\n      dynamic_cast<rtk::MaximumIntensityProjectionImageFilter<OutputImageType, OutputImageType> *>(\n        forwardProjection.GetPointer())\n        ->SetSuperiorClipImage(superiorClipImage);\n    }\n  }\n  if (args_info.sigmazero_given && args_info.fp_arg == fp_arg_Zeng)\n    dynamic_cast<rtk::ZengForwardProjectionImageFilter<OutputImageType, OutputImageType> *>(\n      forwardProjection.GetPointer())\n      ->SetSigmaZero(args_info.sigmazero_arg);\n  if (args_info.alphapsf_given && args_info.fp_arg == fp_arg_Zeng)\n    dynamic_cast<rtk::ZengForwardProjectionImageFilter<OutputImageType, OutputImageType> *>(\n      forwardProjection.GetPointer())\n      ->SetAlpha(args_info.alphapsf_arg);\n  forwardProjection->SetGeometry(geometry);\n  if (!args_info.lowmem_flag)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(forwardProjection->Update())\n  }\n\n  // Write\n  if (args_info.verbose_flag)\n    std::cout << \"Writing... \" << std::endl;\n  auto writer = itk::ImageFileWriter<OutputImageType>::New();\n  writer->SetFileName(args_info.output_arg);\n  writer->SetInput(forwardProjection->GetOutput());\n  if (args_info.lowmem_flag)\n  {\n    writer->SetNumberOfStreamDivisions(sizeOutput[2]);\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(writer->Update())\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkforwardprojections/rtkforwardprojections.ggo",
    "content": "purpose \"Projects a volume according to a geometry file.\"\n\noption \"verbose\"   v \"Verbose execution\"                                         flag     off\noption \"geometry\"  g  \"XML geometry file name\"                                   string   yes\noption \"input\"     i \"Input volume file name\"                                    string   yes\noption \"output\"    o \"Output projections file name\"                              string   yes\noption \"step\"      s \"Step size along ray (for CudaRayCast only)\"                double   no   default=\"1\"\noption \"lowmem\"    l \"Compute only one projection at a time\"                     flag     off\n\nsection \"Projectors\"\noption \"fp\"    f \"Forward projection method\" values=\"Joseph\",\"JosephAttenuated\",\"CudaRayCast\",\"Zeng\",\"MIP\" enum no default=\"Joseph\"\noption \"attenuationmap\" - \"Attenuation map relative to the volume to perfom the attenuation correction\"   string  no\noption \"sigmazero\" - \"PSF value at a distance of 0 meter of the detector\"   double  no\noption \"alphapsf\" - \"Slope of the PSF against the detector distance\"   double  no\noption \"inferiorclipimage\" - \"Value of the inferior clip of the ray for each pixel of the projections (only with Joseph-based projector)\" string no\noption \"superiorclipimage\" - \"Value of the superior clip of the ray for each pixel of the projections (only with Joseph-based projector)\" string no\n"
  },
  {
    "path": "applications/rtkforwardprojections/rtkforwardprojections.py",
    "content": "#!/usr/bin/env python\nimport sys\nimport argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Projects a volume according to a geometry file.\"\n    )\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--geometry\", \"-g\", help=\"XML geometry file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--input\", \"-i\", help=\"Input volume file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output projections file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--step\",\n        \"-s\",\n        help=\"Step size along ray (for CudaRayCast only)\",\n        type=float,\n        default=1,\n    )\n    parser.add_argument(\n        \"--lowmem\",\n        \"-l\",\n        help=\"Compute only one projection at a time\",\n        action=\"store_true\",\n    )\n\n    # Projectors\n    rtkprojectors_group = parser.add_argument_group(\"Projectors\")\n    rtkprojectors_group.add_argument(\n        \"--fp\",\n        \"-f\",\n        help=\"Forward projection method\",\n        choices=[\n            \"Joseph\",\n            \"JosephAttenuated\",\n            \"CudaRayCast\",\n            \"Zeng\",\n            \"MIP\",\n            \"CudaWrapRayCast\",\n        ],\n        default=\"Joseph\",\n    )\n    rtkprojectors_group.add_argument(\n        \"--attenuationmap\",\n        help=\"Attenuation map relative to the volume to perfom the attenuation correction\",\n        type=str,\n    )\n    rtkprojectors_group.add_argument(\n        \"--sigmazero\",\n        help=\"PSF value at a distance of 0 meter of the detector\",\n        type=float,\n    )\n    rtkprojectors_group.add_argument(\n        \"--alphapsf\", help=\"Slope of the PSF against the detector distance\", type=float\n    )\n    rtkprojectors_group.add_argument(\n        \"--inferiorclipimage\",\n        help=\"Value of the inferior clip of the ray for each pixel of the projections (only with Joseph-based projector)\",\n        type=str,\n    )\n    rtkprojectors_group.add_argument(\n        \"--superiorclipimage\",\n        help=\"Value of the superior clip of the ray for each pixel of the projections (only with Joseph-based projector)\",\n        type=str,\n    )\n\n    # Motion compensation options\n    warp_forwardprojection_group = parser.add_argument_group(\n        \"Motion compensation described in [Rit et al, TMI, 2009]\"\n    )\n    warp_forwardprojection_group.add_argument(\n        \"--signal\", help=\"Signal file name\", type=str\n    )\n    warp_forwardprojection_group.add_argument(\"--dvf\", help=\"Input 4D DVF\", type=str)\n\n    rtk.add_rtk3Doutputimage_group(parser)\n\n    return parser\n\n\ndef process(args_info):\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n    if hasattr(itk, \"CudaImage\"):\n        OutputCudaImageType = itk.CudaImage[OutputPixelType, Dimension]\n\n    # Geometry\n    if args_info.verbose:\n        print(\n            f\"Reading geometry information from {args_info.geometry}...\",\n            end=\"\",\n            flush=True,\n        )\n    geometry = rtk.read_geometry(args_info.geometry)\n    if args_info.verbose:\n        print(\" done.\")\n\n    # Create a stack of empty projection images\n    ConstantImageSourceType = rtk.ConstantImageSource[OutputImageType]\n    constantImageSource = ConstantImageSourceType.New()\n    rtk.SetConstantImageSourceFromArgParse(constantImageSource, args_info)\n\n    # Adjust size according to geometry\n    sizeOutput = list(constantImageSource.GetSize())\n    sizeOutput[2] = len(geometry.GetGantryAngles())\n    constantImageSource.SetSize(sizeOutput)\n\n    # Input reader\n    if args_info.verbose:\n        print(f\"Reading input volume {args_info.input}...\")\n    inputVolume = itk.imread(args_info.input)\n\n    attenuation_map = None\n    if args_info.attenuationmap:\n        if args_info.verbose:\n            print(f\"Reading attenuation map {args_info.attenuationmap}...\")\n        attenuation_map = itk.imread(args_info.attenuationmap)\n\n    inferiorClipImage = None\n    superiorClipImage = None\n    if args_info.inferiorclipimage:\n        if args_info.verbose:\n            print(f\"Reading inferior clip image {args_info.inferiorclipimage}...\")\n        inferiorClipImage = itk.imread(args_info.inferiorclipimage)\n    if args_info.superiorclipimage:\n        if args_info.verbose:\n            print(f\"Reading superior clip image {args_info.superiorclipimage}...\")\n        superiorClipImage = itk.imread(args_info.superiorclipimage)\n\n    # Create forward projection image filter\n    if args_info.verbose:\n        print(\"Projecting volume...\")\n\n    # Select the forward projector\n    if args_info.fp == \"Joseph\":\n        forwardProjection = rtk.JosephForwardProjectionImageFilter[\n            OutputImageType, OutputImageType\n        ].New()\n    elif args_info.fp == \"JosephAttenuated\":\n        forwardProjection = rtk.JosephForwardAttenuatedProjectionImageFilter[\n            OutputImageType, OutputImageType\n        ].New()\n        if attenuation_map is None:\n            print(\n                \"JosephAttenuatedForwardProjection requires an attenuation map. \"\n                \"Please provide it using --attenuationmap.\"\n            )\n            sys.exit(1)\n    elif args_info.fp == \"Zeng\":\n        forwardProjection = rtk.ZengForwardProjectionImageFilter[\n            OutputImageType, OutputImageType\n        ].New()\n    elif args_info.fp == \"MIP\":\n        forwardProjection = rtk.MaximumIntensityProjectionImageFilter[\n            OutputImageType, OutputImageType\n        ].New()\n    elif args_info.fp == \"CudaRayCast\":\n        if hasattr(itk, \"CudaImage\"):\n            forwardProjection = rtk.CudaForwardProjectionImageFilter[\n                OutputCudaImageType\n            ].New()\n            forwardProjection.SetStepSize(args_info.step)\n        else:\n            print(\"The program has not been compiled with cuda option\")\n            sys.exit(1)\n    elif args_info.fp == \"CudaWrapRayCast\":\n        if hasattr(itk, \"CudaImage\"):\n            if not args_info.dvf or not args_info.signal:\n                print(\"CudaWrapRayCast requires --dvf and --signal arguments.\")\n                sys.exit(1)\n            forwardProjection = rtk.CudaWarpForwardProjectionImageFilter[\n                OutputCudaImageType\n            ].New()\n            forwardProjection.SetStepSize(args_info.step)\n\n            dvf_image = itk.imread(args_info.dvf)\n            forwardProjection.SetDisplacementField(dvf_image)\n            forwardProjection.SetSignalFilename(args_info.signal)\n        else:\n            print(\"The program has not been compiled with cuda option\")\n            sys.exit(1)\n\n    if args_info.fp in [\"CudaWrapRayCast\", \"CudaRayCast\"]:\n        forwardProjection.SetInput(\n            itk.cuda_image_from_image(constantImageSource.GetOutput())\n        )\n        forwardProjection.SetInput(1, itk.cuda_image_from_image(inputVolume))\n        if attenuation_map:\n            forwardProjection.SetInput(2, itk.cuda_image_from_image(attenuation_map))\n    else:\n        forwardProjection.SetInput(constantImageSource.GetOutput())\n        forwardProjection.SetInput(1, inputVolume)\n        if attenuation_map:\n            forwardProjection.SetInput(2, attenuation_map)\n\n    if inferiorClipImage is not None:\n        if args_info.fp == \"Joseph\":\n            forwardProjection.SetInferiorClipImage(inferiorClipImage)\n        elif args_info.fp == \"JosephAttenuated\":\n            forwardProjection.SetInferiorClipImage(inferiorClipImage)\n        elif args_info.fp == \"MIP\":\n            forwardProjection.SetInferiorClipImage(inferiorClipImage)\n    if superiorClipImage is not None:\n        if args_info.fp == \"Joseph\":\n            forwardProjection.SetSuperiorClipImage(superiorClipImage)\n        elif args_info.fp == \"JosephAttenuated\":\n            forwardProjection.SetSuperiorClipImage(superiorClipImage)\n        elif args_info.fp == \"MIP\":\n            forwardProjection.SetSuperiorClipImage(superiorClipImage)\n    if args_info.sigmazero and args_info.fp == \"Zeng\":\n        forwardProjection.SetSigmaZero(args_info.sigmazero)\n    if args_info.alphapsf and args_info.fp == \"Zeng\":\n        forwardProjection.SetAlpha(args_info.alphapsf)\n\n    forwardProjection.SetGeometry(geometry)\n\n    if not args_info.lowmem:\n        forwardProjection.Update()\n\n    # Write\n    if args_info.verbose:\n        print(\"Writing...\")\n\n    writer = itk.ImageFileWriter[OutputImageType].New()\n    writer.SetFileName(args_info.output)\n    writer.SetInput(forwardProjection.GetOutput())\n    writer.Update()\n\n    if args_info.verbose:\n        print(\"Processing completed successfully.\")\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkfourdconjugategradient/CMakeLists.txt",
    "content": "WRAP_GGO(rtkfourdconjugategradient_GGO_C rtkfourdconjugategradient.ggo ../rtkinputprojections_section.ggo ../rtk4Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkfourdconjugategradient rtkfourdconjugategradient.cxx ${rtkfourdconjugategradient_GGO_C})\ntarget_link_libraries(rtkfourdconjugategradient RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkfourdconjugategradient)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkfourdconjugategradient/rtkfourdconjugategradient.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkfourdconjugategradient_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkFourDConjugateGradientConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkSignalToInterpolationWeights.h\"\n#include \"rtkReorderProjectionsImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#  include \"rtkCudaConstantVolumeSeriesSource.h\"\n#endif\n\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkfourdconjugategradient, args_info);\n\n  using OutputPixelType = float;\n\n#ifdef RTK_USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<ProjectionStackType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkfourdconjugategradient>(reader, args_info);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateLargestPossibleRegion())\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<VolumeSeriesType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<VolumeSeriesType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkfourdconjugategradient>(\n      constantImageSource, args_info);\n\n    // GenGetOpt can't handle default arguments for multiple arguments like size or spacing.\n    // The only default it accepts is to set all components of a multiple argument to the same value.\n    // Default size is 256^4, ie the number of reconstructed instants is 256. It has to be set to a more reasonable\n    // value which is why a \"frames\" argument is introduced\n    auto inputSize = itk::MakeSize(constantImageSource->GetSize()[0],\n                                   constantImageSource->GetSize()[1],\n                                   constantImageSource->GetSize()[2],\n                                   args_info.frames_arg);\n    constantImageSource->SetSize(inputSize);\n\n    inputFilter = constantImageSource;\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(inputFilter->Update())\n  inputFilter->ReleaseDataFlagOn();\n\n  // Re-order geometry and projections\n  // In the new order, projections with identical phases are packed together\n  std::vector<double> signal = rtk::ReadSignalFile(args_info.signal_arg);\n  auto                reorder = rtk::ReorderProjectionsImageFilter<ProjectionStackType>::New();\n  reorder->SetInput(reader->GetOutput());\n  reorder->SetInputGeometry(geometry);\n  reorder->SetInputSignal(signal);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reorder->Update())\n\n  // Release the memory holding the stack of original projections\n  reader->GetOutput()->ReleaseData();\n\n  // Compute the interpolation weights\n  auto signalToInterpolationWeights = rtk::SignalToInterpolationWeights::New();\n  signalToInterpolationWeights->SetSignal(reorder->GetOutputSignal());\n  signalToInterpolationWeights->SetNumberOfReconstructedFrames(\n    inputFilter->GetOutput()->GetLargestPossibleRegion().GetSize(3));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(signalToInterpolationWeights->Update())\n\n  // Set the forward and back projection filters to be used\n  using ConjugateGradientFilterType =\n    rtk::FourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  auto conjugategradient = ConjugateGradientFilterType::New();\n  SetForwardProjectionFromGgo(args_info, conjugategradient.GetPointer());\n  SetBackProjectionFromGgo(args_info, conjugategradient.GetPointer());\n  conjugategradient->SetInputVolumeSeries(inputFilter->GetOutput());\n  conjugategradient->SetNumberOfIterations(args_info.niterations_arg);\n  conjugategradient->SetCudaConjugateGradient(args_info.cudacg_flag);\n  conjugategradient->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  // Set the newly ordered arguments\n  conjugategradient->SetInputProjectionStack(reorder->GetOutput());\n  conjugategradient->SetGeometry(reorder->GetOutputGeometry());\n  conjugategradient->SetWeights(signalToInterpolationWeights->GetOutput());\n  conjugategradient->SetSignal(reorder->GetOutputSignal());\n\n  REPORT_ITERATIONS(conjugategradient, ConjugateGradientFilterType, VolumeSeriesType);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(conjugategradient->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkfourdconjugategradient/rtkfourdconjugategradient.ggo",
    "content": "purpose \"Reconstructs a 3D + time sequence of volumes from a projection stack and a respiratory/cardiac signal, with a conjugate gradient technique\"\n\noption \"verbose\"     v \"Verbose execution\"                                     flag   off\noption \"geometry\"    g \"XML geometry file name\"                                string yes\noption \"output\"      o \"Output file name\"                                      string yes\noption \"niterations\" n \"Number of iterations\"                                  int    no   default=\"5\"\noption \"cudacg\"      - \"Perform conjugate gradient calculations on GPU\"        flag   off\noption \"input\"       i \"Input volume\"                                          string no\noption \"nodisplaced\" - \"Disable the displaced detector filter\"                 flag   off\n\nsection \"Phase gating\"\noption \"signal\"    - \"File containing the phase of each projection\"              string                       yes\n\n"
  },
  {
    "path": "applications/rtkfourdfdk/CMakeLists.txt",
    "content": "WRAP_GGO(rtkfourdfdk_GGO_C rtkfourdfdk.ggo ../rtkinputprojections_section.ggo ../rtk4Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkfourdfdk rtkfourdfdk.cxx ${rtkfourdfdk_GGO_C})\ntarget_link_libraries(rtkfourdfdk RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkfourdfdk)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkfourdfdk/rtkfourdfdk.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkfourdfdk_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkDisplacedDetectorForOffsetFieldOfViewImageFilter.h\"\n#include \"rtkParkerShortScanImageFilter.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaDisplacedDetectorImageFilter.h\"\n// TODO #  include \"rtkCudaDisplacedDetectorForOffsetFieldOfViewImageFilter.h\"\n#  include \"rtkCudaParkerShortScanImageFilter.h\"\n#  include \"rtkCudaFDKConeBeamReconstructionFilter.h\"\n#endif\n#include \"rtkSelectOneProjectionPerCycleImageFilter.h\"\n#include <itkImageRegionConstIterator.h>\n#include <itkStreamingImageFilter.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkfourdfdk, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n  using CPUOutputImageType = itk::Image<OutputPixelType, Dimension>;\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = CPUOutputImageType;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkfourdfdk>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Part specific to 4D\n  auto selector = rtk::SelectOneProjectionPerCycleImageFilter<OutputImageType>::New();\n  selector->SetInput(reader->GetOutput());\n  selector->SetInputGeometry(geometry);\n  selector->SetSignalFilename(args_info.signal_arg);\n\n  // Check on hardware parameter\n#ifndef RTK_USE_CUDA\n  if (!strcmp(args_info.hardware_arg, \"cuda\"))\n  {\n    std::cerr << \"The program has not been compiled with cuda option\" << std::endl;\n    return EXIT_FAILURE;\n  }\n#endif\n\n  // Displaced detector weighting\n#ifdef RTK_USE_CUDA\n  using DDFType = rtk::CudaDisplacedDetectorImageFilter;\n#else\n  using DDFType = rtk::DisplacedDetectorForOffsetFieldOfViewImageFilter<OutputImageType>;\n#endif\n  rtk::DisplacedDetectorImageFilter<OutputImageType>::Pointer ddf;\n  if (!strcmp(args_info.hardware_arg, \"cuda\"))\n    ddf = DDFType::New();\n  else\n    ddf = rtk::DisplacedDetectorForOffsetFieldOfViewImageFilter<OutputImageType>::New();\n  ddf->SetInput(selector->GetOutput());\n  ddf->SetGeometry(selector->GetOutputGeometry());\n\n  // Short scan image filter\n  using PSSFCPUType = rtk::ParkerShortScanImageFilter<OutputImageType>;\n#ifdef RTK_USE_CUDA\n  using PSSFType = rtk::CudaParkerShortScanImageFilter;\n#else\n  using PSSFType = rtk::ParkerShortScanImageFilter<OutputImageType>;\n#endif\n  PSSFCPUType::Pointer pssf;\n  if (!strcmp(args_info.hardware_arg, \"cuda\"))\n    pssf = PSSFType::New();\n  else\n    pssf = PSSFCPUType::New();\n  pssf->SetInput(ddf->GetOutput());\n  pssf->SetGeometry(selector->GetOutputGeometry());\n  pssf->InPlaceOff();\n\n  // Create one frame of the reconstructed image\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkfourdfdk>(constantImageSource, args_info);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantImageSource->Update())\n\n  // This macro sets options for fdk filter which I can not see how to do better\n  // because TFFTPrecision is not the same, e.g. for CPU and CUDA (SR)\n#define SET_FELDKAMP_OPTIONS(f)                                   \\\n  f->SetInput(0, constantImageSource->GetOutput());               \\\n  f->SetInput(1, pssf->GetOutput());                              \\\n  f->SetGeometry(selector->GetOutputGeometry());                  \\\n  f->GetRampFilter()->SetTruncationCorrection(args_info.pad_arg); \\\n  f->GetRampFilter()->SetHannCutFrequency(args_info.hann_arg);    \\\n  f->GetRampFilter()->SetHannCutFrequencyY(args_info.hannY_arg);  \\\n  f->SetProjectionSubsetSize(args_info.subsetsize_arg)\n\n  // FDK reconstruction filtering\n  using FDKCPUType = rtk::FDKConeBeamReconstructionFilter<OutputImageType>;\n  FDKCPUType::Pointer feldkamp;\n#ifdef RTK_USE_CUDA\n  using FDKCUDAType = rtk::CudaFDKConeBeamReconstructionFilter;\n  FDKCUDAType::Pointer feldkampCUDA;\n#endif\n  itk::Image<OutputPixelType, Dimension> * pfeldkamp = nullptr;\n  if (!strcmp(args_info.hardware_arg, \"cpu\"))\n  {\n    feldkamp = FDKCPUType::New();\n    SET_FELDKAMP_OPTIONS(feldkamp);\n\n    pfeldkamp = feldkamp->GetOutput();\n  }\n#ifdef RTK_USE_CUDA\n  else if (!strcmp(args_info.hardware_arg, \"cuda\"))\n  {\n    feldkampCUDA = FDKCUDAType::New();\n    SET_FELDKAMP_OPTIONS(feldkampCUDA);\n    pfeldkamp = feldkampCUDA->GetOutput();\n  }\n#endif\n\n  // Streaming depending on streaming capability of writer\n  auto streamerBP = itk::StreamingImageFilter<CPUOutputImageType, CPUOutputImageType>::New();\n  streamerBP->SetInput(pfeldkamp);\n  streamerBP->SetNumberOfStreamDivisions(args_info.divisions_arg);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(streamerBP->UpdateOutputInformation())\n\n  // Create empty 4D image\n  using FourDOutputImageType = itk::Image<OutputPixelType, Dimension + 1>;\n  using FourDConstantImageSourceType = rtk::ConstantImageSource<FourDOutputImageType>;\n  auto fourDConstantImageSource = FourDConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<FourDConstantImageSourceType, args_info_rtkfourdfdk>(fourDConstantImageSource,\n                                                                                          args_info);\n\n  // GenGetOpt can't handle default arguments for multiple arguments like size or spacing.\n  // The only default it accepts is to set all components of a multiple argument to the same value.\n  // Default size is 256^4, ie the number of reconstructed instants is 256. It has to be set to a more reasonable\n  // value which is why a \"frames\" argument is introduced\n  FourDConstantImageSourceType::SizeType fourDInputSize(fourDConstantImageSource->GetSize());\n  fourDInputSize[3] = args_info.frames_arg;\n  fourDConstantImageSource->SetSize(fourDInputSize);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fourDConstantImageSource->Update())\n\n  // Go over each frame, reconstruct 3D frame and paste with iterators in 4D image\n  for (int f = 0; f < args_info.frames_arg; f++)\n  {\n    if (args_info.verbose_flag)\n      std::cout << \"Reconstructing frame #\" << f << \"...\" << std::endl;\n    selector->SetPhase(f / (double)args_info.frames_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamerBP->UpdateLargestPossibleRegion())\n\n    FourDConstantImageSourceType::OutputImageRegionType region;\n    region = fourDConstantImageSource->GetOutput()->GetLargestPossibleRegion();\n    region.SetIndex(3, f);\n    region.SetSize(3, 1);\n\n    itk::ImageRegionIterator<FourDOutputImageType> it4D(fourDConstantImageSource->GetOutput(), region);\n    itk::ImageRegionIterator<CPUOutputImageType>   it3D(streamerBP->GetOutput(),\n                                                      streamerBP->GetOutput()->GetLargestPossibleRegion());\n    while (!it3D.IsAtEnd())\n    {\n      it4D.Set(it3D.Get());\n      ++it4D;\n      ++it3D;\n    }\n  }\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(fourDConstantImageSource->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkfourdfdk/rtkfourdfdk.ggo",
    "content": "purpose \"Reconstructs a 4D volume from a sequence of projections using FDK with one projection per respiratory cycle in each frame.\"\n\noption \"verbose\"    v \"Verbose execution\"                                           flag                off\noption \"geometry\"   g \"XML geometry file name\"                                      string              yes\noption \"output\"     o \"Output file name\"                                            string              yes\noption \"hardware\"   - \"Hardware used for computation\"                               values=\"cpu\",\"cuda\" no   default=\"cpu\"\noption \"lowmem\"     l \"Load only one projection per thread in memory\"               flag                off\noption \"divisions\"  d \"Streaming option: number of stream divisions of the CT\"      int                 no   default=\"1\"\noption \"subsetsize\" - \"Streaming option: number of projections processed at a time\" int                 no   default=\"16\"\n\nsection \"Ramp filter\"\noption \"pad\"       - \"Data padding parameter to correct for truncation\"          double                       no   default=\"0.0\"\noption \"hann\"      - \"Cut frequency for hann window in ]0,1] (0.0 disables it)\"  double                       no   default=\"0.0\"\noption \"hannY\"     - \"Cut frequency for hann window in ]0,1] (0.0 disables it)\"  double                       no   default=\"0.0\"\n\nsection \"Phase gating\"\noption \"signal\"    - \"File containing the phase of each projection\"                 string              yes\n\n"
  },
  {
    "path": "applications/rtkfourdrooster/CMakeLists.txt",
    "content": "WRAP_GGO(rtkfourdrooster_GGO_C rtkfourdrooster.ggo ../rtkinputprojections_section.ggo ../rtk4Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkfourdrooster rtkfourdrooster.cxx ${rtkfourdrooster_GGO_C})\ntarget_link_libraries(rtkfourdrooster RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkfourdrooster)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkfourdrooster/README.md",
    "content": "# 4DROOSTER: Total variation-regularized 3D + time reconstruction\n\nRTK provides a tool to reconstruct a 3D + time image which does not require explicit motion estimation. Instead, it uses total variation regularization along both space and time. The implementation is based on a paper that we have published ([article](http://www.creatis.insa-lyon.fr/site/fr/publications/MORY-14)). You should read the article to understand the basics of the algorithm before trying to use the software.\n\nThe algorithm requires a set of projection images with the associated RTK geometry, the respiratory phase of each projection image and a motion mask in which the region of the space where movement is expected is set to 1 and the rest is set to 0. Each piece of data is described in more details below and can be downloaded using [Girder](https://data.kitware.com/#collection/5a7706878d777f0649e04776). It is assumed that the breathing motion is periodic, which implies that the mechanical state of the chest depends only on the respiratory phase.\n\n## Projection images\n\nThis example is illustrated with a set of projection images of the [POPI patient](https://github.com/open-vv/popi-model/blob/master/popi-model.md). You can [download the projections](https://data.kitware.com/api/v1/item/5be99af88d777f2179a2e144/download) and the required tables of the Elekta database, [FRAME.DBF](https://data.kitware.com/api/v1/item/5be99a068d777f2179a2cf4f/download) and [IMAGE.DBF](https://data.kitware.com/api/v1/item/5be99a078d777f2179a2cf65/download). The dataset is first used to reconstruct a blurry image:\n\n```\n# Convert Elekta database to RTK geometry\nrtkelektasynergygeometry \\\n  -o geometry.rtk \\\n  -f FRAME.DBF \\\n  -i IMAGE.DBF \\\n  -u 1.3.46.423632.141000.1169042526.68\n\n# Reconstruct a 3D volume from all projection images.\n# We implicitly assume that the patient's chest is static, which is wrong.\n# Therefore the reconstruction will be blurry. This blurry reconstruction is\n# not required for 4D ROOSTER, but there is usually no other way to generate\n# a motion mask, which is required. Additionally, the blurry reconstruction\n# can be used to initialize the 4D ROOSTER reconstruction.\nrtkfdk \\\n  -p . \\\n  -r .*.his \\\n  -o fdk.mha \\\n  -g geometry.rtk \\\n  --hann 0.5 \\\n  --pad 1.0 \\\n  --size 160 \\\n  --spacing 2\n```\n\nYou should obtain something like that with [VV](http://vv.creatis.insa-lyon.fr/):\n\n![Blurred](../../documentation/docs/ExternalData/Blurred.jpg){w=600px alt=\"Blurred image\"}\n\n## Motion mask\n\nThe next piece of data is a 3D motion mask: a volume that contains only zeros, where no movement is expected to occur, and ones, where movement is expected. Typically, during breathing, the whole chest moves, so it is safe to use the [patient mask](https://data.kitware.com/api/v1/item/5be99a418d777f2179a2ddf4/download) (red+green). However, restricting the movement to a smaller region, e.g. the rib cage, can help reconstruct this region more accurately and mitigate artifacts, so we might want to use the [rib cage mask](https://data.kitware.com/api/v1/item/5be99a2c8d777f2179a2dc4f/download) (red):\n\n![Mm](../../documentation/docs/ExternalData/MotionMask.jpg){w=400px alt=\"Motion mask\"}\n\n## Respiratory signal\n\nThe 4D ROOSTER algorithm requires that we associate each projection image with the instant of the respiratory cycle at which it has been acquired. We used the Amsterdam shroud solution of Lambert Zijp (described [here](http://www.creatis.insa-lyon.fr/site/fr/publications/RIT-12a)) which is implemented in RTK\n\n```\nrtkamsterdamshroud --path . \\\n                   --regexp '.*.his' \\\n                   --output shroud.mha \\\n                   --unsharp 650\nrtkextractshroudsignal --input shroud.mha \\\n                       --output signal.txt \\\n                       --phase sphase.txt\n```\n\nto get the phase signal. Note that the phase must go from 0 to 1 where 0.3 corresponds to 30% in the respiratory cycle, i.e., frame 3 if you have a 10-frames 4D reconstruction or frame 6 if you have a 20-frames 4D reconstruction. The [resulting phase](https://data.kitware.com/api/v1/item/5be99af98d777f2179a2e160/download) is in green on top of the blue respiratory signal and the detected end-exhale peaks:\n\n![Signal](../../documentation/docs/ExternalData/Signal.jpg){w=800px alt=\"Phase signal\"}\n\n## ROOSTER for conebeam CT reconstruction\n\nWe now have all the pieces to perform a 3D + time reconstruction. The algorithm will perform \"niter\" iterations of the main loop, and run three inner loops at each iteration:\n\n*   conjugate gradient reconstruction with \"cgiter\" iterations\n*   total-variation regularization in space, with parameter \"gamma_space\" (the higher, the more regularized) and \"tviter\" iterations\n*   total-variation regularization in time, with parameter \"gamma_time\" (the higher, the more regularized) and \"tviter\" iterations\n\nThe number of iterations suggested here should work in most situations. The parameters gamma_space and gamma_time, on the other hand, must be adjusted carefully for each type of datasets (and, unfortunately, for each resolution). Unlike in analytical reconstruction methods like FDK, with 4D ROOSTER it is also very important that the reconstruction volume contains the whole patient's chest. You should therefore adapt the \"size\", \"spacing\" and \"origin\" parameters carefully, based on what you have observed on the blurry FDK reconstruction.\n\n```\n# Reconstruct from all projection images with 4D ROOSTER\nrtkfourdrooster \\\n  -p . \\\n  -r .*.his \\\n  -o rooster.mha \\\n  -g geometry.rtk \\\n  --signal sphase.txt \\\n  --motionmask MotionMask.mha \\\n  --gamma_time 0.0001 \\\n  --gamma_space 0.0001 \\\n  --niter 30 \\\n  --cgiter 4 \\\n  --tviter 10 \\\n  --spacing 2 \\\n  --size 160 \\\n  --frames 5\n```\n\nDepending on the resolution you choose, and even on powerful computers, the reconstruction time can range from a few minutes (very low resolution, typically 32³ * 5, only for tests) to many hours (standard resolution, typically 256³ * 10). To speed things up, it is recommended to use the CUDA version of the forward and back projectors by running this command instead:\n\n```\n# Reconstruct from all projection images with 4D ROOSTER, using CUDA forward and back projectors\nrtkfourdrooster \\\n  -p . \\\n  -r .*.his \\\n  -o rooster.mha \\\n  -g geometry.rtk \\\n  --signal sphase.txt \\\n  --motionmask MotionMask.mha \\\n  --fp CudaRayCast \\\n  --bp CudaVoxelBased \\\n  --gamma_time 0.0001 \\\n  --gamma_space 0.0001 \\\n  --niter 30 \\\n  --cgiter 4 \\\n  --tviter 10 \\\n  --spacing 2 \\\n  --size 160 \\\n  --frames 5\n```\n\nWith a recent GPU, this should allow you to perform a standard resolution reconstruction in less than one hour.\n\nNote that the reconstructed volume in this example does not fully contain the attenuating object, causing hyper-attenuation artifacts on the borders of the result. To avoid these artifacts, reconstruct a larger volume (--size 256) should be fine. Note that you will have to resize your motion mask as well, as 3D the motion mask is expected to have the same size, spacing and origin as the first 3 dimensions of the 4D output.\n\n## Motion-Aware 4D Rooster\n\n4D ROOSTER doesn't require explicit motion information, but can take advantage of it to guide TV-regularization if motion information is available. Please refer to the tutorial on Motion-Compensated FDK to learn how to obtain a valid 4D Displacement Vector Field (DVF). Once you have it, simply adding the option --dvf \"4D_DVF_Filename\" to the list of rtkfourdrooster arguments will run MA-ROOSTER instead of 4D ROOSTER.\n\n```\n# Reconstruct from all projection images with MA ROOSTER\nrtkfourdrooster \\\n  -p . \\\n  -r .*.his \\\n  -o rooster.mha \\\n  -g geometry.rtk \\\n  --signal sphase.txt \\\n  --motionmask MotionMask.mha \\\n  --gamma_time 0.0001 \\\n  --gamma_space 0.0001 \\\n  --niter 30 \\\n  --cgiter 4 \\\n  --tviter 10 \\\n  --spacing 2 \\\n  --size 160 \\\n  --frames 5 \\\n  --dvf deformationField_4D.mhd\n```\n\nMaking use of the motion information adds to computation time. If you have compiled RTK with RTK_USE_CUDA = ON and have a working and CUDA-enabled nVidia GPU, it will automatically be used to speed up that part of the process.\n\nThe article in which the theoretical foundations of MA-ROOSTER are presented (link to be added) contains results obtained on two patients. If you wish to reproduce these results, you can download all the necessary data here:\n\n*   Original projections, log-transformed projections with the table removed, motion mask, respiratory signal, and transform matrices to change from CT to CBCT coordinates and back\n    *   [Patient 1](https://data.kitware.com/api/v1/item/5be97d688d777f2179a28e39/download)\n    *   [Patient 2](https://data.kitware.com/api/v1/item/5be99df68d777f2179a2e904/download)\n*   Inverse-consistent 4D Displacement Vector Fields, to the end-exhale phase and from the end-exhale phase\n    *   [Patient 1](https://data.kitware.com/api/v1/item/5be989e68d777f2179a29e95/download)\n    *   [Patient 2](https://data.kitware.com/api/v1/item/5be9a1388d777f2179a2f44d/download)\n\nExtract the data of each patient in a separate folder. From the folder containing the data of patient 1, run the following command line:\n\n```\n# Reconstruct patient 1 with MA ROOSTER\nrtkfourdrooster \\\n  -p . \\\n  -r correctedProjs.mha \\\n  -o marooster.mha \\\n  -g geom.xml \\\n  --signal cphase.txt \\\n  --motionmask dilated_resampled_mm.mhd \\\n  --gamma_time 0.0002 \\\n  --gamma_space 0.00005 \\\n  --niter 10 \\\n  --cgiter 4 \\\n  --tviter 10 \\\n  --spacing \"1, 1, 1, 1\" \\\n  --size \"220, 280, 370, 10\" \\\n  --origin \"-140, -140, -75, 0\" \\\n  --frames 10 \\\n  --dvf toPhase50_4D.mhd \\\n  --idvf fromPhase50_4D.mhd\n```\n\nFrom the folder containing the data of patient 2, run the following command line (only the size and origin parameters are different):\n\n```\n# Reconstruct patient 2 with MA ROOSTER\nrtkfourdrooster \\\n  -p . \\\n  -r correctedProjs.mha \\\n  -o marooster.mha \\\n  -g geom.xml \\\n  --signal cphase.txt \\\n  --motionmask dilated_resampled_mm.mhd \\\n  --gamma_time 0.0002 \\\n  --gamma_space 0.00005 \\\n  --niter 10 \\\n  --cgiter 4 \\\n  --tviter 10 \\\n  --spacing \"1, 1, 1, 1\" \\\n  --size \"285, 270, 307, 10\" \\\n  --origin \"-167.5, -135, -205, 0\" \\\n  --frames 10 \\\n  --dvf toPhase50_4D.mhd \\\n  --idvf fromPhase50_4D.mhd \\\n```\n\nNote the option \"--idvf\", which allows to provide the inverse DVF. It is used to inverse warp the 4D reconstruction after the temporal regularization. MA-ROOSTER will work with and without the inverse DVF, and yield almost the same results in both cases. Not using the inverse DVF is approximately two times slower, as it requires MA-ROOSTER to perform the inverse warping by an iterative method.\n\nAgain, if you have a CUDA-enabled GPU (in this case with at least 3 GB of VRAM), and have compiled RTK with RTK_USE_CUDA = ON, you can add the \"--bp CudaVoxelBased\" and \"--fp CudaRayCast\" to speed up the computation by performing the forward and back projections on the GPU.\n\nYou do not need the 4D planning CT data to perform the MA-ROOSTER reconstructions. It is only required to compute the DVFs, which can be downloaded above. We do provide it anyway, in case you want to use your own method, or the one described in Motion-Compensated FDK, to extract a DVF from it:\n\n*   4D planning CT\n    *   [Patient 1](https://data.kitware.com/api/v1/item/5be98bd28d777f2179a2a279/download)\n    *   [Patient 2](https://data.kitware.com/api/v1/item/5be9a1918d777f2179a2f568/download)\n"
  },
  {
    "path": "applications/rtkfourdrooster/rtkfourdrooster.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkfourdrooster_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkFourDROOSTERConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkSignalToInterpolationWeights.h\"\n#include \"rtkReorderProjectionsImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkfourdrooster, args_info);\n\n  using OutputPixelType = float;\n  using DVFVectorType = itk::CovariantVector<OutputPixelType, 3>;\n\n#ifdef RTK_USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>;\n#endif\n  using VolumeType = ProjectionStackType;\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<ProjectionStackType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkfourdrooster>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<VolumeSeriesType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<VolumeSeriesType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkfourdrooster>(constantImageSource,\n                                                                                           args_info);\n\n    // GenGetOpt can't handle default arguments for multiple arguments like size or spacing.\n    // The only default it accepts is to set all components of a multiple argument to the same value.\n    // Default size is 256^4, ie the number of reconstructed instants is 256. It has to be set to a more reasonable\n    // value which is why a \"frames\" argument is introduced\n    auto inputSize = itk::MakeSize(constantImageSource->GetSize()[0],\n                                   constantImageSource->GetSize()[1],\n                                   constantImageSource->GetSize()[2],\n                                   args_info.frames_arg);\n    constantImageSource->SetSize(inputSize);\n\n    inputFilter = constantImageSource;\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(inputFilter->Update())\n  inputFilter->ReleaseDataFlagOn();\n\n  // Re-order geometry and projections\n  // In the new order, projections with identical phases are packed together\n  std::vector<double> signal = rtk::ReadSignalFile(args_info.signal_arg);\n  auto                reorder = rtk::ReorderProjectionsImageFilter<ProjectionStackType>::New();\n  reorder->SetInput(reader->GetOutput());\n  reorder->SetInputGeometry(geometry);\n  reorder->SetInputSignal(signal);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reorder->Update())\n\n  // Release the memory holding the stack of original projections\n  reader->GetOutput()->ReleaseData();\n\n  // Compute the interpolation weights\n  auto signalToInterpolationWeights = rtk::SignalToInterpolationWeights::New();\n  signalToInterpolationWeights->SetSignal(reorder->GetOutputSignal());\n  signalToInterpolationWeights->SetNumberOfReconstructedFrames(\n    inputFilter->GetOutput()->GetLargestPossibleRegion().GetSize(3));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(signalToInterpolationWeights->Update())\n\n  // Create the 4DROOSTER filter, connect the basic inputs, and set the basic parameters\n  // Also set the forward and back projection filters to be used\n  using ROOSTERFilterType = rtk::FourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  auto rooster = ROOSTERFilterType::New();\n  SetForwardProjectionFromGgo(args_info, rooster.GetPointer());\n  SetBackProjectionFromGgo(args_info, rooster.GetPointer());\n  rooster->SetInputVolumeSeries(inputFilter->GetOutput());\n  rooster->SetCG_iterations(args_info.cgiter_arg);\n  rooster->SetMainLoop_iterations(args_info.niter_arg);\n  rooster->SetPhaseShift(args_info.shift_arg);\n  rooster->SetCudaConjugateGradient(args_info.cudacg_flag);\n  rooster->SetUseCudaCyclicDeformation(args_info.cudadvfinterpolation_flag);\n  rooster->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  REPORT_ITERATIONS(rooster, ROOSTERFilterType, VolumeSeriesType)\n\n  // Set the newly ordered arguments\n  rooster->SetInputProjectionStack(reorder->GetOutput());\n  rooster->SetGeometry(reorder->GetOutputGeometry());\n  rooster->SetWeights(signalToInterpolationWeights->GetOutput());\n  rooster->SetSignal(reorder->GetOutputSignal());\n\n  // For each optional regularization step, set whether or not\n  // it should be performed, and provide the necessary inputs\n\n  // Positivity\n  if (args_info.nopositivity_flag)\n    rooster->SetPerformPositivity(false);\n  else\n    rooster->SetPerformPositivity(true);\n\n  // Motion mask\n  VolumeType::Pointer motionMask;\n  if (args_info.motionmask_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(motionMask = itk::ReadImage<VolumeType>(args_info.motionmask_arg))\n    rooster->SetMotionMask(motionMask);\n    rooster->SetPerformMotionMask(true);\n  }\n  else\n    rooster->SetPerformMotionMask(false);\n\n  // Spatial TV\n  if (args_info.gamma_space_given)\n  {\n    rooster->SetGammaTVSpace(args_info.gamma_space_arg);\n    rooster->SetTV_iterations(args_info.tviter_arg);\n    rooster->SetPerformTVSpatialDenoising(true);\n  }\n  else\n    rooster->SetPerformTVSpatialDenoising(false);\n\n  // Spatial wavelets\n  if (args_info.threshold_given)\n  {\n    rooster->SetSoftThresholdWavelets(args_info.threshold_arg);\n    rooster->SetOrder(args_info.order_arg);\n    rooster->SetNumberOfLevels(args_info.levels_arg);\n    rooster->SetPerformWaveletsSpatialDenoising(true);\n  }\n  else\n    rooster->SetPerformWaveletsSpatialDenoising(false);\n\n  // Temporal TV\n  if (args_info.gamma_time_given)\n  {\n    rooster->SetGammaTVTime(args_info.gamma_time_arg);\n    rooster->SetTV_iterations(args_info.tviter_arg);\n    rooster->SetPerformTVTemporalDenoising(true);\n  }\n  else\n    rooster->SetPerformTVTemporalDenoising(false);\n\n  // Temporal L0\n  if (args_info.lambda_time_given)\n  {\n    rooster->SetLambdaL0Time(args_info.lambda_time_arg);\n    rooster->SetL0_iterations(args_info.l0iter_arg);\n    rooster->SetPerformL0TemporalDenoising(true);\n  }\n  else\n    rooster->SetPerformL0TemporalDenoising(false);\n\n  // Total nuclear variation\n  if (args_info.gamma_tnv_given)\n  {\n    rooster->SetGammaTNV(args_info.gamma_tnv_arg);\n    rooster->SetTV_iterations(args_info.tviter_arg);\n    rooster->SetPerformTNVDenoising(true);\n  }\n  else\n    rooster->SetPerformTNVDenoising(false);\n\n  // Warping\n  if (args_info.dvf_given)\n  {\n    rooster->SetPerformWarping(true);\n\n    if (args_info.nn_flag)\n      rooster->SetUseNearestNeighborInterpolationInWarping(true);\n\n    // Read DVF\n    DVFSequenceImageType::Pointer dvf;\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(dvf = itk::ReadImage<DVFSequenceImageType>(args_info.dvf_arg))\n    rooster->SetDisplacementField(dvf);\n\n    if (args_info.idvf_given)\n    {\n      rooster->SetComputeInverseWarpingByConjugateGradient(false);\n\n      // Read inverse DVF if provided\n      DVFSequenceImageType::Pointer idvf;\n      TRY_AND_EXIT_ON_ITK_EXCEPTION(idvf = itk::ReadImage<DVFSequenceImageType>(args_info.idvf_arg))\n      rooster->SetInverseDisplacementField(idvf);\n    }\n  }\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rooster->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(rooster->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkfourdrooster/rtkfourdrooster.ggo",
    "content": "purpose \"Reconstructs a 3D + time sequence of volumes from a projection stack and a respiratory/cardiac signal, applying TV regularization in space and time, and restricting motion to a region of interest\"\n\noption \"verbose\"     v \"Verbose execution\"                                     flag   off\noption \"geometry\"    g \"XML geometry file name\"                                string yes\noption \"input\"       i \"Input volume\"                                          string no\noption \"output\"      o \"Output file name\"                                      string yes\noption \"niter\"       n \"Number of main loop iterations\"                        int    no   default=\"5\"\noption \"cgiter\"      - \"Number of conjugate gradient nested iterations\"        int    no   default=\"4\"\noption \"cudacg\"      - \"Perform conjugate gradient calculations on GPU\"        flag   off\noption \"cudadvfinterpolation\"   - \"Perform DVF interpolation calculations on GPU\"        flag   off\noption \"nodisplaced\" - \"Disable the displaced detector filter\"                 flag   off\n\nsection \"Phase gating\"\noption \"signal\"    - \"File containing the phase of each projection\"              string                       yes\noption \"shift\"     - \"Phase shift applied on the DVFs to simulate phase estimation errors\"  float   no  default=\"0\"\n\nsection \"Regularization\"\noption \"nopositivity\" - \"Do not enforce positivity\"                                                             flag    off\noption \"motionmask\"  - \"Motion mask file: binary image with ones where movement can occur and zeros elsewhere\"  string  no\noption \"tviter\"      - \"Total variation (spatial, temporal and nuclear) regularization: number of iterations\"   int     no      default=\"10\"\noption \"gamma_space\" - \"Total variation spatial regularization parameter. The larger, the smoother\"             double  no\noption \"threshold\"   - \"Daubechies wavelets spatial regularization: soft threshold\"                             float   no\noption \"order\"       - \"Daubechies wavelets spatial regularization: order of the wavelets\"                      int     no      default=\"5\"\noption \"levels\"      - \"Daubechies wavelets spatial regularization: number of decomposition levels\"             int     no      default=\"3\"\noption \"gamma_time\"  - \"Total variation temporal regularization parameter. The larger, the smoother\"            double  no\noption \"lambda_time\" - \"Temporal gradient's L0 norm regularization parameter. The larger, the stronger\"         double  no\noption \"l0iter\"      - \"Temporal gradient's L0 norm regularization: number of iterations\"                       int     no      default=\"5\"\noption \"gamma_tnv\"   - \"Total nuclear variation regularization parameter. The larger, the smoother\"             double  no\n\nsection \"Motion-compensation described in [ToBeWritten]\"\noption \"dvf\"       - \"Input 4D DVF\"                       string    no\noption \"idvf\"      - \"Input 4D inverse DVF. Inverse transform computed by conjugate gradient if not provided\"               string    no\noption \"nn\"        - \"Nearest neighbor interpolation (default is trilinear)\"    flag  off\n"
  },
  {
    "path": "applications/rtkfourdsart/CMakeLists.txt",
    "content": "WRAP_GGO(rtkfourdsart_GGO_C rtkfourdsart.ggo ../rtkinputprojections_section.ggo ../rtk4Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkfourdsart rtkfourdsart.cxx ${rtkfourdsart_GGO_C})\ntarget_link_libraries(rtkfourdsart RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkfourdsart)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkfourdsart/rtkfourdsart.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkfourdsart_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkGeneralPurposeFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkFourDSARTConeBeamReconstructionFilter.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#  include \"rtkCudaConstantVolumeSeriesSource.h\"\n#endif\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkfourdsart, args_info);\n\n  using OutputPixelType = float;\n\n#ifdef RTK_USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<ProjectionStackType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkfourdsart>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<VolumeSeriesType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<VolumeSeriesType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkfourdsart>(constantImageSource, args_info);\n\n    // GenGetOpt can't handle default arguments for multiple arguments like size or spacing.\n    // The only default it accepts is to set all components of a multiple argument to the same value.\n    // Default size is 256^4, ie the number of reconstructed instants is 256. It has to be set to a more reasonable\n    // value which is why a \"frames\" argument is introduced\n    auto inputSize = itk::MakeSize(constantImageSource->GetSize()[0],\n                                   constantImageSource->GetSize()[1],\n                                   constantImageSource->GetSize()[2],\n                                   args_info.frames_arg);\n    constantImageSource->SetSize(inputSize);\n    inputFilter = constantImageSource;\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(inputFilter->Update())\n  inputFilter->ReleaseDataFlagOn();\n\n  // Read the phases file\n  auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n  phaseReader->SetFileName(args_info.signal_arg);\n  phaseReader->SetNumberOfReconstructedFrames(inputFilter->GetOutput()->GetLargestPossibleRegion().GetSize(3));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(phaseReader->Update())\n\n  // 4D SART reconstruction filter\n  using FourDSARTConeBeamReconstructionFilterType =\n    rtk::FourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  auto fourdsart = FourDSARTConeBeamReconstructionFilterType::New();\n\n  // Set the forward and back projection filters\n  SetForwardProjectionFromGgo(args_info, fourdsart.GetPointer());\n  SetBackProjectionFromGgo(args_info, fourdsart.GetPointer());\n  fourdsart->SetInputVolumeSeries(inputFilter->GetOutput());\n  fourdsart->SetInputProjectionStack(reader->GetOutput());\n  fourdsart->SetGeometry(geometry);\n  fourdsart->SetNumberOfIterations(args_info.niterations_arg);\n  fourdsart->SetNumberOfProjectionsPerSubset(args_info.nprojpersubset_arg);\n  fourdsart->SetWeights(phaseReader->GetOutput());\n  fourdsart->SetSignal(rtk::ReadSignalFile(args_info.signal_arg));\n  fourdsart->SetLambda(args_info.lambda_arg);\n  fourdsart->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  if (args_info.positivity_flag)\n  {\n    fourdsart->SetEnforcePositivity(true);\n  }\n\n  REPORT_ITERATIONS(fourdsart, FourDSARTConeBeamReconstructionFilterType, VolumeSeriesType)\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fourdsart->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(fourdsart->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkfourdsart/rtkfourdsart.ggo",
    "content": "purpose \"Reconstructs a 4D sequence of volumes from a sequence of projections with a 4D version of the Simulatenous Algebraic Reconstruction Technique [Andersen, 1984].\"\n\noption \"verbose\"     v \"Verbose execution\"                                     flag   off\noption \"geometry\"    g \"XML geometry file name\"                                string yes\noption \"output\"      o \"Output file name\"                                      string yes\noption \"niterations\" n \"Number of iterations\"                                  int    no   default=\"5\"\noption \"lambda\"      l \"Convergence factor\"                                    double no   default=\"0.3\"\noption \"positivity\"  - \"Enforces positivity during the reconstruction\"         flag   off\noption \"input\"     i \"Input volume\"              string          no\noption \"nprojpersubset\" - \"Number of projections processed between each update of the reconstructed volume (1 for SART, several for OSSART, all for SIRT)\" int no default=\"1\"\noption \"nodisplaced\"    - \"Disable the displaced detector filter\"              flag   off\n\nsection \"Phase gating\"\noption \"signal\"       - \"File containing the phase of each projection\"                                              string              no\n\n"
  },
  {
    "path": "applications/rtkgaincorrection/CMakeLists.txt",
    "content": "WRAP_GGO(rtkgaincorrection_GGO_C rtkgaincorrection.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkgaincorrection rtkgaincorrection.cxx ${rtkgaincorrection_GGO_C})\ntarget_link_libraries(rtkgaincorrection RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkgaincorrection)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n"
  },
  {
    "path": "applications/rtkgaincorrection/rtkgaincorrection.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkgaincorrection_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkPolynomialGainCorrectionImageFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaPolynomialGainCorrectionImageFilter.h\"\n#endif\n\n#include <string>\n\n#include <itkImageFileWriter.h>\n#include <itkExtractImageFilter.h>\n#include <itkPasteImageFilter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkgaincorrection, args_info);\n\n  constexpr unsigned int Dimension = 3;\n#ifdef RTK_USE_CUDA\n  using InputImageType = itk::CudaImage<unsigned short, Dimension>;\n  using OutputImageType = itk::CudaImage<float, Dimension>;\n#else\n  using InputImageType = itk::Image<unsigned short, Dimension>;\n  using OutputImageType = itk::Image<float, Dimension>;\n#endif\n\n  using ReaderType = rtk::ProjectionsReader<InputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkgaincorrection>(reader, args_info);\n  reader->ComputeLineIntegralOff(); // Don't want to preprocess data\n  reader->SetFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputInformation())\n\n  // Input projection parameters\n  int Nprojections = reader->GetOutput()->GetLargestPossibleRegion().GetSize(2);\n  if (!Nprojections)\n  {\n    std::cout << \"No DR found to process!\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Load dark image\n  std::string darkFile(args_info.calibDir_arg);\n  darkFile.append(\"\\\\\");\n  darkFile.append(args_info.Dark_arg);\n\n  InputImageType::Pointer darkImage;\n  auto                    readerDark = itk::ImageFileReader<InputImageType>::New();\n  readerDark->SetFileName(darkFile);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerDark->Update())\n  darkImage = readerDark->GetOutput();\n  darkImage->DisconnectPipeline();\n\n  // Get gain image\n  std::string gainFile(args_info.calibDir_arg);\n  gainFile.append(\"\\\\\");\n  gainFile.append(args_info.Gain_arg);\n\n  OutputImageType::Pointer gainImage;\n  auto                     readerGain = itk::ImageFileReader<OutputImageType>::New();\n  readerGain->SetFileName(gainFile);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerGain->Update())\n  gainImage = readerGain->GetOutput();\n  gainImage->DisconnectPipeline();\n\n#ifdef RTK_USE_CUDA\n  using GainType = rtk::CudaPolynomialGainCorrectionImageFilter;\n#else\n  using GainType = rtk::PolynomialGainCorrectionImageFilter<InputImageType, OutputImageType>;\n#endif\n\n  auto gainfilter = GainType::New();\n  gainfilter->SetDarkImage(darkImage);\n  gainfilter->SetGainCoefficients(gainImage);\n  gainfilter->SetK(args_info.K_arg);\n\n  // Create empty volume for storing processed images\n  auto constantSource = rtk::ConstantImageSource<OutputImageType>::New();\n\n\n  auto pasteFilter = itk::PasteImageFilter<OutputImageType, OutputImageType>::New();\n  pasteFilter->SetDestinationImage(constantSource->GetOutput());\n\n  int bufferSize = args_info.bufferSize_arg;\n  int Nbuffers = static_cast<int>(std::ceil(static_cast<float>(Nprojections) / static_cast<float>(bufferSize)));\n\n  bool first = true;\n  for (int bid = 0; bid < Nbuffers; ++bid)\n  {\n    int bufferIdx = bid * bufferSize;\n    int currentBufferSize = std::min(Nprojections - bufferIdx, bufferSize);\n\n    std::cout << \"Processing buffer no \" << bid << \" starting at image \" << bufferIdx << \" of size \"\n              << currentBufferSize << std::endl;\n\n    InputImageType::RegionType sliceRegion = reader->GetOutput()->GetLargestPossibleRegion();\n    InputImageType::RegionType desiredRegion;\n    desiredRegion.SetSize(itk::MakeSize(sliceRegion.GetSize()[0], sliceRegion.GetSize()[1], currentBufferSize));\n    desiredRegion.SetIndex(itk::MakeIndex(sliceRegion.GetIndex()[0], sliceRegion.GetIndex()[1], bufferIdx));\n\n    auto extract = itk::ExtractImageFilter<InputImageType, InputImageType>::New();\n    extract->SetDirectionCollapseToIdentity();\n    extract->SetExtractionRegion(desiredRegion);\n    extract->SetInput(reader->GetOutput());\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(extract->Update())\n\n    InputImageType::Pointer buffer = extract->GetOutput();\n    buffer->DisconnectPipeline();\n\n    gainfilter->SetInput(extract->GetOutput());\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(gainfilter->Update())\n\n    if (first)\n    {\n      // Initialization of the output volume\n      OutputImageType::SizeType sizeInput = gainfilter->GetOutput()->GetLargestPossibleRegion().GetSize();\n      sizeInput[2] = Nprojections;\n      OutputImageType::SpacingType   spacingInput = gainfilter->GetOutput()->GetSpacing();\n      OutputImageType::PointType     originInput = gainfilter->GetOutput()->GetOrigin();\n      OutputImageType::DirectionType imageDirection;\n      imageDirection.SetIdentity();\n\n      constantSource->SetOrigin(originInput);\n      constantSource->SetSpacing(spacingInput);\n      constantSource->SetDirection(imageDirection);\n      constantSource->SetSize(sizeInput);\n      constantSource->SetConstant(0.);\n    }\n\n    OutputImageType::Pointer procBuffer = gainfilter->GetOutput();\n    procBuffer->DisconnectPipeline();\n\n    OutputImageType::IndexType current_idx = procBuffer->GetLargestPossibleRegion().GetIndex();\n    current_idx[2] = bufferIdx;\n\n    if (first)\n    {\n      first = false;\n    }\n    else\n    {\n      pasteFilter->SetDestinationImage(pasteFilter->GetOutput());\n    }\n    pasteFilter->SetSourceImage(procBuffer);\n    pasteFilter->SetSourceRegion(procBuffer->GetLargestPossibleRegion());\n    pasteFilter->SetDestinationIndex(current_idx);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(pasteFilter->Update())\n  }\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(pasteFilter->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkgaincorrection/rtkgaincorrection.ggo",
    "content": "purpose \"Polynomial gain correction projections\"\n\noption  \"verbose\"    v \"Verbose execution\"                                        flag          off\noption  \"output\"     o \"Output file name\"                                         string        yes\n\nsection \"Filter parameters\"\noption  \"calibDir\"   c \"Directory containing the calibration files\"               string        yes\noption  \"Gain\"       - \"Gain maps filename\"                                       string        yes\noption  \"Dark\"       - \"Offset map filename\"                                      string        yes\noption  \"K\"          - \"Normalization coefficient\"                                float         yes  default=\"1.0\"\noption  \"bufferSize\" - \"Number of projections computed at the same time\"         int           no   default=\"4\"\n"
  },
  {
    "path": "applications/rtki0estimation/CMakeLists.txt",
    "content": "WRAP_GGO(rtki0estimation_GGO_C rtki0estimation.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtki0estimation rtki0estimation.cxx ${rtki0estimation_GGO_C})\ntarget_link_libraries(rtki0estimation RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtki0estimation)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtki0estimation/rtki0estimation.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtki0estimation_ggo.h\"\n#include \"rtkMacro.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include <itkExtractImageFilter.h>\n#include \"rtkI0EstimationProjectionFilter.h\"\n#include \"rtkProjectionsReader.h\"\n\n#include <vector>\n#include <algorithm>\n#include <string>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtki0estimation, args_info);\n\n  constexpr unsigned int Dimension = 3;\n  using InputImageType = itk::Image<unsigned short, Dimension>;\n\n  auto reader = rtk::ProjectionsReader<InputImageType>::New();\n  reader->SetFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputInformation())\n\n  using ExtractFilterType = itk::ExtractImageFilter<InputImageType, InputImageType>;\n  auto extract = ExtractFilterType::New();\n  extract->InPlaceOff();\n  extract->SetDirectionCollapseToSubmatrix();\n  extract->SetInput(reader->GetOutput());\n\n  ExtractFilterType::InputImageRegionType subsetRegion = reader->GetOutput()->GetLargestPossibleRegion();\n  subsetRegion = reader->GetOutput()->GetLargestPossibleRegion();\n  extract->SetInput(reader->GetOutput());\n  InputImageType::SizeType extractSize = subsetRegion.GetSize();\n  extractSize[2] = 1;\n  InputImageType::IndexType start = subsetRegion.GetIndex();\n\n\n  std::vector<unsigned short> I0buffer;\n\n  int          istep = 1;\n  unsigned int imin = 1;\n  auto         imax = (unsigned int)subsetRegion.GetSize()[2];\n  if (args_info.range_given)\n  {\n    if ((args_info.range_arg[0] <= args_info.range_arg[2]) &&\n        (istep <= (args_info.range_arg[2] - args_info.range_arg[0])))\n    {\n      imin = args_info.range_arg[0];\n      istep = args_info.range_arg[1];\n      imax = std::min(unsigned(args_info.range_arg[2]), imax);\n    }\n  }\n\n  auto i0est = rtk::I0EstimationProjectionFilter<InputImageType, InputImageType, 2>::New();\n\n  if (args_info.lambda_given)\n  {\n    i0est->SetLambda(args_info.lambda_arg);\n  }\n  if (args_info.expected_arg != 65535)\n  {\n    i0est->SetExpectedI0(args_info.expected_arg);\n  }\n  i0est->SaveHistogramsOn();\n\n  for (unsigned int i = imin; i < imax; i += istep)\n  {\n    i0est->SetInput(extract->GetOutput());\n\n    start[2] = i;\n    InputImageType::RegionType desiredRegion(start, extractSize);\n    extract->SetExtractionRegion(desiredRegion);\n\n    try\n    {\n      TRY_AND_EXIT_ON_ITK_EXCEPTION(i0est->UpdateLargestPossibleRegion())\n    }\n    catch (itk::ExceptionObject & err)\n    {\n      std::cerr << \"ExceptionObject caught !\" << std::endl;\n      std::cerr << err << std::endl;\n      return EXIT_FAILURE;\n    }\n\n    I0buffer.push_back(i0est->GetI0());\n    I0buffer.push_back(i0est->GetI0rls());\n    I0buffer.push_back(i0est->GetI0fwhm());\n  }\n\n  if (args_info.debug_given)\n  {\n    std::ofstream paramFile;\n    paramFile.open(args_info.debug_arg);\n    std::vector<unsigned short>::const_iterator it = I0buffer.begin();\n    for (; it != I0buffer.end(); ++it)\n    {\n      paramFile << *it << \",\";\n    }\n    paramFile.close();\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtki0estimation/rtki0estimation.ggo",
    "content": "purpose \"Reads projection images and estimates the I0 value for each of them\"\n\noption \"verbose\"  v \"Verbose execution\"                                         flag      off\noption \"output\"   o \"Output filename - not implemented\"                         string    no\noption \"debug\"    d \"Debug mode: output CSV file name with I0 estimates\"        string    no\noption \"range\"    - \"Range of projection to analyse min,step,max\"               int     multiple no\n\nsection \"Algorithm parameters\"\noption \"lambda\"    l \"RLS estimate coefficient\"                                  double no default=\"0.8\"\noption \"expected\"  e \"Expected I0 value\"                                         int   no   default=\"65535\"\n"
  },
  {
    "path": "applications/rtkimagxgeometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtkimagxgeometry_GGO_C rtkimagxgeometry.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkimagxgeometry rtkimagxgeometry.cxx ${rtkimagxgeometry_GGO_C})\ntarget_link_libraries(rtkimagxgeometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkimagxgeometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkimagxgeometry/rtkimagxgeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkimagxgeometry_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkImagXGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkimagxgeometry, args_info);\n\n  // Image Type\n  constexpr unsigned int Dimension = 3;\n\n  // Create geometry reader\n  auto imagxReader = rtk::ImagXGeometryReader<itk::Image<float, Dimension>>::New();\n  imagxReader->SetProjectionsFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  if (args_info.calibration_given)\n  {\n    imagxReader->SetCalibrationXMLFileName(args_info.calibration_arg);\n  }\n  if (args_info.room_setup_given)\n  {\n    imagxReader->SetRoomXMLFileName(args_info.room_setup_arg);\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(imagxReader->UpdateOutputData())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(imagxReader->GetGeometry(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkimagxgeometry/rtkimagxgeometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from an iMagX  acquisition.\"\n\noption \"calibration\" c \"iMagX Calibration file\"            string no\noption \"room_setup\"  s \"iMagX room setup file\"             string no\noption \"output\"      o \"Output file name\"                  string yes\noption \"verbose\"     v \"Verbose execution\"                 flag   off\n\nsection \"Projections\"\noption \"path\"      p \"Path containing projections\"                               string                       yes\noption \"regexp\"    r \"Regular expression to select projection files in path\"     string                       yes\noption \"nsort\"     - \"Numeric sort for regular expression matches\"               flag                         off\noption \"submatch\"  - \"Index of the submatch that will be used to sort matches\"   int                          no   default=\"0\"\n\n"
  },
  {
    "path": "applications/rtkinputprojections_group.py",
    "content": "import itk\nfrom itk import RTK as rtk\nimport numpy as np\n\n__all__ = [\n    \"add_rtkinputprojections_group\",\n    \"GetProjectionsFileNamesFromArgParse\",\n]\n\n# Mimicks rtkinputprojections_section.ggo\ndef add_rtkinputprojections_group(parser):\n    rtkinputprojections_group = parser.add_argument_group(\n        \"Input projections and their pre-processing\"\n    )\n    rtkinputprojections_group.add_argument(\n        \"--path\", \"-p\", help=\"Path containing projections\", required=True\n    )\n    rtkinputprojections_group.add_argument(\n        \"--regexp\",\n        \"-r\",\n        help=\"Regular expression to select projection files in path\",\n        required=True,\n    )\n    rtkinputprojections_group.add_argument(\n        \"--nsort\",\n        help=\"Numeric sort for regular expression matches\",\n        action=\"store_true\",\n    )\n    rtkinputprojections_group.add_argument(\n        \"--submatch\",\n        help=\"Index of the submatch that will be used to sort matches\",\n        type=int,\n        default=0,\n    )\n    rtkinputprojections_group.add_argument(\n        \"--nolineint\",\n        help=\"Disable raw to line integral conversion, just casts to float\",\n        type=bool,\n        default=False,\n    )\n    rtkinputprojections_group.add_argument(\n        \"--newdirection\",\n        help=\"New value of input projections (before pre-processing)\",\n        type=float,\n        nargs=\"+\",\n    )\n    rtkinputprojections_group.add_argument(\n        \"--neworigin\",\n        help=\"New origin of input projections (before pre-processing)\",\n        type=float,\n        nargs=\"+\",\n    )\n    rtkinputprojections_group.add_argument(\n        \"--newspacing\",\n        help=\"New spacing of input projections (before pre-processing)\",\n        type=float,\n        nargs=\"+\",\n    )\n    rtkinputprojections_group.add_argument(\n        \"--lowercrop\",\n        help=\"Lower boundary crop size\",\n        type=int,\n        nargs=\"+\",\n        default=[0],\n    )\n    rtkinputprojections_group.add_argument(\n        \"--uppercrop\",\n        help=\"Upper boundary crop size\",\n        type=int,\n        nargs=\"+\",\n        default=[0],\n    )\n    rtkinputprojections_group.add_argument(\n        \"--binning\",\n        help=\"Shrink / Binning factos in each direction\",\n        type=int,\n        nargs=\"+\",\n        default=[1],\n    )\n    rtkinputprojections_group.add_argument(\n        \"--wpc\",\n        help=\"Water precorrection coefficients (default is no correction)\",\n        type=float,\n        nargs=\"+\",\n    )\n    rtkinputprojections_group.add_argument(\n        \"--spr\",\n        help=\"Boellaard scatter correction: scatter-to-primary ratio\",\n        type=float,\n        default=0,\n    )\n    rtkinputprojections_group.add_argument(\n        \"--nonneg\",\n        help=\"Boellaard scatter correction: non-negativity threshold\",\n        type=float,\n    )\n    rtkinputprojections_group.add_argument(\n        \"--airthres\", help=\"Boellaard scatter correction: air threshold\", type=float\n    )\n    rtkinputprojections_group.add_argument(\n        \"--i0\",\n        help=\"I0 value (when assumed constant per projection), 0 means auto\",\n        type=float,\n    )\n    rtkinputprojections_group.add_argument(\n        \"--idark\",\n        help=\"IDark value, i.e., value when beam is off\",\n        type=float,\n        default=0,\n    )\n    rtkinputprojections_group.add_argument(\n        \"--component\",\n        help=\"Vector component to extract, for multi-material projections\",\n        type=int,\n        default=0,\n    )\n    rtkinputprojections_group.add_argument(\n        \"--radius\",\n        help=\"Radius of neighborhood for conditional median filtering\",\n        type=int,\n        nargs=\"+\",\n        default=[0],\n    )\n    rtkinputprojections_group.add_argument(\n        \"--multiplier\",\n        help=\"Threshold multiplier for conditional median filtering\",\n        type=float,\n        default=0,\n    )\n\n\n# Mimicks GetProjectionsFileNamesFromGgo\ndef GetProjectionsFileNamesFromArgParse(args_info):\n    # Generate file names\n    names = itk.RegularExpressionSeriesFileNames.New()\n    names.SetDirectory(args_info.path)\n    names.SetNumericSort(args_info.nsort)\n    names.SetRegularExpression(args_info.regexp)\n    names.SetSubMatch(args_info.submatch)\n\n    if args_info.verbose:\n        print(f\"Regular expression matches {len(names.GetFileNames())} file(s)...\")\n\n    # Check submatch in file names TODO\n    # rtk.RegisterIOFactories() TODO\n\n    fileNames = []\n    for fn in names.GetFileNames():\n        imageio = itk.ImageIOFactory.CreateImageIO(fn, itk.CommonEnums.IOFileMode_ReadMode)\n        if imageio is None:\n            print(f\"Ignoring file: {fn}\")\n            continue\n        fileNames.append(fn)\n\n    return fileNames\n\n# Mimicks SetProjectionsReaderFromGgo\ndef SetProjectionsReaderFromArgParse(reader, args_info):\n    fileNames = GetProjectionsFileNamesFromArgParse(args_info)\n\n    # Vector component extraction\n    if args_info.component is not None:\n        reader.SetVectorComponent(args_info.component)\n\n    # Change image information\n    Dimension = reader.GetOutput().GetImageDimension()\n    if args_info.newdirection is not None:\n        direction = [args_info.newdirection[0]] * 9\n        for i in range(min(9, len(args_info.newdirection))):\n            direction[i] = args_info.newdirection[i]\n        direction = np.array(direction).reshape((3, 3))\n        reader.SetDirection(itk.matrix_from_array(direction))\n\n    if args_info.newspacing is not None:\n        spacing = itk.Vector[itk.D, Dimension]()\n        spacing.Fill(args_info.newspacing[0])\n        for i in range(len(args_info.newspacing)):\n            spacing[i] = args_info.newspacing[i]\n        reader.SetSpacing(spacing)\n\n    if args_info.neworigin is not None:\n        origin = itk.Point[itk.D, Dimension]()\n        origin.Fill(args_info.neworigin[0])\n        for i in range(len(args_info.neworigin)):\n            origin[i] = args_info.neworigin[i]\n        reader.SetOrigin(origin)\n\n    # Crop boundaries\n    upperCrop = [0] * Dimension\n    lowerCrop = [0] * Dimension\n    if args_info.lowercrop is not None:\n        for i in range(len(args_info.lowercrop)):\n            lowerCrop[i] = args_info.lowercrop[i]\n    reader.SetLowerBoundaryCropSize(lowerCrop)\n    if args_info.uppercrop is not None:\n        for i in range(len(args_info.uppercrop)):\n            upperCrop[i] = args_info.uppercrop[i]\n    reader.SetUpperBoundaryCropSize(upperCrop)\n\n    # Conditional median\n    medianRadius = reader.GetMedianRadius()\n    if args_info.radius is not None:\n        for i in range(len(args_info.radius)):\n            medianRadius[i] = args_info.radius[i]\n    reader.SetMedianRadius(medianRadius)\n    if args_info.multiplier is not None:\n        reader.SetConditionalMedianThresholdMultiplier(args_info.multiplier)\n\n    # Shrink / Binning\n    binFactors = reader.GetShrinkFactors()\n    if args_info.binning is not None:\n        for i in range(len(args_info.binning)):\n            binFactors[i] = args_info.binning[i]\n    reader.SetShrinkFactors(binFactors)\n\n    # Boellaard scatter correction\n    if args_info.spr is not None:\n        reader.SetScatterToPrimaryRatio(args_info.spr)\n    if args_info.nonneg is not None:\n        reader.SetNonNegativityConstraintThreshold(args_info.nonneg)\n    if args_info.airthres is not None:\n        reader.SetAirThreshold(args_info.airthres)\n\n    # I0 and IDark\n    if args_info.i0 is not None:\n        reader.SetI0(args_info.i0)\n    reader.SetIDark(args_info.idark)\n\n    # Line integral flag\n    if args_info.nolineint:\n        reader.ComputeLineIntegralOff()\n\n    # Water precorrection\n    if args_info.wpc is not None:\n        reader.SetWaterPrecorrectionCoefficients(args_info.wpc)\n\n    # Pass list to projections reader\n    reader.SetFileNames(fileNames)\n    reader.UpdateOutputInformation()\n"
  },
  {
    "path": "applications/rtkinputprojections_section.ggo",
    "content": "section \"Input projections and their pre-processing\"\noption \"path\"         p \"Path containing projections\"                                   string           yes\noption \"regexp\"       r \"Regular expression to select projection files in path\"         string           yes\noption \"nsort\"        - \"Numeric sort for regular expression matches\"                   flag             off\noption \"submatch\"     - \"Index of the submatch that will be used to sort matches\"       int              no   default=\"0\"\noption \"nolineint\"    - \"Disable raw to line integral conversion, just casts to float\"  flag             off\noption \"newdirection\" - \"New value of input projections (before pre-processing)\"        double  multiple no\noption \"neworigin\"    - \"New origin of input projections (before pre-processing)\"       double  multiple no\noption \"newspacing\"   - \"New spacing of input projections (before pre-processing)\"      double  multiple no\noption \"lowercrop\"    - \"Lower boundary crop size\"                                      int     multiple no   default=\"0\"\noption \"uppercrop\"    - \"Upper boundary crop size\"                                      int     multiple no   default=\"0\"\noption \"binning\"      - \"Shrink / Binning factos in each direction\"                     int     multiple no   default=\"1\"\noption \"wpc\"          - \"Water precorrection coefficients (default is no correction)\"   double  multiple no\noption \"spr\"          - \"Boellaard scatter correction: scatter-to-primary ratio\"        double           no   default=\"0\"\noption \"nonneg\"       - \"Boellaard scatter correction: non-negativity threshold\"        double           no\noption \"airthres\"     - \"Boellaard scatter correction: air threshold\"                   double           no\noption \"i0\"           - \"I0 value (when assumed constant per projection), 0 means auto\" double           no\noption \"idark\"        - \"IDark value, i.e., value when beam is off\"                     double           no   default=\"0\"\noption \"component\"    - \"Vector component to extract, for multi-material projections\"   int              no   default=\"0\"\noption \"radius\"       - \"Radius of neighborhood for conditional median filtering\"       int     multiple no   default=\"0\"\noption \"multiplier\"   - \"Threshold multiplier for conditional median filtering\"         double           no   default=\"0\"\n"
  },
  {
    "path": "applications/rtkiterations_group.py",
    "content": "import itk\n\n__all__ = [\n    \"add_rtkiterations_group\",\n    \"SetIterationsReportFromArgParse\",\n]\n\n# Mimicks rtkiterations_section.ggo\ndef add_rtkiterations_group(parser):\n    rtkiterations_group = parser.add_argument_group(\"Iteration reporting\")\n    rtkiterations_group.add_argument(\n        \"--outputevery\",\n        help=\"Output intermediate reconstruction after some iterations\",\n        type=int,\n    )\n    rtkiterations_group.add_argument(\n        \"--iterationfilename\",\n        help=\"File name to output intermediate iterations with {i} as a placeholder for iteration number\",\n    )\n\n\n# Mimicks VerboseIterationCommand\nclass VerboseIterationCommand:\n    def __init__(self):\n        self.count = 0\n\n    def callback(self):\n        self.count = self.count + 1\n        print(f\"Iteration {self.count}\", end=\"\\r\")\n\n\nclass VerboseEndCommand:\n    def callback(self):\n        print(\"\")\n\n\n# Mimicks OutputIterationCommand\nclass OutputIterationCommand:\n    def __init__(self, reconstruction_filter, outputevery, iterationfilename):\n        self.count = 0\n        self.reconstruction_filter = reconstruction_filter\n        self.outputevery = outputevery\n        self.iterationfilename = iterationfilename\n\n    def callback(self):\n        self.count = self.count + 1\n        if self.count % self.outputevery == 0:\n            output = self.reconstruction_filter.GetOutput()\n            OutputImageType = type(output)\n            if hasattr(output, \"GetCudaDataManager\"):\n                OutputImageType = OutputImageType.__bases__[0]\n            writer = itk.ImageFileWriter[OutputImageType].New()\n            writer.SetInput(output)\n            writer.SetFileName(self.iterationfilename.format(i=self.count))\n            writer.Update()\n\n\n# Mimicks macro REPORT_ITERATIONS\ndef SetIterationsReportFromArgParse(args_info, filt):\n    if args_info.verbose:\n        cmd = VerboseIterationCommand()\n        filt.AddObserver(itk.IterationEvent(), cmd.callback)\n        cmd = VerboseEndCommand()\n        filt.AddObserver(itk.EndEvent(), cmd.callback)\n    if args_info.outputevery is not None:\n        cmd = OutputIterationCommand(\n            filt, args_info.outputevery, args_info.iterationfilename\n        )\n        filt.AddObserver(itk.IterationEvent(), cmd.callback)\n"
  },
  {
    "path": "applications/rtkiterations_section.ggo",
    "content": "section \"Iteration reporting\"\noption \"output-every\"   - \"Output intermediate reconstruction after some iterations\"                                  int    no\noption \"iteration-file-name\" - \"File name to output intermediate iterations with %d as a placeholder for iteration number\" string no\n"
  },
  {
    "path": "applications/rtkiterativefdk/CMakeLists.txt",
    "content": "WRAP_GGO(rtkiterativefdk_GGO_C rtkiterativefdk.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkiterativefdk rtkiterativefdk.cxx ${rtkiterativefdk_GGO_C})\ntarget_link_libraries(rtkiterativefdk RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkiterativefdk)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkiterativefdk/rtkiterativefdk.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkiterativefdk_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkIterativeFDKConeBeamReconstructionFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaIterativeFDKConeBeamReconstructionFilter.h\"\n#endif\n\n#include <itkStreamingImageFilter.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkiterativefdk, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkiterativefdk>(reader, args_info);\n\n  if (args_info.verbose_flag)\n    std::cout << \"Reading... \" << std::endl;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update())\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create reconstructed image\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkiterativefdk>(constantImageSource,\n                                                                                         args_info);\n\n  bool enforcePositivity = false;\n  if (args_info.positivity_flag)\n    enforcePositivity = true;\n  else\n    enforcePositivity = false;\n\n  // Since the last template argument for IterativeFDKConeBeamReconstructionFilter is\n  // double for the CPU version, and float for the CUDA one, we cannot have a single\n  // pointer for both possibilities. In order to set the options only once,\n  // we therefore create a macro, exactly as in rtkfdk.cxx\n#define SET_IFDK_OPTIONS(f)                               \\\n  f->SetInput(0, constantImageSource->GetOutput());       \\\n  f->SetInput(1, reader->GetOutput());                    \\\n  f->SetGeometry(geometry);                               \\\n  SetForwardProjectionFromGgo(args_info, f.GetPointer()); \\\n  f->SetNumberOfIterations(args_info.niterations_arg);    \\\n  f->SetTruncationCorrection(args_info.pad_arg);          \\\n  f->SetHannCutFrequency(args_info.hann_arg);             \\\n  f->SetHannCutFrequencyY(args_info.hannY_arg);           \\\n  f->SetProjectionSubsetSize(args_info.subsetsize_arg);   \\\n  f->SetLambda(args_info.lambda_arg);                     \\\n  f->SetEnforcePositivity(enforcePositivity);             \\\n  f->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  // Create Iterative FDK filter and connect it\n  using IFDKCPUType = rtk::IterativeFDKConeBeamReconstructionFilter<OutputImageType, OutputImageType, double>;\n  IFDKCPUType::Pointer ifdk;\n#ifdef RTK_USE_CUDA\n  using IFDKCUDAType = rtk::CudaIterativeFDKConeBeamReconstructionFilter;\n  IFDKCUDAType::Pointer ifdkCUDA;\n#endif\n\n  OutputImageType::Pointer IFDKOutputPointer;\n  if (!strcmp(args_info.hardware_arg, \"cpu\"))\n  {\n    ifdk = IFDKCPUType::New();\n    REPORT_ITERATIONS(ifdk, IFDKCPUType, OutputImageType)\n    SET_IFDK_OPTIONS(ifdk);\n    IFDKOutputPointer = ifdk->GetOutput();\n  }\n#ifdef RTK_USE_CUDA\n  else if (!strcmp(args_info.hardware_arg, \"cuda\"))\n  {\n    ifdkCUDA = IFDKCUDAType::New();\n    REPORT_ITERATIONS(ifdkCUDA, IFDKCPUType, OutputImageType)\n    SET_IFDK_OPTIONS(ifdkCUDA);\n    IFDKOutputPointer = ifdkCUDA->GetOutput();\n  }\n#endif\n\n  // Write\n  if (args_info.verbose_flag)\n    std::cout << \"Reconstructing and writing... \" << std::endl;\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(IFDKOutputPointer, args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkiterativefdk/rtkiterativefdk.ggo",
    "content": "purpose \"Reconstructs a 3D volume from a sequence of projections [Feldkamp, David, Kress, 1984].\"\n\noption \"verbose\"    v \"Verbose execution\"                                           flag                         off\noption \"geometry\"   g \"XML geometry file name\"                                      string                       yes\noption \"output\"     o \"Output file name\"                                            string                       yes\noption \"hardware\"   - \"Hardware used for computation\"                               values=\"cpu\",\"cuda\"          no   default=\"cpu\"\noption \"subsetsize\" - \"Streaming option: number of projections processed at a time\" int                          no   default=\"16\"\noption \"niterations\" n \"Number of iterations\"                                       int                          no   default=\"3\"\noption \"lambda\"      - \"Convergence factor\"                                         double                       no   default=\"0.3\"\noption \"positivity\"  - \"Enforces positivity during the reconstruction\"              flag                         off\noption \"nodisplaced\"    - \"Disable the displaced detector filter\"                   flag                         off\n\nsection \"Ramp filter\"\noption \"pad\"       - \"Data padding parameter to correct for truncation\"          double                       no   default=\"0.0\"\noption \"hann\"      - \"Cut frequency for hann window in ]0,1] (0.0 disables it)\"  double                       no   default=\"0.0\"\noption \"hannY\"     - \"Cut frequency for hann window in ]0,1] (0.0 disables it)\"  double                       no   default=\"0.0\"\n\nsection \"Projectors\"\noption \"fp\"    f \"Forward projection method\" values=\"Joseph\",\"CudaRayCast\",\"JosephAttenuated\",\"Zeng\" enum no default=\"Joseph\"\noption \"attenuationmap\" - \"Attenuation map relative to the volume to perfom the attenuation correction\"   string  no\noption \"sigmazero\" - \"PSF value at a distance of 0 meter of the detector\"   double  no\noption \"alphapsf\" - \"Slope of the PSF against the detector distance\"   double  no\noption \"inferiorclipimage\" - \"Value of the inferior clip of the ray for each pixel of the projections (only with Joseph-based projector)\" string no\noption \"superiorclipimage\" - \"Value of the superior clip of the ray for each pixel of the projections (only with Joseph-based projector)\" string no\noption \"step\" - \"Step size along ray (for CudaRayCast only)\"                double   no   default=\"1\""
  },
  {
    "path": "applications/rtklagcorrection/CMakeLists.txt",
    "content": "WRAP_GGO(rtklagcorrection_GGO_C rtklagcorrection.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtklagcorrection rtklagcorrection.cxx ${rtklagcorrection_GGO_C})\ntarget_link_libraries(rtklagcorrection RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtklagcorrection)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n"
  },
  {
    "path": "applications/rtklagcorrection/rtklagcorrection.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtklagcorrection_ggo.h\"\n\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaLagCorrectionImageFilter.h\"\n#  include <itkCudaImage.h>\n#else\n#  include \"rtkLagCorrectionImageFilter.h\"\n#endif\n\nusing namespace rtk;\n\n#include <itkImageFileWriter.h>\n\nconst unsigned VModelOrder = 4;\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtklagcorrection, args_info);\n\n  constexpr unsigned int Dimension = 3;\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<unsigned short, Dimension>;\n#else\n  using OutputImageType = itk::Image<unsigned short, Dimension>;\n#endif\n  using VectorType = itk::Vector<float, VModelOrder>; // Parameter type always float/double\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtklagcorrection>(reader, args_info);\n  reader->ComputeLineIntegralOff(); // Don't want to preprocess data\n  reader->SetFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update())\n\n  if ((args_info.coefficients_given != VModelOrder) && (args_info.rates_given != VModelOrder))\n  {\n    std::cerr << \"Expecting 4 lags rates and coefficients values\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  VectorType a, b;\n  for (unsigned int i = 0; i < VModelOrder; ++i)\n  {\n    a[i] = args_info.rates_arg[i];\n    b[i] = args_info.coefficients_arg[i];\n  }\n\n#ifdef RTK_USE_CUDA\n  using LagType = rtk::CudaLagCorrectionImageFilter;\n#else\n  using LagType = rtk::LagCorrectionImageFilter<OutputImageType, VModelOrder>;\n#endif\n  auto lagfilter = LagType::New();\n  lagfilter->SetInput(reader->GetOutput());\n  lagfilter->SetCoefficients(a, b);\n  lagfilter->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(lagfilter->Update())\n\n  // Streaming filter\n  auto streamer = itk::StreamingImageFilter<OutputImageType, OutputImageType>::New();\n  streamer->SetInput(lagfilter->GetOutput());\n  streamer->SetNumberOfStreamDivisions(100);\n\n  // Save corrected projections\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(streamer->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtklagcorrection/rtklagcorrection.ggo",
    "content": "purpose \"4th order LTI Lag correction\"\n\noption  \"verbose\"      v \"Verbose execution\"                                 flag           off\noption  \"output\"       o \"Output file name\"                                  string         yes\noption  \"rates\"        a \"Lag rates (a0, a1, a2, a3)\"                        float multiple yes\noption  \"coefficients\" c \"Lag coefficients (b0, b1, b2, b3)\"                 float multiple yes\n"
  },
  {
    "path": "applications/rtkmaskcollimation/CMakeLists.txt",
    "content": "WRAP_GGO(rtkmaskcollimation_GGO_C rtkmaskcollimation.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkmaskcollimation rtkmaskcollimation.cxx ${rtkmaskcollimation_GGO_C})\ntarget_link_libraries(rtkmaskcollimation RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkmaskcollimation)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkmaskcollimation/rtkmaskcollimation.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkmaskcollimation_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkMaskCollimationImageFilter.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkmaskcollimation, args_info);\n\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkmaskcollimation>(reader, args_info);\n\n  // Create projection image filter\n  auto ofm = rtk::MaskCollimationImageFilter<OutputImageType, OutputImageType>::New();\n  ofm->SetInput(reader->GetOutput());\n  ofm->SetGeometry(geometry);\n\n  // Write\n  auto writer = itk::ImageFileWriter<OutputImageType>::New();\n  writer->SetFileName(args_info.output_arg);\n  writer->SetInput(ofm->GetOutput());\n  if (args_info.verbose_flag)\n    std::cout << \"Projecting and writing... \" << std::flush;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(writer->UpdateOutputInformation())\n  writer->SetNumberOfStreamDivisions(reader->GetOutput()->GetLargestPossibleRegion().GetSize(2));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(writer->Update())\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkmaskcollimation/rtkmaskcollimation.ggo",
    "content": "purpose \"Masks out the collimator from the projections\"\n\noption \"verbose\"    v \"Verbose execution\"                                         flag     off\noption \"geometry\"   g  \"XML geometry file name\"                                   string   yes\noption \"output\"     o \"Output projections file name\"                              string   yes\n\n"
  },
  {
    "path": "applications/rtkmcrooster/CMakeLists.txt",
    "content": "WRAP_GGO(rtkmcrooster_GGO_C rtkmcrooster.ggo ../rtkinputprojections_section.ggo ../rtk4Doutputimage_section.ggo ../rtkprojectors_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkmcrooster rtkmcrooster.cxx ${rtkmcrooster_GGO_C})\ntarget_link_libraries(rtkmcrooster RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkmcrooster)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkmcrooster/rtkmcrooster.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkmcrooster_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkGeneralPurposeFunctions.h\"\n\n#include \"rtkMotionCompensatedFourDROOSTERConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkSignalToInterpolationWeights.h\"\n#include \"rtkReorderProjectionsImageFilter.h\"\n#include \"rtkWarpSequenceImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkmcrooster, args_info);\n\n  using OutputPixelType = float;\n  using DVFVectorType = itk::CovariantVector<OutputPixelType, 3>;\n\n#ifdef RTK_USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension - 1>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension - 1>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<ProjectionStackType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkmcrooster>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<VolumeSeriesType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    using InputReaderType = itk::ImageFileReader<VolumeSeriesType>;\n    auto inputReader = InputReaderType::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkmcrooster>(constantImageSource, args_info);\n\n    // GenGetOpt can't handle default arguments for multiple arguments like size or spacing.\n    // The only default it accepts is to set all components of a multiple argument to the same value.\n    // Default size is 256^4, ie the number of reconstructed instants is 256. It has to be set to a more reasonable\n    // value which is why a \"frames\" argument is introduced\n    auto inputSize = itk::MakeSize(constantImageSource->GetSize()[0],\n                                   constantImageSource->GetSize()[1],\n                                   constantImageSource->GetSize()[2],\n                                   args_info.frames_arg);\n    constantImageSource->SetSize(inputSize);\n\n    inputFilter = constantImageSource;\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(inputFilter->Update())\n  inputFilter->ReleaseDataFlagOn();\n\n  // Re-order geometry and projections\n  // In the new order, projections with identical phases are packed together\n  std::vector<double> signal = rtk::ReadSignalFile(args_info.signal_arg);\n  auto                reorder = rtk::ReorderProjectionsImageFilter<ProjectionStackType>::New();\n  reorder->SetInput(reader->GetOutput());\n  reorder->SetInputGeometry(geometry);\n  reorder->SetInputSignal(signal);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reorder->Update())\n\n  // Release the memory holding the stack of original projections\n  reader->GetOutput()->ReleaseData();\n\n  // Compute the interpolation weights\n  auto signalToInterpolationWeights = rtk::SignalToInterpolationWeights::New();\n  signalToInterpolationWeights->SetSignal(reorder->GetOutputSignal());\n  signalToInterpolationWeights->SetNumberOfReconstructedFrames(\n    inputFilter->GetOutput()->GetLargestPossibleRegion().GetSize(3));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(signalToInterpolationWeights->Update())\n\n  // Create the 4DROOSTER filter, connect the basic inputs, and set the basic parameters\n  auto mcrooster =\n    rtk::MotionCompensatedFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::New();\n  SetForwardProjectionFromGgo(args_info, mcrooster.GetPointer());\n  SetBackProjectionFromGgo(args_info, mcrooster.GetPointer());\n  mcrooster->SetInputVolumeSeries(inputFilter->GetOutput());\n  mcrooster->SetCG_iterations(args_info.cgiter_arg);\n  mcrooster->SetMainLoop_iterations(args_info.niter_arg);\n  mcrooster->SetCudaConjugateGradient(args_info.cudacg_flag);\n  mcrooster->SetUseCudaCyclicDeformation(args_info.cudadvfinterpolation_flag);\n  mcrooster->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  // Set the newly ordered arguments\n  mcrooster->SetInputProjectionStack(reorder->GetOutput());\n  mcrooster->SetGeometry(reorder->GetOutputGeometry());\n  mcrooster->SetWeights(signalToInterpolationWeights->GetOutput());\n  mcrooster->SetSignal(reorder->GetOutputSignal());\n\n  // For each optional regularization step, set whether or not\n  // it should be performed, and provide the necessary inputs\n\n  // Positivity\n  if (args_info.nopositivity_flag)\n    mcrooster->SetPerformPositivity(false);\n  else\n    mcrooster->SetPerformPositivity(true);\n\n  // Motion mask\n  using InputReaderType = itk::ImageFileReader<ProjectionStackType>;\n  if (args_info.motionmask_given)\n  {\n    auto motionMaskReader = InputReaderType::New();\n    motionMaskReader->SetFileName(args_info.motionmask_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(motionMaskReader->Update())\n    mcrooster->SetMotionMask(motionMaskReader->GetOutput());\n    mcrooster->SetPerformMotionMask(true);\n  }\n  else\n    mcrooster->SetPerformMotionMask(false);\n\n  // Spatial TV\n  if (args_info.gamma_space_given)\n  {\n    mcrooster->SetGammaTVSpace(args_info.gamma_space_arg);\n    mcrooster->SetTV_iterations(args_info.tviter_arg);\n    mcrooster->SetPerformTVSpatialDenoising(true);\n  }\n  else\n    mcrooster->SetPerformTVSpatialDenoising(false);\n\n  // Spatial wavelets\n  if (args_info.threshold_given)\n  {\n    mcrooster->SetSoftThresholdWavelets(args_info.threshold_arg);\n    mcrooster->SetOrder(args_info.order_arg);\n    mcrooster->SetNumberOfLevels(args_info.levels_arg);\n    mcrooster->SetPerformWaveletsSpatialDenoising(true);\n  }\n  else\n    mcrooster->SetPerformWaveletsSpatialDenoising(false);\n\n  // Temporal TV\n  if (args_info.gamma_time_given)\n  {\n    mcrooster->SetGammaTVTime(args_info.gamma_time_arg);\n    mcrooster->SetTV_iterations(args_info.tviter_arg);\n    mcrooster->SetPerformTVTemporalDenoising(true);\n  }\n  else\n    mcrooster->SetPerformTVTemporalDenoising(false);\n\n  // Temporal L0\n  if (args_info.lambda_time_arg)\n  {\n    mcrooster->SetLambdaL0Time(args_info.lambda_time_arg);\n    mcrooster->SetL0_iterations(args_info.l0iter_arg);\n    mcrooster->SetPerformL0TemporalDenoising(true);\n  }\n  else\n    mcrooster->SetPerformL0TemporalDenoising(false);\n\n  // Read DVF\n  DVFSequenceImageType::Pointer dvf;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dvf = itk::ReadImage<DVFSequenceImageType>(args_info.dvf_arg))\n  mcrooster->SetDisplacementField(dvf);\n\n  // Read inverse DVF if provided\n  DVFSequenceImageType::Pointer idvf;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(idvf = itk::ReadImage<DVFSequenceImageType>(args_info.idvf_arg))\n  mcrooster->SetInverseDisplacementField(idvf);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mcrooster->Update())\n\n  auto warp =\n    rtk::WarpSequenceImageFilter<VolumeSeriesType, DVFSequenceImageType, ProjectionStackType, DVFImageType>::New();\n\n  if (args_info.nofinalwarp_flag)\n  {\n    // MCROOSTER outputs a motion-compensated reconstruction\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(mcrooster->GetOutput(), args_info.output_arg))\n  }\n  else\n  {\n    // Warp the output of MCROOSTER with the inverse field so\n    // that it is similar to that of rtkfourdrooster\n    warp->SetInput(mcrooster->GetOutput());\n    warp->SetDisplacementField(idvf);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(warp->Update())\n\n    // Write\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(warp->GetOutput(), args_info.output_arg))\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkmcrooster/rtkmcrooster.ggo",
    "content": "purpose \"Reconstructs a 3D + time sequence of volumes from a projection stack and a respiratory/cardiac signal, applying TV regularization in space and time, and restricting motion to a region of interest\"\n\noption \"verbose\"     v \"Verbose execution\"                                     flag   off\noption \"geometry\"    g \"XML geometry file name\"                                string yes\noption \"input\"       i \"Input volume\"                                          string no\noption \"output\"      o \"Output file name\"                                      string yes\noption \"niter\"       n \"Number of main loop iterations\"                        int    no   default=\"5\"\noption \"cgiter\"      - \"Number of conjugate gradient nested iterations\"        int    no   default=\"4\"\noption \"cudacg\"      - \"Perform conjugate gradient calculations on GPU\"        flag   off\noption \"cudadvfinterpolation\"   - \"Perform DVF interpolation calculations on GPU\"        flag   off\noption \"nodisplaced\"    - \"Disable the displaced detector filter\"              flag   off\n\nsection \"Phase gating\"\noption \"signal\"    - \"File containing the phase of each projection\"              string                       yes\n\nsection \"Regularization\"\noption \"nopositivity\" - \"Do not enforce positivity\"                                                             flag    off\noption \"motionmask\"  - \"Motion mask file: binary image with ones where movement can occur and zeros elsewhere\"  string  no\noption \"tviter\"      - \"Total variation (spatial and temporal) regularization: number of iterations\"            int     no      default=\"10\"\noption \"gamma_space\" - \"Total variation spatial regularization parameter. The larger, the smoother\"             double  no\noption \"threshold\"   - \"Daubechies wavelets spatial regularization: soft threshold\"                             float   no\noption \"order\"       - \"Daubechies wavelets spatial regularization: order of the wavelets\"                      int     no      default=\"5\"\noption \"levels\"      - \"Daubechies wavelets spatial regularization: number of decomposition levels\"             int     no      default=\"3\"\noption \"gamma_time\"  - \"Total variation temporal regularization parameter. The larger, the smoother\"            double  no\noption \"lambda_time\" - \"Temporal gradient's L0 norm regularization parameter. The larger, the stronger\"         double  no\noption \"l0iter\"      - \"Temporal gradient's L0 norm regularization: number of iterations\"                       int     no      default=\"5\"\n\nsection \"Motion-compensation\"\noption \"dvf\"       - \"Input 4D DVF\"             string    yes\noption \"idvf\"      - \"Input 4D inverse DVF\"     string    yes\noption \"nofinalwarp\" - \"Outputs the motion-compensated sequence, without warping it\"        flag off\n"
  },
  {
    "path": "applications/rtkmotioncompensatedfourdconjugategradient/CMakeLists.txt",
    "content": "WRAP_GGO(rtkmotioncompensatedfourdconjugategradient_GGO_C rtkmotioncompensatedfourdconjugategradient.ggo ../rtkinputprojections_section.ggo ../rtk4Doutputimage_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkmotioncompensatedfourdconjugategradient rtkmotioncompensatedfourdconjugategradient.cxx ${rtkmotioncompensatedfourdconjugategradient_GGO_C})\ntarget_link_libraries(rtkmotioncompensatedfourdconjugategradient RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkmotioncompensatedfourdconjugategradient)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkmotioncompensatedfourdconjugategradient/rtkmotioncompensatedfourdconjugategradient.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkmotioncompensatedfourdconjugategradient_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n#include \"rtkWarpSequenceImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkmotioncompensatedfourdconjugategradient, args_info);\n\n  using OutputPixelType = float;\n  using DVFVectorType = itk::CovariantVector<OutputPixelType, 3>;\n\n#ifdef RTK_USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension - 1>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension - 1>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<ProjectionStackType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkmotioncompensatedfourdconjugategradient>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<VolumeSeriesType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<VolumeSeriesType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkmotioncompensatedfourdconjugategradient>(\n      constantImageSource, args_info);\n\n    // GenGetOpt can't handle default arguments for multiple arguments like size or spacing.\n    // The only default it accepts is to set all components of a multiple argument to the same value.\n    // Default size is 256^4, ie the number of reconstructed instants is 256. It has to be set to a more reasonable\n    // value which is why a \"frames\" argument is introduced\n    constantImageSource->SetSize(itk::MakeSize(constantImageSource->GetSize()[0],\n                                               constantImageSource->GetSize()[1],\n                                               constantImageSource->GetSize()[2],\n                                               args_info.frames_arg));\n\n    inputFilter = constantImageSource;\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(inputFilter->Update())\n  inputFilter->ReleaseDataFlagOn();\n\n  // Read the phases file\n  auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n  phaseReader->SetFileName(args_info.signal_arg);\n  phaseReader->SetNumberOfReconstructedFrames(inputFilter->GetOutput()->GetLargestPossibleRegion().GetSize(3));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(phaseReader->Update())\n\n\n  // Create the mcfourdcg filter, connect the basic inputs, and set the basic parameters\n  using MCFourDCGFilterType =\n    rtk::MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  auto mcfourdcg = MCFourDCGFilterType::New();\n  mcfourdcg->SetInputVolumeSeries(inputFilter->GetOutput());\n  mcfourdcg->SetInputProjectionStack(reader->GetOutput());\n  mcfourdcg->SetGeometry(geometry);\n  mcfourdcg->SetWeights(phaseReader->GetOutput());\n  mcfourdcg->SetNumberOfIterations(args_info.niter_arg);\n  mcfourdcg->SetCudaConjugateGradient(args_info.cudacg_flag);\n  mcfourdcg->SetSignal(rtk::ReadSignalFile(args_info.signal_arg));\n  mcfourdcg->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  REPORT_ITERATIONS(mcfourdcg, MCFourDCGFilterType, VolumeSeriesType)\n\n  // Read DVF\n  DVFSequenceImageType::Pointer dvf;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dvf = itk::ReadImage<DVFSequenceImageType>(args_info.dvf_arg))\n  mcfourdcg->SetDisplacementField(dvf);\n\n  // Read inverse DVF if provided\n  DVFSequenceImageType::Pointer idvf;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(idvf = itk::ReadImage<DVFSequenceImageType>(args_info.idvf_arg))\n  mcfourdcg->SetInverseDisplacementField(idvf);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mcfourdcg->Update())\n\n  // The mcfourdcg filter reconstructs a static 4D volume (if the DVFs perfectly model the actual motion)\n  // Warp this sequence with the inverse DVF so as to obtain a result similar to the classical 4D CG filter\n  auto warp =\n    rtk::WarpSequenceImageFilter<VolumeSeriesType, DVFSequenceImageType, ProjectionStackType, DVFImageType>::New();\n  warp->SetInput(mcfourdcg->GetOutput());\n  warp->SetDisplacementField(idvf);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(warp->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(warp->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkmotioncompensatedfourdconjugategradient/rtkmotioncompensatedfourdconjugategradient.ggo",
    "content": "purpose \"Performs a motion-compensated 4D reconstruction by the conjugate gradient method\"\n\noption \"verbose\"     v \"Verbose execution\"                                     flag   off\noption \"geometry\"    g \"XML geometry file name\"                                string yes\noption \"input\"       i \"Input volume\"                                          string no\noption \"output\"      o \"Output file name\"                                      string yes\noption \"niter\"       n \"Number of main loop iterations\"                        int    no   default=\"5\"\noption \"cudacg\"      - \"Perform conjugate gradient calculations on GPU\"        flag   off\noption \"nodisplaced\" - \"Disable the displaced detector filter\"                 flag   off\n\nsection \"Phase gating\"\noption \"signal\"    - \"File containing the phase of each projection\"              string                       yes\n\nsection \"Motion-compensation described in [ToBeWritten]\"\noption \"dvf\"       - \"Input 4D DVF\"                       string    no\noption \"idvf\"      - \"Input 4D inverse DVF. Inverse transform computed by conjugate gradient if not provided\"               string    no\n"
  },
  {
    "path": "applications/rtkorageometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtkorageometry_GGO_C rtkorageometry.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkorageometry rtkorageometry.cxx ${rtkorageometry_GGO_C})\ntarget_link_libraries(rtkorageometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkorageometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkorageometry/rtkorageometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkorageometry_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkOraGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkorageometry, args_info);\n\n  rtk::OraGeometryReader::MarginVectorType margin;\n  margin.Fill(args_info.margin_arg[0]);\n  for (unsigned int i = 0; i < std::min(args_info.margin_given, margin.GetVectorDimension()); i++)\n    margin[i] = args_info.margin_arg[i];\n\n  // Create geometry reader\n  auto oraReader = rtk::OraGeometryReader::New();\n  oraReader->SetProjectionsFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  oraReader->SetCollimationMargin(margin);\n  oraReader->SetOptiTrackObjectID(args_info.optitrack_arg);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(oraReader->UpdateOutputData())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(\n    const_cast<rtk::ThreeDCircularProjectionGeometry *>(oraReader->GetGeometry()), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkorageometry/rtkorageometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from a sequence of ora.xml files (radART / medPhoton file format).\"\n\noption \"verbose\"     v \"Verbose execution\"                           flag   off\noption \"output\"      o \"Output file name\"                            string yes\noption \"margin\"      m \"Collimation margin (uinf, usup, vinf, vsup)\" double no  multiple default=\"0.\"\noption \"optitrack\"   - \"OptiTrack object ID (unused by default)\"     int no default=\"-1\"\n\nsection \"Projections\"\noption \"path\"      p \"Path containing projections\"                             string yes\noption \"regexp\"    r \"Regular expression to select projection files in path\"   string yes\noption \"nsort\"     - \"Numeric sort for regular expression matches\"             flag   off\noption \"submatch\"  - \"Index of the submatch that will be used to sort matches\" int    no   default=\"0\"\n\n"
  },
  {
    "path": "applications/rtkorageometry/rtkorageometry.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Creates an RTK geometry file from a Varian OBI acquisition.\"\n    )\n\n    parser.add_argument(\"--verbose\", \"-v\", help=\"Verbose execution\", type=bool)\n    parser.add_argument(\n        \"--xml_file\", \"-x\", help=\"Varian OBI XML information file on projections\"\n    )\n    parser.add_argument(\"--output\", \"-o\", help=\"Output file name\", required=True)\n    parser.add_argument(\n        \"--path\", \"-p\", help=\"Path containing projections\", required=True\n    )\n    parser.add_argument(\n        \"--regexp\", \"-r\", help=\"Regular expression to select projection files in path\"\n    )\n    parser.add_argument(\n        \"--margin\",\n        \"-m\",\n        help=\"Collimation margin (uinf, usup, vinf, vsup)\",\n        type=float,\n        nargs=\"+\",\n        default=0.0,\n    )\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args: argparse.Namespace):\n\n    margin = args.margin\n    if type(margin) is float:\n        margin = [margin]\n    for i in range(len(margin), 4, 1):\n        margin.append(margin[0])\n    print(margin)\n\n    names = itk.RegularExpressionSeriesFileNames.New()\n    names.SetDirectory(args.path)\n    names.SetRegularExpression(args.regexp)\n\n    reader = rtk.OraGeometryReader.New()\n    reader.SetProjectionsFileNames(names.GetFileNames())\n    reader.SetCollimationMargin(margin)\n    reader.UpdateOutputData()\n\n    rtk.write_geometry(reader.GetGeometry(), args.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkosem/CMakeLists.txt",
    "content": "WRAP_GGO(rtkosem_GGO_C rtkosem.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkosem rtkosem.cxx ${rtkosem_GGO_C})\ntarget_link_libraries(rtkosem RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkosem)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkosem/rtkosem.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkosem_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkOSEMConeBeamReconstructionFilter.h\"\n#include \"rtkPhaseGatingImageFilter.h\"\n#include \"rtkIterationCommands.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkosem, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkosem>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<OutputImageType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<OutputImageType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkosem>(constantImageSource, args_info);\n    constantImageSource->SetConstant(1.);\n    inputFilter = constantImageSource;\n  }\n\n  // OSEM reconstruction filter\n  auto osem = rtk::OSEMConeBeamReconstructionFilter<OutputImageType>::New();\n\n  // Set the forward and back projection filters\n  SetForwardProjectionFromGgo(args_info, osem.GetPointer());\n  SetBackProjectionFromGgo(args_info, osem.GetPointer());\n  osem->SetInput(inputFilter->GetOutput());\n  osem->SetInput(1, reader->GetOutput());\n  osem->SetGeometry(geometry);\n  if (args_info.betaregularization_given)\n    osem->SetBetaRegularization(args_info.betaregularization_arg);\n\n  osem->SetNumberOfIterations(args_info.niterations_arg);\n  osem->SetNumberOfProjectionsPerSubset(args_info.nprojpersubset_arg);\n  osem->SetStoreNormalizationImages(!args_info.nostorenormalizationimages_flag);\n  REPORT_ITERATIONS(osem, rtk::OSEMConeBeamReconstructionFilter<OutputImageType>, OutputImageType)\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(osem->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkosem/rtkosem.ggo",
    "content": "purpose \"Reconstructs a 3D volume from a sequence of projections with Ordered subset expectation maximization.\"\n\noption \"verbose\"     v \"Verbose execution\"                                     flag   off\noption \"geometry\"    g \"XML geometry file name\"                                string yes\noption \"output\"      o \"Output file name\"                                      string yes\noption \"niterations\" n \"Number of iterations\"                                  int    no   default=\"5\"\noption \"input\"     i \"Input volume\"              string          no\noption \"nprojpersubset\" - \"Number of projections processed between each update of the reconstructed volume (several for OSEM, all for MLEM)\" int no default=\"1\"\noption \"betaregularization\" - \"Hyperparameter for the regularization\"          float  no   default=\"0\"\noption \"nostorenormalizationimages\"       - \"Do not store the normalization images during the reconstruction\"   flag   off\n"
  },
  {
    "path": "applications/rtkoverlayphaseandshroud/CMakeLists.txt",
    "content": "WRAP_GGO(rtkoverlayphaseandshroud_GGO_C rtkoverlayphaseandshroud.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkoverlayphaseandshroud rtkoverlayphaseandshroud.cxx ${rtkoverlayphaseandshroud_GGO_C})\ntarget_link_libraries(rtkoverlayphaseandshroud RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkoverlayphaseandshroud)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkoverlayphaseandshroud/rtkoverlayphaseandshroud.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkoverlayphaseandshroud_ggo.h\"\n#include \"rtkMacro.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n#include <itkCSVArray2DFileReader.h>\n#include <itkRGBPixel.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkNumericTraits.h>\n\n#include <fstream>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkoverlayphaseandshroud, args_info);\n\n  using RGBPixelType = itk::RGBPixel<unsigned char>;\n  constexpr unsigned int Dimension = 2;\n\n  using InputImageType = itk::Image<double, Dimension>;\n  using OutputImageType = itk::Image<RGBPixelType, Dimension>;\n\n  // Read\n  InputImageType::Pointer readImage;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readImage = itk::ReadImage<InputImageType>(args_info.input_arg))\n\n  // Read signal file\n  auto signalReader = itk::CSVArray2DFileReader<double>::New();\n  signalReader->SetFileName(args_info.signal_arg);\n  signalReader->SetFieldDelimiterCharacter(';');\n  signalReader->HasRowHeadersOff();\n  signalReader->HasColumnHeadersOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(signalReader->Update())\n  std::vector<double> signal = signalReader->GetArray2DDataObject()->GetColumn(0);\n\n  // Locate the minima in the signal\n  std::vector<bool> minima;\n  minima.push_back(false);\n  for (unsigned int i = 1; i < signal.size(); i++)\n  {\n    minima.push_back((signal[i] < signal[i - 1]));\n  }\n\n  // Create output RGB image\n  auto RGBout = OutputImageType::New();\n  RGBout->SetRegions(readImage->GetLargestPossibleRegion());\n  RGBout->Allocate();\n\n  // Compute min and max of shroud to scale output\n  itk::ImageRegionConstIterator<InputImageType>      itIn(readImage, readImage->GetLargestPossibleRegion());\n  itk::ImageRegionIteratorWithIndex<OutputImageType> itOut(RGBout, RGBout->GetLargestPossibleRegion());\n\n  double min = itk::NumericTraits<double>::max();\n  double max = -itk::NumericTraits<double>::max();\n  while (!itIn.IsAtEnd())\n  {\n    double currentPixel = itIn.Get();\n    if (currentPixel < min)\n      min = currentPixel;\n    if (currentPixel > max)\n      max = currentPixel;\n    ++itIn;\n  }\n\n  // Fill the output\n  itIn.GoToBegin();\n  itOut.GoToBegin();\n  while (!itOut.IsAtEnd())\n  {\n    RGBPixelType pix;\n\n    if (minima[itOut.GetIndex()[1]]) // If it is a minimum, draw a red pixel\n    {\n      pix.Fill(0);\n      pix.SetRed(255);\n    }\n    else // Otherwise, copy the input image, scaled to [0 - 255], in all channels\n    {\n      pix.Fill(floor((itIn.Get() - min) * 255.0 / (max - min)));\n    }\n\n    itOut.Set(pix);\n\n    ++itIn;\n    ++itOut;\n  }\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(RGBout, args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkoverlayphaseandshroud/rtkoverlayphaseandshroud.ggo",
    "content": "purpose \"Generates an RGB image showing the phase peaks on top of the shroud\"\n\noption \"verbose\"    v   \"Verbose execution\"                           flag                    off\noption \"input\"      i   \"Input shroud image file name\"\t\t            string                  yes\noption \"output\"     o   \"Output RGB image file name (.png, .jpg, ...)\"  string                  yes\noption \"signal\"     -   \"File containing the phase of each projection\"  string                       yes\n"
  },
  {
    "path": "applications/rtkprojectgeometricphantom/CMakeLists.txt",
    "content": "WRAP_GGO(rtkprojectgeometricphantom_GGO_C rtkprojectgeometricphantom.ggo ../rtk3Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkprojectgeometricphantom rtkprojectgeometricphantom.cxx ${rtkprojectgeometricphantom_GGO_C})\ntarget_link_libraries(rtkprojectgeometricphantom RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkprojectgeometricphantom)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkprojectgeometricphantom/rtkprojectgeometricphantom.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkprojectgeometricphantom_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkProjectGeometricPhantomImageFilter.h\"\n\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkprojectgeometricphantom, args_info);\n\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create a stack of empty projection images\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkprojectgeometricphantom>(constantImageSource,\n                                                                                                    args_info);\n\n  // Adjust size according to geometry\n  constantImageSource->SetSize(itk::MakeSize(\n    constantImageSource->GetSize()[0], constantImageSource->GetSize()[1], geometry->GetGantryAngles().size()));\n\n  using PPCType = rtk::ProjectGeometricPhantomImageFilter<OutputImageType, OutputImageType>;\n\n  // Offset, scale, rotation\n  PPCType::VectorType offset(0.);\n  if (args_info.offset_given)\n  {\n    if (args_info.offset_given > 3)\n    {\n      std::cerr << \"--offset needs up to 3 values\" << std::endl;\n      exit(EXIT_FAILURE);\n    }\n    offset[0] = args_info.offset_arg[0];\n    offset[1] = args_info.offset_arg[1];\n    offset[2] = args_info.offset_arg[2];\n  }\n  PPCType::VectorType scale;\n  scale.Fill(args_info.phantomscale_arg[0]);\n  if (args_info.phantomscale_given)\n  {\n    if (args_info.phantomscale_given > 3)\n    {\n      std::cerr << \"--phantomscale needs up to 3 values\" << std::endl;\n      exit(EXIT_FAILURE);\n    }\n    for (unsigned int i = 0; i < std::min(args_info.phantomscale_given, Dimension); i++)\n      scale[i] = args_info.phantomscale_arg[i];\n  }\n  PPCType::RotationMatrixType rot;\n  rot.SetIdentity();\n  if (args_info.rotation_given)\n  {\n    if (args_info.rotation_given != 9)\n    {\n      std::cerr << \"--rotation needs exactly 9 values\" << std::endl;\n      exit(EXIT_FAILURE);\n    }\n    for (unsigned int i = 0; i < Dimension; i++)\n      for (unsigned int j = 0; j < Dimension; j++)\n        rot[i][j] = args_info.rotation_arg[i * Dimension + j];\n  }\n\n  auto ppc = PPCType::New();\n  ppc->SetInput(constantImageSource->GetOutput());\n  ppc->SetGeometry(geometry);\n  ppc->SetPhantomScale(scale);\n  ppc->SetOriginOffset(offset);\n  ppc->SetRotationMatrix(rot);\n  ppc->SetConfigFile(args_info.phantomfile_arg);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(ppc->Update())\n\n  // Write\n  if (args_info.verbose_flag)\n    std::cout << \"Projecting and writing... \" << std::flush;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(ppc->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkprojectgeometricphantom/rtkprojectgeometricphantom.ggo",
    "content": "purpose \"Computes projections through a 3D phantom described by a file, according to a geometry\"\n\noption \"verbose\"      v \"Verbose execution\"                         flag            off\noption \"geometry\"     g  \"XML geometry file name\"                   string          yes\noption \"output\"       o \"Output projections file name\"              string          yes\noption \"phantomfile\"  - \"Configuration parameteres for the phantom\" string          yes\noption \"phantomscale\" - \"Scaling factor for the phantom dimensions\" double multiple no default=\"1.\"\noption \"offset\"       - \"3D spatial offset of the phantom center\"   double multiple no\noption \"rotation\"     - \"Rotation matrix for the phantom\"           double multiple no\n\n"
  },
  {
    "path": "applications/rtkprojectgeometricphantom/rtkprojectgeometricphantom.py",
    "content": "import argparse\nimport sys\nimport itk\nfrom itk import RTK as rtk\nimport numpy as np\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Computes projections through a 3D phantom described by a file, according to a geometry\"\n    )\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--geometry\", \"-g\", help=\"XML geometry file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output projections file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--phantomfile\",\n        help=\"Configuration parameters for the phantom\",\n        type=str,\n        required=True,\n    )\n    parser.add_argument(\n        \"--phantomscale\",\n        help=\"Scaling factor for the phantom dimensions\",\n        type=float,\n        nargs=\"+\",\n        default=[1.0],\n    )\n    parser.add_argument(\n        \"--offset\",\n        help=\"3D spatial offset of the phantom center\",\n        type=float,\n        nargs=\"+\",\n    )\n    parser.add_argument(\n        \"--rotation\",\n        help=\"Rotation matrix for the phantom\",\n        type=float,\n        nargs=\"+\",\n    )\n\n    rtk.add_rtk3Doutputimage_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Geometry\n    if args_info.verbose:\n        print(f\"Reading geometry information from {args_info.geometry}...\")\n    geometry = rtk.read_geometry(args_info.geometry)\n\n    # Create a stack of empty projection images\n    constantImageSource = rtk.ConstantImageSource[OutputImageType].New()\n    rtk.SetConstantImageSourceFromArgParse(constantImageSource, args_info)\n\n    # Adjust size according to geometry\n    sizeOutput = constantImageSource.GetSize()\n    sizeOutput[2] = len(geometry.GetGantryAngles())\n    constantImageSource.SetSize(sizeOutput)\n\n    # Create SheppLogan Phantom\n    offset = [0] * Dimension\n    if args_info.offset is not None:\n        if len(args_info.offset) > 3:\n            print(\"--offset needs up to 3 values\")\n            sys.exit(1)\n        for i in range(len(args_info.offset)):\n            offset[i] = args_info.offset[i]\n\n    scale = [args_info.phantomscale[0]] * 3\n    if len(args_info.phantomscale) > 3:\n        print(\"--phantomscale needs up to 3 values\")\n        sys.exit(1)\n    for i in range(len(args_info.phantomscale)):\n        scale[i] = args_info.phantomscale[i]\n\n    rot = itk.Matrix[itk.D, Dimension, Dimension]()\n    rot.SetIdentity()\n\n    if args_info.rotation is not None:\n        if len(args_info.rotation) != 9:\n            print(\"--rotation needs exactly 9 values\")\n            sys.exit(1)\n        rot = itk.matrix_from_array(np.array(args_info.rotation).reshape(3, 3))\n\n    ppc = rtk.ProjectGeometricPhantomImageFilter[OutputImageType, OutputImageType].New()\n    ppc.SetInput(constantImageSource.GetOutput())\n    ppc.SetGeometry(geometry)\n    ppc.SetPhantomScale(scale)\n    ppc.SetOriginOffset(offset)\n    ppc.SetRotationMatrix(rot)\n    ppc.SetConfigFile(args_info.phantomfile)\n    ppc.Update()\n\n    # Write\n    if args_info.verbose:\n        print(\"Projecting and writing... \")\n\n    itk.imwrite(ppc.GetOutput(), args_info.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkprojectionmatrix/CMakeLists.txt",
    "content": "WRAP_GGO(rtkprojectionmatrix_GGO_C rtkprojectionmatrix.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkprojectionmatrix rtkprojectionmatrix.cxx ${rtkprojectionmatrix_GGO_C})\ntarget_link_libraries(rtkprojectionmatrix RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkprojectionmatrix)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkprojectionmatrix/rtkMatlabSparseMatrix.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMatlabSparseMatrix_h\n#define rtkMatlabSparseMatrix_h\n\n#include <vnl/vnl_sparse_matrix.h>\n\nnamespace rtk\n{\n/** \\class MatlabSparseMatrix\n *\n * sparse matrix in Matlab format\n * Initilaize it with vnl_sparse_matrix\n * Save it into .mat format\n *\n */\n\nclass MatlabSparseMatrix\n{\npublic:\n  template <class TOutputImage>\n  MatlabSparseMatrix(const vnl_sparse_matrix<double> & sparseMatrix, TOutputImage * output);\n  void\n  Save(std::ostream & out);\n  void\n  Print();\n\n  struct MatlabSparseMatrixStruct\n  {\n    unsigned char       s_headerMatlab[116];\n    unsigned char       s_headerOffset[8];\n    unsigned short int  s_headerVersion;\n    unsigned char       s_headerEndian[2];\n    unsigned long int   s_mainTag;\n    unsigned long int   s_dataLength;\n    unsigned long int   s_arrayTag;\n    unsigned long int   s_arrayLength;\n    unsigned short int  s_arrayUndefined;\n    unsigned char       s_arrayFlags;\n    unsigned char       s_arrayClass;\n    unsigned long int   s_arrayNzmax;\n    unsigned long int   s_dimensionTag;\n    unsigned long int   s_dimensionLength;\n    unsigned long int   s_dimensionNbRow;\n    unsigned long int   s_dimensionNbColumn;\n    unsigned short int  s_nameLength;\n    unsigned short int  s_nameTag;\n    unsigned char       s_nameChar;\n    unsigned char       s_namePadding[3];\n    unsigned long int   s_rowIndexTag;\n    unsigned long int   s_rowIndexLength;\n    unsigned long int * s_rowIndex;\n    unsigned long int   s_rowIndexPadding;\n    unsigned long int   s_columnIndexTag;\n    unsigned long int   s_columnIndexLength;\n    unsigned long int * s_columnIndex;\n    unsigned long int   s_columnIndexPadding;\n    unsigned long int   s_valueTag;\n    unsigned long int   s_valueLength;\n    double *            s_value;\n  };\n\nprotected:\n  MatlabSparseMatrixStruct m_MatlabSparseMatrix;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkMatlabSparseMatrix.hxx\"\n#endif\n\n#endif"
  },
  {
    "path": "applications/rtkprojectionmatrix/rtkMatlabSparseMatrix.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include <fstream>\n#include <iostream>\n\n//====================================================================\ntemplate <class TOutputImage>\nrtk::MatlabSparseMatrix::MatlabSparseMatrix(const vnl_sparse_matrix<double> & sparseMatrix, TOutputImage * output)\n{\n  unsigned int nbColumn = output->GetLargestPossibleRegion().GetSize()[0] *\n                          output->GetLargestPossibleRegion().GetSize()[2]; // it's not sparseMatrix.columns()\n\n  // Take the number of non-zero elements:\n  // Compute the column index\n  // Store elements in std::vector and sort them according 1\\ index of column and 2\\ index of row\n  unsigned int nonZeroElement(0);\n  using sparseMatrixColumn = std::vector<std::pair<unsigned int, double>>;\n  auto * columnsVector = new sparseMatrixColumn[nbColumn];\n  sparseMatrix.reset();\n  while (sparseMatrix.next())\n  {\n    typename TOutputImage::IndexType idx = output->ComputeIndex(sparseMatrix.getcolumn());\n    if (idx[1] != 1)\n      continue;\n    unsigned int indexColumn = idx[0] + idx[2] * output->GetLargestPossibleRegion().GetSize()[2];\n    auto         it = columnsVector[indexColumn].begin();\n    while (it != columnsVector[indexColumn].end())\n    {\n      if ((unsigned int)sparseMatrix.getrow() < it->first)\n        break;\n      ++it;\n    }\n    columnsVector[indexColumn].insert(it, std::make_pair(sparseMatrix.getrow(), sparseMatrix.value()));\n    ++nonZeroElement;\n  }\n\n  // Store the sparse matrix into a matlab structure\n  std::string headerMatlab(\"MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Fri May 18 14:11:56 2018               \"\n                           \"                        \");\n  for (unsigned int i = 0; i < 116; ++i)\n    m_MatlabSparseMatrix.s_headerMatlab[i] = headerMatlab[i];\n  for (unsigned char & i : m_MatlabSparseMatrix.s_headerOffset)\n    i = 0;\n  m_MatlabSparseMatrix.s_headerVersion = 0x0100;\n  m_MatlabSparseMatrix.s_headerEndian[0] = 'I';\n  m_MatlabSparseMatrix.s_headerEndian[1] = 'M';\n  m_MatlabSparseMatrix.s_mainTag = 14;\n  m_MatlabSparseMatrix.s_arrayTag = 6;\n  m_MatlabSparseMatrix.s_arrayLength = 8;\n  m_MatlabSparseMatrix.s_arrayFlags = 5;\n  m_MatlabSparseMatrix.s_arrayClass = 16;\n  m_MatlabSparseMatrix.s_arrayUndefined = 0;\n  m_MatlabSparseMatrix.s_arrayNzmax = nonZeroElement;\n  m_MatlabSparseMatrix.s_dimensionTag = 5;\n  m_MatlabSparseMatrix.s_dimensionLength = 8;\n  m_MatlabSparseMatrix.s_dimensionNbRow = sparseMatrix.rows();\n  m_MatlabSparseMatrix.s_dimensionNbColumn = nbColumn;\n  m_MatlabSparseMatrix.s_nameLength = 1;\n  m_MatlabSparseMatrix.s_nameTag = 1;\n  m_MatlabSparseMatrix.s_nameChar = 'A';\n  for (unsigned char & i : m_MatlabSparseMatrix.s_namePadding)\n    i = 0;\n  m_MatlabSparseMatrix.s_dataLength = 64 + nonZeroElement * 8 + 4 * m_MatlabSparseMatrix.s_arrayNzmax +\n                                      4 * (m_MatlabSparseMatrix.s_dimensionNbColumn + 1);\n  if (m_MatlabSparseMatrix.s_arrayNzmax * 4 % 8 != 0)\n    m_MatlabSparseMatrix.s_dataLength += 4;\n  if ((m_MatlabSparseMatrix.s_dimensionNbColumn + 1) * 4 % 8 != 0)\n    m_MatlabSparseMatrix.s_dataLength += 4;\n  m_MatlabSparseMatrix.s_rowIndexTag = 5;\n  m_MatlabSparseMatrix.s_rowIndexLength = 4 * m_MatlabSparseMatrix.s_arrayNzmax; // put it in hexa\n  m_MatlabSparseMatrix.s_rowIndex = new unsigned long int[m_MatlabSparseMatrix.s_arrayNzmax];\n  m_MatlabSparseMatrix.s_rowIndexPadding = 0;\n  m_MatlabSparseMatrix.s_columnIndexTag = 5;\n  m_MatlabSparseMatrix.s_columnIndexLength = 4 * (m_MatlabSparseMatrix.s_dimensionNbColumn + 1);\n  m_MatlabSparseMatrix.s_columnIndex = new unsigned long int[m_MatlabSparseMatrix.s_dimensionNbColumn + 1];\n  m_MatlabSparseMatrix.s_columnIndexPadding = 0;\n  m_MatlabSparseMatrix.s_valueTag = 9;\n  m_MatlabSparseMatrix.s_valueLength = 8 * m_MatlabSparseMatrix.s_arrayNzmax;\n  m_MatlabSparseMatrix.s_value = new double[m_MatlabSparseMatrix.s_arrayNzmax];\n  // Copy data\n  unsigned int elementIndex(0);\n  for (unsigned int i = 0; i < m_MatlabSparseMatrix.s_dimensionNbColumn; ++i)\n  {\n    m_MatlabSparseMatrix.s_columnIndex[i] = elementIndex;\n    for (const auto & it : columnsVector[i])\n    {\n      m_MatlabSparseMatrix.s_rowIndex[elementIndex] = it.first;\n      m_MatlabSparseMatrix.s_value[elementIndex] = it.second;\n      ++elementIndex;\n    }\n  }\n  m_MatlabSparseMatrix.s_columnIndex[m_MatlabSparseMatrix.s_dimensionNbColumn] = m_MatlabSparseMatrix.s_arrayNzmax;\n}\n\nvoid\nrtk::MatlabSparseMatrix::Save(std::ostream & out)\n{\n  // Write data\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_headerMatlab), 116);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_headerOffset), 8);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_headerVersion), 2);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_headerEndian), 2);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_mainTag), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_dataLength), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_arrayTag), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_arrayLength), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_arrayFlags), 1);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_arrayClass), 1);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_arrayUndefined), 2);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_arrayNzmax), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_dimensionTag), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_dimensionLength), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_dimensionNbRow), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_dimensionNbColumn), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_nameLength), 2);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_nameTag), 2);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_nameChar), 1);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_namePadding), 3);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_rowIndexTag), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_rowIndexLength), 4);\n  for (unsigned int i = 0; i < m_MatlabSparseMatrix.s_arrayNzmax; ++i)\n    out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_rowIndex[i]), 4);\n  if (m_MatlabSparseMatrix.s_arrayNzmax * 4 % 8 != 0)\n    out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_rowIndexPadding), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_columnIndexTag), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_columnIndexLength), 4);\n  for (unsigned int i = 0; i < m_MatlabSparseMatrix.s_dimensionNbColumn + 1; ++i)\n    out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_columnIndex[i]), 4);\n  if ((m_MatlabSparseMatrix.s_dimensionNbColumn + 1) * 4 % 8 != 0)\n    out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_columnIndexPadding), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_valueTag), 4);\n  out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_valueLength), 4);\n  for (unsigned int i = 0; i < m_MatlabSparseMatrix.s_arrayNzmax; ++i)\n    out.write(reinterpret_cast<const char *>(&m_MatlabSparseMatrix.s_value[i]), 8);\n}\n\nvoid\nrtk::MatlabSparseMatrix::Print()\n{\n  std::cout << \"m_MatlabSparseMatrix.s_headerMatlab : \\\"\" << m_MatlabSparseMatrix.s_headerMatlab << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_headerOffset : \\\"\" << m_MatlabSparseMatrix.s_headerOffset << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_headerVersion : \\\"\" << std::hex << +m_MatlabSparseMatrix.s_headerVersion << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_headerEndian : \\\"\" << m_MatlabSparseMatrix.s_headerEndian << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_mainTag : \\\"\" << m_MatlabSparseMatrix.s_mainTag << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_dataLength : \\\"\" << m_MatlabSparseMatrix.s_dataLength << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayTag : \\\"\" << m_MatlabSparseMatrix.s_arrayTag << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayLength : \\\"\" << m_MatlabSparseMatrix.s_arrayLength << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayFlags : \\\"\" << (unsigned int)m_MatlabSparseMatrix.s_arrayFlags << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayClass : \\\"\" << (unsigned int)m_MatlabSparseMatrix.s_arrayClass << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayUndefined : \\\"\" << m_MatlabSparseMatrix.s_arrayUndefined << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayNzmax : \\\"\" << m_MatlabSparseMatrix.s_arrayNzmax << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_dimensionTag : \\\"\" << m_MatlabSparseMatrix.s_dimensionTag << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_dimensionLength : \\\"\" << m_MatlabSparseMatrix.s_dimensionLength << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_dimensionNbRow : \\\"\" << m_MatlabSparseMatrix.s_dimensionNbRow << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_dimensionNbColumn : \\\"\" << m_MatlabSparseMatrix.s_dimensionNbColumn << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_nameLength : \\\"\" << m_MatlabSparseMatrix.s_nameLength << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_nameTag : \\\"\" << m_MatlabSparseMatrix.s_nameTag << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_nameChar : \\\"\" << m_MatlabSparseMatrix.s_nameChar << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_namePadding : \\\"\" << m_MatlabSparseMatrix.s_namePadding << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_rowIndexTag : \\\"\" << m_MatlabSparseMatrix.s_rowIndexTag << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_rowIndexLength : \\\"\" << m_MatlabSparseMatrix.s_rowIndexLength << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_rowIndex : \\\"\";\n  for (unsigned int i = 0; i < m_MatlabSparseMatrix.s_arrayNzmax; ++i)\n    std::cout << m_MatlabSparseMatrix.s_rowIndex[i] << \" \";\n  std::cout << \"\\\"\" << std::endl;\n  if (m_MatlabSparseMatrix.s_arrayNzmax * 4 % 8 != 0)\n    std::cout << \"m_MatlabSparseMatrix.s_rowIndexPadding : \\\"\" << m_MatlabSparseMatrix.s_rowIndexPadding << \"\\\"\"\n              << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_columnIndexTag : \\\"\" << m_MatlabSparseMatrix.s_columnIndexTag << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_columnIndexLength : \\\"\" << m_MatlabSparseMatrix.s_columnIndexLength << \"\\\"\"\n            << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_columnIndex : \\\"\";\n  for (unsigned int i = 0; i < m_MatlabSparseMatrix.s_dimensionNbColumn + 1; ++i)\n    std::cout << m_MatlabSparseMatrix.s_columnIndex[i] << \" \";\n  std::cout << \"\\\"\" << std::endl;\n  if ((m_MatlabSparseMatrix.s_dimensionNbColumn + 1) * 4 % 8 != 0)\n    std::cout << \"m_MatlabSparseMatrix.s_columnIndexPadding : \\\"\" << m_MatlabSparseMatrix.s_columnIndexPadding << \"\\\"\"\n              << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_valueTag : \\\"\" << m_MatlabSparseMatrix.s_valueTag << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_valueLength : \\\"\" << m_MatlabSparseMatrix.s_valueLength << \"\\\"\" << std::endl;\n  std::cout << \"m_MatlabSparseMatrix.s_value : \\\"\";\n  for (unsigned int i = 0; i < m_MatlabSparseMatrix.s_arrayNzmax; ++i)\n    std::cout << m_MatlabSparseMatrix.s_value[i] << \" \";\n  std::cout << \"\\\"\" << std::endl;\n}\n\n/*\nstd::istream& operator>>(std::istream& in) {\n  char temp1(0);\n  unsigned short int temp2(0);\n  unsigned long int temp4(0);\n  double temp8(0);\n\n  //header\n  for (unsigned int i=0; i<116; ++i) {\n    in.read(reinterpret_cast<char*>(&temp1),1);\n    m_MatlabSparseMatrix.s_headerMatlab[i] = temp1;\n  }\n  std::cout << \"m_MatlabSparseMatrix.s_headerMatlab : \\\"\" << m_MatlabSparseMatrix.s_headerMatlab << \"\\\"\" << std::endl;\n  for (unsigned int i=0; i<8; ++i) {\n    in.read(reinterpret_cast<char*>(&temp1),1);\n    m_MatlabSparseMatrix.s_headerOffset[i] = temp1;\n  }\n  std::cout << \"m_MatlabSparseMatrix.s_headerOffset : \\\"\" << m_MatlabSparseMatrix.s_headerOffset << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp2), 2);\n  m_MatlabSparseMatrix.s_headerVersion = temp2;\n  std::cout << \"m_MatlabSparseMatrix.s_headerVersion : \\\"\" << std::hex << +m_MatlabSparseMatrix.s_headerVersion << \"\\\"\"\n<< std::endl; for (unsigned int i=0; i<2; ++i) { in.read(reinterpret_cast<char*>(&temp1),1);\n    m_MatlabSparseMatrix.s_headerEndian[i] = temp1;\n  }\n  std::cout << \"m_MatlabSparseMatrix.s_headerEndian : \\\"\" << m_MatlabSparseMatrix.s_headerEndian << \"\\\"\" << std::endl;\n  //data\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_mainTag = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_mainTag : \\\"\" << m_MatlabSparseMatrix.s_mainTag << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_dataLength = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_dataLength : \\\"\" << m_MatlabSparseMatrix.s_dataLength << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_arrayTag = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayTag : \\\"\" << m_MatlabSparseMatrix.s_arrayTag << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_arrayLength = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayLength : \\\"\" << m_MatlabSparseMatrix.s_arrayLength << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp1), 1);\n  m_MatlabSparseMatrix.s_arrayFlags = temp1;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayFlags : \\\"\" << (unsigned int)m_MatlabSparseMatrix.s_arrayFlags << \"\\\"\" <<\nstd::endl; in.read(reinterpret_cast<char*>(&temp1),1); m_MatlabSparseMatrix.s_arrayClass = temp1; std::cout <<\n\"m_MatlabSparseMatrix.s_arrayClass : \\\"\" << (unsigned int)m_MatlabSparseMatrix.s_arrayClass << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp2), 2);\n  m_MatlabSparseMatrix.s_arrayUndefined = temp2;\n  std::cout << \"m_MatlabSparseMatrix.s_arrayUndefined : \\\"\" << m_MatlabSparseMatrix.s_arrayUndefined << \"\\\"\" <<\nstd::endl; in.read(reinterpret_cast<char*>(&temp4), 4); m_MatlabSparseMatrix.s_arrayNzmax = temp4; std::cout <<\n\"m_MatlabSparseMatrix.s_arrayNzmax : \\\"\" << m_MatlabSparseMatrix.s_arrayNzmax << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_dimensionTag = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_dimensionTag : \\\"\" << m_MatlabSparseMatrix.s_dimensionTag << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_dimensionLength = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_dimensionLength : \\\"\" << m_MatlabSparseMatrix.s_dimensionLength << \"\\\"\" <<\nstd::endl; in.read(reinterpret_cast<char*>(&temp4), 4); m_MatlabSparseMatrix.s_dimensionNbRow = temp4; std::cout <<\n\"m_MatlabSparseMatrix.s_dimensionNbRow : \\\"\" << m_MatlabSparseMatrix.s_dimensionNbRow << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_dimensionNbColumn = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_dimensionNbColumn : \\\"\" << m_MatlabSparseMatrix.s_dimensionNbColumn << \"\\\"\" <<\nstd::endl; in.read(reinterpret_cast<char*>(&temp2), 2); m_MatlabSparseMatrix.s_nameLength = temp2; std::cout <<\n\"m_MatlabSparseMatrix.s_nameLength : \\\"\" << m_MatlabSparseMatrix.s_nameLength << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp2), 2);\n  m_MatlabSparseMatrix.s_nameTag = temp2;\n  std::cout << \"m_MatlabSparseMatrix.s_nameTag : \\\"\" << m_MatlabSparseMatrix.s_nameTag << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp1),1);\n  m_MatlabSparseMatrix.s_nameChar = temp1;\n  std::cout << \"m_MatlabSparseMatrix.s_nameChar : \\\"\" << m_MatlabSparseMatrix.s_nameChar << \"\\\"\" << std::endl;\n  for (unsigned int i=0; i<3; ++i) {\n    in.read(reinterpret_cast<char*>(&temp1),1);\n    m_MatlabSparseMatrix.s_namePadding[i] = temp1;\n  }\n  std::cout << \"m_MatlabSparseMatrix.s_namePadding : \\\"\" << m_MatlabSparseMatrix.s_namePadding << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_rowIndexTag = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_rowIndexTag : \\\"\" << m_MatlabSparseMatrix.s_rowIndexTag << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_rowIndexLength = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_rowIndexLength : \\\"\" << m_MatlabSparseMatrix.s_rowIndexLength << \"\\\"\" <<\nstd::endl; m_MatlabSparseMatrix.s_rowIndex = new unsigned long int[m_MatlabSparseMatrix.s_arrayNzmax]; std::cout <<\n\"m_MatlabSparseMatrix.s_rowIndex : \\\"\"; for (unsigned int i=0; i<m_MatlabSparseMatrix.s_arrayNzmax; ++i) {\n    in.read(reinterpret_cast<char*>(&temp4),4);\n    m_MatlabSparseMatrix.s_rowIndex[i] = temp4;\n    std::cout << m_MatlabSparseMatrix.s_rowIndex[i] << \" \";\n  }\n  std::cout << \"\\\"\" << std::endl;\n  if (m_MatlabSparseMatrix.s_arrayNzmax*4%8 != 0) {\n    in.read(reinterpret_cast<char*>(&temp4), 4);\n    m_MatlabSparseMatrix.s_rowIndexPadding = temp4;\n    std::cout << \"m_MatlabSparseMatrix.s_rowIndexPadding : \\\"\" << m_MatlabSparseMatrix.s_rowIndexPadding << \"\\\"\" <<\nstd::endl;\n  }\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_columnIndexTag = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_columnIndexTag : \\\"\" << m_MatlabSparseMatrix.s_columnIndexTag << \"\\\"\" <<\nstd::endl; in.read(reinterpret_cast<char*>(&temp4), 4); m_MatlabSparseMatrix.s_columnIndexLength = temp4; std::cout <<\n\"m_MatlabSparseMatrix.s_columnIndexLength : \\\"\" << m_MatlabSparseMatrix.s_columnIndexLength << \"\\\"\" << std::endl;\n  m_MatlabSparseMatrix.s_columnIndex = new unsigned long int[m_MatlabSparseMatrix.s_dimensionNbColumn+1];\n  std::cout << \"m_MatlabSparseMatrix.s_columnIndex : \\\"\";\n  for (unsigned int i=0; i<m_MatlabSparseMatrix.s_dimensionNbColumn+1; ++i) {\n    in.read(reinterpret_cast<char*>(&temp4),4);\n    m_MatlabSparseMatrix.s_columnIndex[i] = temp4;\n    std::cout << m_MatlabSparseMatrix.s_columnIndex[i] << \" \";\n  }\n  std::cout << \"\\\"\" << std::endl;\n  if ((m_MatlabSparseMatrix.s_dimensionNbColumn+1)*4%8 != 0) {\n    in.read(reinterpret_cast<char*>(&temp4), 4);\n    m_MatlabSparseMatrix.s_columnIndexPadding = temp4;\n    std::cout << \"m_MatlabSparseMatrix.s_columnIndexPadding : \\\"\" << m_MatlabSparseMatrix.s_columnIndexPadding << \"\\\"\"\n<< std::endl;\n  }\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_valueTag = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_valueTag : \\\"\" << m_MatlabSparseMatrix.s_valueTag << \"\\\"\" << std::endl;\n  in.read(reinterpret_cast<char*>(&temp4), 4);\n  m_MatlabSparseMatrix.s_valueLength = temp4;\n  std::cout << \"m_MatlabSparseMatrix.s_valueLength : \\\"\" << m_MatlabSparseMatrix.s_valueLength << \"\\\"\" << std::endl;\n  m_MatlabSparseMatrix.s_value = new double[m_MatlabSparseMatrix.s_arrayNzmax];\n  std::cout << \"m_MatlabSparseMatrix.s_value : \\\"\";\n  for (unsigned int i=0; i<m_MatlabSparseMatrix.s_arrayNzmax; ++i) {\n    in.read(reinterpret_cast<char*>(&temp8),8);\n    m_MatlabSparseMatrix.s_value[i] = temp8;\n    std::cout << m_MatlabSparseMatrix.s_value[i] << \" \";\n  }\n  std::cout << \"\\\"\" << std::endl;\n\n  return in;\n}\n*/\n"
  },
  {
    "path": "applications/rtkprojectionmatrix/rtkprojectionmatrix.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include <vnl/vnl_sparse_matrix.h>\n#include <fstream>\n\n#include \"rtkprojectionmatrix_ggo.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkJosephBackProjectionImageFilter.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMatlabSparseMatrix.h\"\n\nnamespace rtk\n{\nnamespace Functor\n{\ntemplate <class TInput, class TCoordinateType, class TOutput = TCoordinateType>\nclass StoreSparseMatrixSplatWeightMultiplication\n{\npublic:\n  StoreSparseMatrixSplatWeightMultiplication() = default;\n  ~StoreSparseMatrixSplatWeightMultiplication() = default;\n\n  bool\n  operator!=(const StoreSparseMatrixSplatWeightMultiplication &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const StoreSparseMatrixSplatWeightMultiplication & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const TInput &        rayValue,\n             TOutput &             output,\n             const double          stepLengthInVoxel,\n             const double          voxelSize,\n             const TCoordinateType weight)\n  {\n    // One row of the matrix is one ray, it should be thread safe\n    m_SystemMatrix.put(\n      &rayValue - m_ProjectionsBuffer, &output - m_VolumeBuffer, weight * voxelSize * stepLengthInVoxel);\n  }\n  vnl_sparse_matrix<double> &\n  GetVnlSparseMatrix()\n  {\n    return m_SystemMatrix;\n  }\n  void\n  SetProjectionsBuffer(TInput * pb)\n  {\n    m_ProjectionsBuffer = pb;\n  }\n  void\n  SetVolumeBuffer(TOutput * vb)\n  {\n    m_VolumeBuffer = vb;\n  }\n\nprivate:\n  vnl_sparse_matrix<double> m_SystemMatrix;\n  TInput *                  m_ProjectionsBuffer;\n  TOutput *                 m_VolumeBuffer;\n};\n} // namespace Functor\n} // namespace rtk\n\nstd::ostream &\noperator<<(std::ostream & out, rtk::MatlabSparseMatrix & matlabSparseMatrix)\n{\n  matlabSparseMatrix.Save(out);\n  return out;\n}\n\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkprojectionmatrix, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkprojectionmatrix>(reader, args_info);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update())\n\n  // Create back projection image filter\n  if (reader->GetOutput()->GetLargestPossibleRegion().GetSize()[1] != 1)\n  {\n    std::cerr << \"This tool has been designed for 2D, i.e., with one row in the sinogram only.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n  const OutputImageType::DirectionType dir = reader->GetOutput()->GetDirection();\n  if (itk::Math::abs(dir[0][0]) != 1. || itk::Math::abs(dir[1][1]) != 1.)\n  {\n    std::cerr << \"Projections with non-diagonal Direction is not handled.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n  if (args_info.verbose_flag)\n    std::cout << \" done.\" << std::endl;\n\n  // Create reconstructed image\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkprojectionmatrix>(constantImageSource,\n                                                                                             args_info);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantImageSource->Update())\n  if (constantImageSource->GetOutput()->GetLargestPossibleRegion().GetSize()[1] != 3)\n  {\n    std::cerr << \"This tool has been designed for 2D with Joseph project. \"\n              << \"Joseph requires at least 2 slices in the y direction for bilinear interpolation. \"\n              << \"To have one slice exactly in front of the row, use 3 slices in the volume \"\n              << \"with the central slice in front of the single projection row.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n  if (!constantImageSource->GetOutput()->GetDirection().GetVnlMatrix().is_identity())\n  {\n    std::cerr << \"Volume with non-identity Direction is not handled.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Adjust size according to geometry\n  if (reader->GetOutput()->GetLargestPossibleRegion().GetSize()[2] != geometry->GetGantryAngles().size())\n  {\n    std::cerr << \"Number of projections in the geometry and in the stack do not match.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Create back projection image filter\n  if (args_info.verbose_flag)\n    std::cout << \"Backprojecting volume and recording matrix values...\" << std::endl;\n\n  auto backProjection = rtk::JosephBackProjectionImageFilter<\n    OutputImageType,\n    OutputImageType,\n    rtk::Functor::InterpolationWeightMultiplicationBackProjection<OutputPixelType, OutputPixelType>,\n    rtk::Functor::StoreSparseMatrixSplatWeightMultiplication<OutputPixelType, double, OutputPixelType>>::New();\n  backProjection->SetInput(constantImageSource->GetOutput());\n  backProjection->SetInput(1, reader->GetOutput());\n  backProjection->SetGeometry(geometry);\n  backProjection->GetSplatWeightMultiplication().SetProjectionsBuffer(reader->GetOutput()->GetBufferPointer());\n  backProjection->GetSplatWeightMultiplication().SetVolumeBuffer(constantImageSource->GetOutput()->GetBufferPointer());\n  backProjection->GetSplatWeightMultiplication().GetVnlSparseMatrix().resize(\n    reader->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels(),\n    constantImageSource->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(backProjection->Update())\n\n  // Write matrix to disk\n  if (args_info.verbose_flag)\n    std::cout << \"Writing matrix to disk...\" << std::endl;\n  std::ofstream ofs(args_info.output_arg, std::ofstream::binary);\n  if (!ofs)\n  {\n    std::cerr << \"Failed to open \" << args_info.output_arg << std::endl;\n    return EXIT_FAILURE;\n  }\n  rtk::MatlabSparseMatrix matlabSparseMatrix(backProjection->GetSplatWeightMultiplication().GetVnlSparseMatrix(),\n                                             backProjection->GetOutput());\n  ofs << matlabSparseMatrix;\n  ofs.close();\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkprojectionmatrix/rtkprojectionmatrix.ggo",
    "content": "purpose \"Saves the sparse system matrix of rtk::JosephForwardProjectionImageFilter in a file. Only works in 2D.\"\n\noption \"verbose\"   v \"Verbose execution\"                                     flag   off\noption \"geometry\"  g  \"XML geometry file name\"                               string yes\noption \"output\"    o \"Output file name for the sparse matrix\"                string yes\n\n"
  },
  {
    "path": "applications/rtkprojections/CMakeLists.txt",
    "content": "WRAP_GGO(rtkprojections_GGO_C rtkprojections.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkprojections rtkprojections.cxx ${rtkprojections_GGO_C})\ntarget_link_libraries(rtkprojections RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkprojections)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkprojections/rtkprojections.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkprojections_ggo.h\"\n#include \"rtkMacro.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkprojections, args_info);\n\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkprojections>(reader, args_info);\n\n  // Write\n  auto writer = itk::ImageFileWriter<OutputImageType>::New();\n  writer->SetFileName(args_info.output_arg);\n  writer->SetInput(reader->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(writer->UpdateOutputInformation())\n  writer->SetNumberOfStreamDivisions(1 + reader->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() /\n                                           (1024 * 1024 * 4));\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(writer->Update())\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkprojections/rtkprojections.ggo",
    "content": "purpose \"Reads raw projection images, converts them to attenuation and stacks them into a single output image file\"\n\noption \"verbose\"  v \"Verbose execution\"                                         flag      off\noption \"output\"   o \"Output file name\"                                          string    yes\n\n"
  },
  {
    "path": "applications/rtkprojections/rtkprojections.py",
    "content": "import argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\"Reads raw projection images, converts them to attenuation and stacks them into a single output image file\"\n    )\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output file name\", type=str, required=True\n    )\n    rtk.add_rtkinputprojections_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Projections reader\n    reader = rtk.ProjectionsReader[OutputImageType].New()\n    rtk.SetProjectionsReaderFromArgParse(reader, args_info)\n    if args_info.verbose:\n        print(f\"Reading projections...\")\n\n    # Write\n    writer = itk.ImageFileWriter[OutputImageType].New()\n    writer.SetFileName(args_info.output)\n    writer.SetInput(reader.GetOutput())\n    if args_info.verbose:\n        print(f\"Writing output to: {args_info.output}\")\n    writer.Update()\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkprojectors_group.py",
    "content": "__all__ = [\n    \"add_rtkprojectors_group\",\n    \"SetForwardProjectionFromArgParse\",\n    \"SetBackProjectionFromArgParse\",\n]\n\n\n# Mimicks rtkprojectors_section.ggo\ndef add_rtkprojectors_group(parser):\n    rtkprojectors_group = parser.add_argument_group(\"Projectors\")\n    rtkprojectors_group.add_argument(\n        \"--fp\",\n        \"-f\",\n        help=\"Forward projection method\",\n        choices=[\"Joseph\", \"CudaRayCast\", \"JosephAttenuated\", \"Zeng\"],\n        default=\"Joseph\",\n    )\n    rtkprojectors_group.add_argument(\n        \"--bp\",\n        \"-b\",\n        help=\"Back projection method\",\n        choices=[\n            \"VoxelBasedBackProjection\",\n            \"Joseph\",\n            \"CudaVoxelBased\",\n            \"CudaRayCast\",\n            \"JosephAttenuated\",\n            \"Zeng\",\n        ],\n        default=\"VoxelBasedBackProjection\",\n    )\n    rtkprojectors_group.add_argument(\n        \"--attenuationmap\",\n        help=\"Attenuation map relative to the volume to perfom the attenuation correction (JosephAttenuated and Zeng)\",\n    )\n    rtkprojectors_group.add_argument(\n        \"--sigmazero\",\n        help=\"PSF value at a distance of 0 meter of the detector (Zeng only)\",\n        type=float,\n    )\n    rtkprojectors_group.add_argument(\n        \"--alphapsf\",\n        help=\"Slope of the PSF against the detector distance (Zeng only)\",\n        type=float,\n    )\n    rtkprojectors_group.add_argument(\n        \"--inferiorclipimage\",\n        help=\"Inferior clip of the ray for each pixel of the projections (Joseph only)\",\n    )\n    rtkprojectors_group.add_argument(\n        \"--superiorclipimage\",\n        help=\"Superior clip of the ray for each pixel of the projections (Joseph only)\",\n    )\n\n\n# Mimicks SetBackProjectionFromGgo\ndef SetBackProjectionFromArgParse(args_info, recon):\n    if args_info.attenuationmap is not None:\n        attenuation_map = itk.imread(args_info.attenuationmap)\n    if args_info.inferiorclipimage is not None:\n        inferior_clip_image = itk.imread(args_info.inferiorclipimage)\n    if args_info.superiorclipimage is not None:\n        superior_clip_image = itk.imread(args_info.superiorclipimage)\n    ReconType = type(recon)\n    if args_info.bp == \"VoxelBasedBackProjection\":  # bp_arg_VoxelBasedBackProjection\n        recon.SetBackProjectionFilter(ReconType.BackProjectionType_BP_VOXELBASED)\n    elif args_info.bp == \"Joseph\":  # bp_arg_Joseph\n        recon.SetBackProjectionFilter(ReconType.BackProjectionType_BP_JOSEPH)\n    elif args_info.bp == \"CudaVoxelBased\":  # bp_arg_CudaVoxelBased\n        recon.SetBackProjectionFilter(ReconType.BackProjectionType_BP_CUDAVOXELBASED)\n    elif args_info.bp == \"CudaRayCast\":  # bp_arg_CudaRayCast\n        recon.SetBackProjectionFilter(ReconType.BackProjectionType_BP_CUDARAYCAST)\n    elif args_info.bp == \"JosephAttenuated\":  # bp_arg_JosephAttenuated\n        recon.SetBackProjectionFilter(ReconType.BackProjectionType_BP_JOSEPHATTENUATED)\n        if args_info.inferiorclipimage is not None:\n            recon.SetInferiorClipImage(inferior_clip_image)\n        if args_info.superiorclipimage is not None:\n            recon.SetSuperiorClipImage(superior_clip_image)\n        if args_info.attenuationmap is not None:\n            recon.SetAttenuationMap(attenuation_map)\n    elif args_info.bp == \"Zeng\":  # bp_arg_RotationBased\n        recon.SetBackProjectionFilter(ReconType.BackProjectionType_BP_ZENG)\n        if args_info.sigmazero is not None:\n            recon.SetSigmaZero(args_info.sigmazero)\n        if args_info.alphapsf is not None:\n            recon.SetAlphaPSF(args_info.alphapsf)\n        if args_info.attenuationmap is not None:\n            recon.SetAttenuationMap(args_info.attenuationMap)\n\n\n# Mimicks SetForwardProjectionFromGgo\ndef SetForwardProjectionFromArgParse(args_info, recon):\n    if args_info.attenuationmap is not None:\n        attenuation_map = itk.imread(args_info.attenuationmap)\n    ReconType = type(recon)\n    if args_info.fp == \"Joseph\":  # fp_arg_Joseph\n        recon.SetForwardProjectionFilter(ReconType.ForwardProjectionType_FP_JOSEPH)\n    elif args_info.fp == \"CudaRayCast\":  # fp_arg_CudaRayCast\n        recon.SetForwardProjectionFilter(ReconType.ForwardProjectionType_FP_CUDARAYCAST)\n    elif args_info.fp == \"JosephAttenuated\":  # fp_arg_JosephAttenuated\n        recon.SetForwardProjectionFilter(\n            ReconType.ForwardProjectionType_FP_JOSEPHATTENUATED\n        )\n        if args_info.attenuationmap is not None:\n            recon.SetAttenuationMap(attenuation_map)\n    elif args_info.fp == \"Zeng\":  # fp_arg_RotationBased\n        recon.SetForwardProjectionFilter(ReconType.ForwardProjectionType_FP_ZENG)\n        if args_info.sigmazero is not None:\n            recon.SetSigmaZero(args_info.sigmazero)\n        if args_info.alphapsf is not None:\n            recon.SetAlphaPSF(args_info.alphapsf)\n        if args_info.attenuationmap is not None:\n            recon.SetAttenuationMap(args_info.attenuationMap)\n"
  },
  {
    "path": "applications/rtkprojectors_section.ggo",
    "content": "section \"Projectors\"\noption \"fp\"    f \"Forward projection method\" values=\"Joseph\",\"CudaRayCast\",\"JosephAttenuated\",\"Zeng\" enum no default=\"Joseph\"\noption \"bp\"    b \"Back projection method\" values=\"VoxelBasedBackProjection\",\"Joseph\",\"CudaVoxelBased\",\"CudaRayCast\",\"JosephAttenuated\", \"Zeng\" enum no default=\"VoxelBasedBackProjection\"\noption \"step\" - \"Step size along ray (for CudaRayCast only)\"                double   no   default=\"1\"\noption \"attenuationmap\" - \"Attenuation map relative to the volume to perfom the attenuation correction (JosephAttenuated and Zeng)\"   string  no\noption \"sigmazero\" - \"PSF value at a distance of 0 meter of the detector (Zeng only)\"   double  no\noption \"alphapsf\" - \"Slope of the PSF against the detector distance (Zeng only)\"   double  no\noption \"inferiorclipimage\" - \"Inferior clip of the ray for each pixel of the projections (Joseph only)\" string no\noption \"superiorclipimage\" - \"Superior clip of the ray for each pixel of the projections (Joseph only)\" string no\n"
  },
  {
    "path": "applications/rtkprojectshepploganphantom/CMakeLists.txt",
    "content": "WRAP_GGO(rtkprojectshepploganphantom_GGO_C rtkprojectshepploganphantom.ggo ../rtk3Doutputimage_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkprojectshepploganphantom rtkprojectshepploganphantom.cxx ${rtkprojectshepploganphantom_GGO_C})\ntarget_link_libraries(rtkprojectshepploganphantom RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkprojectshepploganphantom)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkprojectshepploganphantom/rtkprojectshepploganphantom.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkprojectshepploganphantom_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkAdditiveGaussianNoiseImageFilter.h\"\n\n#include <itkImageFileWriter.h>\n\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkprojectshepploganphantom, args_info);\n\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create a stack of empty projection images\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantImageSource = ConstantImageSourceType::New();\n  rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkprojectshepploganphantom>(\n    constantImageSource, args_info);\n\n  // Adjust size according to geometry\n  constantImageSource->SetSize(itk::MakeSize(\n    constantImageSource->GetSize()[0], constantImageSource->GetSize()[1], geometry->GetGantryAngles().size()));\n\n  using SLPType = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>;\n  auto                slp = SLPType::New();\n  SLPType::VectorType offset(0.);\n  SLPType::VectorType scale;\n  if (args_info.offset_given)\n  {\n    offset[0] = args_info.offset_arg[0];\n    offset[1] = args_info.offset_arg[1];\n    offset[2] = args_info.offset_arg[2];\n  }\n  scale.Fill(args_info.phantomscale_arg[0]);\n  if (args_info.phantomscale_given)\n  {\n    for (unsigned int i = 0; i < std::min(args_info.phantomscale_given, Dimension); i++)\n      scale[i] = args_info.phantomscale_arg[i];\n  }\n  slp->SetInput(constantImageSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(scale);\n  slp->SetOriginOffset(offset);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update())\n\n  // Add noise\n  OutputImageType::Pointer output = slp->GetOutput();\n  if (args_info.noise_given)\n  {\n    auto noisy = rtk::AdditiveGaussianNoiseImageFilter<OutputImageType>::New();\n    noisy->SetInput(slp->GetOutput());\n    noisy->SetMean(0.0);\n    noisy->SetStandardDeviation(args_info.noise_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(noisy->Update())\n    output = noisy->GetOutput();\n  }\n\n  // Write\n  if (args_info.verbose_flag)\n    std::cout << \"Projecting and writing... \" << std::flush;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(output, args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkprojectshepploganphantom/rtkprojectshepploganphantom.ggo",
    "content": "purpose \"Computes projections through a 3D Shepp & Logan phantom, according to a geometry\"\n\noption \"verbose\"      v \"Verbose execution\"                         flag     off\noption \"geometry\"     g  \"XML geometry file name\"                   string   yes\noption \"output\"       o \"Output projections file name\"              string   yes\noption \"phantomscale\" - \"Scaling factor for the phantom dimensions\" double   multiple no default=\"128\"\noption \"noise\"        - \"Gaussian noise parameter (SD)\"             double   no\noption \"offset\"       - \"3D spatial offset of the phantom center\"   double   multiple no\n"
  },
  {
    "path": "applications/rtkprojectshepploganphantom/rtkprojectshepploganphantom.py",
    "content": "import argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Computes projections through a 3D Shepp & Logan phantom, according to a geometry\"\n    )\n    # General options\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\n        \"--geometry\", \"-g\", help=\"XML geometry file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--output\", \"-o\", help=\"Output projections file name\", type=str, required=True\n    )\n    parser.add_argument(\n        \"--phantomscale\",\n        help=\"Scaling factor for the phantom dimensions\",\n        type=float,\n        nargs=\"+\",\n        default=[128],\n    )\n    parser.add_argument(\"--noise\", help=\"Gaussian noise parameter (SD)\", type=float)\n    parser.add_argument(\n        \"--offset\",\n        help=\"3D spatial offset of the phantom center\",\n        type=float,\n        nargs=\"+\",\n    )\n\n    rtk.add_rtk3Doutputimage_group(parser)\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n\n    OutputPixelType = itk.F\n    Dimension = 3\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    # Geometry\n    if args_info.verbose:\n        print(f\"Reading geometry information from {args_info.geometry}\")\n    geometry = rtk.read_geometry(args_info.geometry)\n\n    # Create a stack of empty projection images\n    constantImageSource = rtk.ConstantImageSource[OutputImageType].New()\n    rtk.SetConstantImageSourceFromArgParse(constantImageSource, args_info)\n\n    # Adjust size according to geometry\n    sizeOutput = constantImageSource.GetSize()\n    sizeOutput[2] = len(geometry.GetGantryAngles())\n    constantImageSource.SetSize(sizeOutput)\n\n    # Create SheppLogan Phantom\n    offset = [0] * Dimension\n    if args_info.offset is not None:\n        for i in range((min(len(args_info.offset), Dimension))):\n            offset[i] = args_info.offset[i]\n\n    scale = [args_info.phantomscale[0]] * 3\n    for i in range(min(len(args_info.phantomscale), Dimension)):\n        scale[i] = args_info.phantomscale[i]\n\n    slp = rtk.SheppLoganPhantomFilter[OutputImageType, OutputImageType].New()\n    slp.SetInput(constantImageSource.GetOutput())\n    slp.SetGeometry(geometry)\n    slp.SetPhantomScale(scale)\n    slp.SetOriginOffset(offset)\n    slp.Update()\n\n    output = slp.GetOutput()\n\n    # Add noise\n    if args_info.noise:\n        noisy = rtk.AdditiveGaussianNoiseImageFilter[\n            OutputImageType, OutputImageType\n        ].New()\n        noisy.SetInput(slp.GetOutput())\n        noisy.SetMean(0.0)\n        noisy.SetStandardDeviation(args_info.noise)\n        noisy.Update()\n        output = noisy.GetOutput()\n\n    # Write\n    if args_info.verbose:\n        print(\"Projecting and writing... \")\n\n    itk.imwrite(output, args_info.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkregularizedconjugategradient/CMakeLists.txt",
    "content": "WRAP_GGO(rtkregularizedconjugategradient_GGO_C rtkregularizedconjugategradient.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkregularizedconjugategradient rtkregularizedconjugategradient.cxx ${rtkregularizedconjugategradient_GGO_C})\ntarget_link_libraries(rtkregularizedconjugategradient RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkregularizedconjugategradient)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkregularizedconjugategradient/rtkregularizedconjugategradient.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkregularizedconjugategradient_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkRegularizedConjugateGradientConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#  include \"rtkCudaConstantVolumeSource.h\"\n#endif\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkregularizedconjugategradient, args_info);\n\n  using OutputPixelType = float;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, 3>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, 3>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtkregularizedconjugategradient>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<OutputImageType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<OutputImageType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkregularizedconjugategradient>(\n      constantImageSource, args_info);\n    inputFilter = constantImageSource;\n  }\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(inputFilter->Update())\n  inputFilter->ReleaseDataFlagOn();\n\n  // Read weights if given, otherwise default to weights all equal to one\n  itk::ImageSource<OutputImageType>::Pointer weightsSource;\n  if (args_info.weights_given)\n  {\n    auto weightsReader = itk::ImageFileReader<OutputImageType>::New();\n    weightsReader->SetFileName(args_info.weights_arg);\n    weightsSource = weightsReader;\n  }\n  else\n  {\n    auto constantWeightsSource = rtk::ConstantImageSource<OutputImageType>::New();\n\n    // Set the weights to be like the projections\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputInformation())\n    constantWeightsSource->SetInformationFromImage(reader->GetOutput());\n    constantWeightsSource->SetConstant(1.0);\n    weightsSource = constantWeightsSource;\n  }\n\n  // Read Support Mask if given\n  OutputImageType::Pointer supportmaskSource;\n  if (args_info.mask_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(supportmaskSource = itk::ReadImage<OutputImageType>(args_info.mask_arg))\n  }\n\n  // Set the forward and back projection filters to be used\n  using ConjugateGradientFilterType = rtk::RegularizedConjugateGradientConeBeamReconstructionFilter<OutputImageType>;\n  auto regularizedConjugateGradient = ConjugateGradientFilterType::New();\n  SetForwardProjectionFromGgo(args_info, regularizedConjugateGradient.GetPointer());\n  SetBackProjectionFromGgo(args_info, regularizedConjugateGradient.GetPointer());\n  regularizedConjugateGradient->SetInputVolume(inputFilter->GetOutput());\n  regularizedConjugateGradient->SetInputProjectionStack(reader->GetOutput());\n  regularizedConjugateGradient->SetInputWeights(weightsSource->GetOutput());\n  regularizedConjugateGradient->SetGeometry(geometry);\n  regularizedConjugateGradient->SetMainLoop_iterations(args_info.niter_arg);\n  regularizedConjugateGradient->SetCudaConjugateGradient(!args_info.nocudacg_flag);\n  regularizedConjugateGradient->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n  if (args_info.mask_given)\n  {\n    regularizedConjugateGradient->SetSupportMask(supportmaskSource);\n  }\n\n  // Positivity\n  if (args_info.nopositivity_flag)\n    regularizedConjugateGradient->SetPerformPositivity(false);\n  else\n    regularizedConjugateGradient->SetPerformPositivity(true);\n\n  if (args_info.gammalaplacian_given)\n    regularizedConjugateGradient->SetGamma(args_info.gammalaplacian_arg);\n  if (args_info.tikhonov_given)\n    regularizedConjugateGradient->SetTikhonov(args_info.tikhonov_arg);\n\n  // Spatial TV\n  if (args_info.gammatv_given)\n  {\n    regularizedConjugateGradient->SetGammaTV(args_info.gammatv_arg);\n    regularizedConjugateGradient->SetTV_iterations(args_info.tviter_arg);\n    regularizedConjugateGradient->SetPerformTVSpatialDenoising(true);\n  }\n  else\n    regularizedConjugateGradient->SetPerformTVSpatialDenoising(false);\n\n  // Spatial wavelets\n  if (args_info.threshold_given)\n  {\n    regularizedConjugateGradient->SetSoftThresholdWavelets(args_info.threshold_arg);\n    regularizedConjugateGradient->SetOrder(args_info.order_arg);\n    regularizedConjugateGradient->SetNumberOfLevels(args_info.levels_arg);\n    regularizedConjugateGradient->SetPerformWaveletsSpatialDenoising(true);\n  }\n  else\n    regularizedConjugateGradient->SetPerformWaveletsSpatialDenoising(false);\n\n  // Sparsity in image domain\n  if (args_info.soft_given)\n  {\n    regularizedConjugateGradient->SetSoftThresholdOnImage(args_info.soft_arg);\n    regularizedConjugateGradient->SetPerformSoftThresholdOnImage(true);\n  }\n  else\n    regularizedConjugateGradient->SetSoftThresholdOnImage(false);\n\n  REPORT_ITERATIONS(regularizedConjugateGradient, ConjugateGradientFilterType, OutputImageType)\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(regularizedConjugateGradient->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(regularizedConjugateGradient->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkregularizedconjugategradient/rtkregularizedconjugategradient.ggo",
    "content": "purpose \"Alternates between conjugate gradient reconstruction and regularization\"\n\noption \"verbose\"        v \"Verbose execution\"                                                                         flag   off\noption \"geometry\"       g \"XML geometry file name\"                                                                    string yes\noption \"output\"         o \"Output file name\"                                                                          string yes\noption \"niter\"          n \"Number of iterations\"                                                                      int    no   default=\"5\"\noption \"input\"          i \"Input volume\"                                                                              string no\noption \"weights\"        w \"Weights file for Weighted Least Squares (WLS)\"                                             string no\noption \"gammalaplacian\"\t- \"Laplacian regularization weight\"                                                           float  no   default=\"0\"\noption \"tikhonov\"       - \"Tikhonov regularization weight\"                                                            float  no   default=\"0\"\noption \"cgiter\"         - \"Number of conjugate gradient nested iterations\"                                            int    no   default=\"4\"\noption \"nocudacg\"       - \"Do not perform conjugate gradient calculations on GPU\"                                     flag   off\noption \"mask\"           m \"Apply a support binary mask: reconstruction kept null outside the mask)\"                   string no\noption \"nodisplaced\"    - \"Disable the displaced detector filter\"                                                     flag   off\n\nsection \"Regularization\"\noption \"nopositivity\" - \"Do not enforce positivity\"                                                             flag    off\noption \"tviter\"      - \"Total variation regularization: number of iterations\"            \t\t\tint     no      default=\"10\"\noption \"gammatv\"     - \"Total variation spatial regularization parameter. The larger, the smoother\"             double  no\noption \"threshold\"   - \"Daubechies wavelets spatial regularization: soft threshold\"                             float   no\noption \"order\"       - \"Daubechies wavelets spatial regularization: order of the wavelets\"                      int     no      default=\"5\"\noption \"levels\"      - \"Daubechies wavelets spatial regularization: number of decomposition levels\"             int     no      default=\"3\"\noption \"soft\"        - \"Soft threshold for image domain sparsity enforcement\"                                   float   no\n"
  },
  {
    "path": "applications/rtksart/CMakeLists.txt",
    "content": "WRAP_GGO(rtksart_GGO_C rtksart.ggo ../rtkinputprojections_section.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtksart rtksart.cxx ${rtksart_GGO_C})\ntarget_link_libraries(rtksart RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtksart)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtksart/rtksart.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtksart_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkSARTConeBeamReconstructionFilter.h\"\n#include \"rtkPhaseGatingImageFilter.h\"\n#include \"rtkIterationCommands.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtksart, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtksart>(reader, args_info);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Phase gating weights reader\n  auto phaseGating = rtk::PhaseGatingImageFilter<OutputImageType>::New();\n  if (args_info.signal_given)\n  {\n    phaseGating->SetPhasesFileName(args_info.signal_arg);\n    phaseGating->SetGatingWindowWidth(args_info.windowwidth_arg);\n    phaseGating->SetGatingWindowCenter(args_info.windowcenter_arg);\n    phaseGating->SetGatingWindowShape(args_info.windowshape_arg);\n    phaseGating->SetInputProjectionStack(reader->GetOutput());\n    phaseGating->SetInputGeometry(geometry);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(phaseGating->Update())\n  }\n\n  // Create input: either an existing volume read from a file or a blank image\n  itk::ImageSource<OutputImageType>::Pointer inputFilter;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    auto inputReader = itk::ImageFileReader<OutputImageType>::New();\n    inputReader->SetFileName(args_info.input_arg);\n    inputFilter = inputReader;\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtksart>(constantImageSource, args_info);\n    inputFilter = constantImageSource;\n  }\n\n  // SART reconstruction filter\n  auto sart = rtk::SARTConeBeamReconstructionFilter<OutputImageType>::New();\n\n  // Set the forward and back projection filters\n  SetForwardProjectionFromGgo(args_info, sart.GetPointer());\n  SetBackProjectionFromGgo(args_info, sart.GetPointer());\n  sart->SetInput(inputFilter->GetOutput());\n  if (args_info.signal_given)\n  {\n    sart->SetInput(1, phaseGating->GetOutput());\n    sart->SetGeometry(phaseGating->GetOutputGeometry());\n    sart->SetGatingWeights(phaseGating->GetGatingWeightsOnSelectedProjections());\n  }\n  else\n  {\n    sart->SetInput(1, reader->GetOutput());\n    sart->SetGeometry(geometry);\n  }\n  sart->SetNumberOfIterations(args_info.niterations_arg);\n  sart->SetNumberOfProjectionsPerSubset(args_info.nprojpersubset_arg);\n  sart->SetLambda(args_info.lambda_arg);\n  sart->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n  sart->SetResetNesterovEvery(args_info.reset_nesterov_arg);\n\n  if (args_info.positivity_flag)\n  {\n    sart->SetEnforcePositivity(true);\n  }\n\n  if (args_info.divisionthreshold_given)\n  {\n    sart->SetDivisionThreshold(args_info.divisionthreshold_arg);\n  }\n\n  REPORT_ITERATIONS(sart, rtk::SARTConeBeamReconstructionFilter<OutputImageType>, OutputImageType)\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(sart->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(sart->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtksart/rtksart.ggo",
    "content": "purpose \"Reconstructs a 3D volume from a sequence of projections with Simulatenous Algebraic Reconstruction Technique [Andersen, 1984].\"\n\noption \"verbose\"           v \"Verbose execution\"                                             flag   off\noption \"geometry\"          g \"XML geometry file name\"                                        string yes\noption \"output\"            o \"Output file name\"                                              string yes\noption \"niterations\"       n \"Number of iterations\"                                          int    no   default=\"5\"\noption \"lambda\"            l \"Convergence factor\"                                            double no   default=\"0.3\"\noption \"positivity\"        - \"Enforces positivity during the reconstruction\"                 flag   off\noption \"input\"             i \"Input volume\"                                                  string          no\noption \"nprojpersubset\"    - \"Number of projections processed between each update of the reconstructed volume (1 for SART, several for OSSART, all for SIRT)\" int no default=\"1\"\noption \"nodisplaced\"       - \"Disable the displaced detector filter\"                         flag   off\noption \"divisionthreshold\" - \"Denominator threshold below which denominator pixels are zero\" double  no\noption \"reset_nesterov\"    - \"Reset Nesterov after a number of subset (1 means no momentum)\" int no default=\"1\"\n\nsection \"Phase gating\"\noption \"signal\"       - \"File containing the phase of each projection\"                                              string              no\noption \"windowcenter\" c \"Target reconstruction phase\"                                                               float   no default=\"0\"\noption \"windowwidth\"  w \"Tolerance around the target phase to determine in-phase and out-of-phase projections\"      float   no default=\"1\"\noption \"windowshape\"  s \"Shape of the gating window\"     values=\"Rectangular\",\"Triangular\"                          enum    no default=\"Rectangular\"\n\n\n"
  },
  {
    "path": "applications/rtkscatterglarecorrection/CMakeLists.txt",
    "content": "WRAP_GGO(rtkscatterglarecorrection_GGO_C rtkscatterglarecorrection.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkscatterglarecorrection rtkscatterglarecorrection.cxx ${rtkscatterglarecorrection_GGO_C})\ntarget_link_libraries(rtkscatterglarecorrection RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkscatterglarecorrection)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkscatterglarecorrection/rtkscatterglarecorrection.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkscatterglarecorrection_ggo.h\"\n#include \"rtkMacro.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaScatterGlareCorrectionImageFilter.h\"\n#else\n#  include \"rtkScatterGlareCorrectionImageFilter.h\"\n#endif\n\n#include \"rtkProjectionsReader.h\"\n#include <itkPasteImageFilter.h>\n#include <rtkConstantImageSource.h>\n#include <itkImageFileWriter.h>\n\n#include <vector>\n#include <algorithm>\n#include <string>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkscatterglarecorrection, args_info);\n\n  using InputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n#ifdef RTK_USE_CUDA\n  using InputImageType = itk::CudaImage<InputPixelType, Dimension>;\n#else\n  using InputImageType = itk::Image<InputPixelType, Dimension>;\n#endif\n\n  using ReaderType = rtk::ProjectionsReader<InputImageType>; // Warning: preprocess images\n  auto reader = ReaderType::New();\n  reader->SetFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  reader->ComputeLineIntegralOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputInformation())\n\n  // Input projection parameters\n  InputImageType::SizeType sizeInput = reader->GetOutput()->GetLargestPossibleRegion().GetSize();\n  int                      Nproj = sizeInput[2];\n\n\n  std::vector<float> coef;\n  if (args_info.coefficients_given == 2)\n  {\n    coef.push_back(args_info.coefficients_arg[0]);\n    coef.push_back(args_info.coefficients_arg[1]);\n  }\n  else\n  {\n    std::cerr << \"--coefficients requires exactly 2 coefficients\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n#ifdef RTK_USE_CUDA\n  using ScatterCorrectionType = rtk::CudaScatterGlareCorrectionImageFilter;\n#else\n  using ScatterCorrectionType = rtk::ScatterGlareCorrectionImageFilter<InputImageType, InputImageType, float>;\n#endif\n  auto SFilter = ScatterCorrectionType::New();\n  SFilter->SetTruncationCorrection(0.0);\n  SFilter->SetCoefficients(coef);\n\n  auto constantSource = rtk::ConstantImageSource<InputImageType>::New();\n\n  auto paste = itk::PasteImageFilter<InputImageType, InputImageType>::New();\n  paste->SetSourceImage(SFilter->GetOutput());\n  paste->SetDestinationImage(constantSource->GetOutput());\n\n  std::cout << \"Starting processing\" << std::endl;\n  int  projid = 0;\n  bool first = true;\n  while (projid < Nproj)\n  {\n    int curBufferSize = std::min(args_info.bufferSize_arg, Nproj - projid);\n\n    InputImageType::RegionType sliceRegionA = reader->GetOutput()->GetLargestPossibleRegion();\n    InputImageType::RegionType desiredRegionA;\n    desiredRegionA.SetSize(itk::MakeSize(sliceRegionA.GetSize()[0], sliceRegionA.GetSize()[1], curBufferSize));\n    desiredRegionA.SetIndex(itk::MakeIndex(sliceRegionA.GetIndex()[0], sliceRegionA.GetIndex()[1], projid));\n\n    auto extract = itk::ExtractImageFilter<InputImageType, InputImageType>::New();\n    extract->SetDirectionCollapseToIdentity();\n    extract->SetExtractionRegion(desiredRegionA);\n    extract->SetInput(reader->GetOutput());\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(extract->Update())\n\n    InputImageType::Pointer image = extract->GetOutput();\n    image->DisconnectPipeline();\n\n    SFilter->SetInput(image);\n    SFilter->GetOutput()->SetRequestedRegion(image->GetRequestedRegion());\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(SFilter->Update())\n\n    InputImageType::Pointer procImage = SFilter->GetOutput();\n    procImage->DisconnectPipeline();\n\n    InputImageType::Pointer outImage;\n    if (args_info.difference_flag)\n    {\n      auto subtractFilter = itk::SubtractImageFilter<InputImageType, InputImageType>::New();\n      subtractFilter->SetInput1(image);\n      subtractFilter->SetInput2(procImage);\n      TRY_AND_EXIT_ON_ITK_EXCEPTION(subtractFilter->Update())\n      outImage = subtractFilter->GetOutput();\n      outImage->DisconnectPipeline();\n    }\n    else\n    {\n      outImage = procImage;\n    }\n\n    InputImageType::IndexType current_idx = outImage->GetLargestPossibleRegion().GetIndex();\n    current_idx[2] = projid;\n\n    if (first)\n    {\n      // Initialization of the output volume\n      InputImageType::SizeType sizeInput_local = outImage->GetLargestPossibleRegion().GetSize();\n      sizeInput_local[2] = Nproj;\n      InputImageType::SpacingType   spacingInput = outImage->GetSpacing();\n      InputImageType::PointType     originInput = outImage->GetOrigin();\n      InputImageType::DirectionType imageDirection;\n      imageDirection.SetIdentity();\n\n      constantSource->SetOrigin(originInput);\n      constantSource->SetSpacing(spacingInput);\n      constantSource->SetDirection(imageDirection);\n      constantSource->SetSize(sizeInput_local);\n      constantSource->SetConstant(0.);\n      first = false;\n    }\n    else\n    {\n      paste->SetDestinationImage(paste->GetOutput());\n    }\n\n    paste->SetSourceImage(outImage);\n    paste->SetSourceRegion(outImage->GetLargestPossibleRegion());\n\n    paste->SetDestinationIndex(current_idx);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(paste->Update())\n\n    projid += curBufferSize;\n  }\n\n  if (args_info.output_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(paste->GetOutput(), args_info.output_arg))\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkscatterglarecorrection/rtkscatterglarecorrection.ggo",
    "content": "purpose \"Reads projection images and correct them for scatter glare\"\n\noption \"verbose\"      v \"Verbose execution\"                                         flag      off\noption \"output\"       o \"Output filename\"                                           string    no\noption \"bufferSize\"   - \"Number of projections computed at the same time\"           int       no   default=\"4\"\noption \"difference\"   d \"Output the difference between input and corrected images\"  flag      off\n\nsection \"Algorithm parameters\"\noption \"coefficients\"  c  \"Deconvolution kernel coefficients\"                   float   multiple yes\n\n"
  },
  {
    "path": "applications/rtkshowgeometry/README.md",
    "content": "# Geometry viewer\n\n`rtkshowgeometry` is a Python-only command line tool which provides an **interactive three-dimensional (3D) visualization** of RTK geometry files, projections and volumes using [`pyvista`](https://pyvista.org). It is useful for visually assessing a geometry, i.e., how it relates the CT image with the projection images by displaying the source positions and the projections positions and orientations in a 3D scene.\n\n![geom](../../documentation/docs/ExternalData/ShowGeometry.png){w=800 alt=\"Show Geometry\"}\n\nAll geometries described in the [documentation](../../documentation/docs/Geometry.md) are supported: cone-beam and parallel (`SDD = 0`), flat and cylindrical (`RadiusCylindricalDetector > 0`) detectors. If no projections are given, the detector size defaults to 40% of the Source-to-Isocenter Distance (SID) and is centered around point `(u,v)=(0,0)`.\n\n```{literalinclude} showgeometry.sh\n```\n"
  },
  {
    "path": "applications/rtkshowgeometry/rtkshowgeometry.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport numpy as np\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    parser = rtk.RTKArgumentParser(\n        description=\" Create an interactive 3D viewer for the given geometry and projections.\",\n    )\n\n    parser.add_argument(\n        \"--verbose\", \"-v\", help=\"Verbose execution\", action=\"store_true\"\n    )\n    parser.add_argument(\"--geometry\", \"-g\", help=\"Geometry file name\", required=True)\n    parser.add_argument(\n        \"--show_trajectory\", \"-t\", help=\"Show source trajectory\", action=\"store_true\"\n    )\n    parser.add_argument(\"--input\", \"-i\", help=\"Input volume\")\n    parser.add_argument(\"--hide_volume\", help=\"hide input volume\", action=\"store_true\")\n\n    rtk.add_rtkinputprojections_group(parser)\n\n    # Remove the required flag for '--path' and '--regexp' arguments\n    for action in parser._actions:\n        if action.dest == \"path\":\n            action.required = False\n        if action.dest == \"regexp\":\n            action.required = False\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args_info: argparse.Namespace):\n    try:\n        import pyvista as pv\n    except ImportError:\n        raise ImportError(\n            \"rtkshowgeometry requires the 'pyvista' package. \"\n            \"Please install it with 'pip install pyvista' to use this feature.\"\n        )\n\n    OutputPixelType = itk.F\n    Dimension = 3\n\n    OutputImageType = itk.Image[OutputPixelType, Dimension]\n\n    if args_info.regexp:\n        reader = rtk.ProjectionsReader[OutputImageType].New()\n        rtk.SetProjectionsReaderFromArgParse(reader, args_info)\n        reader.Update()\n        projections = reader.GetOutput()\n    else:\n        projections = None\n\n    if args_info.geometry:\n        geometry = rtk.read_geometry(args_info.geometry)\n\n    if args_info.input:\n        volume = itk.imread(args_info.input)\n\n    plotter = pv.Plotter()\n\n    all_points_list = []\n    source_positions = []\n\n    # Iterate through all frames to calculate bounds and positions\n    for frame in range(len(geometry.GetGantryAngles())):\n        source_pos = np.asarray(geometry.GetSourcePosition(frame), dtype=float)[:3]\n        source_positions.append(source_pos)\n\n        SDD = geometry.GetSourceToDetectorDistances()[frame]\n        SID = geometry.GetSourceToIsocenterDistances()[frame]\n\n        m = geometry.GetProjectionCoordinatesToFixedSystemMatrix(frame)\n        m_np = np.asarray(m)\n\n        if projections is not None:\n            corners = []\n            idx = list(projections.GetLargestPossibleRegion().GetIndex())\n            size = list(projections.GetLargestPossibleRegion().GetSize())\n\n            # Calculate detector corners from projection indices\n            for i in range(4):\n                corner_pt = projections.TransformIndexToPhysicalPoint(idx)\n                corner = np.asarray(corner_pt, dtype=float)\n                corner = np.append(corner, 1.0)\n                corner = m_np.dot(corner)\n                corners.append(corner[:3])\n\n                if i == 0:\n                    idx[0] += size[0] - 1\n                elif i == 1:\n                    idx[1] += size[1] - 1\n                elif i == 2:\n                    idx[0] -= size[0] - 1\n        else:\n            # Simulate detector corners for cases without projections\n            detector_size = max(abs(source_pos)) * 0.4\n            half_size = detector_size / 2\n            local_corners = [\n                [-half_size, -half_size, 0],\n                [half_size, -half_size, 0],\n                [half_size, half_size, 0],\n                [-half_size, half_size, 0],\n            ]\n            for corner in local_corners:\n                corners = [m_np.dot(np.append(corner, 1.0))[:3]]\n\n        # Handle parallel geometry (SDD = 0)\n        if SDD == 0:\n            rot_matrix = np.asarray(geometry.GetRotationMatrix(frame))\n            direction = np.array(\n                [-rot_matrix[2][0], -rot_matrix[2][1], -rot_matrix[2][2]]\n            )\n            direction *= 2.0 * SID\n            source_corners = [corner - direction for corner in corners]\n            frame_points = np.vstack([source_pos] + corners + source_corners)\n        else:\n            frame_points = np.vstack([source_pos] + corners)\n\n        all_points_list.append(frame_points)\n\n    if args_info.show_trajectory:\n        source_positions = np.array(source_positions)\n        source_trajectory = pv.PolyData(source_positions)\n        plotter.add_mesh(source_trajectory, color=\"red\", opacity=0.3)\n\n    # Calculate bounds for the entire geometry\n    all_points = np.vstack(all_points_list)\n    max_value = np.max(all_points)\n    min_value = np.min(all_points)\n\n    # Compute \"nice\" tick spacing for grid\n    raw_spacing = (abs(max_value) + abs(min_value)) / 4.0\n    exp_val = np.floor(np.log10(raw_spacing))\n    f = raw_spacing / (10**exp_val)\n    if f < 1.5:\n        nf = 1.0\n    elif f < 3.0:\n        nf = 2.0\n    elif f < 7.0:\n        nf = 5.0\n    else:\n        nf = 10.0\n    nice_tick = nf * (10**exp_val)\n\n    # Adjust bounds to align with tick spacing\n    min_bounds = np.floor(min_value / nice_tick) * nice_tick\n    max_bounds = np.ceil(max_value / nice_tick) * nice_tick\n\n    # Add bounding box\n    box = pv.Cube(\n        bounds=[min_bounds, max_bounds, min_bounds, max_bounds, min_bounds, max_bounds]\n    )\n    plotter.add_mesh(box, style=\"wireframe\", opacity=0)\n\n    # Configure plotter view\n    plotter.show_grid(minor_ticks=True)\n    plotter.renderer.SetGradientBackground(True)\n    plotter.enable_parallel_projection()\n\n    actors = {}\n\n    if not args_info.hide_volume:\n        # Handle volume visualization if provided\n        if args_info.input:\n            volume_array = itk.GetArrayFromImage(volume)\n            spacing = volume.GetSpacing()\n            origin = volume.GetOrigin()\n            direction = volume.GetDirection()\n\n            # Adjust volume array for correct orientation\n            volume_array = np.transpose(volume_array, (2, 1, 0))\n\n            dims = volume_array.shape\n            grid = pv.ImageData(dimensions=dims, spacing=spacing, origin=origin)\n            grid.point_data[\"values\"] = volume_array.ravel(order=\"F\")\n\n            # Apply direction matrix if needed\n            if not np.allclose(direction, np.eye(3)):\n                transform = pv.transform_matrix(direction.flatten())\n                grid.transform(transform)\n\n            center = grid.center\n            slice_x = grid.slice(normal=\"x\", origin=center)\n            slice_y = grid.slice(normal=\"y\", origin=center)\n            slice_z = grid.slice(normal=\"z\", origin=center)\n\n            # Add slices with opacity\n            plotter.add_mesh(slice_x, cmap=\"gray\", show_scalar_bar=False, opacity=0.5)\n            plotter.add_mesh(slice_y, cmap=\"gray\", show_scalar_bar=False, opacity=0.5)\n            plotter.add_mesh(slice_z, cmap=\"gray\", show_scalar_bar=False, opacity=0.5)\n        else:\n            # Add a placeholder sphere if no volume is provided\n            volume_sphere = pv.Sphere(\n                radius=0.1 * geometry.GetSourceToIsocenterDistances()[0],\n                center=[0, 0, 0],\n            )\n            plotter.add_mesh(volume_sphere, color=\"blue\", opacity=0.5)\n\n    def update(frame):\n        frame = int(frame)\n\n        # Update geometry parameters for the current frame\n        gantry_angle = np.degrees(geometry.GetGantryAngles()[frame])\n        out_of_plane_angle = np.degrees(geometry.GetOutOfPlaneAngles()[frame])\n        in_plane_angle = np.degrees(geometry.GetInPlaneAngles()[frame])\n        SID = geometry.GetSourceToIsocenterDistances()[frame]\n        offset_x = geometry.GetSourceOffsetsX()[frame]\n        offset_y = geometry.GetSourceOffsetsY()[frame]\n        SDD = geometry.GetSourceToDetectorDistances()[frame]\n        proj_offset_x = geometry.GetProjectionOffsetsX()[frame]\n        proj_offset_y = geometry.GetProjectionOffsetsY()[frame]\n\n        info_text = (\n            f\"Frame index {frame}\\n\"\n            f\"Gantry: {gantry_angle:.2f}°\\n\"\n            f\"Out-of-Plane: {out_of_plane_angle:.2f}°\\n\"\n            f\"In-Plane: {in_plane_angle:.2f}°\\n\"\n            f\"SID: {SID:.2f} mm\\n\"\n            f\"Offset X: {offset_x:.2f} mm\\n\"\n            f\"Offset Y: {offset_y:.2f} mm\\n\"\n            f\"SDD: {SDD:.2f} mm\\n\"\n            f\"Proj Offset X: {proj_offset_x:.2f} mm\\n\"\n            f\"Proj Offset Y: {proj_offset_y:.2f} mm\"\n        )\n\n        m = geometry.GetProjectionCoordinatesToFixedSystemMatrix(frame)\n        m_np = np.asarray(m)\n        detector_position = m_np[:3, 3]\n        source_pos = np.asarray(geometry.GetSourcePosition(frame), dtype=float)[:3]\n\n        # Detector setup\n        if projections is not None:\n            corners = []\n            idx = list(projections.GetLargestPossibleRegion().GetIndex())\n            size = list(projections.GetLargestPossibleRegion().GetSize())\n\n            for i in range(4):\n                corner_pt = projections.TransformIndexToPhysicalPoint(idx)\n                corner = np.asarray(corner_pt, dtype=float)\n                corner = np.append(corner, 1.0)\n                corner = m_np.dot(corner)\n                corners.append(corner[:3])\n\n                if i == 0:\n                    idx[0] += size[0] - 1\n                elif i == 1:\n                    idx[1] += size[1] - 1\n                elif i == 2:\n                    idx[0] -= size[0] - 1\n\n            proj_array = np.asarray(itk.GetArrayFromImage(projections))\n            proj_slice = proj_array[frame].astype(np.float32)\n            proj_slice -= proj_slice.min()\n            proj_slice /= proj_slice.max() + 1e-8\n            texture_data = (proj_slice * 255).astype(np.uint8)\n        else:\n            detector_size = SID * 0.4\n            half_size = detector_size / 2\n            local_corners = [\n                [-half_size, -half_size, 0],\n                [half_size, -half_size, 0],\n                [half_size, half_size, 0],\n                [-half_size, half_size, 0],\n            ]\n\n            corners = []\n            for corner in local_corners:\n                corner = np.append(corner, 1.0)\n                corner = m_np.dot(corner)\n                corners.append(corner[:3])\n\n            texture_data = np.zeros((2, 2), dtype=np.uint8)\n\n        corners_array = np.asarray(corners, dtype=float)\n\n        # Handle cylindrical detector if radius is non-zero\n        radius = geometry.GetRadiusCylindricalDetector()\n        if radius > 0:\n            detector_width = np.linalg.norm(corners[1] - corners[0])\n            detector_height = np.linalg.norm(corners[3] - corners[0])\n\n            # Create grid points\n            n_points = 100\n            u = np.linspace(-detector_width / 2, detector_width / 2, n_points)\n            v = np.linspace(-detector_height / 2, detector_height / 2, n_points)\n            U, V = np.meshgrid(u, v)\n\n            # Calculate cylindrical coordinates\n            Theta = U / radius\n            detector_center = np.mean(corners_array, axis=0)\n            u_dir = (corners[1] - corners[0]) / np.linalg.norm(corners[1] - corners[0])\n            v_dir = (corners[3] - corners[0]) / np.linalg.norm(corners[3] - corners[0])\n            n_dir = np.cross(u_dir, v_dir)\n\n            # Create rotation matrix for detector orientation\n            rot_matrix = np.column_stack([u_dir, v_dir, n_dir])\n\n            # Calculate curved surface points\n            X = radius * np.sin(Theta)\n            Z = radius * (1 - np.cos(Theta))\n            Y = V\n            points = np.column_stack([X.ravel(), Y.ravel(), Z.ravel()])\n            points = points @ rot_matrix.T + detector_center\n\n            # Create faces for the curved surface\n            curved_faces = []\n            for i in range(n_points - 1):\n                for j in range(n_points - 1):\n                    idx00 = i * n_points + j\n                    idx01 = i * n_points + (j + 1)\n                    idx10 = (i + 1) * n_points + j\n                    idx11 = (i + 1) * n_points + (j + 1)\n                    curved_faces.extend([3, idx00, idx01, idx11])\n                    curved_faces.extend([3, idx00, idx11, idx10])\n\n            # Create texture coordinates\n            tcoords = np.zeros((n_points * n_points, 2), dtype=np.float32)\n            u_coords, v_coords = np.meshgrid(\n                np.linspace(0, 1, n_points),\n                np.linspace(1, 0, n_points),\n            )\n            tcoords[:, 0] = u_coords.ravel()\n            tcoords[:, 1] = v_coords.ravel()\n\n            # Get the corner points of the curved surface\n            curved_corners = [\n                points[0],  # Bottom left\n                points[n_points - 1],  # Bottom right\n                points[-1],  # Top right\n                points[-n_points],  # Top left\n            ]\n\n            corners_array = points\n            faces = np.array(curved_faces)\n            detector_poly = pv.PolyData(corners_array, faces)\n            detector_poly.active_texture_coordinates = tcoords\n            corners = curved_corners\n\n        else:\n            faces = np.hstack([[4], np.arange(4)])\n            detector_poly = pv.PolyData(corners_array, faces)\n            tcoords = np.asarray([[0, 1], [1, 1], [1, 0], [0, 0]], dtype=np.float32)\n            detector_poly.active_texture_coordinates = tcoords\n\n        texture = pv.Texture(texture_data)\n\n        u_vec = (corners[1] - corners[0]) * 0.5\n        v_vec = (corners[3] - corners[0]) * 0.5\n\n        arrow_params = {\n            \"tip_length\": 0.1,\n            \"tip_radius\": 0.04,\n            \"shaft_radius\": 0.02,\n            \"scale\": \"auto\",\n        }\n\n        # Create arrows from center\n        u_arrow = pv.Arrow(start=detector_position, direction=u_vec, **arrow_params)\n        v_arrow = pv.Arrow(start=detector_position, direction=v_vec, **arrow_params)\n\n        # Update label positions to be near arrow tips\n        u_label_pos = detector_position + u_vec\n        v_label_pos = detector_position + v_vec\n\n        if SDD == 0:\n            rot_matrix = np.asarray(geometry.GetRotationMatrix(frame))\n            direction = (\n                np.array([-rot_matrix[2][0], -rot_matrix[2][1], -rot_matrix[2][2]])\n                * 2.0\n                * SID\n            )\n            source = detector_position - direction\n            central_line = pv.Line(source, detector_position)\n        else:\n            central_line = pv.Line(source_pos, detector_position)\n\n        # Update or create visualization actors\n        if not actors:\n            actors[\"detector\"] = plotter.add_mesh(\n                detector_poly, texture=texture, opacity=0.5\n            )\n            actors[\"central_line\"] = plotter.add_mesh(\n                central_line, color=\"black\", line_width=2\n            )\n            actors[\"text\"] = plotter.add_text(\n                info_text, position=\"upper_right\", font_size=10, color=\"white\"\n            )\n            actors[\"u_dir\"] = plotter.add_mesh(u_arrow, color=\"green\")\n            actors[\"v_dir\"] = plotter.add_mesh(v_arrow, color=\"green\")\n        else:\n            actors[\"detector\"].GetMapper().GetInput().points = corners_array\n            actors[\"detector\"].texture = texture\n            actors[\"central_line\"].GetMapper().GetInput().points = central_line.points\n            actors[\"text\"].SetText(3, info_text)\n            actors[\"u_dir\"].GetMapper().GetInput().points = u_arrow.points\n            actors[\"v_dir\"].GetMapper().GetInput().points = v_arrow.points\n\n        # Handle parallel geometry (SDD = 0)\n        if SDD == 0:\n            rot_matrix = np.asarray(geometry.GetRotationMatrix(frame))\n            direction = np.array(\n                [-rot_matrix[2][0], -rot_matrix[2][1], -rot_matrix[2][2]]\n            )\n            direction *= 2.0 * SID\n            source_corners = [corner - direction for corner in corners]\n            source_corners_array = np.asarray(source_corners, dtype=float)\n            source_faces = np.hstack([[4], np.arange(4)])\n            source_poly = pv.PolyData(source_corners_array, source_faces)\n\n            if \"source_plane\" not in actors:\n                actors[\"source_plane\"] = plotter.add_mesh(\n                    source_poly, color=\"red\", opacity=0.3\n                )\n            else:\n                actors[\"source_plane\"].GetMapper().GetInput().points = (\n                    source_corners_array\n                )\n\n            if \"lines\" not in actors:\n                actors[\"lines\"] = []\n                for src_corner, det_corner in zip(source_corners, corners):\n                    line = pv.Line(src_corner, det_corner)\n                    actors[\"lines\"].append(\n                        plotter.add_mesh(line, color=\"black\", line_width=1)\n                    )\n            else:\n                for i, (src_corner, det_corner) in enumerate(\n                    zip(source_corners, corners)\n                ):\n                    line = pv.Line(src_corner, det_corner)\n                    actors[\"lines\"][i].GetMapper().GetInput().points = line.points\n\n        else:\n            if \"lines\" not in actors:\n                actors[\"lines\"] = []\n                for corner in corners:\n                    line = pv.Line(source_pos, corner)\n                    actors[\"lines\"].append(\n                        plotter.add_mesh(line, color=\"black\", line_width=1)\n                    )\n            else:\n                for i, corner in enumerate(corners):\n                    line = pv.Line(source_pos, corner)\n                    actors[\"lines\"][i].GetMapper().GetInput().points = line.points\n\n        if \"labels\" in actors:\n            plotter.remove_actor(actors[\"labels\"])\n        actors[\"labels\"] = plotter.add_point_labels(\n            points=[u_label_pos, v_label_pos],\n            labels=[\"u\", \"v\"],\n            text_color=\"green\",\n            font_size=24,\n            shape_opacity=0,\n            always_visible=True,\n            show_points=False,\n        )\n\n    plotter.camera.zoom(0.8)\n\n    plotter.add_slider_widget(\n        callback=update,\n        rng=[0, len(geometry.GetGantryAngles()) - 1],\n        value=0,\n        title=\"Frame\",\n        style=\"modern\",\n        pointa=(0.02, 0.07),\n        pointb=(0.98, 0.07),\n        color=\"lightgrey\",\n        fmt=\"%.0f\",\n        interaction_event=\"always\",\n    )\n\n    update(0)\n    plotter.show_axes()\n    plotter.show()\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkshowgeometry/showgeometry.sh",
    "content": "# Create a simulated geometry\nrtksimulatedgeometry -n 180 -o geometry.xml\n\n# Create projections of the phantom file\nrtkprojectshepploganphantom -g geometry.xml -o projections.mha --spacing 2 --size 256\n\n# Reconstruct\nrtkfdk -p . -r projections.mha -o fdk.mha -g geometry.xml --spacing 2 --size 256\n\n# Show geometry\nrtkshowgeometry -p . -r projections.mha --geometry geometry.xml  --input fdk.mha --show_trajectory\n"
  },
  {
    "path": "applications/rtksimulatedgeometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtksimulatedgeometry_GGO_C rtksimulatedgeometry.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtksimulatedgeometry rtksimulatedgeometry.cxx ${rtksimulatedgeometry_GGO_C})\ntarget_link_libraries(rtksimulatedgeometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtksimulatedgeometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtksimulatedgeometry/rtksimulatedgeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtksimulatedgeometry_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtksimulatedgeometry, args_info);\n\n  // RTK geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n\n  // Projection matrices\n  for (int noProj = 0; noProj < args_info.nproj_arg; noProj++)\n  {\n    double angle = args_info.first_angle_arg + noProj * args_info.arc_arg / args_info.nproj_arg;\n    geometry->AddProjection(args_info.sid_arg,\n                            args_info.sdd_arg,\n                            angle,\n                            args_info.proj_iso_x_arg,\n                            args_info.proj_iso_y_arg,\n                            args_info.out_angle_arg,\n                            args_info.in_angle_arg,\n                            args_info.source_x_arg,\n                            args_info.source_y_arg);\n  }\n\n  // Set cylindrical detector radius\n  if (args_info.rad_cyl_given)\n    geometry->SetRadiusCylindricalDetector(args_info.rad_cyl_arg);\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(geometry, args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtksimulatedgeometry/rtksimulatedgeometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from simulated/regular trajectory. See https://docs.openrtk.org/en/latest/documentation/docs/Geometry.html for more information.\"\n\noption \"verbose\"     v \"Verbose execution\"                                                    flag   off\n\noption \"output\"      o \"Output file name\"                                                     string yes\noption \"first_angle\" f \"First angle in degrees\"                                               double no  default=\"0\"\noption \"nproj\"       n \"Number of projections\"                                                int    yes\noption \"arc\"         a \"Angular arc covevered by the acquisition in degrees\"                  double no  default=\"360\"\noption \"sdd\"         - \"Source to detector distance (mm)\"                                     double no  default=\"1536\"\noption \"sid\"         - \"Source to isocenter distance (mm)\"                                    double no  default=\"1000\"\noption \"proj_iso_x\"  - \"X coordinate of detector point (0,0) mm in rotated coordinate system\" double no  default=\"0\"\noption \"proj_iso_y\"  - \"Y coordinate of detector point (0,0) mm in rotated coordinate system\" double no  default=\"0\"\noption \"source_x\"    - \"X coordinate of source in rotated coordinate system\"                  double no  default=\"0\"\noption \"source_y\"    - \"Y coordinate of source in rotated coordinate system\"                  double no  default=\"0\"\noption \"out_angle\"   - \"Out of plane angle\"                                                   double no  default=\"0\"\noption \"in_angle\"    - \"In plane angle\"                                                       double no  default=\"0\"\noption \"rad_cyl\"     - \"Radius cylinder of cylindrical detector\"                              double no  default=\"0\"\n\n"
  },
  {
    "path": "applications/rtksimulatedgeometry/rtksimulatedgeometry.py",
    "content": "#!/usr/bin/env python\nimport argparse\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Creates an RTK geometry file from simulated/regular trajectory. See https://docs.openrtk.org/en/latest/documentation/docs/Geometry.html for more information.\"\n    )\n\n    parser.add_argument(\n        \"--verbose\", \"-v\", type=bool, default=False, help=\"Verbose execution\"\n    )\n    parser.add_argument(\n        \"--nproj\", \"-n\", type=int, help=\"Number of projections\", required=True\n    )\n    parser.add_argument(\"--output\", \"-o\", help=\"Output file name\", required=True)\n    parser.add_argument(\n        \"--first_angle\", \"-f\", type=float, default=0, help=\"First angle in degrees\"\n    )\n    parser.add_argument(\n        \"--arc\",\n        \"-a\",\n        type=float,\n        default=360,\n        help=\"Angular arc covevered by the acquisition in degrees\",\n    )\n    parser.add_argument(\n        \"--sdd\", type=float, default=1536, help=\"Source to detector distance (mm)\"\n    )\n    parser.add_argument(\n        \"--sid\", type=float, default=1000, help=\"Source to isocenter distance (mm)\"\n    )\n    parser.add_argument(\n        \"--proj_iso_x\",\n        type=float,\n        default=0,\n        help=\"X coordinate of detector point (0,0) mm in rotated coordinate system\",\n    )\n    parser.add_argument(\n        \"--proj_iso_y\",\n        type=float,\n        default=0,\n        help=\"Y coordinate of detector point (0,0) mm in rotated coordinate system\",\n    )\n    parser.add_argument(\n        \"--source_x\",\n        type=float,\n        default=0,\n        help=\"X coordinate of source in rotated coordinate system\",\n    )\n    parser.add_argument(\n        \"--source_y\",\n        type=float,\n        default=0,\n        help=\"Y coordinate of source in rotated coordinate system\",\n    )\n    parser.add_argument(\"--out_angle\", type=float, default=0, help=\"Out of plane angle\")\n    parser.add_argument(\"--in_angle\", type=float, default=0, help=\"In plane angle\")\n    parser.add_argument(\n        \"--rad_cyl\",\n        type=float,\n        default=0,\n        help=\"Radius cylinder of cylindrical detector\",\n    )\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args: argparse.Namespace):\n    # Simulated Geometry\n    GeometryType = rtk.ThreeDCircularProjectionGeometry\n    geometry = GeometryType.New()\n\n    for noProj in range(0, args.nproj):\n        angle = args.first_angle + noProj * args.arc / args.nproj\n        geometry.AddProjection(\n            args.sid,\n            args.sdd,\n            angle,\n            args.proj_iso_x,\n            args.proj_iso_y,\n            args.out_angle,\n            args.in_angle,\n            args.source_x,\n            args.source_y,\n        )\n\n    geometry.SetRadiusCylindricalDetector(args.rad_cyl)\n\n    rtk.write_geometry(geometry, args.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkspectraldenoiseprojections/CMakeLists.txt",
    "content": "WRAP_GGO(rtkspectraldenoiseprojections_GGO_C rtkspectraldenoiseprojections.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkspectraldenoiseprojections rtkspectraldenoiseprojections.cxx ${rtkspectraldenoiseprojections_GGO_C})\ntarget_link_libraries(rtkspectraldenoiseprojections RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkspectraldenoiseprojections)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkspectraldenoiseprojections/rtkspectraldenoiseprojections.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkspectraldenoiseprojections_ggo.h\"\n#include \"rtkMacro.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConditionalMedianImageFilter.h\"\n\n#include <itkImageFileWriter.h>\n#include <itkImageFileReader.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkspectraldenoiseprojections, args_info);\n\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::VectorImage<float, Dimension>;\n\n  // Reader\n  OutputImageType::Pointer input;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(input = itk::ReadImage<OutputImageType>(args_info.input_arg))\n\n  // Remove aberrant pixels\n  using MedianType = rtk::ConditionalMedianImageFilter<OutputImageType>;\n  auto median = MedianType::New();\n  median->SetThresholdMultiplier(args_info.multiplier_arg);\n  MedianType::MedianRadiusType radius;\n  if (args_info.radius_given)\n  {\n    radius.Fill(args_info.radius_arg[0]);\n    for (unsigned int i = 0; i < args_info.radius_given; i++)\n      radius[i] = args_info.radius_arg[i];\n  }\n  median->SetRadius(radius);\n  median->SetInput(input);\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(median->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkspectraldenoiseprojections/rtkspectraldenoiseprojections.ggo",
    "content": "purpose \"Replaces aberrant pixels by the median in a small neighborhood around them. Pixels are aberrant if the difference between their value and the median is larger that threshold multiplier * the standard deviation in the neighborhood\"\n\noption \"verbose\"  v \"Verbose execution\"                                                                                   flag      off\noption \"input\"    i \"Input file name\"                                                                                    string    yes\noption \"output\"   o \"Output file name\"                                                                                    string    yes\noption \"multiplier\" m \"Threshold multiplier (actual threshold is obtained by multiplying by standard dev. of neighborhood)\" double no default=\"1\"\noption \"radius\"    r \"Radius of neighborhood in each direction (actual radius is 2r+1)\"                                   int     multiple no   default=\"1\"\n"
  },
  {
    "path": "applications/rtkspectralforwardmodel/CMakeLists.txt",
    "content": "WRAP_GGO(rtkspectralforwardmodel_GGO_C rtkspectralforwardmodel.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkspectralforwardmodel rtkspectralforwardmodel.cxx ${rtkspectralforwardmodel_GGO_C})\ntarget_link_libraries(rtkspectralforwardmodel RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkspectralforwardmodel)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n"
  },
  {
    "path": "applications/rtkspectralforwardmodel/rtkspectralforwardmodel.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkspectralforwardmodel_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n#include \"rtkSpectralForwardModelImageFilter.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkspectralforwardmodel, args_info);\n\n  using PixelValueType = float;\n  constexpr unsigned int Dimension = 3;\n  using DecomposedProjectionType = itk::VectorImage<PixelValueType, Dimension>;\n  using MeasuredProjectionsType = itk::VectorImage<PixelValueType, Dimension>;\n  using IncidentSpectrumImageType = itk::Image<PixelValueType, Dimension>;\n  using DetectorResponseImageType = itk::Image<PixelValueType, Dimension - 1>;\n  using MaterialAttenuationsImageType = itk::Image<PixelValueType, Dimension - 1>;\n\n  // Read all inputs\n  DecomposedProjectionType::Pointer decomposedProjection;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(decomposedProjection = itk::ReadImage<DecomposedProjectionType>(args_info.input_arg))\n\n  IncidentSpectrumImageType::Pointer incidentSpectrum;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(incidentSpectrum = itk::ReadImage<IncidentSpectrumImageType>(args_info.incident_arg))\n\n  DetectorResponseImageType::Pointer detectorResponse;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(detectorResponse = itk::ReadImage<DetectorResponseImageType>(args_info.detector_arg))\n\n  MaterialAttenuationsImageType::Pointer materialAttenuations;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(materialAttenuations =\n                                  itk::ReadImage<MaterialAttenuationsImageType>(args_info.attenuations_arg))\n\n  // Get parameters from the images\n  const unsigned int NumberOfMaterials = materialAttenuations->GetLargestPossibleRegion().GetSize()[0];\n  const unsigned int NumberOfSpectralBins = args_info.thresholds_given;\n  const unsigned int MaximumEnergy = incidentSpectrum->GetLargestPossibleRegion().GetSize()[0];\n\n  // Generate a set of zero-filled photon count projections\n  auto measuredProjections = MeasuredProjectionsType::New();\n  measuredProjections->CopyInformation(decomposedProjection);\n  measuredProjections->SetVectorLength(NumberOfSpectralBins);\n  measuredProjections->Allocate();\n\n  // Read the thresholds on command line\n  itk::VariableLengthVector<unsigned int> thresholds;\n  thresholds.SetSize(NumberOfSpectralBins + 1);\n  for (unsigned int i = 0; i < NumberOfSpectralBins; i++)\n    thresholds[i] = args_info.thresholds_arg[i];\n\n  // Add the maximum pulse height at the end\n  unsigned int MaximumPulseHeight = detectorResponse->GetLargestPossibleRegion().GetSize()[1];\n  thresholds[NumberOfSpectralBins] = MaximumPulseHeight;\n\n  // Check that the inputs have the expected size\n  DecomposedProjectionType::IndexType indexDecomp;\n  indexDecomp.Fill(0);\n  if (decomposedProjection->GetPixel(indexDecomp).Size() != NumberOfMaterials)\n    itkGenericExceptionMacro(<< \"Decomposed projections (i.e. initialization data) image has vector size \"\n                             << decomposedProjection->GetPixel(indexDecomp).Size() << \", should be \"\n                             << NumberOfMaterials);\n\n  MeasuredProjectionsType::IndexType indexSpect;\n  indexSpect.Fill(0);\n  if (measuredProjections->GetPixel(indexSpect).Size() != NumberOfSpectralBins)\n    itkGenericExceptionMacro(<< \"Spectral projections (i.e. photon count data) image has vector size \"\n                             << measuredProjections->GetPixel(indexSpect).Size() << \", should be \"\n                             << NumberOfSpectralBins);\n\n  if (detectorResponse->GetLargestPossibleRegion().GetSize()[0] != MaximumEnergy)\n    itkGenericExceptionMacro(<< \"Detector response image has \"\n                             << detectorResponse->GetLargestPossibleRegion().GetSize()[0] << \"energies, should have \"\n                             << MaximumEnergy);\n\n  // Create and set the filter\n  auto forward = rtk::SpectralForwardModelImageFilter<DecomposedProjectionType,\n                                                      MeasuredProjectionsType,\n                                                      IncidentSpectrumImageType>::New();\n  forward->SetInputDecomposedProjections(decomposedProjection);\n  forward->SetInputMeasuredProjections(measuredProjections);\n  forward->SetInputIncidentSpectrum(incidentSpectrum);\n  forward->SetDetectorResponse(detectorResponse);\n  forward->SetMaterialAttenuations(materialAttenuations);\n  forward->SetThresholds(thresholds);\n  forward->SetIsSpectralCT(true);\n  if (args_info.cramer_rao_given)\n    forward->SetComputeCramerRaoLowerBound(true);\n  if (args_info.variances_given)\n    forward->SetComputeVariances(true);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(forward->Update())\n\n  // Write output\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(forward->GetOutput(), args_info.output_arg))\n\n  // If requested, write the Cramer-Rao lower bound\n  if (args_info.cramer_rao_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(forward->GetOutputCramerRaoLowerBound(), args_info.cramer_rao_arg))\n  }\n\n  // If requested, write the variance\n  if (args_info.variances_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(forward->GetOutputVariances(), args_info.variances_arg))\n  }\n\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkspectralforwardmodel/rtkspectralforwardmodel.ggo",
    "content": "purpose \"Computes expected photon counts from incident spectrum, material attenuations, detector response and material-decomposed projections\"\n\noption \"verbose\"    v \"Verbose execution\"                                                 flag                         off\noption \"output\"     o \"Output file name (photon counts)\"                                  string                       yes\noption \"input\"      i \"Material-decomposed projections\"                                   string                       yes\noption \"detector\"   d \"Detector response file\"                                            string                       yes\noption \"incident\"   - \"Incident spectrum file\"                                            string                       yes\noption \"attenuations\" a \"Material attenuations file\"                                      string                       yes\noption \"thresholds\" t \"Lower threshold of bins, expressed in pulse height\"                double                       yes multiple\noption \"cramer_rao\" - \"File name for the output Cramer Rao Lower Bound (estimation of the variance in the material decomposed images)\"  string   no\noption \"variances\"  - \"Output variances of photon counts, file name\"                      string                       no\n"
  },
  {
    "path": "applications/rtkspectralonestep/CMakeLists.txt",
    "content": "WRAP_GGO(rtkspectralonestep_GGO_C rtkspectralonestep.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ../rtkiterations_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkspectralonestep rtkspectralonestep.cxx ${rtkspectralonestep_GGO_C})\ntarget_link_libraries(rtkspectralonestep RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkspectralonestep)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkspectralonestep/rtkspectralonestep.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkspectralonestep_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkMechlemOneStepSpectralReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkReorderProjectionsImageFilter.h\"\n#include \"rtkSpectralForwardModelImageFilter.h\"\n\n#include <algorithm> // std::shuffle\n#include <vector>    // std::vector\n#include <random>    // std::default_random_engine\n#include <iostream>\n#include <iterator>\n\n#include <itkImageFileWriter.h>\n\nitk::ImageIOBase::Pointer\nGetFileHeader(const std::string & filename)\n{\n  itk::ImageIOBase::Pointer reader =\n    itk::ImageIOFactory::CreateImageIO(filename.c_str(), itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n  if (!reader)\n  {\n    itkGenericExceptionMacro(<< \"Could not read \" << filename);\n  }\n  reader->SetFileName(filename);\n  reader->ReadImageInformation();\n  return reader;\n}\n\nnamespace rtk\n{\ntemplate <unsigned int VNumberOfBins, unsigned int VNumberOfMaterials>\nvoid\nrtkspectralonestep(const args_info_rtkspectralonestep & args_info)\n{\n  using dataType = float;\n  constexpr unsigned int Dimension = 3;\n\n  // Define types for the input images\n#ifdef RTK_USE_CUDA\n  using MaterialVolumesType = typename itk::CudaImage<itk::Vector<dataType, VNumberOfMaterials>, Dimension>;\n  using MeasuredProjectionsType = typename itk::CudaImage<itk::Vector<dataType, VNumberOfBins>, Dimension>;\n  using IncidentSpectrumType = itk::CudaImage<dataType, Dimension>;\n  using DetectorResponseType = itk::CudaImage<dataType, 2>;\n  using MaterialAttenuationsType = itk::CudaImage<dataType, 2>;\n#else\n  using MaterialVolumesType = typename itk::Image<itk::Vector<dataType, VNumberOfMaterials>, Dimension>;\n  using MeasuredProjectionsType = typename itk::Image<itk::Vector<dataType, VNumberOfBins>, Dimension>;\n  using IncidentSpectrumType = itk::Image<dataType, Dimension>;\n  using DetectorResponseType = itk::Image<dataType, 2>;\n  using MaterialAttenuationsType = itk::Image<dataType, 2>;\n#endif\n\n  // Instantiate and update the readers\n  typename MeasuredProjectionsType::Pointer mea;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mea = itk::ReadImage<MeasuredProjectionsType>(args_info.spectral_arg))\n\n  IncidentSpectrumType::Pointer incidentSpectrum;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(incidentSpectrum = itk::ReadImage<IncidentSpectrumType>(args_info.incident_arg))\n\n  DetectorResponseType::Pointer detectorResponse;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(detectorResponse = itk::ReadImage<DetectorResponseType>(args_info.detector_arg))\n\n  MaterialAttenuationsType::Pointer materialAttenuations;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(materialAttenuations =\n                                  itk::ReadImage<MaterialAttenuationsType>(args_info.attenuations_arg))\n\n  // Read Support Mask if given\n  IncidentSpectrumType::Pointer supportmask;\n  if (args_info.mask_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(supportmask = itk::ReadImage<IncidentSpectrumType>(args_info.mask_arg))\n  }\n\n  // Read spatial regularization weights if given\n  IncidentSpectrumType::Pointer spatialRegulWeighs;\n  if (args_info.regul_spatial_weights_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(spatialRegulWeighs =\n                                    itk::ReadImage<IncidentSpectrumType>(args_info.regul_spatial_weights_arg))\n  }\n\n  // Read projections weights if given\n  IncidentSpectrumType::Pointer projectionWeights;\n  if (args_info.projection_weights_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(projectionWeights =\n                                    itk::ReadImage<IncidentSpectrumType>(args_info.projection_weights_arg))\n  }\n\n  // Create input: either an existing volume read from a file or a blank image\n  typename MaterialVolumesType::Pointer input;\n  if (args_info.input_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(input = itk::ReadImage<MaterialVolumesType>(args_info.input_arg))\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = typename rtk::ConstantImageSource<MaterialVolumesType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkspectralonestep>(constantImageSource,\n                                                                                              args_info);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(constantImageSource->Update())\n    input = constantImageSource->GetOutput();\n  }\n\n  // Read the material attenuations image as a matrix\n  MaterialAttenuationsType::IndexType indexMat;\n  unsigned int                        nEnergies = materialAttenuations->GetLargestPossibleRegion().GetSize()[1];\n  vnl_matrix<dataType>                materialAttenuationsMatrix(nEnergies, VNumberOfMaterials);\n  for (unsigned int energy = 0; energy < nEnergies; energy++)\n  {\n    indexMat[1] = energy;\n    for (unsigned int material = 0; material < VNumberOfMaterials; material++)\n    {\n      indexMat[0] = material;\n      materialAttenuationsMatrix[energy][material] = materialAttenuations->GetPixel(indexMat);\n    }\n  }\n\n  // Read the thresholds on command line and check their number\n  itk::VariableLengthVector<double> thresholds;\n  thresholds.SetSize(VNumberOfBins + 1);\n  if (args_info.thresholds_given == VNumberOfBins)\n  {\n    for (unsigned int bin = 0; bin < VNumberOfBins; bin++)\n      thresholds[bin] = args_info.thresholds_arg[bin];\n\n    // Add the maximum pulse height at the end\n    double MaximumPulseHeight = detectorResponse->GetLargestPossibleRegion().GetSize()[1];\n    thresholds[VNumberOfBins] = MaximumPulseHeight;\n  }\n  else\n  {\n    itkGenericExceptionMacro(<< \"Number of thresholds \" << args_info.thresholds_given\n                             << \" does not match the number of bins \" << VNumberOfBins);\n  }\n\n  // Read the detector response image as a matrix, and bin it\n  vnl_matrix<dataType> drm =\n    rtk::SpectralBinDetectorResponse<dataType>(detectorResponse.GetPointer(), thresholds, nEnergies);\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Read the regularization parameters\n  typename MaterialVolumesType::RegionType::SizeType regulRadius;\n  if (args_info.regul_radius_given)\n    for (unsigned int i = 0; i < Dimension; i++)\n      regulRadius[i] = args_info.regul_radius_arg[std::min(i, args_info.regul_radius_given - 1)];\n  else\n    regulRadius.Fill(0);\n\n  typename MaterialVolumesType::PixelType regulWeights;\n  if (args_info.regul_weights_given)\n    for (unsigned int i = 0; i < VNumberOfMaterials; i++)\n      regulWeights[i] = args_info.regul_weights_arg[std::min(i, args_info.regul_weights_given - 1)];\n  else\n    regulWeights.Fill(0);\n\n  // Set the forward and back projection filters to be used\n  using MechlemFilterType = typename rtk::\n    MechlemOneStepSpectralReconstructionFilter<MaterialVolumesType, MeasuredProjectionsType, IncidentSpectrumType>;\n  auto mechlemOneStep = MechlemFilterType::New();\n  SetForwardProjectionFromGgo(args_info, mechlemOneStep.GetPointer());\n  SetBackProjectionFromGgo(args_info, mechlemOneStep.GetPointer());\n  mechlemOneStep->SetInputMaterialVolumes(input);\n  mechlemOneStep->SetInputIncidentSpectrum(incidentSpectrum);\n  mechlemOneStep->SetBinnedDetectorResponse(drm);\n  mechlemOneStep->SetMaterialAttenuations(materialAttenuationsMatrix);\n  mechlemOneStep->SetNumberOfIterations(args_info.niterations_arg);\n  mechlemOneStep->SetNumberOfSubsets(args_info.subsets_arg);\n  mechlemOneStep->SetRegularizationRadius(regulRadius);\n  mechlemOneStep->SetRegularizationWeights(regulWeights);\n  if (args_info.reset_nesterov_given)\n    mechlemOneStep->SetResetNesterovEvery(args_info.reset_nesterov_arg);\n  if (args_info.mask_given)\n    mechlemOneStep->SetSupportMask(supportmask);\n  if (args_info.regul_spatial_weights_given)\n    mechlemOneStep->SetSpatialRegularizationWeights(spatialRegulWeighs);\n  mechlemOneStep->SetInputMeasuredProjections(mea);\n  mechlemOneStep->SetGeometry(geometry);\n  if (args_info.projection_weights_given)\n    mechlemOneStep->SetProjectionWeights(projectionWeights);\n\n  REPORT_ITERATIONS(mechlemOneStep, MechlemFilterType, MaterialVolumesType);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mechlemOneStep->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(mechlemOneStep->GetOutput(), args_info.output_arg))\n}\n} // namespace rtk\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkspectralonestep, args_info);\n  try\n  {\n    itk::ImageIOBase::Pointer headerInputMeasuredProjections = GetFileHeader(args_info.spectral_arg);\n    unsigned int              nBins = headerInputMeasuredProjections->GetNumberOfComponents();\n    itk::ImageIOBase::Pointer headerAttenuations = GetFileHeader(args_info.attenuations_arg);\n    unsigned int              nMaterials = headerAttenuations->GetDimensions(0);\n\n    if (nMaterials == 3 && nBins == 1)\n      rtk::rtkspectralonestep<1, 3>(args_info);\n    else if (nMaterials == 2 && nBins == 1)\n      rtk::rtkspectralonestep<1, 2>(args_info);\n    else if (nMaterials == 2 && nBins == 2)\n      rtk::rtkspectralonestep<2, 2>(args_info);\n    else if (nMaterials == 2 && nBins == 5)\n      rtk::rtkspectralonestep<5, 2>(args_info);\n    else if (nMaterials == 3 && nBins == 5)\n      rtk::rtkspectralonestep<5, 3>(args_info);\n    else\n    {\n      std::cerr << nMaterials << \" materials and \" << nBins << \" bins is not handled\" << std::endl;\n      return EXIT_FAILURE;\n    }\n  }\n  catch (itk::ExceptionObject & err)\n  {\n    std::cerr << \"ExceptionObject caught in rtkspectraleonestep.\" << std::endl;\n    std::cerr << err << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkspectralonestep/rtkspectralonestep.ggo",
    "content": "purpose \"Reconstructs a set of 3D volumes from a set of photon counts projections, using the method described by Mechlem et al. in IEEE TMI in 2017\"\n\noption \"verbose\"               v \"Verbose execution\"                                                 flag   off\noption \"geometry\"              g \"XML geometry file name\"                                            string yes\noption \"output\"                o \"Output file name\"                                                  string yes\noption \"niterations\"           n \"Number of iterations\"                                              int    no   default=\"5\"\noption \"input\"                 i \"Material volumes initial guess\"                                    string no\noption \"spectral\"              s \"Spectral projections, i.e. photon counts\"                          string yes\noption \"detector\"              d \"Detector response file\"                                            string yes\noption \"incident\"              - \"Incident spectrum file (mhd image)\"                                string yes\noption \"attenuations\"          a \"Material attenuations file\"                                        string yes\noption \"mask\"                  m \"Apply a support binary mask: reconstruction kept null outside\"     string no\noption \"regul_spatial_weights\" - \"One-component image of spatial regularization weights\"             string no\noption \"projection_weights\"    - \"One-component image of projection weights (size of photon counts)\" string no\noption \"thresholds\"            t \"Lower threshold of bins, expressed in pulse height\"                double yes  multiple\noption \"subsets\"               - \"Number of subsets of projections (should not exceed 6)\"            int    no   default=\"4\"\noption \"regul_weights\"         - \"Regularization parameters for each material\"                       double multiple no\noption \"regul_radius\"          - \"Radius of the neighborhood for regularization\"                     int    multiple no\noption \"reset_nesterov\"        - \"Reset Nesterov after a number of subsets\"                          int    no\n"
  },
  {
    "path": "applications/rtkspectralrooster/CMakeLists.txt",
    "content": "WRAP_GGO(rtkspectralrooster_GGO_C rtkspectralrooster.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkspectralrooster rtkspectralrooster.cxx ${rtkspectralrooster_GGO_C})\ntarget_link_libraries(rtkspectralrooster RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkspectralrooster)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkspectralrooster/rtkspectralrooster.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkspectralrooster_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkFourDROOSTERConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkSignalToInterpolationWeights.h\"\n#include \"rtkVectorImageToImageFilter.h\"\n#include \"rtkImageToVectorImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"itkCudaImage.h\"\n#  include \"rtkCudaConstantVolumeSeriesSource.h\"\n#endif\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkspectralrooster, args_info);\n\n  using PixelValueType = float;\n  constexpr unsigned int Dimension = 3;\n\n  using DecomposedProjectionType = itk::VectorImage<PixelValueType, Dimension>;\n\n  using MaterialsVolumeType = itk::VectorImage<PixelValueType, Dimension>;\n\n#ifdef RTK_USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<PixelValueType, Dimension + 1>;\n  using ProjectionStackType = itk::CudaImage<PixelValueType, Dimension>;\n#else\n  using VolumeSeriesType = itk::Image<PixelValueType, Dimension + 1>;\n  using ProjectionStackType = itk::Image<PixelValueType, Dimension>;\n#endif\n\n  // Projections reader\n  DecomposedProjectionType::Pointer decomposedProjection;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(decomposedProjection =\n                                  itk::ReadImage<DecomposedProjectionType>(args_info.projection_arg))\n\n  const unsigned int NumberOfMaterials = decomposedProjection->GetVectorLength();\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create 4D input. Fill it either with an existing materials volume read from a file or a blank image\n  VolumeSeriesType::Pointer input;\n\n  auto vecVol2VolSeries = rtk::VectorImageToImageFilter<MaterialsVolumeType, VolumeSeriesType>::New();\n\n  if (args_info.input_given)\n  {\n    // Using std::cout because itkWarningMacro cannot be used outside a class\n    if (args_info.like_given)\n      std::cout << \"WARNING: Option --like ignored, since option --input was passed\" << std::endl;\n\n    MaterialsVolumeType::Pointer reference;\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(reference = itk::ReadImage<MaterialsVolumeType>(args_info.input_arg))\n    vecVol2VolSeries->SetInput(reference);\n    vecVol2VolSeries->Update();\n    input = vecVol2VolSeries->GetOutput();\n  }\n  else if (args_info.like_given)\n  {\n    MaterialsVolumeType::Pointer reference;\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(reference = itk::ReadImage<MaterialsVolumeType>(args_info.like_arg))\n    vecVol2VolSeries->SetInput(reference);\n    vecVol2VolSeries->UpdateOutputInformation();\n\n    using ConstantImageSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    constantImageSource->SetInformationFromImage(vecVol2VolSeries->GetOutput());\n    constantImageSource->Update();\n    input = constantImageSource->GetOutput();\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n\n    VolumeSeriesType::SizeType      inputSize;\n    VolumeSeriesType::SpacingType   inputSpacing;\n    VolumeSeriesType::PointType     inputOrigin;\n    VolumeSeriesType::DirectionType inputDirection;\n\n    inputSize[Dimension] = decomposedProjection->GetVectorLength();\n    inputSpacing[Dimension] = 1;\n    inputOrigin[Dimension] = 0;\n    inputDirection.SetIdentity();\n\n    for (unsigned int i = 0; i < std::min(args_info.size_given, Dimension); i++)\n      inputSize[i] = args_info.size_arg[i];\n\n    inputSpacing.Fill(args_info.spacing_arg[0]);\n    for (unsigned int i = 0; i < std::min(args_info.spacing_given, Dimension); i++)\n      inputSpacing[i] = args_info.spacing_arg[i];\n\n    for (unsigned int i = 0; i < Dimension; i++)\n      inputOrigin[i] = inputSpacing[i] * (inputSize[i] - 1) * -0.5;\n    for (unsigned int i = 0; i < std::min(args_info.origin_given, Dimension); i++)\n      inputOrigin[i] = args_info.origin_arg[i];\n\n    if (args_info.direction_given)\n      for (unsigned int i = 0; i < Dimension; i++)\n        for (unsigned int j = 0; j < Dimension; j++)\n          inputDirection[i][j] = args_info.direction_arg[i * Dimension + j];\n    else\n      inputDirection.SetIdentity();\n\n    constantImageSource->SetOrigin(inputOrigin);\n    constantImageSource->SetSpacing(inputSpacing);\n    constantImageSource->SetDirection(inputDirection);\n    constantImageSource->SetSize(inputSize);\n    constantImageSource->SetConstant(0.);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(constantImageSource->Update());\n    input = constantImageSource->GetOutput();\n  }\n\n  // Duplicate geometry and transform the N M-vector projections into N*M scalar projections\n  // Each material will occupy one frame of the 4D reconstruction, therefore all projections\n  // of one material need to have the same phase.\n  // Note : the 4D CG filter is optimized when projections with identical phases are packed together\n\n  // Geometry\n  unsigned int initialNumberOfProjections = decomposedProjection->GetLargestPossibleRegion().GetSize()[Dimension - 1];\n  for (unsigned int material = 1; material < NumberOfMaterials; material++)\n  {\n    for (unsigned int proj = 0; proj < initialNumberOfProjections; proj++)\n    {\n      geometry->AddProjectionInRadians(geometry->GetSourceToIsocenterDistances()[proj],\n                                       geometry->GetSourceToDetectorDistances()[proj],\n                                       geometry->GetGantryAngles()[proj],\n                                       geometry->GetProjectionOffsetsX()[proj],\n                                       geometry->GetProjectionOffsetsY()[proj],\n                                       geometry->GetOutOfPlaneAngles()[proj],\n                                       geometry->GetInPlaneAngles()[proj],\n                                       geometry->GetSourceOffsetsX()[proj],\n                                       geometry->GetSourceOffsetsY()[proj]);\n      geometry->SetCollimationOfLastProjection(geometry->GetCollimationUInf()[proj],\n                                               geometry->GetCollimationUSup()[proj],\n                                               geometry->GetCollimationVInf()[proj],\n                                               geometry->GetCollimationVSup()[proj]);\n    }\n  }\n\n  // Signal\n  std::vector<double> fakeSignal;\n  for (unsigned int material = 0; material < NumberOfMaterials; material++)\n  {\n    for (unsigned int proj = 0; proj < initialNumberOfProjections; proj++)\n    {\n      fakeSignal.push_back(itk::Math::Round<double, double>((double)material / (double)NumberOfMaterials * 1000) /\n                           1000);\n    }\n  }\n\n  // Projections\n  auto vproj2proj = rtk::VectorImageToImageFilter<DecomposedProjectionType, ProjectionStackType>::New();\n  vproj2proj->SetInput(decomposedProjection);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(vproj2proj->Update())\n\n  // Release the memory holding the stack of original projections\n  decomposedProjection->ReleaseData();\n\n  // Compute the interpolation weights\n  auto signalToInterpolationWeights = rtk::SignalToInterpolationWeights::New();\n  signalToInterpolationWeights->SetSignal(fakeSignal);\n  signalToInterpolationWeights->SetNumberOfReconstructedFrames(NumberOfMaterials);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(signalToInterpolationWeights->Update())\n\n  // Set the forward and back projection filters to be used\n  auto rooster = rtk::FourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::New();\n  SetForwardProjectionFromGgo(args_info, rooster.GetPointer());\n  SetBackProjectionFromGgo(args_info, rooster.GetPointer());\n  rooster->SetInputVolumeSeries(input);\n  rooster->SetCG_iterations(args_info.cgiter_arg);\n  rooster->SetMainLoop_iterations(args_info.niter_arg);\n  rooster->SetCudaConjugateGradient(args_info.cudacg_flag);\n  rooster->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  // Set the newly ordered arguments\n  rooster->SetInputProjectionStack(vproj2proj->GetOutput());\n  rooster->SetGeometry(geometry);\n  rooster->SetWeights(signalToInterpolationWeights->GetOutput());\n  rooster->SetSignal(fakeSignal);\n\n  // For each optional regularization step, set whether or not\n  // it should be performed, and provide the necessary inputs\n\n  // Positivity\n  if (args_info.nopositivity_flag)\n    rooster->SetPerformPositivity(false);\n  else\n    rooster->SetPerformPositivity(true);\n\n  // No motion mask is used, since there is no motion\n  rooster->SetPerformMotionMask(false);\n\n  // Spatial TV\n  if (args_info.gamma_space_given)\n  {\n    rooster->SetGammaTVSpace(args_info.gamma_space_arg);\n    rooster->SetTV_iterations(args_info.tviter_arg);\n    rooster->SetPerformTVSpatialDenoising(true);\n  }\n  else\n    rooster->SetPerformTVSpatialDenoising(false);\n\n  // Spatial wavelets\n  if (args_info.threshold_given)\n  {\n    rooster->SetSoftThresholdWavelets(args_info.threshold_arg);\n    rooster->SetOrder(args_info.order_arg);\n    rooster->SetNumberOfLevels(args_info.levels_arg);\n    rooster->SetPerformWaveletsSpatialDenoising(true);\n  }\n  else\n    rooster->SetPerformWaveletsSpatialDenoising(false);\n\n  // Temporal TV\n  if (args_info.gamma_time_given)\n  {\n    rooster->SetGammaTVTime(args_info.gamma_time_arg);\n    rooster->SetTV_iterations(args_info.tviter_arg);\n    rooster->SetPerformTVTemporalDenoising(true);\n  }\n  else\n    rooster->SetPerformTVTemporalDenoising(false);\n\n  // Temporal L0\n  if (args_info.lambda_time_arg)\n  {\n    rooster->SetLambdaL0Time(args_info.lambda_time_arg);\n    rooster->SetL0_iterations(args_info.l0iter_arg);\n    rooster->SetPerformL0TemporalDenoising(true);\n  }\n  else\n    rooster->SetPerformL0TemporalDenoising(false);\n\n  // Total nuclear variation\n  if (args_info.gamma_tnv_given)\n  {\n    rooster->SetGammaTNV(args_info.gamma_tnv_arg);\n    rooster->SetTV_iterations(args_info.tviter_arg);\n    rooster->SetPerformTNVDenoising(true);\n  }\n  else\n    rooster->SetPerformTNVDenoising(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rooster->Update())\n\n  // Convert to result to a vector image\n  auto volSeries2VecVol = rtk::ImageToVectorImageFilter<VolumeSeriesType, MaterialsVolumeType>::New();\n  volSeries2VecVol->SetInput(rooster->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(volSeries2VecVol->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(volSeries2VecVol->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkspectralrooster/rtkspectralrooster.ggo",
    "content": "purpose \"Reconstructs a 3D + material vector volume from a vector projection stack, alternating between conjugate gradient optimization and regularization, including between materials\"\n\noption \"verbose\"     v \"Verbose execution\"                                     flag   off\noption \"geometry\"    g \"XML geometry file name\"                                string yes\noption \"output\"      o \"Output file name\"                                      string yes\noption \"niter\"       n \"Number of main loop iterations\"                        int    no   default=\"5\"\noption \"cgiter\"      - \"Number of conjugate gradient nested iterations\"        int    no   default=\"4\"\noption \"cudacg\"      - \"Perform conjugate gradient calculations on GPU\"        flag   off\noption \"input\"       i \"Input volume\"                                          string no\noption \"projection\"  p \"Vector projections file\"                               string yes\noption \"nodisplaced\" - \"Disable the displaced detector filter\"                 flag   off\n\nsection \"Regularization\"\noption \"nopositivity\" - \"Do not enforce positivity\"                                                             flag    off\noption \"tviter\"      - \"Total variation (spatial, temporal and nuclear) regularization: number of iterations\"   int     no      default=\"10\"\noption \"gamma_space\" - \"Total variation spatial regularization parameter. The larger, the smoother\"             double  no\noption \"threshold\"   - \"Daubechies wavelets spatial regularization: soft threshold\"                             float   no\noption \"order\"       - \"Daubechies wavelets spatial regularization: order of the wavelets\"                      int     no      default=\"5\"\noption \"levels\"      - \"Daubechies wavelets spatial regularization: number of decomposition levels\"             int     no      default=\"3\"\noption \"gamma_time\"  - \"Total variation temporal regularization parameter. The larger, the smoother\"            double  no\noption \"lambda_time\" - \"Temporal gradient's L0 norm regularization parameter. The larger, the stronger\"         double  no\noption \"l0iter\"      - \"Temporal gradient's L0 norm regularization: number of iterations\"                       int     no      default=\"5\"\noption \"gamma_tnv\"   - \"Total nuclear variation regularization parameter. The larger, the smoother\"             double  no\n"
  },
  {
    "path": "applications/rtkspectralsimplexdecomposition/CMakeLists.txt",
    "content": "WRAP_GGO(rtkspectralsimplexdecomposition_GGO_C rtkspectralsimplexdecomposition.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkspectralsimplexdecomposition rtkspectralsimplexdecomposition.cxx ${rtkspectralsimplexdecomposition_GGO_C})\ntarget_link_libraries(rtkspectralsimplexdecomposition RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkspectralsimplexdecomposition)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n"
  },
  {
    "path": "applications/rtkspectralsimplexdecomposition/rtkspectralsimplexdecomposition.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkspectralsimplexdecomposition_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n#include \"rtkSimplexSpectralProjectionsDecompositionImageFilter.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkspectralsimplexdecomposition, args_info);\n\n  using PixelValueType = float;\n  constexpr unsigned int Dimension = 3;\n\n  using DecomposedProjectionType = itk::VectorImage<PixelValueType, Dimension>;\n\n  using SpectralProjectionsType = itk::VectorImage<PixelValueType, Dimension>;\n\n  using IncidentSpectrumImageType = itk::Image<PixelValueType, Dimension>;\n\n  using DetectorResponseImageType = itk::Image<PixelValueType, Dimension - 1>;\n\n  using MaterialAttenuationsImageType = itk::Image<PixelValueType, Dimension - 1>;\n\n  // Read all inputs\n  DecomposedProjectionType::Pointer decomposedProjection;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(decomposedProjection = itk::ReadImage<DecomposedProjectionType>(args_info.input_arg))\n\n  SpectralProjectionsType::Pointer spectralProjection;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(spectralProjection = itk::ReadImage<SpectralProjectionsType>(args_info.spectral_arg))\n\n  IncidentSpectrumImageType::Pointer incidentSpectrum;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(incidentSpectrum = itk::ReadImage<IncidentSpectrumImageType>(args_info.incident_arg))\n\n  DetectorResponseImageType::Pointer detectorResponse;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(detectorResponse = itk::ReadImage<DetectorResponseImageType>(args_info.detector_arg))\n\n  MaterialAttenuationsImageType::Pointer materialAttenuations;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(materialAttenuations =\n                                  itk::ReadImage<MaterialAttenuationsImageType>(args_info.attenuations_arg))\n\n  // Get parameters from the images\n  const unsigned int NumberOfMaterials = materialAttenuations->GetLargestPossibleRegion().GetSize()[0];\n  const unsigned int NumberOfSpectralBins = spectralProjection->GetVectorLength();\n  const unsigned int MaximumEnergy = incidentSpectrum->GetLargestPossibleRegion().GetSize()[0];\n\n  // Read the thresholds on command line and check their number\n  itk::VariableLengthVector<unsigned int> thresholds;\n  thresholds.SetSize(NumberOfSpectralBins + 1);\n  if (args_info.thresholds_given == NumberOfSpectralBins)\n  {\n    for (unsigned int i = 0; i < NumberOfSpectralBins; i++)\n      thresholds[i] = args_info.thresholds_arg[i];\n\n    // Add the maximum pulse height at the end\n    unsigned int MaximumPulseHeight = detectorResponse->GetLargestPossibleRegion().GetSize()[1];\n    thresholds[NumberOfSpectralBins] = MaximumPulseHeight;\n  }\n  else\n    itkGenericExceptionMacro(<< \"Number of thresholds \" << args_info.thresholds_given\n                             << \" does not match the number of bins \" << NumberOfSpectralBins);\n\n  // Check that the inputs have the expected size\n  DecomposedProjectionType::IndexType indexDecomp;\n  indexDecomp.Fill(0);\n  if (decomposedProjection->GetPixel(indexDecomp).Size() != NumberOfMaterials)\n    itkGenericExceptionMacro(<< \"Decomposed projections (i.e. initialization data) image has vector size \"\n                             << decomposedProjection->GetPixel(indexDecomp).Size() << \", should be \"\n                             << NumberOfMaterials);\n\n  SpectralProjectionsType::IndexType indexSpect;\n  indexSpect.Fill(0);\n  if (spectralProjection->GetPixel(indexSpect).Size() != NumberOfSpectralBins)\n    itkGenericExceptionMacro(<< \"Spectral projections (i.e. photon count data) image has vector size \"\n                             << spectralProjection->GetPixel(indexSpect).Size() << \", should be \"\n                             << NumberOfSpectralBins);\n\n  if (detectorResponse->GetLargestPossibleRegion().GetSize()[0] != MaximumEnergy)\n    itkGenericExceptionMacro(<< \"Detector response image has \"\n                             << detectorResponse->GetLargestPossibleRegion().GetSize()[0] << \"energies, should have \"\n                             << MaximumEnergy);\n\n  // Create and set the filter\n  auto simplex = rtk::SimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionType,\n                                                                         SpectralProjectionsType,\n                                                                         IncidentSpectrumImageType>::New();\n  simplex->SetInputDecomposedProjections(decomposedProjection);\n  simplex->SetGuessInitialization(args_info.guess_flag);\n  simplex->SetInputMeasuredProjections(spectralProjection);\n  simplex->SetInputIncidentSpectrum(incidentSpectrum);\n  simplex->SetDetectorResponse(detectorResponse);\n  simplex->SetMaterialAttenuations(materialAttenuations);\n  simplex->SetThresholds(thresholds);\n  simplex->SetNumberOfIterations(args_info.niterations_arg);\n  simplex->SetOptimizeWithRestarts(args_info.restarts_flag);\n  simplex->SetLogTransformEachBin(args_info.log_flag);\n  simplex->SetIsSpectralCT(true);\n\n  // Note: The simplex filter is set to perform several searches for each pixel,\n  // with different initializations, and keep the best one (SetOptimizeWithRestart(true)).\n  // While it may yield better results, these initializations are partially random,\n  // which makes the output non-reproducible.\n  // The default behavior, used for example in the tests, is not to use this feature\n  // (SetOptimizeWithRestart(false)), which makes the output reproducible.\n\n  if (args_info.weightsmap_given)\n    simplex->SetOutputInverseCramerRaoLowerBound(true);\n\n  if (args_info.fischer_given)\n    simplex->SetOutputFischerMatrix(true);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(simplex->Update())\n\n  // Write output\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(simplex->GetOutput(0), args_info.output_arg))\n\n  // If requested, write the weightsmap\n  if (args_info.weightsmap_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(simplex->GetOutput(1), args_info.weightsmap_arg))\n  }\n\n  // If requested, write the fisher information matrix\n  if (args_info.fischer_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(simplex->GetOutput(2), args_info.fischer_arg))\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkspectralsimplexdecomposition/rtkspectralsimplexdecomposition.ggo",
    "content": "purpose \"Decomposes spectral projections into materials\"\n\noption \"verbose\"    v \"Verbose execution\"                                                 flag                         off\noption \"output\"     o \"Output file name (decomposed projections)\"                         string                       yes\noption \"input\"      i \"Decomposed projections for initialization file name\"               string                       no\noption \"spectral\"   s \"Spectral projections to be decomposed\"                             string                       yes\noption \"detector\"   d \"Detector response file\"                                            string                       yes\noption \"incident\"   - \"Incident spectrum file\"                                            string                       yes\noption \"attenuations\" a \"Material attenuations file\"                                      string                       yes\noption \"niterations\" n \"Number of iterations\"                                             int                          no   default=\"300\"\noption \"thresholds\" t \"Lower threshold of bins, expressed in pulse height\"                double                       yes  multiple\noption \"weightsmap\" w \"File name for the output weights map (inverse noise variance)\"     string                       no\noption \"restarts\"   r \"Allow random restarts during optimization\"                         flag                         off\noption \"fischer\"    f \"File name for the Fischer information matrix\"                       string                      no\noption \"log\"        l \"Log transform each bin, and concatenate the projections with the decomposed ones\"      flag     off\noption \"guess\"      g \"Ignore values in input and initialize the simplex with a simple heuristic instead\"     flag     off\n"
  },
  {
    "path": "applications/rtksubselect/CMakeLists.txt",
    "content": "WRAP_GGO(rtksubselect_GGO_C rtksubselect.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtksubselect rtksubselect.cxx ${rtksubselect_GGO_C})\ntarget_link_libraries(rtksubselect RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtksubselect)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtksubselect/rtksubselect.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtksubselect_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkConstantImageSource.h\"\n\n#include <itkImageFileWriter.h>\n#include <itkRegularExpressionSeriesFileNames.h>\n#include <itkPasteImageFilter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtksubselect, args_info);\n\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<OutputImageType>;\n  auto reader = ReaderType::New();\n  rtk::SetProjectionsReaderFromGgo<ReaderType, args_info_rtksubselect>(reader, args_info);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update())\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Compute the indices of the selected projections\n  std::vector<int> indices;\n  int              n = geometry->GetGantryAngles().size();\n  if (args_info.last_given)\n    n = std::min(args_info.last_arg, n);\n  if (args_info.list_given)\n    for (unsigned int i = 0; i < args_info.list_given; i++)\n    {\n      indices.push_back(args_info.list_arg[i]);\n    }\n  else\n    for (int noProj = args_info.first_arg; noProj < n; noProj += args_info.step_arg)\n    {\n      indices.push_back(noProj);\n    }\n\n  // Output RTK geometry object\n  auto outputGeometry = rtk::ThreeDCircularProjectionGeometry::New();\n\n  // Output projections object\n  auto source = rtk::ConstantImageSource<OutputImageType>::New();\n  source->SetInformationFromImage(reader->GetOutput());\n  OutputImageType::SizeType outputSize = reader->GetOutput()->GetLargestPossibleRegion().GetSize();\n  outputSize[Dimension - 1] = indices.size();\n  source->SetSize(outputSize);\n  source->SetConstant(0);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(source->Update())\n\n  // Fill in the outputGeometry and the output projections\n  auto paste = itk::PasteImageFilter<OutputImageType>::New();\n  paste->SetSourceImage(reader->GetOutput());\n  paste->SetDestinationImage(source->GetOutput());\n\n  OutputImageType::RegionType sourceRegion;\n  OutputImageType::IndexType  destinationIndex;\n  for (unsigned int i = 0; i < indices.size(); i++)\n  {\n    // If it is not the first projection, we need to use the output of\n    // the paste filter as input\n    if (i)\n    {\n      OutputImageType::Pointer pimg = paste->GetOutput();\n      pimg->DisconnectPipeline();\n      paste->SetDestinationImage(pimg);\n    }\n\n    sourceRegion = reader->GetOutput()->GetLargestPossibleRegion();\n    sourceRegion.SetIndex(Dimension - 1, indices[i]);\n    sourceRegion.SetSize(Dimension - 1, 1);\n    paste->SetSourceRegion(sourceRegion);\n\n    destinationIndex = reader->GetOutput()->GetLargestPossibleRegion().GetIndex();\n    destinationIndex[Dimension - 1] = i;\n    paste->SetDestinationIndex(destinationIndex);\n\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(paste->Update())\n\n    // Fill in the output geometry object\n    outputGeometry->SetRadiusCylindricalDetector(geometry->GetRadiusCylindricalDetector());\n    outputGeometry->AddProjectionInRadians(geometry->GetSourceToIsocenterDistances()[indices[i]],\n                                           geometry->GetSourceToDetectorDistances()[indices[i]],\n                                           geometry->GetGantryAngles()[indices[i]],\n                                           geometry->GetProjectionOffsetsX()[indices[i]],\n                                           geometry->GetProjectionOffsetsY()[indices[i]],\n                                           geometry->GetOutOfPlaneAngles()[indices[i]],\n                                           geometry->GetInPlaneAngles()[indices[i]],\n                                           geometry->GetSourceOffsetsX()[indices[i]],\n                                           geometry->GetSourceOffsetsY()[indices[i]]);\n    outputGeometry->SetCollimationOfLastProjection(geometry->GetCollimationUInf()[indices[i]],\n                                                   geometry->GetCollimationUSup()[indices[i]],\n                                                   geometry->GetCollimationVInf()[indices[i]],\n                                                   geometry->GetCollimationVSup()[indices[i]]);\n  }\n\n  // Geometry writer\n  if (args_info.verbose_flag)\n    std::cout << \"Writing geometry information in \" << args_info.out_geometry_arg << \"...\" << std::endl;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(outputGeometry, args_info.out_geometry_arg))\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(paste->GetOutput(), args_info.out_proj_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtksubselect/rtksubselect.ggo",
    "content": "purpose \"Subselects a few projections from a list of projection files and a geometry file.\"\n\noption \"verbose\"       v \"Verbose execution\"                                         flag         off\noption \"geometry\"      g  \"XML geometry file name\"                                   string       yes\noption \"out_geometry\"  -  \"Output geometry file name\"                                string       yes\noption \"out_proj\"      -  \"Output projections stack file name\"                       string       yes\n\noption \"first\"     f \"First projection index\"                                    int          no  default=\"0\"\noption \"last\"      l \"Last projection index\"                                     int          no\noption \"step\"      s \"Step between projections\"                                  int          no  default=\"1\"\noption \"list\"      - \"List of projection indices to keep (0-based)\"              int multiple no\n\n"
  },
  {
    "path": "applications/rtktotalnuclearvariationdenoising/CMakeLists.txt",
    "content": "WRAP_GGO(rtktotalnuclearvariationdenoising_GGO_C rtktotalnuclearvariationdenoising.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtktotalnuclearvariationdenoising rtktotalnuclearvariationdenoising.cxx ${rtktotalnuclearvariationdenoising_GGO_C})\ntarget_link_libraries(rtktotalnuclearvariationdenoising RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtktotalnuclearvariationdenoising)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtktotalnuclearvariationdenoising/rtktotalnuclearvariationdenoising.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtktotalnuclearvariationdenoising_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n\n#include \"rtkTotalNuclearVariationDenoisingBPDQImageFilter.h\"\n\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtktotalnuclearvariationdenoising, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 4;           // Number of dimensions of the input image\n  constexpr unsigned int DimensionsProcessed = 3; // Number of dimensions along which the gradient is computed\n\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n\n  // Read input\n  OutputImageType::Pointer input;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(input = itk::ReadImage<OutputImageType>(args_info.input_arg))\n\n  // Apply total nuclear variation denoising\n  auto tv = rtk::TotalNuclearVariationDenoisingBPDQImageFilter<\n    OutputImageType,\n    itk::Image<itk::CovariantVector<OutputPixelType, DimensionsProcessed>, Dimension>>::New();\n  tv->SetInput(input);\n  tv->SetGamma(args_info.gamma_arg);\n  tv->SetNumberOfIterations(args_info.niter_arg);\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(tv->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtktotalnuclearvariationdenoising/rtktotalnuclearvariationdenoising.ggo",
    "content": "purpose \"Performs total nuclear variation denoising of a 3D + channels image.\"\n\noption \"verbose\"   v \"Verbose execution\"                                            flag         off\noption \"input\"     i \"Input file name\"                                              string       yes\noption \"output\"    o \"Output file name\"                                             string       yes\noption \"gamma\"     g \"TV term's weighting parameter\"                                double       no  default=\"1.0\"\noption \"niter\"     n \"Number of iterations\"                                         int          no  default=\"5\"\n"
  },
  {
    "path": "applications/rtktotalvariationdenoising/CMakeLists.txt",
    "content": "WRAP_GGO(rtktotalvariationdenoising_GGO_C rtktotalvariationdenoising.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtktotalvariationdenoising rtktotalvariationdenoising.cxx ${rtktotalvariationdenoising_GGO_C})\ntarget_link_libraries(rtktotalvariationdenoising RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtktotalvariationdenoising)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtktotalvariationdenoising/rtktotalvariationdenoising.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtktotalvariationdenoising_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkConfiguration.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaTotalVariationDenoisingBPDQImageFilter.h\"\n#else\n#  include \"rtkTotalVariationDenoisingBPDQImageFilter.h\"\n#endif\n\n#include \"rtkTotalVariationImageFilter.h\"\n\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtktotalvariationdenoising, args_info);\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3; // Number of dimensions of the input image\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n  using TVDenoisingFilterType = rtk::CudaTotalVariationDenoisingBPDQImageFilter;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n  using TVDenoisingFilterType = rtk::TotalVariationDenoisingBPDQImageFilter<\n    OutputImageType,\n    itk::Image<itk::CovariantVector<OutputPixelType, Dimension>, Dimension>>;\n#endif\n\n  // Read input\n  OutputImageType::Pointer input;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(input = itk::ReadImage<OutputImageType>(args_info.input_arg))\n\n  // Compute total variation before denoising\n  auto tv = rtk::TotalVariationImageFilter<OutputImageType>::New();\n  tv->SetInput(input);\n  if (args_info.verbose_flag)\n  {\n    tv->Update();\n    std::cout << \"TV before denoising = \" << tv->GetTotalVariation() << std::endl;\n  }\n\n  // Apply total variation denoising\n  auto tvdenoising = TVDenoisingFilterType::New();\n  tvdenoising->SetInput(input);\n  tvdenoising->SetGamma(args_info.gamma_arg);\n  tvdenoising->SetNumberOfIterations(args_info.niter_arg);\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(tvdenoising->GetOutput(), args_info.output_arg))\n\n  // Compute total variation after denoising\n  if (args_info.verbose_flag)\n  {\n    tv->SetInput(tvdenoising->GetOutput());\n    tv->Update();\n    std::cout << \"TV after denoising = \" << tv->GetTotalVariation() << std::endl;\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtktotalvariationdenoising/rtktotalvariationdenoising.ggo",
    "content": "purpose \"Performs total variation denoising along the specified dimensions of a 3D image.\"\n\noption \"verbose\"   v \"Verbose execution\"                                            flag         off\noption \"input\"     i \"Input file name\"                                              string       yes\noption \"output\"    o \"Output file name\"                                             string       yes\noption \"gamma\"     g \"TV term's weighting parameter\"                                double       no  default=\"1.0\"\noption \"niter\"     n \"Number of iterations\"                                         int          no  default=\"5\"\n"
  },
  {
    "path": "applications/rtktutorialapplication/CMakeLists.txt",
    "content": "WRAP_GGO(rtktutorialapplication_GGO_C rtktutorialapplication.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtktutorialapplication rtktutorialapplication.cxx ${rtktutorialapplication_GGO_C})\ntarget_link_libraries(rtktutorialapplication RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtktutorialapplication)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtktutorialapplication/rtktutorialapplication.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtktutorialapplication_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include <itkAddImageFilter.h>\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtktutorialapplication, args_info);\n\n  // This small application can be used by RTK beginners\n  // as a starting point. It reads a volume and a scalar,\n  // adds the scalar to all voxels of the volume, and\n  // writes the result\n\n  // Below is a list of a few possible challenges for beginners:\n\n  // Copy/paste the folder of this application to a new one, named\n  // \"rtkMyApp\", and modify the following files\n  //      -> applications/CMakeLists.txt\n  //      -> applications/rtkMyApp/rtkMyApp.cxx\n  //      -> applications/rtkMyApp/rtkMyApp.ggo\n  //      -> applications/rtkMyApp/CMakeLists.txt\n  // so that rtkMyApp compiles and runs fine.\n\n  // Modify the following files\n  //      -> applications/rtkMyApp/rtkMyApp.cxx\n  //      -> applications/rtkMyApp/rtkMyApp.ggo\n  // so that rtkMyApp takes two volumes in input, adds them,\n  // and writes the result in output\n\n  // Modify the following files\n  //      -> applications/rtkMyApp/rtkMyApp.cxx\n  //      -> applications/rtkMyApp/rtkMyApp.ggo\n  // so that rtkMyApp takes a volume in input, adds a scalar to\n  // all voxels, multiplies the output by an other scalar, and\n  // writes the result in output\n\n  // !! HARDER !!\n  // Modify the following files\n  //      -> applications/rtkMyApp/rtkMyApp.cxx\n  // so that rtkMyApp computes the n-th element of the\n  // Collatz sequence of each voxel, using only one\n  // itk::AddImageFilter, one itk::MultiplyImageFilter,\n  // and one itk::DivideImageFilter\n  // https://en.wikipedia.org/wiki/Collatz_conjecture\n  //\n  // You will need to use the DisconnectPipeline()\n  // function. You can see how it is used in\n  // rtkSARTConeBeamReconstructionFilter.hxx\n\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Read the input volume\n  OutputImageType::Pointer input;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(input = itk::ReadImage<OutputImageType>(args_info.input_arg))\n\n  // Create the Add filter\n  auto add = itk::AddImageFilter<OutputImageType>::New();\n  add->SetInput1(input);\n  add->SetConstant2(args_info.constant_arg);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(add->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(add->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtktutorialapplication/rtktutorialapplication.ggo",
    "content": "purpose \"A simple application you can use to train yourself to writing rtk programs\"\n\noption \"verbose\"     v \"Verbose execution\"                                     flag   off\noption \"output\"      o \"Output file name\"                                      string yes\noption \"input\"       i \"Input volume\"                                          string yes\noption \"constant\"    c \"Scalar added to input\"                                 float no default=\"1\"\n"
  },
  {
    "path": "applications/rtkvarianobigeometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtkvarianobigeometry_GGO_C rtkvarianobigeometry.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkvarianobigeometry rtkvarianobigeometry.cxx ${rtkvarianobigeometry_GGO_C})\ntarget_link_libraries(rtkvarianobigeometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkvarianobigeometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkvarianobigeometry/README.md",
    "content": "# Varian Reconstruction\n\n`````{tab-set}\n\n````{tab-item} OBI\n\n## Varian OBI Reconstruction\n\nThe first step before proceeding with reconstruction is to convert Varian's geometry into RTK's format using a command-line tool. Follow these simple steps:\n\n### 1. Download Varian Dataset\n\nDownload the dataset from [Varian-data](https://data.kitware.com/api/v1/item/5be94de88d777f2179a24de0/download).\n\n### 2. Convert Geometry\n\nRun the application to convert Varian's geometry into RTK's format:\n\n```bash\nrtkvarianobigeometry \\\n  --xml_file ProjectionInfo.xml \\\n  --path Scan0/ \\\n  --regexp Proj_.*.hnd \\\n  -o geometry.xml\n```\n\n### 3. Reconstruct Using RTK Applications\n\nReconstruct a slice (e.g., slice 30) of the volume using the `rtkfdk` algorithm:\n\n```bash\nrtkfdk \\\n  --geometry geometry.xml \\\n  --regexp .*\\.hnd \\\n  --path Scan0 \\\n  --output slice30.mha \\\n  --verbose \\\n  --spacing 0.25,0.25,0.25 \\\n  --size 1024,1,1024 \\\n  --origin -127.875,30,-127.875\n```\n\n### 4. Apply the FOV Filter\n\nApply the field-of-view (FOV) filter to discard everything outside the FOV:\n\n```bash\nrtkfieldofview \\\n  --geometry geometry.xml \\\n  --regexp .*\\.hnd \\\n  --path Scan0 \\\n  --reconstruction slice30.mha \\\n  --output slice30.mha \\\n  --verbose\n```\n\n### 5. Visualize the Result\n\nYou can visualize the result using a viewer (e.g., VV). The resulting image should look like this:\n\n![../../documentation/docs/ExternalData/Varian](../../documentation/docs/ExternalData/Varian.png){w=400px alt=\"Varian snapshot\"}\n\n````\n````{tab-item} ProBeam\n\n## Varian ProBeam Reconstruction\n\nFollow these steps for the Varian ProBeam format:\n\n### 1. Download Dataset\n\nDownload the dataset from [Varian-ProBeam-data](https://data.kitware.com/api/v1/item/5be94bef8d777f2179a24ae1/download).\n\n### 2. Convert Geometry\n\nRun the application to convert Varian ProBeam's geometry into RTK's format:\n\n```bash\nrtkvarianprobeamgeometry \\\n  --xml_file Scan.xml \\\n  --path Acquisitions/733061622 \\\n  --regexp Proj_.*.xim \\\n  -o geometry.xml\n```\n\n### 3. Reconstruct Using RTK Applications\n\nReconstruct a slice (e.g., slice 58) of the volume using the `rtkfdk` algorithm:\n\n```bash\nrtkfdk \\\n  --geometry geometry.xml \\\n  --regexp .*\\.xim \\\n  --path Acquisitions/733061622 \\\n  --output slice58.mha \\\n  --verbose \\\n  --spacing 0.25,0.25,0.25 \\\n  --size 1024,1,1024 \\\n  --origin -127.875,-58,-127.875\n```\n\n### 4. Apply the FOV Filter\n\nApply the field-of-view (FOV) filter to discard everything outside the FOV:\n\n```bash\nrtkfieldofview \\\n  --geometry geometry.xml \\\n  --regexp .*\\.xim \\\n  --path Acquisitions/733061622 \\\n  --reconstruction slice58.mha \\\n  --output slice58.mha \\\n  --verbose\n```\n\n### 5. Visualize the Result\n\nYou can visualize the result using a viewer (e.g., VV). The resulting image should look like this:\n\n![../../documentation/docs/ExternalData/VarianProBeam](../../documentation/docs/ExternalData/VarianProBeam.png){w=400px alt=\"VarianProBeam snapshot\"}\n`````\n````\n"
  },
  {
    "path": "applications/rtkvarianobigeometry/rtkvarianobigeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkvarianobigeometry_ggo.h\"\n#include \"rtkMacro.h\"\n#include \"rtkVarianObiGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkvarianobigeometry, args_info);\n\n  // Create geometry reader\n  rtk::VarianObiGeometryReader::Pointer reader;\n  reader = rtk::VarianObiGeometryReader::New();\n  reader->SetXMLFileName(args_info.xml_file_arg);\n  reader->SetProjectionsFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputData())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(reader->GetGeometry(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkvarianobigeometry/rtkvarianobigeometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from a Varian OBI acquisition.\"\n\noption \"verbose\"   v \"Verbose execution\"                                     flag            off\noption \"xml_file\"  x \"Varian OBI XML information file on projections\"        string          yes\noption \"output\"    o \"Output file name\"                                      string          yes\n\n"
  },
  {
    "path": "applications/rtkvarianobigeometry/rtkvarianobigeometry.py",
    "content": "#!/usr/bin/env python\nimport argparse\nimport itk\nfrom itk import RTK as rtk\n\n\ndef build_parser():\n    # Argument parsing\n    parser = rtk.RTKArgumentParser(\n        description=\"Creates an RTK geometry file from a Varian OBI acquisition.\"\n    )\n\n    parser.add_argument(\"--verbose\", \"-v\", help=\"Verbose execution\", type=bool)\n    parser.add_argument(\n        \"--xml_file\",\n        \"-x\",\n        help=\"Varian OBI XML information file on projections\",\n        required=True,\n    )\n    parser.add_argument(\"--output\", \"-o\", help=\"Output file name\", required=True)\n    parser.add_argument(\n        \"--path\", \"-p\", help=\"Path containing projections\", required=True\n    )\n    parser.add_argument(\n        \"--regexp\",\n        \"-r\",\n        help=\"Regular expression to select projection files in path\",\n        required=True,\n    )\n\n    # Parse the command line arguments\n    return parser\n\n\ndef process(args: argparse.Namespace):\n\n    names = itk.RegularExpressionSeriesFileNames.New()\n    names.SetDirectory(args.path)\n    names.SetRegularExpression(args.regexp)\n\n    reader = rtk.VarianObiGeometryReader.New()\n    reader.SetXMLFileName(args.xml_file)\n    reader.SetProjectionsFileNames(names.GetFileNames())\n    reader.UpdateOutputData()\n\n    rtk.write_geometry(reader.GetGeometry(), args.output)\n\n\ndef main(argv=None):\n    parser = build_parser()\n    args_info = parser.parse_args(argv)\n    process(args_info)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "applications/rtkvarianprobeamgeometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtkvarianprobeamgeometry_GGO_C rtkvarianprobeamgeometry.ggo ../rtkinputprojections_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkvarianprobeamgeometry rtkvarianprobeamgeometry.cxx ${rtkvarianprobeamgeometry_GGO_C})\ntarget_link_libraries(rtkvarianprobeamgeometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkvarianprobeamgeometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkvarianprobeamgeometry/rtkvarianprobeamgeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkvarianprobeamgeometry_ggo.h\"\n#include \"rtkMacro.h\"\n#include \"rtkVarianProBeamGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkGgoFunctions.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkvarianprobeamgeometry, args_info);\n\n  // Create geometry reader\n  rtk::VarianProBeamGeometryReader::Pointer reader;\n  reader = rtk::VarianProBeamGeometryReader::New();\n  reader->SetXMLFileName(args_info.xml_file_arg);\n  reader->SetProjectionsFileNames(rtk::GetProjectionsFileNamesFromGgo(args_info));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputData())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(reader->GetGeometry(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkvarianprobeamgeometry/rtkvarianprobeamgeometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from a Varian ProBeam acquisition.\"\n\noption \"verbose\"   v \"Verbose execution\"                                     flag            off\noption \"xml_file\"  x \"Varian ProBeam XML information file on projections\"    string          yes\noption \"output\"    o \"Output file name\"                                      string          yes\n\n"
  },
  {
    "path": "applications/rtkvectorconjugategradient/CMakeLists.txt",
    "content": "WRAP_GGO(rtkvectorconjugategradient_GGO_C rtkvectorconjugategradient.ggo ../rtk3Doutputimage_section.ggo ../rtkprojectors_section.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkvectorconjugategradient rtkvectorconjugategradient.cxx ${rtkvectorconjugategradient_GGO_C})\ntarget_link_libraries(rtkvectorconjugategradient RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkvectorconjugategradient)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkvectorconjugategradient/rtkvectorconjugategradient.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkvectorconjugategradient_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkConjugateGradientConeBeamReconstructionFilter.h\"\n\n#include <iostream>\n#include <fstream>\n#include <iterator>\n\n#ifdef RTK_USE_CUDA\n#  include <itkCudaImage.h>\n#endif\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkvectorconjugategradient, args_info);\n\n  constexpr unsigned int Dimension = 3;\n  constexpr unsigned int nMaterials = 3;\n\n  using DataType = float;\n  using PixelType = itk::Vector<DataType, nMaterials>;\n  using WeightsType = itk::Vector<DataType, nMaterials * nMaterials>;\n\n#ifdef RTK_USE_CUDA\n  using SingleComponentImageType = itk::CudaImage<DataType, Dimension>;\n  using OutputImageType = itk::CudaImage<PixelType, Dimension>;\n  using WeightsImageType = itk::CudaImage<WeightsType, Dimension>;\n#else\n  using SingleComponentImageType = itk::Image<DataType, Dimension>;\n  using OutputImageType = itk::Image<PixelType, Dimension>;\n  using WeightsImageType = itk::Image<WeightsType, Dimension>;\n#endif\n\n  // Projections reader\n  OutputImageType::Pointer projections;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(projections = itk::ReadImage<OutputImageType>(args_info.projections_arg))\n\n  // Geometry\n  if (args_info.verbose_flag)\n    std::cout << \"Reading geometry information from \" << args_info.geometry_arg << \"...\" << std::endl;\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geometry = rtk::ReadGeometry(args_info.geometry_arg));\n\n  // Create input: either an existing volume read from a file or a blank image\n  OutputImageType::Pointer input;\n  if (args_info.input_given)\n  {\n    // Read an existing image to initialize the volume\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(input = itk::ReadImage<OutputImageType>(args_info.input_arg))\n  }\n  else\n  {\n    // Create new empty volume\n    using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n    auto constantImageSource = ConstantImageSourceType::New();\n    rtk::SetConstantImageSourceFromGgo<ConstantImageSourceType, args_info_rtkvectorconjugategradient>(\n      constantImageSource, args_info);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(constantImageSource->Update())\n    input = constantImageSource->GetOutput();\n  }\n\n  // Read weights if given\n  WeightsImageType::Pointer inputWeights;\n  if (args_info.weights_given)\n  {\n    using WeightsReaderType = itk::ImageFileReader<WeightsImageType>;\n    auto weightsReader = WeightsReaderType::New();\n    weightsReader->SetFileName(args_info.weights_arg);\n    inputWeights = weightsReader->GetOutput();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(inputWeights->Update())\n  }\n\n  // Read regularization weights if given\n  SingleComponentImageType::Pointer localRegWeights;\n  if (args_info.regweights_given)\n  {\n    using WeightsReaderType = itk::ImageFileReader<SingleComponentImageType>;\n    auto localRegWeightsReader = WeightsReaderType::New();\n    localRegWeightsReader->SetFileName(args_info.regweights_arg);\n    localRegWeights = localRegWeightsReader->GetOutput();\n    localRegWeights->Update();\n  }\n\n  // Read Support Mask if given\n  SingleComponentImageType::Pointer supportmask;\n  if (args_info.mask_given)\n  {\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(supportmask = itk::ReadImage<SingleComponentImageType>(args_info.mask_arg))\n  }\n\n  // Set the forward and back projection filters to be used\n  auto conjugategradient = rtk::\n    ConjugateGradientConeBeamReconstructionFilter<OutputImageType, SingleComponentImageType, WeightsImageType>::New();\n  SetForwardProjectionFromGgo(args_info, conjugategradient.GetPointer());\n  SetBackProjectionFromGgo(args_info, conjugategradient.GetPointer());\n  conjugategradient->SetInputVolume(input);\n  conjugategradient->SetInputProjectionStack(projections);\n  conjugategradient->SetInputWeights(inputWeights);\n  conjugategradient->SetLocalRegularizationWeights(localRegWeights);\n  conjugategradient->SetCudaConjugateGradient(!args_info.nocudacg_flag);\n  if (args_info.mask_given)\n  {\n    conjugategradient->SetSupportMask(supportmask);\n  }\n\n  if (args_info.gamma_given)\n    conjugategradient->SetGamma(args_info.gamma_arg);\n  if (args_info.tikhonov_given)\n    conjugategradient->SetTikhonov(args_info.tikhonov_arg);\n\n  conjugategradient->SetGeometry(geometry);\n  conjugategradient->SetNumberOfIterations(args_info.niterations_arg);\n  conjugategradient->SetDisableDisplacedDetectorFilter(args_info.nodisplaced_flag);\n\n  itk::TimeProbe readerProbe;\n  if (args_info.time_flag)\n  {\n    std::cout << \"Recording elapsed time... \" << std::flush;\n    readerProbe.Start();\n  }\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update())\n\n  if (args_info.time_flag)\n  {\n    //    conjugategradient->PrintTiming(std::cout);\n    readerProbe.Stop();\n    std::cout << \"It took...  \" << readerProbe.GetMean() << ' ' << readerProbe.GetUnit() << std::endl;\n  }\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(conjugategradient->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkvectorconjugategradient/rtkvectorconjugategradient.ggo",
    "content": "purpose \"Reconstructs a 3D volume from a sequence of projections with a conjugate gradient technique\"\n\noption \"verbose\"        v \"Verbose execution\"                                                                         flag   off\noption \"geometry\"       g \"XML geometry file name\"                                                                    string yes\noption \"output\"         o \"Output file name\"                                                                          string yes\noption \"projections\"    - \"Projections file name\"                                                                     string yes\noption \"niterations\"    n \"Number of iterations\"                                                                      int    no   default=\"5\"\noption \"time\"           t \"Records elapsed time during the process\"                                                   flag   off\noption \"input\"          i \"Input volume\"                                                                              string no\noption \"weights\"        w \"Weights file for Weighted Least Squares (WLS)\"                                             string no\noption \"regweights\"     - \"Local regularization weights file\"                                                         string no\noption \"gamma\"          - \"Laplacian regularization weight\"                                                           float  no   default=\"0\"\noption \"tikhonov\"       - \"Tikhonov regularization weight\"                                                            float  no   default=\"0\"\noption \"nocudacg\"       - \"Do not perform conjugate gradient calculations on GPU\"                                     flag   off\noption \"mask\"           m \"Apply a support binary mask: reconstruction kept null outside the mask)\"                   string no\noption \"nodisplaced\"    - \"Disable the displaced detector filter\"                                                     flag   off\noption \"targetSDD\"      - \"Target sum of squared difference between consecutive iterates, as stopping criterion\"      double no   default=\"0\"\n"
  },
  {
    "path": "applications/rtkversion.py.in",
    "content": "__all__ = [\n    \"version\"\n]\n\nRTK_VERSION_MAJOR = \"@RTK_VERSION_MAJOR@\"\nRTK_VERSION_MINOR = \"@RTK_VERSION_MINOR@\"\nRTK_VERSION_PATCH = \"@RTK_VERSION_PATCH@\"\nRTK_VERSION_HASH = \"@RTK_VERSION_HASH@\"\n\ndef version():\n    return f\"RTK {RTK_VERSION_MAJOR}.{RTK_VERSION_MINOR}.{RTK_VERSION_PATCH}{RTK_VERSION_HASH}\""
  },
  {
    "path": "applications/rtkwaveletsdenoising/CMakeLists.txt",
    "content": "WRAP_GGO(rtkwaveletsdenoising_GGO_C rtkwaveletsdenoising.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkwaveletsdenoising rtkwaveletsdenoising.cxx ${rtkwaveletsdenoising_GGO_C})\ntarget_link_libraries(rtkwaveletsdenoising RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkwaveletsdenoising)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkwaveletsdenoising/rtkwaveletsdenoising.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkwaveletsdenoising_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n\n#include \"rtkDeconstructSoftThresholdReconstructImageFilter.h\"\n#include <itkImageFileWriter.h>\n#include <itkImageFileReader.h>\n#include <string>\n#include <sstream>\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkwaveletsdenoising, args_info);\n\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Read the input image\n  OutputImageType::Pointer input;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(input = itk::ReadImage<OutputImageType>(args_info.input_arg))\n\n  // Create the denoising filter\n  auto wst = rtk::DeconstructSoftThresholdReconstructImageFilter<OutputImageType>::New();\n  wst->SetInput(input);\n  wst->SetOrder(args_info.order_arg);\n  wst->SetThreshold(args_info.threshold_arg);\n  wst->SetNumberOfLevels(args_info.level_arg);\n\n  // Write reconstruction\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(wst->GetOutput(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkwaveletsdenoising/rtkwaveletsdenoising.ggo",
    "content": "purpose \"Denoises a volume using Daubechies wavelets soft thresholding\"\n\noption \"verbose\"   v \"Verbose execution\"                                         flag     off\noption \"input\"     i \"Input file name\"                              string   yes\noption \"output\"    o \"Input file name\"                              string   yes\noption \"order\"     - \"Order of the Daubechies wavelets\"                          int   yes\noption \"level\"     l \"Number of deconstruction levels\"                           int   yes\noption \"threshold\" t \"Threshold used in soft thresholding of the wavelets coefficients\" float yes\n"
  },
  {
    "path": "applications/rtkxradgeometry/CMakeLists.txt",
    "content": "WRAP_GGO(rtkxradgeometry_GGO_C rtkxradgeometry.ggo ${RTK_BINARY_DIR}/rtkVersion.ggo)\nadd_executable(rtkxradgeometry rtkxradgeometry.cxx ${rtkxradgeometry_GGO_C})\ntarget_link_libraries(rtkxradgeometry RTK)\n\n# Installation code\nif(NOT RTK_INSTALL_NO_EXECUTABLES)\n  foreach(EXE_NAME rtkxradgeometry)\n    install(TARGETS ${EXE_NAME}\n      RUNTIME DESTINATION ${RTK_INSTALL_RUNTIME_DIR} COMPONENT Runtime\n      LIBRARY DESTINATION ${RTK_INSTALL_LIB_DIR} COMPONENT RuntimeLibraries\n      ARCHIVE DESTINATION ${RTK_INSTALL_ARCHIVE_DIR} COMPONENT Development)\n  endforeach()\nendif()\n\n"
  },
  {
    "path": "applications/rtkxradgeometry/rtkxradgeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkxradgeometry_ggo.h\"\n#include \"rtkGgoFunctions.h\"\n#include \"rtkXRadGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\nint\nmain(int argc, char * argv[])\n{\n  GGO(rtkxradgeometry, args_info);\n\n  // Create geometry reader\n  auto reader = rtk::XRadGeometryReader::New();\n  reader->SetImageFileName(args_info.input_arg);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputData())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rtk::WriteGeometry(reader->GetGeometry(), args_info.output_arg))\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "applications/rtkxradgeometry/rtkxradgeometry.ggo",
    "content": "purpose \"Creates an RTK geometry file from an acquisition exported on the XRad system.\"\n\noption \"verbose\"   v \"Verbose execution\"                 flag   off\noption \"input\"     i \"Input sinogram header file\"        string yes\noption \"output\"    o \"Output file name\"                  string yes\n\n"
  },
  {
    "path": "cmake/FindGengetopt.cmake",
    "content": "# Attempt to find gengetopt. If not found, compile it.\nif (NOT TARGET gengetopt)\n  find_program(GENGETOPT gengetopt)\n  if ((GENGETOPT STREQUAL \"GENGETOPT-NOTFOUND\") OR (GENGETOPT STREQUAL \"\"))\n    get_filename_component(CLITK_CMAKE_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)\n    add_subdirectory(${CLITK_CMAKE_DIR}/../utilities/gengetopt ${CMAKE_CURRENT_BINARY_DIR}/gengetopt)\n  else()\n    if(EXISTS ${GENGETOPT})\n      add_executable(gengetopt IMPORTED)\n      set_property(TARGET gengetopt PROPERTY IMPORTED_LOCATION ${GENGETOPT})\n    else()\n      set(GENGETOPT \"GENGETOPT-NOTFOUND\" CACHE FILEPATH \"Path to a program.\" FORCE)\n      message(FATAL_ERROR \"No gengetopt executable found at the specified location\")\n    endif()\n  endif()\nendif()\n\n# Create a cmake script to cat a list of files\nfile(WRITE \"${CMAKE_BINARY_DIR}/cat.cmake\" \"\nfile(WRITE \\\"\\${OUTPUT}\\\" \\\"\\\")\nforeach(INPUT \\${INPUTS})\n  string(REPLACE \\\";\\\" \\\" \\\" INPUT \\\"\\${INPUT}\\\")\n  file(READ \\\"\\${INPUT}\\\" CONTENT)\n  file(APPEND \\\"\\${OUTPUT}\\\" \\\"\\${CONTENT}\\\")\nendforeach()\n\")\n\nmacro (WRAP_GGO GGO_SRCS)\n\n  # Set current list of files to zero for a new target\n  set(GGO_FILES_ABS \"\")\n\n  # Convert list of a file in a list with absolute file names\n  foreach(GGO_FILE ${ARGN})\n    get_filename_component(GGO_FILE_ABS ${GGO_FILE} ABSOLUTE)\n    list(APPEND GGO_FILES_ABS \"${GGO_FILE_ABS}\")\n  endforeach()\n\n  # Append to a new ggo file containing all files\n  list(GET GGO_FILES_ABS 0 FIRST_GGO_FILE)\n  get_filename_component(FIRST_GGO_BASEFILENAME ${FIRST_GGO_FILE} NAME)\n  separate_arguments(GGO_FILES_ABS_LIST NATIVE_COMMAND \"${GGO_FILES_ABS}\")\n  add_custom_command(\n      OUTPUT \"${CMAKE_CURRENT_BINARY_DIR}/${FIRST_GGO_BASEFILENAME}\"\n      COMMAND ${CMAKE_COMMAND} -D INPUTS=\"${GGO_FILES_ABS_LIST}\"\n                               -D OUTPUT=${CMAKE_CURRENT_BINARY_DIR}/${FIRST_GGO_BASEFILENAME}\n                               -P \"${CMAKE_BINARY_DIR}/cat.cmake\"\n      DEPENDS ${GGO_FILES_ABS}\n  )\n  set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${FIRST_GGO_BASEFILENAME} PROPERTIES GENERATED TRUE)\n\n  # Now add ggo command\n  get_filename_component(GGO_BASEFILENAME ${FIRST_GGO_FILE} NAME_WE)\n  set(GGO_H ${GGO_BASEFILENAME}_ggo.h)\n  set(GGO_C ${GGO_BASEFILENAME}_ggo.c)\n  set(GGO_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${GGO_H} ${CMAKE_CURRENT_BINARY_DIR}/${GGO_C})\n  add_custom_command(OUTPUT ${GGO_OUTPUT}\n                     COMMAND gengetopt\n                     ARGS --input=${CMAKE_CURRENT_BINARY_DIR}/${FIRST_GGO_BASEFILENAME}\n                          --output-dir=${CMAKE_CURRENT_BINARY_DIR}\n                          --arg-struct-name=args_info_${GGO_BASEFILENAME}\n                          --func-name=cmdline_parser_${GGO_BASEFILENAME}\n                          --file-name=${GGO_BASEFILENAME}_ggo\n                          --unamed-opts\n                          --conf-parser\n                          --include-getopt\n                          --set-package ${CMAKE_PROJECT_NAME}\n                     DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${FIRST_GGO_BASEFILENAME}\n                    )\n  set(${GGO_SRCS} ${${GGO_SRCS}} ${GGO_OUTPUT})\n  include_directories(\"${CMAKE_CURRENT_BINARY_DIR}\")\n\n  set_source_files_properties(${${GGO_SRCS}} PROPERTIES GENERATED TRUE)\n  if(CMAKE_COMPILER_IS_GNUCXX)\n    set_source_files_properties(${${GGO_SRCS}} PROPERTIES COMPILE_FLAGS \"-Wno-unused-but-set-variable\")\n  endif()\n  if(MSVC)\n    # Disable double to float truncation warning as gengetopt cannot append \"f\"\n    # to force default numeric float values in the .ggo config file\n    set_source_files_properties(${${GGO_SRCS}} PROPERTIES COMPILE_FLAGS \"/wd4305\")\n  endif()\nendmacro ()\n"
  },
  {
    "path": "cmake/GetGitRevisionDescription.cmake",
    "content": "# - Returns a version string from Git\n#\n# These functions force a re-configure on each git commit so that you can\n# trust the values of the variables in your build system.\n#\n#  get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])\n#\n# Returns the refspec and sha hash of the current head revision\n#\n#  git_describe(<var> [<additional arguments to git describe> ...])\n#\n# Returns the results of git describe on the source tree, and adjusting\n# the output so that it tests false if an error occurs.\n#\n#  git_get_exact_tag(<var> [<additional arguments to git describe> ...])\n#\n# Returns the results of git describe --exact-match on the source tree,\n# and adjusting the output so that it tests false if there was no exact\n# matching tag.\n#\n# Requires CMake 2.6 or newer (uses the 'function' command)\n#\n# Original Author:\n# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>\n# http://academic.cleardefinition.com\n# Iowa State University HCI Graduate Program/VRAC\n#\n# Copyright Iowa State University 2009-2010.\n# Distributed under the Boost Software License, Version 1.0.\n# (See accompanying file LICENSE_1_0.txt or copy at\n# https://www.boost.org/LICENSE_1_0.txt)\n\nif(__get_git_revision_description)\n\treturn()\nendif()\nset(__get_git_revision_description YES)\n\n# We must run the following at \"include\" time, not at function call time,\n# to find the path to this module rather than the path to a calling list file\nget_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)\n\nfunction(get_git_head_revision _refspecvar _hashvar)\n\tset(GIT_PARENT_DIR \"${CMAKE_CURRENT_SOURCE_DIR}\")\n\tset(GIT_DIR \"${GIT_PARENT_DIR}/.git\")\n\twhile(NOT EXISTS \"${GIT_DIR}\")\t# .git dir not found, search parent directories\n\t\tset(GIT_PREVIOUS_PARENT \"${GIT_PARENT_DIR}\")\n\t\tget_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)\n\t\tif(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)\n\t\t\t# We have reached the root directory, we are not in git\n\t\t\tset(${_refspecvar} \"GITDIR-NOTFOUND\" PARENT_SCOPE)\n\t\t\tset(${_hashvar} \"GITDIR-NOTFOUND\" PARENT_SCOPE)\n\t\t\treturn()\n\t\tendif()\n\t\tset(GIT_DIR \"${GIT_PARENT_DIR}/.git\")\n\tendwhile()\n\t# check if this is a submodule\n\tif(NOT IS_DIRECTORY ${GIT_DIR})\n\t\tfile(READ ${GIT_DIR} submodule)\n\t\tstring(REGEX REPLACE \"gitdir: (.*)\\n$\" \"\\\\1\" GIT_DIR_RELATIVE ${submodule})\n\t\tget_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)\n\t\tget_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)\n\tendif()\n\tset(GIT_DATA \"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data\")\n\tif(NOT EXISTS \"${GIT_DATA}\")\n\t\tfile(MAKE_DIRECTORY \"${GIT_DATA}\")\n\tendif()\n\n\tif(NOT EXISTS \"${GIT_DIR}/HEAD\")\n\t\treturn()\n\tendif()\n\tset(HEAD_FILE \"${GIT_DATA}/HEAD\")\n\tconfigure_file(\"${GIT_DIR}/HEAD\" \"${HEAD_FILE}\" COPYONLY)\n\n\tconfigure_file(\"${_gitdescmoddir}/GetGitRevisionDescription.cmake.in\"\n\t\t\"${GIT_DATA}/grabRef.cmake\"\n\t\t@ONLY)\n\tinclude(\"${GIT_DATA}/grabRef.cmake\")\n\n\tset(${_refspecvar} \"${HEAD_REF}\" PARENT_SCOPE)\n\tset(${_hashvar} \"${HEAD_HASH}\" PARENT_SCOPE)\nendfunction()\n\nfunction(git_describe _var)\n\tif(NOT GIT_FOUND)\n\t\tfind_package(Git QUIET)\n\tendif()\n\tget_git_head_revision(refspec hash)\n\tif(NOT GIT_FOUND)\n\t\tset(${_var} \"GIT-NOTFOUND\" PARENT_SCOPE)\n\t\treturn()\n\tendif()\n\tif(NOT hash)\n\t\tset(${_var} \"HEAD-HASH-NOTFOUND\" PARENT_SCOPE)\n\t\treturn()\n\tendif()\n\n\t# TODO sanitize\n\t#if((${ARGN}\" MATCHES \"&&\") OR\n\t#\t(ARGN MATCHES \"||\") OR\n\t#\t(ARGN MATCHES \"\\\\;\"))\n\t#\tmessage(\"Please report the following error to the project!\")\n\t#\tmessage(FATAL_ERROR \"Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}\")\n\t#endif()\n\n\t#message(STATUS \"Arguments to execute_process: ${ARGN}\")\n\n\texecute_process(COMMAND\n\t\t\"${GIT_EXECUTABLE}\"\n\t\tdescribe\n\t\t${hash}\n\t\t${ARGN}\n\t\tWORKING_DIRECTORY\n\t\t\"${CMAKE_SOURCE_DIR}\"\n\t\tRESULT_VARIABLE\n\t\tres\n\t\tOUTPUT_VARIABLE\n\t\tout\n\t\tERROR_QUIET\n\t\tOUTPUT_STRIP_TRAILING_WHITESPACE)\n\tif(NOT res EQUAL 0)\n\t\tset(out \"${out}-${res}-NOTFOUND\")\n\tendif()\n\n\tset(${_var} \"${out}\" PARENT_SCOPE)\nendfunction()\n\nfunction(git_get_exact_tag _var)\n\tgit_describe(out --exact-match ${ARGN})\n\tset(${_var} \"${out}\" PARENT_SCOPE)\nendfunction()\n"
  },
  {
    "path": "cmake/GetGitRevisionDescription.cmake.in",
    "content": "#\n# Internal file for GetGitRevisionDescription.cmake\n#\n# Requires CMake 2.6 or newer (uses the 'function' command)\n#\n# Original Author:\n# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>\n# http://academic.cleardefinition.com\n# Iowa State University HCI Graduate Program/VRAC\n#\n# Copyright Iowa State University 2009-2010.\n# Distributed under the Boost Software License, Version 1.0.\n# (See accompanying file LICENSE_1_0.txt or copy at\n# https://www.boost.org/LICENSE_1_0.txt)\n\nset(HEAD_HASH)\n\nfile(READ \"@HEAD_FILE@\" HEAD_CONTENTS LIMIT 1024)\n\nstring(STRIP \"${HEAD_CONTENTS}\" HEAD_CONTENTS)\nif(HEAD_CONTENTS MATCHES \"ref\")\n\t# named branch\n\tstring(REPLACE \"ref: \" \"\" HEAD_REF \"${HEAD_CONTENTS}\")\n\tif(EXISTS \"@GIT_DIR@/${HEAD_REF}\")\n\t\tconfigure_file(\"@GIT_DIR@/${HEAD_REF}\" \"@GIT_DATA@/head-ref\" COPYONLY)\n\telseif(EXISTS \"@GIT_DIR@/logs/${HEAD_REF}\")\n\t\tconfigure_file(\"@GIT_DIR@/logs/${HEAD_REF}\" \"@GIT_DATA@/head-ref\" COPYONLY)\n\t\tset(HEAD_HASH \"${HEAD_REF}\")\n\tendif()\nelse()\n\t# detached HEAD\n\tconfigure_file(\"@GIT_DIR@/HEAD\" \"@GIT_DATA@/head-ref\" COPYONLY)\nendif()\n\nif(NOT HEAD_HASH)\n\tfile(READ \"@GIT_DATA@/head-ref\" HEAD_HASH LIMIT 1024)\n\tstring(STRIP \"${HEAD_HASH}\" HEAD_HASH)\nendif()\n"
  },
  {
    "path": "cmake/Hooks/pre-commit",
    "content": "#!/bin/sh\necho 'Your work tree has not been configured for RTK development.\nPaste the following commands into a shell:\n ./utilities/SetupForDevelopment.sh'\nexit 1"
  },
  {
    "path": "cmake/Hooks/pre-commit-style.bash",
    "content": "#=============================================================================\n# Copyright 2010-2011 Kitware, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#=============================================================================\n\n# Run clangformat and KWStyle pre-commit hooks.\n#\n# 'git config' is used to enable the hooks and set their configuration files.\n# The repository .gitattributes must also enable the hooks on the targeted\n# files.\n\ndie() {\n          echo 'pre-commit hook failure' 1>&2\n          echo '-----------------------' 1>&2\n          echo '' 1>&2\n          echo \"$@\" 1>&2\n          exit 1\n}\n\ndo_KWStyle=$(git config --bool hooks.KWStyle) || do_KWStyle=true\n\ndo_clangformat=$(git config --bool hooks.clangformat) || do_clangformat=true\n\n#-----------------------------------------------------------------------------\n# Check if we want to run the style on a given file.  Uses git attributes.  If\n# the hook.style attribute is set, then all styles are executed.  If the\n# hook.style attribute is set to a value, only the values given are executed.\n# Also, do not run the style check if there are unstaged changes in the file.\n# The first positional parameter is the file to check.\n# The second positional parameter is the style to check.\n# Returns 0 for execute, 1 for don't execute.\nrun_style_on_file() {\n  # Do not run on submodule changes.\n  if git diff-index --cached HEAD -- \"$1\" | grep -q '^:...... 160000'; then\n    return 1\n  fi\n  style=$(git check-attr hooks.style -- \"$1\" |\n      sed 's/^[^:]*: hooks.style: //')\n  has_style_attr=1\n  case \"$style\" in\n    'unset')        has_style_attr=1 ;;\n    'set')          has_style_attr=0 ;;\n    'unspecified')  has_style_attr=1 ;;\n    *)              echo \",$style,\" | grep -iq \",$2,\" && has_style_attr=0 ;;\n  esac\n  if ! git diff-files --quiet -- \"$1\" && test $has_style_attr -eq 0; then\n    # A way to always allow skipping.\n    skip_unstaged=$(git config --bool hooks.styleSkipUnstaged) ||\n    skip_unstaged=false\n    file_sha=$(git diff-index --cached --abbrev=7 HEAD -- \"$1\" | \\\n    awk '{print substr($3,1,9) substr($4,1,7)}')\n    if file_skip_unstaged=$(git config \"hooks.$1.styleSkipUnstaged\"); then\n      if test \",$file_skip_unstaged,\" = \",$file_sha,\" -o \\\n        \",$file_skip_unstaged,\" = \",true,\"; then\n        skip_unstaged=true\n      fi\n    fi\n\n    if $skip_unstaged; then\n      echo \"The file '$1' contains unstaged stages.  Skipping style \\\ncheck '$2'.\"\n    else\n      die \"Style check '$2' cannot run on '$1' with unstaged stages.\n\nAllow skipping the style check for this commit with\n\n  git config \\\"hooks.$1.styleSkipUnstaged\\\" $file_sha\"\n    fi\n    return 1\n  fi\n  return $has_style_attr\n}\n\n#-----------------------------------------------------------------------------\n# KWStyle.\ncheck_for_KWStyle() {\n  KWStyle_path=$(git config hooks.KWStyle.path) ||\n  KWStyle_path=$(which KWStyle)\n  if [ $? != 0 ] ; then\n    echo \"KWStyle executable was not found.\n\n  No style verification will be performed with KWStyle!\n\nA KWStyle executable will be built and configured when ITK\nis built with the BUILD_TESTING CMake configuration option enabled.\nAlternatively, set the KWStyle executable location with\n\n  git config hooks.KWStyle.path /path/to/KWStyle\n\nSee https://kitware.github.io/KWStyle/\n\" >&2\n    return 1\n  fi\n  KWStyle_conf=$(git config hooks.KWStyle.conf)\n  if ! test -f \"$KWStyle_conf\"; then\n    die \"The file '$KWStyle_conf' does not exist.\n\nPlease run\n\n  git config hooks.KWStyle.conf path/to/KWStyle.conf.xml\"\n  fi\n  KWStyle_overWriteRulesConf=$(git config hooks.KWStyle.overwriteRulesConf)\n  if test $? -eq 0 && ! test -f \"$KWStyle_overWriteRulesConf\"; then\n    die \"The hooks.KWStyle.overwriteRulesConf file '$KWStyle_overWriteRulesConf' does not exist.\"\n  fi\n}\n\nrun_KWStyle_on_file() {\n  local_KWStyle_overWriteRulesConf=\"`pwd`/${1%/*}/../ITKKWStyleOverwrite.txt\"\n  if test -f \"$local_KWStyle_overWriteRulesConf\"; then\n    \"$KWStyle_path\" -gcc -xml \"$KWStyle_conf\" -o \"$local_KWStyle_overWriteRulesConf\" \"$1\"\n  elif test -z \"$KWStyle_overWriteRulesConf\"; then\n    \"$KWStyle_path\" -gcc -xml \"$KWStyle_conf\" \"$1\"\n  else\n    echo \"$KWStyle_overWriteRulesConf\"\n    \"$KWStyle_path\" -gcc -xml \"$KWStyle_conf\" -o \"$KWStyle_overWriteRulesConf\" \"$1\"\n  fi\n\n  if test $? -ne 0; then\n    cp -- \"$1\"{,.kws}\n    die \"KWStyle check failed.\n\nLine numbers in the errors shown refer to the file:\n${1}.kws\"\n  fi\n  return 0\n}\n\nrun_KWStyle() {\n  git diff-index --cached --diff-filter=ACMR --name-only HEAD -- |\n  while read f; do\n    if run_style_on_file \"$f\" KWStyle; then\n      run_KWStyle_on_file \"$f\"\n    fi || return\n  done\n}\n\n#-----------------------------------------------------------------------------\n# clangformat.\ncheck_for_clangformat() {\n  clangformat_required_version=19.1\n  system_tools=\"\n    clang-format-$clangformat_required_version\n    clang-format\n\"\n  for tool in $system_tools; do\n    if type -p \"$tool\" >/dev/null; then\n      system_clang_format=\"$tool\"\n      break\n    fi\n  done\n  clangformat_path=$(git config clangFormat.binary) ||\n  clangformat_path=$(type -p \"$system_clang_format\" >/dev/null) ||\n  die \"clang-format executable was not found.\n\nA clang-format binary will be downloaded and configured when ITK\nis built with the BUILD_TESTING CMake configuration option enabled.\n\nAlternatively, install clang-format version $clangformat_required_version or set the executable location with\n\n  git config clangFormat.binary /path/to/clang-format\n\"\n  if ! \"$clangformat_path\" --version | grep \"clang-format version $clangformat_required_version\" >/dev/null 2>/dev/null; then\n    die \"clang-format version $clangformat_required_version is required\n\nSet the path the clang-format $clangformat_required_version executable with\n\n  git config clangFormat.binary /path/to/clang-format\n\nor disable the clang-format pre-commit hook with\n\n  git config hooks.clangformat false\n\"\n  fi\n}\n\nrun_clang_format_check_attr()\n{\n    IN=$1\n    OUT=$2\n    ERR=$3\n    \"${clangformat_path}\" -style=file \"$IN\" > \"$OUT\" 2> \"$ERR\"\n    return $?\n}\n\nrun_clangformat_on_file() {\n  MERGED=\"$1\"\n  if run_style_on_file \"$MERGED\" \"clangformat\"; then\n    ext=\"$$$(expr \"$MERGED\" : '.*\\(\\.[^/]*\\)$')\"\n    BACKUP=\"./$MERGED.BACKUP.$ext\"\n    LOCAL=\"./$MERGED.STAGED.$ext\"\n    REMOTE=\"./$MERGED.CLANGFORMAT.$ext\"\n    NEW_MERGED=\"./$MERGED.NEW.$ext\"\n    ERROR_LOG=\"./$MERGED.$ext.log\"\n    OLD_MERGED=\"$MERGED\"\n\n    mv -- \"$MERGED\" \"$BACKUP\"\n    # We temporarily change MERGED because the file might already be open, and\n    # the text editor may complain.\n    MERGED=\"$NEW_MERGED\"\n    cp -- \"$BACKUP\" \"$LOCAL\"\n\n    run_clang_format_check_attr \"$LOCAL\" \"$REMOTE\" \"$ERROR_LOG\"\n    clang_format_status=$?\n    if [  $clang_format_status -ne 0 ]; then\n      mv -- \"$BACKUP\" \"$OLD_MERGED\"\n\n      if $merge_keep_temporaries; then\n        rm -f -- \"$LOCAL\" \"$REMOTE\" \"$BACKUP\"\n      fi\n      die \"error when running clang-format on $OLD_MERGED\"\n    fi\n    cp -- \"$REMOTE\" \"$MERGED\"\n\n    if test $(git hash-object -- \"$LOCAL\") != $(git hash-object -- \"$REMOTE\"); then\n      if [ \"$(uname)\" == \"Darwin\" ]; then\n        run_merge_tool \"$merge_tool\" \"false\" </dev/tty\n      elif [ \"$(expr substr $(uname -s) 1 5)\" == \"Linux\" ]; then\n        run_merge_tool \"$merge_tool\" \"false\" </dev/tty\n      else\n        run_merge_tool \"$merge_tool\" \"false\"\n      fi\n      if [ $? -ne 0 ]; then\n        mv -- \"$BACKUP\" \"$OLD_MERGED\"\n\n        if $merge_keep_temporaries; then\n          rm -f -- \"$LOCAL\" \"$REMOTE\" \"$BACKUP\" \"$NEW_MERGED\"\n        fi\n\n        die \"clang-format merge of $OLD_MERGED failed\n        Error log: $ERROR_LOG\"\n      fi\n    fi\n\n    mv -- \"$NEW_MERGED\" \"$OLD_MERGED\"\n    MERGED=\"$OLD_MERGED\"\n\n    if $merge_keep_backup; then\n      mv -- \"$BACKUP\" \"$MERGED.orig\"\n    else\n      rm -- \"$BACKUP\"\n    fi\n\n    git add -- \"$MERGED\"\n    rm -f -- \"$LOCAL\" \"$REMOTE\" \"$BACKUP\" \"$ERROR_LOG\" \"$NEW_MERGED\"\n\n  fi # end if run clang-format on file\n\n  if $do_KWStyle &&\n    $have_KWStyle &&\n    run_style_on_file \"$MERGED\" KWStyle\n  then\n    run_KWStyle_on_file \"$MERGED\"\n  else\n    return 0\n  fi\n}\n\nrun_clangformat() {\n  $do_KWStyle && check_for_KWStyle\n  if test $? -eq 0; then\n    have_KWStyle=true\n  else\n    have_KWStyle=false\n  fi\n\n  merge_tool=$(get_merge_tool \"$merge_tool\") || die \"Merge tool not configured.\n\nSet the merge tool with\n\n  git config merge.tool <toolname>\n\nFor more information, see\n\n  git help mergetool\"\n  merge_keep_backup=\"$(git config --bool mergetool.keepBackup || echo true)\"\n  merge_keep_temporaries=\"$(git config --bool mergetool.keepTemporaries || echo false)\"\n  git diff-index --cached --diff-filter=ACMR --name-only HEAD -- |\n  while read MERGED; do\n    run_clangformat_on_file \"$MERGED\" || return\n  done # end for changed files\n}\n\n# Do not run during merge commits for now.\nif test -f \"$GIT_DIR/MERGE_HEAD\"; then\n  :\nelif $do_clangformat; then\n  # We use git-mergetool settings to review the clangformat changes.\n  TOOL_MODE=merge\n  . \"$(git --exec-path)/git-mergetool--lib\"\n  # Redefine check_unchanged because we do not need to check if the merge was\n  # successful.\n  check_unchanged() {\n    status=0\n  }\n  check_for_clangformat\n  run_clangformat || exit 1\n# do_clangformat will run KWStyle on the files incrementally so excessive\n# clangformat merges do not have to occur.\nelif $do_KWStyle; then\n  if check_for_KWStyle; then\n    run_KWStyle || exit 1\n  fi\nfi\n\n# vim: set fenc=utf-8 ff=unix sw=8 tw=0 :\n"
  },
  {
    "path": "cmake/KWStyle/RTK.kws.xml",
    "content": "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<Description>\n<LineLength>200</LineLength>\n<DeclarationOrder>0,1,2</DeclarationOrder>\n<Typedefs>[A-Z]</Typedefs>\n<InternalVariables>m_[A-Z]</InternalVariables>\n<SemicolonSpace>0</SemicolonSpace>\n<EndOfFileNewLine>1</EndOfFileNewLine>\n<Tabs>1</Tabs>\n<Spaces>3</Spaces>\n<Comments>/**, *, */,true</Comments>\n<Namespace>rtk</Namespace>\n<NameOfClass>[NameOfClass],rtk</NameOfClass>\n<IfNDefDefine>[NameOfClass]_[Extension]</IfNDefDefine>\n<EmptyLines>2</EmptyLines>\n<Template>[TNV]</Template>\n<Operator>1,1</Operator>\n<Header>cmake/KWStyle/RTKHeader.h,false,true</Header>\n</Description>\n"
  },
  {
    "path": "cmake/KWStyle/RTKHeader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/"
  },
  {
    "path": "cmake/KWStyle/RTKOverwrite.txt",
    "content": "test/.*\\.cxx Namespace Disable\ntest/.*\\.cxx Header Disable\nexamples/.*\\.cxx Namespace Disable\nexamples/.*\\.cxx Header Disable\n"
  },
  {
    "path": "cmake/rtkCompilerFlags.cmake",
    "content": "macro(rtk_module_warnings_disable)\n  # Remove compiler warnings flags for the languages sent as argument.\n  #\n  # Mirrors itk_module_warnings_disable to avoid inclusion of ITKModuleMacros\n  # where the macro is defined. ITKModuleMacros has the side effect of adding\n  # KWStyle/ClangFormat external projects so it should only be included once\n  # per ITK External/Remote module through the inclusion of ITKModuleExternal.\n  foreach(lang ${ARGN})\n    if(MSVC)\n      string(REGEX REPLACE \"(^| )[/-]W[0-4]( |$)\" \" \"\n        CMAKE_${lang}_FLAGS \"${CMAKE_${lang}_FLAGS}\")\n      set(CMAKE_${lang}_FLAGS \"${CMAKE_${lang}_FLAGS} /W0\")\n    elseif(BORLAND)\n      set(CMAKE_${lang}_FLAGS \"${CMAKE_${lang}_FLAGS} -w-\")\n    else()\n      set(CMAKE_${lang}_FLAGS \"${CMAKE_${lang}_FLAGS} -w\")\n    endif()\n  endforeach()\nendmacro()\n"
  },
  {
    "path": "conf.py",
    "content": "# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common options. For a full\n# list see the documentation:\n# https://www.sphinx-doc.org/en/master/usage/configuration.html\n\nfrom datetime import date\n\nimport subprocess\nimport os\n\n# -- Build setup -------------------------------------------------------------\ndef setup(app):\n    # Fetch documentation images\n    cwd = os.getcwd()\n    subprocess.check_call(\n        f\"cmake -DRTK_SOURCE_DIR:PATH={cwd}\"\n        f\"      -DRTK_DOC_OUTPUT_DIR:PATH={cwd}\"\n        \"      -P documentation/docs/copy_and_fetch_sphinx_doc_files.cmake\",\n        stderr=subprocess.STDOUT,\n        shell=True,\n    )\n\n\n# -- Project information -----------------------------------------------------\nproject = \"RTK\"\ncopyright = f\"{date.today().year}, RTK Consortium\"\nauthor = \"RTK Consortium\"\n\n# The full version, including alpha/beta/rc tags\n# release = '2.6.0'\n\n# -- General configuration ---------------------------------------------------\nextensions = [\n    \"myst_parser\",\n    \"sphinx.ext.autodoc\",\n    \"sphinx_copybutton\",\n    \"sphinx_design\",\n    \"sphinx.ext.graphviz\",\n]\n\nmyst_enable_extensions = [\n    \"attrs_inline\",  # inline image attributes\n    \"colon_fence\",\n    \"dollarmath\",  # Support syntax for inline and block math using `$...$` and `$$...$$`\n    # (see https://myst-parser.readthedocs.io/en/latest/syntax/optional.html#dollar-delimited-math)\n    \"fieldlist\",\n    \"linkify\",  # convert bare links to hyperlinks\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = [\"_templates\"]\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path.\nexclude_patterns = [\"_build\", \"Thumbs.db\", \".DS_Store\"]\n\n# The output format for Graphviz when building HTML files. This must be either 'png' or 'svg'; the default is 'png'.\ngraphviz_output_format = \"svg\"\n\n# -- Options for HTML output -------------------------------------------------\nhtml_theme = \"furo\"\n\n# Furo options\nhtml_theme_options = {\n    \"top_of_page_button\": \"edit\",\n    \"source_repository\": \"https://github.com/RTKConsortium/RTK/\",\n    \"source_branch\": \"main\",\n    \"source_directory\": \"\",\n}\n\n# Add any paths that contain custom static files (such as style sheets or icons)\n# here, relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = []\nhtml_logo = \"https://www.openrtk.org/opensourcelogos/rtk75.png\"\nhtml_title = f\"{project}'s documentation\"\nhtml_favicon = \"https://www.openrtk.org/RTK/img/rtk_favicon.ico\"\n\n# -- Master document -------------------------------------------------\nmaster_doc = \"index\"\n"
  },
  {
    "path": "documentation/Doxygen/CMakeLists.txt",
    "content": "if(RTK_BUILD_DOXYGEN)\n  find_package(UnixCommands)\n  find_package(Doxygen)\n  find_package(Gnuplot)\n  find_package(HTMLHelp)\n  find_package(Perl)\n  find_package(Wget)\n\n  #\n  # Configure the script and the doxyfile, then add target\n  #\n\n  # Information on how to retrieve the ITK documentation tag file\n  set(ITK_DOXYGEN_TAG_LOCATION \"https://itk.org/files/NightlyDoxygen/InsightDoxygenDocTag.gz\")\n  set(ITK_DOXYGEN_COMPRESSED_TAG_FILE ${PROJECT_BINARY_DIR}/Doxygen/InsightDoxygen.tag.gz)\n  set(ITK_DOXYGEN_TAG_FILE ${PROJECT_BINARY_DIR}/Doxygen/InsightDoxygen.tag)\n\n  # Get the ITK documentation tag file\n  if(NOT EXISTS ${ITK_DOXYGEN_COMPRESSED_TAG_FILE})\n    file( DOWNLOAD\n          ${ITK_DOXYGEN_TAG_LOCATION}\n\t  ${ITK_DOXYGEN_COMPRESSED_TAG_FILE}\n          TIMEOUT 60\n          STATUS statusITKDoxygenTagFile\n          SHOW_PROGRESS )\n    list(GET statusITKDoxygenTagFile 0 statusITKDoxygenTagFile)\n    if(statusITKDoxygenTagFile)\n\t    file(REMOVE ${ITK_DOXYGEN_COMPRESSED_TAG_FILE})\n    endif()\n  endif()\n  if(EXISTS ${ITK_DOXYGEN_COMPRESSED_TAG_FILE})\n    find_program(GZIP_TOOL NAMES gzip)\n    if(GZIP_TOOL)\n      execute_process(COMMAND ${GZIP_TOOL} -dkf ${ITK_DOXYGEN_COMPRESSED_TAG_FILE})\n      set(DOXYGEN_TAGFILES_PARAMETER \"${ITK_DOXYGEN_TAG_FILE}=https://www.itk.org/Doxygen/html/\")\n    endif()\n  else()\n    set(DOXYGEN_TAGFILES_PARAMETER \"\")\n  endif()\n\n  configure_file(${PROJECT_SOURCE_DIR}/documentation/Doxygen/doxygen.config.in\n                 ${PROJECT_BINARY_DIR}/Doxygen/doxygen.config)\n\n  configure_file(${PROJECT_SOURCE_DIR}/documentation/Doxygen/itkdoxygen.pl.in\n                 ${PROJECT_BINARY_DIR}/Doxygen/itkdoxygen.pl)\n\n  add_custom_target(Documentation\n    COMMAND ${DOXYGEN_EXECUTABLE} ${PROJECT_BINARY_DIR}/Doxygen/doxygen.config\n    MAIN_DEPENDENCY ${PROJECT_BINARY_DIR}/Doxygen/doxygen.config\n    DEPENDS         ${PROJECT_BINARY_DIR}/Doxygen/itkdoxygen.pl ${LATEXTARGETS}\n    WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/Doxygen\n    )\n\nendif ()\n"
  },
  {
    "path": "documentation/Doxygen/DoxygenFooter.html",
    "content": "<!-- HTML footer for doxygen 1.8.15-->\n<!-- start footer part -->\n<!--BEGIN GENERATE_TREEVIEW-->\n<div id=\"nav-path\" class=\"navpath\"><!-- id is needed for treeview function! -->\n  <ul>\n    $navpath\n    <li class=\"footer\">$generatedby\n    <a href=\"https://www.doxygen.org/index.html\">\n    <img class=\"footer\" src=\"$relpath^doxygen.png\" alt=\"doxygen\"/></a> $doxygenversion </li>\n  </ul>\n</div>\n<!--END GENERATE_TREEVIEW-->\n<!--BEGIN !GENERATE_TREEVIEW-->\n<hr class=\"footer\"/>\n<address class=\"footer\"><small>\n$generatedby &#160;<a href=\"https://www.doxygen.org/index.html\">\n<img class=\"footer\" src=\"$relpath^doxygen.png\" alt=\"doxygen\"/>\n</a> $doxygenversion\n</small></address>\n<!--END !GENERATE_TREEVIEW-->\n</body>\n</html>\n"
  },
  {
    "path": "documentation/Doxygen/DoxygenHeader.html",
    "content": "<!-- HTML header for doxygen 1.8.15-->\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"https://www.w3.org/1999/xhtml\" lang=\"en\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=9\"/>\n<meta name=\"generator\" content=\"Doxygen $doxygenversion\"/>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->\n<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->\n<link href=\"$relpath^tabs.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<script type=\"text/javascript\" src=\"$relpath^jquery.js\"></script>\n<script type=\"text/javascript\" src=\"$relpath^dynsections.js\"></script>\n$treeview\n$search\n$mathjax\n<link href=\"$relpath^$stylesheet\" rel=\"stylesheet\" type=\"text/css\" />\n$extrastylesheet\n</head>\n<body>\n<div id=\"top\"><!-- do not remove this div, it is closed by doxygen! -->\n\n<!--BEGIN TITLEAREA-->\n<div id=\"titlearea\">\n<table cellspacing=\"0\" cellpadding=\"0\">\n <tbody>\n <tr style=\"height: 56px;\">\n  <!--BEGIN PROJECT_LOGO-->\n  <td id=\"projectlogo\"><img alt=\"Logo\" src=\"https://www.openrtk.org/opensourcelogos/rtk75.png\" height=\"100\"/></td>\n  <!--END PROJECT_LOGO-->\n  <!--BEGIN PROJECT_NAME-->\n  <td id=\"projectalign\" style=\"padding-left: 0.5em;\">\n   <div id=\"projectname\">$projectname\n   <!--BEGIN PROJECT_NUMBER-->&#160;<span id=\"projectnumber\">$projectnumber</span><!--END PROJECT_NUMBER-->\n   </div>\n   <!--BEGIN PROJECT_BRIEF--><div id=\"projectbrief\">$projectbrief</div><!--END PROJECT_BRIEF-->\n  </td>\n  <!--END PROJECT_NAME-->\n  <!--BEGIN !PROJECT_NAME-->\n   <!--BEGIN PROJECT_BRIEF-->\n    <td style=\"padding-left: 0.5em;\">\n    <div id=\"projectbrief\">$projectbrief</div>\n    </td>\n   <!--END PROJECT_BRIEF-->\n  <!--END !PROJECT_NAME-->\n  <!--BEGIN DISABLE_INDEX-->\n   <!--BEGIN SEARCHENGINE-->\n   <td>$searchbox</td>\n   <!--END SEARCHENGINE-->\n  <!--END DISABLE_INDEX-->\n </tr>\n </tbody>\n</table>\n</div>\n<!--END TITLEAREA-->\n<!-- end header part -->\n<!--  Scripts intended to allow users to submit patches with documentation fixes -->\n<!-- <script src=\"https://www.itk.org/Doxygen/js/jquery-1.4.3.min.js\" type=\"text/javascript\" charset=\"utf-8\"></script> -->\n<!-- <script src=\"https://www.itk.org/Doxygen/js/editdoxygen.js\" type=\"text/javascript\" charset=\"utf-8\"></script> -->\n"
  },
  {
    "path": "documentation/Doxygen/DoxygenStyle.css",
    "content": "/* The standard CSS for doxygen 1.8.15 */\n\nbody, table, div, p, dl {\n\tfont: 400 14px/22px Roboto,sans-serif;\n}\n\np.reference, p.definition {\n\tfont: 400 14px/22px Roboto,sans-serif;\n}\n\n/* @group Heading Levels */\n\nh1.groupheader {\n\tfont-size: 150%;\n}\n\n.title {\n\tfont: 400 14px/28px Roboto,sans-serif;\n\tfont-size: 150%;\n\tfont-weight: bold;\n\tmargin: 10px 2px;\n}\n\nh2.groupheader {\n\tborder-bottom: 1px solid #879ECB;\n\tcolor: #354C7B;\n\tfont-size: 150%;\n\tfont-weight: normal;\n\tmargin-top: 1.75em;\n\tpadding-top: 8px;\n\tpadding-bottom: 4px;\n\twidth: 100%;\n}\n\nh3.groupheader {\n\tfont-size: 100%;\n}\n\nh1, h2, h3, h4, h5, h6 {\n\t-webkit-transition: text-shadow 0.5s linear;\n\t-moz-transition: text-shadow 0.5s linear;\n\t-ms-transition: text-shadow 0.5s linear;\n\t-o-transition: text-shadow 0.5s linear;\n\ttransition: text-shadow 0.5s linear;\n\tmargin-right: 15px;\n}\n\nh1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {\n\ttext-shadow: 0 0 15px cyan;\n}\n\ndt {\n\tfont-weight: bold;\n}\n\ndiv.multicol {\n\t-moz-column-gap: 1em;\n\t-webkit-column-gap: 1em;\n\t-moz-column-count: 3;\n\t-webkit-column-count: 3;\n}\n\np.startli, p.startdd {\n\tmargin-top: 2px;\n}\n\np.starttd {\n\tmargin-top: 0px;\n}\n\np.endli {\n\tmargin-bottom: 0px;\n}\n\np.enddd {\n\tmargin-bottom: 4px;\n}\n\np.endtd {\n\tmargin-bottom: 2px;\n}\n\np.interli {\n}\n\np.interdd {\n}\n\np.intertd {\n}\n\n/* @end */\n\ncaption {\n\tfont-weight: bold;\n}\n\nspan.legend {\n        font-size: 70%;\n        text-align: center;\n}\n\nh3.version {\n        font-size: 90%;\n        text-align: center;\n}\n\ndiv.qindex, div.navtab{\n\tbackground-color: #EBEFF6;\n\tborder: 1px solid #A3B4D7;\n\ttext-align: center;\n}\n\ndiv.qindex, div.navpath {\n\twidth: 100%;\n\tline-height: 140%;\n}\n\ndiv.navtab {\n\tmargin-right: 15px;\n}\n\n/* @group Link Styling */\n\na {\n\tcolor: #3D578C;\n\tfont-weight: normal;\n\ttext-decoration: none;\n}\n\n.contents a:visited {\n\tcolor: #4665A2;\n}\n\na:hover {\n\ttext-decoration: underline;\n}\n\na.qindex {\n\tfont-weight: bold;\n}\n\na.qindexHL {\n\tfont-weight: bold;\n\tbackground-color: #9CAFD4;\n\tcolor: #FFFFFF;\n\tborder: 1px double #869DCA;\n}\n\n.contents a.qindexHL:visited {\n        color: #FFFFFF;\n}\n\na.el {\n\tfont-weight: bold;\n}\n\na.elRef {\n}\n\na.code, a.code:visited, a.line, a.line:visited {\n\tcolor: #4665A2;\n}\n\na.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {\n\tcolor: #4665A2;\n}\n\n/* @end */\n\ndl.el {\n\tmargin-left: -1cm;\n}\n\nul {\n  overflow: hidden; /*Fixed: list item bullets overlap floating elements*/\n}\n\n#side-nav ul {\n  overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */\n}\n\n#main-nav ul {\n  overflow: visible; /* reset ul rule for the navigation bar drop down lists */\n}\n\n.fragment {\n  text-align: left;\n  direction: ltr;\n  overflow-x: auto; /*Fixed: fragment lines overlap floating elements*/\n  overflow-y: hidden;\n}\n\npre.fragment {\n        border: 1px solid #C4CFE5;\n        background-color: #FBFCFD;\n        padding: 4px 6px;\n        margin: 4px 8px 4px 2px;\n        overflow: auto;\n        word-wrap: break-word;\n        font-size:  9pt;\n        line-height: 125%;\n        font-family: monospace, fixed;\n        font-size: 105%;\n}\n\ndiv.fragment {\n  padding: 0 0 1px 0; /*Fixed: last line underline overlap border*/\n  margin: 4px 8px 4px 2px;\n\tbackground-color: #FBFCFD;\n\tborder: 1px solid #C4CFE5;\n}\n\ndiv.line {\n\tfont-family: monospace, fixed;\n        font-size: 13px;\n\tmin-height: 13px;\n\tline-height: 1.0;\n\ttext-wrap: unrestricted;\n\twhite-space: -moz-pre-wrap; /* Moz */\n\twhite-space: -pre-wrap;     /* Opera 4-6 */\n\twhite-space: -o-pre-wrap;   /* Opera 7 */\n\twhite-space: pre-wrap;      /* CSS3  */\n\tword-wrap: break-word;      /* IE 5.5+ */\n\ttext-indent: -53px;\n\tpadding-left: 53px;\n\tpadding-bottom: 0px;\n\tmargin: 0px;\n\t-webkit-transition-property: background-color, box-shadow;\n\t-webkit-transition-duration: 0.5s;\n\t-moz-transition-property: background-color, box-shadow;\n\t-moz-transition-duration: 0.5s;\n\t-ms-transition-property: background-color, box-shadow;\n\t-ms-transition-duration: 0.5s;\n\t-o-transition-property: background-color, box-shadow;\n\t-o-transition-duration: 0.5s;\n\ttransition-property: background-color, box-shadow;\n\ttransition-duration: 0.5s;\n}\n\ndiv.line:after {\n    content:\"\\000A\";\n    white-space: pre;\n}\n\ndiv.line.glow {\n\tbackground-color: cyan;\n\tbox-shadow: 0 0 10px cyan;\n}\n\n\nspan.lineno {\n\tpadding-right: 4px;\n\ttext-align: right;\n\tborder-right: 2px solid #0F0;\n\tbackground-color: #E8E8E8;\n        white-space: pre;\n}\nspan.lineno a {\n\tbackground-color: #D8D8D8;\n}\n\nspan.lineno a:hover {\n\tbackground-color: #C8C8C8;\n}\n\n.lineno {\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-khtml-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n\ndiv.ah, span.ah {\n\tbackground-color: black;\n\tfont-weight: bold;\n\tcolor: #FFFFFF;\n\tmargin-bottom: 3px;\n\tmargin-top: 3px;\n\tpadding: 0.2em;\n\tborder: solid thin #333;\n\tborder-radius: 0.5em;\n\t-webkit-border-radius: .5em;\n\t-moz-border-radius: .5em;\n\tbox-shadow: 2px 2px 3px #999;\n\t-webkit-box-shadow: 2px 2px 3px #999;\n\t-moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;\n\tbackground-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));\n\tbackground-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%);\n}\n\ndiv.classindex ul {\n        list-style: none;\n        padding-left: 0;\n}\n\ndiv.classindex span.ai {\n        display: inline-block;\n}\n\ndiv.groupHeader {\n\tmargin-left: 16px;\n\tmargin-top: 12px;\n\tfont-weight: bold;\n}\n\ndiv.groupText {\n\tmargin-left: 16px;\n\tfont-style: italic;\n}\n\nbody {\n\tbackground-color: white;\n\tcolor: black;\n        margin: 0;\n}\n\ndiv.contents {\n\tmargin-top: 10px;\n\tmargin-left: 12px;\n\tmargin-right: 8px;\n}\n\ntd.indexkey {\n\tbackground-color: #EBEFF6;\n\tfont-weight: bold;\n\tborder: 1px solid #C4CFE5;\n\tmargin: 2px 0px 2px 0;\n\tpadding: 2px 10px;\n        white-space: nowrap;\n        vertical-align: top;\n}\n\ntd.indexvalue {\n\tbackground-color: #EBEFF6;\n\tborder: 1px solid #C4CFE5;\n\tpadding: 2px 10px;\n\tmargin: 2px 0px;\n}\n\ntr.memlist {\n\tbackground-color: #EEF1F7;\n}\n\np.formulaDsp {\n\ttext-align: center;\n}\n\nimg.formulaDsp {\n\n}\n\nimg.formulaInl, img.inline {\n\tvertical-align: middle;\n}\n\ndiv.center {\n\ttext-align: center;\n        margin-top: 0px;\n        margin-bottom: 0px;\n        padding: 0px;\n}\n\ndiv.center img {\n\tborder: 0px;\n}\n\naddress.footer {\n\ttext-align: right;\n\tpadding-right: 12px;\n}\n\nimg.footer {\n\tborder: 0px;\n\tvertical-align: middle;\n}\n\n/* @group Code Colorization */\n\nspan.keyword {\n\tcolor: #008000\n}\n\nspan.keywordtype {\n\tcolor: #604020\n}\n\nspan.keywordflow {\n\tcolor: #e08000\n}\n\nspan.comment {\n\tcolor: #800000\n}\n\nspan.preprocessor {\n\tcolor: #806020\n}\n\nspan.stringliteral {\n\tcolor: #002080\n}\n\nspan.charliteral {\n\tcolor: #008080\n}\n\nspan.vhdldigit {\n\tcolor: #ff00ff\n}\n\nspan.vhdlchar {\n\tcolor: #000000\n}\n\nspan.vhdlkeyword {\n\tcolor: #700070\n}\n\nspan.vhdllogic {\n\tcolor: #ff0000\n}\n\nblockquote {\n        background-color: #F7F8FB;\n        border-left: 2px solid #9CAFD4;\n        margin: 0 24px 0 4px;\n        padding: 0 12px 0 16px;\n}\n\nblockquote.DocNodeRTL {\n   border-left: 0;\n   border-right: 2px solid #9CAFD4;\n   margin: 0 4px 0 24px;\n   padding: 0 16px 0 12px;\n}\n\n/* @end */\n\n/*\n.search {\n\tcolor: #003399;\n\tfont-weight: bold;\n}\n\nform.search {\n\tmargin-bottom: 0px;\n\tmargin-top: 0px;\n}\n\ninput.search {\n\tfont-size: 75%;\n\tcolor: #000080;\n\tfont-weight: normal;\n\tbackground-color: #e8eef2;\n}\n*/\n\ntd.tiny {\n\tfont-size: 75%;\n}\n\n.dirtab {\n\tpadding: 4px;\n\tborder-collapse: collapse;\n\tborder: 1px solid #A3B4D7;\n}\n\nth.dirtab {\n\tbackground: #EBEFF6;\n\tfont-weight: bold;\n}\n\nhr {\n\theight: 0px;\n\tborder: none;\n\tborder-top: 1px solid #4A6AAA;\n}\n\nhr.footer {\n\theight: 1px;\n}\n\n/* @group Member Descriptions */\n\ntable.memberdecls {\n\tborder-spacing: 0px;\n\tpadding: 0px;\n}\n\n.memberdecls td, .fieldtable tr {\n\t-webkit-transition-property: background-color, box-shadow;\n\t-webkit-transition-duration: 0.5s;\n\t-moz-transition-property: background-color, box-shadow;\n\t-moz-transition-duration: 0.5s;\n\t-ms-transition-property: background-color, box-shadow;\n\t-ms-transition-duration: 0.5s;\n\t-o-transition-property: background-color, box-shadow;\n\t-o-transition-duration: 0.5s;\n\ttransition-property: background-color, box-shadow;\n\ttransition-duration: 0.5s;\n}\n\n.memberdecls td.glow, .fieldtable tr.glow {\n\tbackground-color: cyan;\n\tbox-shadow: 0 0 15px cyan;\n}\n\n.mdescLeft, .mdescRight,\n.memItemLeft, .memItemRight,\n.memTemplItemLeft, .memTemplItemRight, .memTemplParams {\n\tbackground-color: #F9FAFC;\n\tborder: none;\n\tmargin: 4px;\n\tpadding: 1px 0 0 8px;\n}\n\n.mdescLeft, .mdescRight {\n\tpadding: 0px 8px 4px 8px;\n\tcolor: #555;\n}\n\n.memSeparator {\n        border-bottom: 1px solid #DEE4F0;\n        line-height: 1px;\n        margin: 0px;\n        padding: 0px;\n}\n\n.memItemLeft, .memTemplItemLeft {\n        white-space: nowrap;\n}\n\n.memItemRight {\n\twidth: 100%;\n}\n\n.memTemplParams {\n\tcolor: #4665A2;\n        white-space: nowrap;\n\tfont-size: 80%;\n}\n\n/* @end */\n\n/* @group Member Details */\n\n/* Styles for detailed member documentation */\n\n.memtitle {\n\tpadding: 8px;\n\tborder-top: 1px solid #A8B8D9;\n\tborder-left: 1px solid #A8B8D9;\n\tborder-right: 1px solid #A8B8D9;\n\tborder-top-right-radius: 4px;\n\tborder-top-left-radius: 4px;\n\tmargin-bottom: -1px;\n\tbackground-image: url('nav_f.png');\n\tbackground-repeat: repeat-x;\n\tbackground-color: #E2E8F2;\n\tline-height: 1.25;\n\tfont-weight: 300;\n\tfloat:left;\n}\n\n.permalink\n{\n        font-size: 65%;\n        display: inline-block;\n        vertical-align: middle;\n}\n\n.memtemplate {\n\tfont-size: 80%;\n\tcolor: #4665A2;\n\tfont-weight: normal;\n\tmargin-left: 9px;\n}\n\n.memnav {\n\tbackground-color: #EBEFF6;\n\tborder: 1px solid #A3B4D7;\n\ttext-align: center;\n\tmargin: 2px;\n\tmargin-right: 15px;\n\tpadding: 2px;\n}\n\n.mempage {\n\twidth: 100%;\n}\n\n.memitem {\n\tpadding: 0;\n\tmargin-bottom: 10px;\n\tmargin-right: 5px;\n        -webkit-transition: box-shadow 0.5s linear;\n        -moz-transition: box-shadow 0.5s linear;\n        -ms-transition: box-shadow 0.5s linear;\n        -o-transition: box-shadow 0.5s linear;\n        transition: box-shadow 0.5s linear;\n        display: table !important;\n        width: 100%;\n}\n\n.memitem.glow {\n         box-shadow: 0 0 15px cyan;\n}\n\n.memname {\n        font-weight: 400;\n        margin-left: 6px;\n}\n\n.memname td {\n\tvertical-align: bottom;\n}\n\n.memproto, dl.reflist dt {\n        border-top: 1px solid #A8B8D9;\n        border-left: 1px solid #A8B8D9;\n        border-right: 1px solid #A8B8D9;\n        padding: 6px 0px 6px 0px;\n        color: #253555;\n        font-weight: bold;\n        text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);\n        background-color: #DFE5F1;\n        /* opera specific markup */\n        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);\n        border-top-right-radius: 4px;\n        /* firefox specific markup */\n        -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;\n        -moz-border-radius-topright: 4px;\n        /* webkit specific markup */\n        -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);\n        -webkit-border-top-right-radius: 4px;\n\n}\n\n.overload {\n        font-family: \"courier new\",courier,monospace;\n\tfont-size: 65%;\n}\n\n.memdoc, dl.reflist dd {\n        border-bottom: 1px solid #A8B8D9;\n        border-left: 1px solid #A8B8D9;\n        border-right: 1px solid #A8B8D9;\n        padding: 6px 10px 2px 10px;\n        background-color: #FBFCFD;\n        border-top-width: 0;\n        background-image:url('nav_g.png');\n        background-repeat:repeat-x;\n        background-color: #FFFFFF;\n        /* opera specific markup */\n        border-bottom-left-radius: 4px;\n        border-bottom-right-radius: 4px;\n        box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);\n        /* firefox specific markup */\n        -moz-border-radius-bottomleft: 4px;\n        -moz-border-radius-bottomright: 4px;\n        -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;\n        /* webkit specific markup */\n        -webkit-border-bottom-left-radius: 4px;\n        -webkit-border-bottom-right-radius: 4px;\n        -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);\n}\n\ndl.reflist dt {\n        padding: 5px;\n}\n\ndl.reflist dd {\n        margin: 0px 0px 10px 0px;\n        padding: 5px;\n}\n\n.paramkey {\n\ttext-align: right;\n}\n\n.paramtype {\n\twhite-space: nowrap;\n}\n\n.paramname {\n\tcolor: #602020;\n\twhite-space: nowrap;\n}\n.paramname em {\n\tfont-style: normal;\n}\n.paramname code {\n        line-height: 14px;\n}\n\n.params, .retval, .exception, .tparams {\n        margin-left: 0px;\n        padding-left: 0px;\n}\n\n.params .paramname, .retval .paramname, .tparams .paramname {\n        font-weight: bold;\n        vertical-align: top;\n}\n\n.params .paramtype, .tparams .paramtype {\n        font-style: italic;\n        vertical-align: top;\n}\n\n.params .paramdir, .tparams .paramdir {\n        font-family: \"courier new\",courier,monospace;\n        vertical-align: top;\n}\n\ntable.mlabels {\n\tborder-spacing: 0px;\n}\n\ntd.mlabels-left {\n\twidth: 100%;\n\tpadding: 0px;\n}\n\ntd.mlabels-right {\n\tvertical-align: bottom;\n\tpadding: 0px;\n\twhite-space: nowrap;\n}\n\nspan.mlabels {\n        margin-left: 8px;\n}\n\nspan.mlabel {\n        background-color: #728DC1;\n        border-top:1px solid #5373B4;\n        border-left:1px solid #5373B4;\n        border-right:1px solid #C4CFE5;\n        border-bottom:1px solid #C4CFE5;\n\ttext-shadow: none;\n\tcolor: white;\n\tmargin-right: 4px;\n\tpadding: 2px 3px;\n\tborder-radius: 3px;\n\tfont-size: 7pt;\n\twhite-space: nowrap;\n\tvertical-align: middle;\n}\n\n\n\n/* @end */\n\n/* these are for tree view inside a (index) page */\n\ndiv.directory {\n        margin: 10px 0px;\n        border-top: 1px solid #9CAFD4;\n        border-bottom: 1px solid #9CAFD4;\n        width: 100%;\n}\n\n.directory table {\n        border-collapse:collapse;\n}\n\n.directory td {\n        margin: 0px;\n        padding: 0px;\n\tvertical-align: top;\n}\n\n.directory td.entry {\n        white-space: nowrap;\n        padding-right: 6px;\n\tpadding-top: 3px;\n}\n\n.directory td.entry a {\n        outline:none;\n}\n\n.directory td.entry a img {\n        border: none;\n}\n\n.directory td.desc {\n        width: 100%;\n        padding-left: 6px;\n\tpadding-right: 6px;\n\tpadding-top: 3px;\n\tborder-left: 1px solid rgba(0,0,0,0.05);\n}\n\n.directory tr.even {\n\tpadding-left: 6px;\n\tbackground-color: #F7F8FB;\n}\n\n.directory img {\n\tvertical-align: -30%;\n}\n\n.directory .levels {\n        white-space: nowrap;\n        width: 100%;\n        text-align: right;\n        font-size: 9pt;\n}\n\n.directory .levels span {\n        cursor: pointer;\n        padding-left: 2px;\n        padding-right: 2px;\n\tcolor: #3D578C;\n}\n\n.arrow {\n    color: #9CAFD4;\n    -webkit-user-select: none;\n    -khtml-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    user-select: none;\n    cursor: pointer;\n    font-size: 80%;\n    display: inline-block;\n    width: 16px;\n    height: 22px;\n}\n\n.icon {\n    font-family: Arial, Helvetica;\n    font-weight: bold;\n    font-size: 12px;\n    height: 14px;\n    width: 16px;\n    display: inline-block;\n    background-color: #728DC1;\n    color: white;\n    text-align: center;\n    border-radius: 4px;\n    margin-left: 2px;\n    margin-right: 2px;\n}\n\n.icona {\n    width: 24px;\n    height: 22px;\n    display: inline-block;\n}\n\n.iconfopen {\n    width: 24px;\n    height: 18px;\n    margin-bottom: 4px;\n    background-image:url('folderopen.png');\n    background-position: 0px -4px;\n    background-repeat: repeat-y;\n    vertical-align:top;\n    display: inline-block;\n}\n\n.iconfclosed {\n    width: 24px;\n    height: 18px;\n    margin-bottom: 4px;\n    background-image:url('folderclosed.png');\n    background-position: 0px -4px;\n    background-repeat: repeat-y;\n    vertical-align:top;\n    display: inline-block;\n}\n\n.icondoc {\n    width: 24px;\n    height: 18px;\n    margin-bottom: 4px;\n    background-image:url('doc.png');\n    background-position: 0px -4px;\n    background-repeat: repeat-y;\n    vertical-align:top;\n    display: inline-block;\n}\n\ntable.directory {\n    font: 400 14px Roboto,sans-serif;\n}\n\n/* @end */\n\ndiv.dynheader {\n        margin-top: 8px;\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-khtml-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n\naddress {\n\tfont-style: normal;\n\tcolor: #2A3D61;\n}\n\ntable.doxtable caption {\n\tcaption-side: top;\n}\n\ntable.doxtable {\n\tborder-collapse:collapse;\n        margin-top: 4px;\n        margin-bottom: 4px;\n}\n\ntable.doxtable td, table.doxtable th {\n\tborder: 1px solid #2D4068;\n\tpadding: 3px 7px 2px;\n}\n\ntable.doxtable th {\n\tbackground-color: #374F7F;\n\tcolor: #FFFFFF;\n\tfont-size: 110%;\n\tpadding-bottom: 4px;\n\tpadding-top: 5px;\n}\n\ntable.fieldtable {\n        /*width: 100%;*/\n        margin-bottom: 10px;\n        border: 1px solid #A8B8D9;\n        border-spacing: 0px;\n        -moz-border-radius: 4px;\n        -webkit-border-radius: 4px;\n        border-radius: 4px;\n        -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;\n        -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);\n        box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);\n}\n\n.fieldtable td, .fieldtable th {\n        padding: 3px 7px 2px;\n}\n\n.fieldtable td.fieldtype, .fieldtable td.fieldname {\n        white-space: nowrap;\n        border-right: 1px solid #A8B8D9;\n        border-bottom: 1px solid #A8B8D9;\n        vertical-align: top;\n}\n\n.fieldtable td.fieldname {\n        padding-top: 3px;\n}\n\n.fieldtable td.fielddoc {\n        border-bottom: 1px solid #A8B8D9;\n        /*width: 100%;*/\n}\n\n.fieldtable td.fielddoc p:first-child {\n        margin-top: 0px;\n}\n\n.fieldtable td.fielddoc p:last-child {\n        margin-bottom: 2px;\n}\n\n.fieldtable tr:last-child td {\n        border-bottom: none;\n}\n\n.fieldtable th {\n        background-image:url('nav_f.png');\n        background-repeat:repeat-x;\n        background-color: #E2E8F2;\n        font-size: 90%;\n        color: #253555;\n        padding-bottom: 4px;\n        padding-top: 5px;\n        text-align:left;\n        font-weight: 400;\n        -moz-border-radius-topleft: 4px;\n        -moz-border-radius-topright: 4px;\n        -webkit-border-top-left-radius: 4px;\n        -webkit-border-top-right-radius: 4px;\n        border-top-left-radius: 4px;\n        border-top-right-radius: 4px;\n        border-bottom: 1px solid #A8B8D9;\n}\n\n\n.tabsearch {\n\ttop: 0px;\n\tleft: 10px;\n\theight: 36px;\n\tbackground-image: url('tab_b.png');\n\tz-index: 101;\n\toverflow: hidden;\n\tfont-size: 13px;\n}\n\n.navpath ul\n{\n\tfont-size: 11px;\n\tbackground-image:url('tab_b.png');\n\tbackground-repeat:repeat-x;\n\tbackground-position: 0 -5px;\n\theight:30px;\n\tline-height:30px;\n\tcolor:#8AA0CC;\n\tborder:solid 1px #C2CDE4;\n\toverflow:hidden;\n\tmargin:0px;\n\tpadding:0px;\n}\n\n.navpath li\n{\n\tlist-style-type:none;\n\tfloat:left;\n\tpadding-left:10px;\n\tpadding-right:15px;\n\tbackground-image:url('bc_s.png');\n\tbackground-repeat:no-repeat;\n\tbackground-position:right;\n\tcolor:#364D7C;\n}\n\n.navpath li.navelem a\n{\n\theight:32px;\n\tdisplay:block;\n\ttext-decoration: none;\n\toutline: none;\n\tcolor: #283A5D;\n\tfont-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;\n\ttext-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);\n\ttext-decoration: none;\n}\n\n.navpath li.navelem a:hover\n{\n\tcolor:#6884BD;\n}\n\n.navpath li.footer\n{\n        list-style-type:none;\n        float:right;\n        padding-left:10px;\n        padding-right:15px;\n        background-image:none;\n        background-repeat:no-repeat;\n        background-position:right;\n        color:#364D7C;\n        font-size: 8pt;\n}\n\n\ndiv.summary\n{\n\tfloat: right;\n\tfont-size: 8pt;\n\tpadding-right: 5px;\n\twidth: 50%;\n\ttext-align: right;\n}\n\ndiv.summary a\n{\n\twhite-space: nowrap;\n}\n\ntable.classindex\n{\n        margin: 10px;\n        white-space: nowrap;\n        margin-left: 3%;\n        margin-right: 3%;\n        width: 94%;\n        border: 0;\n        border-spacing: 0;\n        padding: 0;\n}\n\ndiv.ingroups\n{\n\tfont-size: 8pt;\n\twidth: 50%;\n\ttext-align: left;\n}\n\ndiv.ingroups a\n{\n\twhite-space: nowrap;\n}\n\ndiv.header\n{\n        background-image:url('nav_h.png');\n        background-repeat:repeat-x;\n\tbackground-color: #F9FAFC;\n\tmargin:  0px;\n\tborder-bottom: 1px solid #C4CFE5;\n}\n\ndiv.headertitle\n{\n\tpadding: 5px 5px 5px 10px;\n}\n\n.PageDocRTL-title div.headertitle {\n  text-align: right;\n  direction: rtl;\n}\n\ndl {\n        padding: 0 0 0 0;\n}\n\n/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug, dl.examples */\ndl.section {\n\tmargin-left: 0px;\n\tpadding-left: 0px;\n}\n\ndl.section.DocNodeRTL {\n  margin-right: 0px;\n  padding-right: 0px;\n}\n\ndl.note {\n  margin-left: -7px;\n  padding-left: 3px;\n  border-left: 4px solid;\n  border-color: #D0C000;\n}\n\ndl.note.DocNodeRTL {\n  margin-left: 0;\n  padding-left: 0;\n  border-left: 0;\n  margin-right: -7px;\n  padding-right: 3px;\n  border-right: 4px solid;\n  border-color: #D0C000;\n}\n\ndl.warning, dl.attention {\n  margin-left: -7px;\n  padding-left: 3px;\n  border-left: 4px solid;\n  border-color: #FF0000;\n}\n\ndl.warning.DocNodeRTL, dl.attention.DocNodeRTL {\n  margin-left: 0;\n  padding-left: 0;\n  border-left: 0;\n  margin-right: -7px;\n  padding-right: 3px;\n  border-right: 4px solid;\n  border-color: #FF0000;\n}\n\ndl.pre, dl.post, dl.invariant {\n  margin-left: -7px;\n  padding-left: 3px;\n  border-left: 4px solid;\n  border-color: #00D000;\n}\n\ndl.pre.DocNodeRTL, dl.post.DocNodeRTL, dl.invariant.DocNodeRTL {\n  margin-left: 0;\n  padding-left: 0;\n  border-left: 0;\n  margin-right: -7px;\n  padding-right: 3px;\n  border-right: 4px solid;\n  border-color: #00D000;\n}\n\ndl.deprecated {\n  margin-left: -7px;\n  padding-left: 3px;\n  border-left: 4px solid;\n  border-color: #505050;\n}\n\ndl.deprecated.DocNodeRTL {\n  margin-left: 0;\n  padding-left: 0;\n  border-left: 0;\n  margin-right: -7px;\n  padding-right: 3px;\n  border-right: 4px solid;\n  border-color: #505050;\n}\n\ndl.todo {\n  margin-left: -7px;\n  padding-left: 3px;\n  border-left: 4px solid;\n  border-color: #00C0E0;\n}\n\ndl.todo.DocNodeRTL {\n  margin-left: 0;\n  padding-left: 0;\n  border-left: 0;\n  margin-right: -7px;\n  padding-right: 3px;\n  border-right: 4px solid;\n  border-color: #00C0E0;\n}\n\ndl.test {\n  margin-left: -7px;\n  padding-left: 3px;\n  border-left: 4px solid;\n  border-color: #3030E0;\n}\n\ndl.test.DocNodeRTL {\n  margin-left: 0;\n  padding-left: 0;\n  border-left: 0;\n  margin-right: -7px;\n  padding-right: 3px;\n  border-right: 4px solid;\n  border-color: #3030E0;\n}\n\ndl.bug {\n  margin-left: -7px;\n  padding-left: 3px;\n  border-left: 4px solid;\n  border-color: #C08050;\n}\n\ndl.bug.DocNodeRTL {\n  margin-left: 0;\n  padding-left: 0;\n  border-left: 0;\n  margin-right: -7px;\n  padding-right: 3px;\n  border-right: 4px solid;\n  border-color: #C08050;\n}\n\ndl.section dd {\n\tmargin-bottom: 6px;\n}\n\n\n#projectlogo\n{\n\ttext-align: center;\n\tvertical-align: bottom;\n\tborder-collapse: separate;\n}\n\n#projectlogo img\n{\n\tborder: 0px none;\n}\n\n#projectalign\n{\n        vertical-align: middle;\n}\n\n#projectname\n{\n\tfont: 300% Tahoma, Arial,sans-serif;\n\tmargin: 0px;\n\tpadding: 2px 0px;\n}\n\n#projectbrief\n{\n\tfont: 120% Tahoma, Arial,sans-serif;\n\tmargin: 0px;\n\tpadding: 0px;\n}\n\n#projectnumber\n{\n\tfont: 50% Tahoma, Arial,sans-serif;\n\tmargin: 0px;\n\tpadding: 0px;\n}\n\n#titlearea\n{\n\tpadding: 0px;\n\tmargin: 0px;\n\twidth: 100%;\n\tborder-bottom: 1px solid #5373B4;\n}\n\n.image\n{\n        text-align: center;\n}\n\n.dotgraph\n{\n        text-align: center;\n}\n\n.mscgraph\n{\n        text-align: center;\n}\n\n.plantumlgraph\n{\n        text-align: center;\n}\n\n.diagraph\n{\n        text-align: center;\n}\n\n.caption\n{\n\tfont-weight: bold;\n}\n\ndiv.zoom\n{\n\tborder: 1px solid #90A5CE;\n}\n\ndl.citelist {\n        margin-bottom:50px;\n}\n\ndl.citelist dt {\n        color:#334975;\n        float:left;\n        font-weight:bold;\n        margin-right:10px;\n        padding:5px;\n}\n\ndl.citelist dd {\n        margin:2px 0;\n        padding:5px 0;\n}\n\ndiv.toc {\n        padding: 14px 25px;\n        background-color: #F4F6FA;\n        border: 1px solid #D8DFEE;\n        border-radius: 7px 7px 7px 7px;\n        float: right;\n        height: auto;\n        margin: 0 8px 10px 10px;\n        width: 200px;\n}\n\n.PageDocRTL-title div.toc {\n  float: left !important;\n  text-align: right;\n}\n\ndiv.toc li {\n        background: url(\"bdwn.png\") no-repeat scroll 0 5px transparent;\n        font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif;\n        margin-top: 5px;\n        padding-left: 10px;\n        padding-top: 2px;\n}\n\n.PageDocRTL-title div.toc li {\n  background-position-x: right !important;\n  padding-left: 0 !important;\n  padding-right: 10px;\n}\n\ndiv.toc h3 {\n        font: bold 12px/1.2 Arial,FreeSans,sans-serif;\n\tcolor: #4665A2;\n        border-bottom: 0 none;\n        margin: 0;\n}\n\ndiv.toc ul {\n        list-style: none outside none;\n        border: medium none;\n        padding: 0px;\n}\n\ndiv.toc li.level1 {\n        margin-left: 0px;\n}\n\ndiv.toc li.level2 {\n        margin-left: 15px;\n}\n\ndiv.toc li.level3 {\n        margin-left: 30px;\n}\n\ndiv.toc li.level4 {\n        margin-left: 45px;\n}\n\n.PageDocRTL-title div.toc li.level1 {\n  margin-left: 0 !important;\n  margin-right: 0;\n}\n\n.PageDocRTL-title div.toc li.level2 {\n  margin-left: 0 !important;\n  margin-right: 15px;\n}\n\n.PageDocRTL-title div.toc li.level3 {\n  margin-left: 0 !important;\n  margin-right: 30px;\n}\n\n.PageDocRTL-title div.toc li.level4 {\n  margin-left: 0 !important;\n  margin-right: 45px;\n}\n\n.inherit_header {\n        font-weight: bold;\n        color: gray;\n        cursor: pointer;\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-khtml-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n\n.inherit_header td {\n        padding: 6px 0px 2px 5px;\n}\n\n.inherit {\n        display: none;\n}\n\ntr.heading h2 {\n        margin-top: 12px;\n        margin-bottom: 4px;\n}\n\n/* tooltip related style info */\n\n.ttc {\n        position: absolute;\n        display: none;\n}\n\n#powerTip {\n\tcursor: default;\n\twhite-space: nowrap;\n\tbackground-color: white;\n\tborder: 1px solid gray;\n\tborder-radius: 4px 4px 4px 4px;\n\tbox-shadow: 1px 1px 7px gray;\n\tdisplay: none;\n\tfont-size: smaller;\n\tmax-width: 80%;\n\topacity: 0.9;\n\tpadding: 1ex 1em 1em;\n\tposition: absolute;\n\tz-index: 2147483647;\n}\n\n#powerTip div.ttdoc {\n        color: grey;\n\tfont-style: italic;\n}\n\n#powerTip div.ttname a {\n        font-weight: bold;\n}\n\n#powerTip div.ttname {\n        font-weight: bold;\n}\n\n#powerTip div.ttdeci {\n        color: #006318;\n}\n\n#powerTip div {\n        margin: 0px;\n        padding: 0px;\n        font: 12px/16px Roboto,sans-serif;\n}\n\n#powerTip:before, #powerTip:after {\n\tcontent: \"\";\n\tposition: absolute;\n\tmargin: 0px;\n}\n\n#powerTip.n:after,  #powerTip.n:before,\n#powerTip.s:after,  #powerTip.s:before,\n#powerTip.w:after,  #powerTip.w:before,\n#powerTip.e:after,  #powerTip.e:before,\n#powerTip.ne:after, #powerTip.ne:before,\n#powerTip.se:after, #powerTip.se:before,\n#powerTip.nw:after, #powerTip.nw:before,\n#powerTip.sw:after, #powerTip.sw:before {\n\tborder: solid transparent;\n\tcontent: \" \";\n\theight: 0;\n\twidth: 0;\n\tposition: absolute;\n}\n\n#powerTip.n:after,  #powerTip.s:after,\n#powerTip.w:after,  #powerTip.e:after,\n#powerTip.nw:after, #powerTip.ne:after,\n#powerTip.sw:after, #powerTip.se:after {\n\tborder-color: rgba(255, 255, 255, 0);\n}\n\n#powerTip.n:before,  #powerTip.s:before,\n#powerTip.w:before,  #powerTip.e:before,\n#powerTip.nw:before, #powerTip.ne:before,\n#powerTip.sw:before, #powerTip.se:before {\n\tborder-color: rgba(128, 128, 128, 0);\n}\n\n#powerTip.n:after,  #powerTip.n:before,\n#powerTip.ne:after, #powerTip.ne:before,\n#powerTip.nw:after, #powerTip.nw:before {\n\ttop: 100%;\n}\n\n#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after {\n\tborder-top-color: #FFFFFF;\n\tborder-width: 10px;\n\tmargin: 0px -10px;\n}\n#powerTip.n:before {\n\tborder-top-color: #808080;\n\tborder-width: 11px;\n\tmargin: 0px -11px;\n}\n#powerTip.n:after, #powerTip.n:before {\n\tleft: 50%;\n}\n\n#powerTip.nw:after, #powerTip.nw:before {\n\tright: 14px;\n}\n\n#powerTip.ne:after, #powerTip.ne:before {\n\tleft: 14px;\n}\n\n#powerTip.s:after,  #powerTip.s:before,\n#powerTip.se:after, #powerTip.se:before,\n#powerTip.sw:after, #powerTip.sw:before {\n\tbottom: 100%;\n}\n\n#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after {\n\tborder-bottom-color: #FFFFFF;\n\tborder-width: 10px;\n\tmargin: 0px -10px;\n}\n\n#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before {\n\tborder-bottom-color: #808080;\n\tborder-width: 11px;\n\tmargin: 0px -11px;\n}\n\n#powerTip.s:after, #powerTip.s:before {\n\tleft: 50%;\n}\n\n#powerTip.sw:after, #powerTip.sw:before {\n\tright: 14px;\n}\n\n#powerTip.se:after, #powerTip.se:before {\n\tleft: 14px;\n}\n\n#powerTip.e:after, #powerTip.e:before {\n\tleft: 100%;\n}\n#powerTip.e:after {\n\tborder-left-color: #FFFFFF;\n\tborder-width: 10px;\n\ttop: 50%;\n\tmargin-top: -10px;\n}\n#powerTip.e:before {\n\tborder-left-color: #808080;\n\tborder-width: 11px;\n\ttop: 50%;\n\tmargin-top: -11px;\n}\n\n#powerTip.w:after, #powerTip.w:before {\n\tright: 100%;\n}\n#powerTip.w:after {\n\tborder-right-color: #FFFFFF;\n\tborder-width: 10px;\n\ttop: 50%;\n\tmargin-top: -10px;\n}\n#powerTip.w:before {\n\tborder-right-color: #808080;\n\tborder-width: 11px;\n\ttop: 50%;\n\tmargin-top: -11px;\n}\n\n@media print\n{\n  #top { display: none; }\n  #side-nav { display: none; }\n  #nav-path { display: none; }\n  body { overflow:visible; }\n  h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }\n  .summary { display: none; }\n  .memitem { page-break-inside: avoid; }\n  #doc-content\n  {\n    margin-left:0 !important;\n    height:auto !important;\n    width:auto !important;\n    overflow:inherit;\n    display:inline;\n  }\n}\n\n/* @group Markdown */\n\n/*\ntable.markdownTable {\n\tborder-collapse:collapse;\n        margin-top: 4px;\n        margin-bottom: 4px;\n}\n\ntable.markdownTable td, table.markdownTable th {\n\tborder: 1px solid #2D4068;\n\tpadding: 3px 7px 2px;\n}\n\ntable.markdownTableHead tr {\n}\n\ntable.markdownTableBodyLeft td, table.markdownTable th {\n\tborder: 1px solid #2D4068;\n\tpadding: 3px 7px 2px;\n}\n\nth.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone {\n\tbackground-color: #374F7F;\n\tcolor: #FFFFFF;\n\tfont-size: 110%;\n\tpadding-bottom: 4px;\n\tpadding-top: 5px;\n}\n\nth.markdownTableHeadLeft {\n\ttext-align: left\n}\n\nth.markdownTableHeadRight {\n\ttext-align: right\n}\n\nth.markdownTableHeadCenter {\n\ttext-align: center\n}\n*/\n\ntable.markdownTable {\n\tborder-collapse:collapse;\n        margin-top: 4px;\n        margin-bottom: 4px;\n}\n\ntable.markdownTable td, table.markdownTable th {\n\tborder: 1px solid #2D4068;\n\tpadding: 3px 7px 2px;\n}\n\ntable.markdownTable tr {\n}\n\nth.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone {\n\tbackground-color: #374F7F;\n\tcolor: #FFFFFF;\n\tfont-size: 110%;\n\tpadding-bottom: 4px;\n\tpadding-top: 5px;\n}\n\nth.markdownTableHeadLeft, td.markdownTableBodyLeft {\n\ttext-align: left\n}\n\nth.markdownTableHeadRight, td.markdownTableBodyRight {\n\ttext-align: right\n}\n\nth.markdownTableHeadCenter, td.markdownTableBodyCenter {\n\ttext-align: center\n}\n\n.DocNodeRTL {\n  text-align: right;\n  direction: rtl;\n}\n\n.DocNodeLTR {\n  text-align: left;\n  direction: ltr;\n}\n\ntable.DocNodeRTL {\n   width: auto;\n   margin-right: 0;\n   margin-left: auto;\n}\n\ntable.DocNodeLTR {\n   width: auto;\n   margin-right: auto;\n   margin-left: 0;\n}\n\ntt, code, kbd, samp\n{\n  display: inline-block;\n  direction:ltr;\n}\n/* @end */\n\nu {\n\ttext-decoration: underline;\n}\n"
  },
  {
    "path": "documentation/Doxygen/MainPage.dox",
    "content": "/**\n *\n * \\mainpage  Reconstruction Toolkit\n *\n * \\image html https://www.openrtk.org/opensourcelogos/rtk100.png width=200\n *\n * Welcome to the RTK project! The objective of this project is to develop\n * open-source software for fast tomographic reconstruction compatible with\n * ITK. The Home Page of the Reconstruction toolkit can be found at :\n *\n * https://www.openrtk.org/\n *\n * This documentation describes the API of the Toolkit. The Modules\n * link presents a hierarchy of classes organized according to their\n * functionality.\n *\n */\n\n"
  },
  {
    "path": "documentation/Doxygen/Modules.dox",
    "content": "/**\n \\defgroup Projector Objects related to forward- / back-projection.\n*/\n\n/**\n \\defgroup ReconstructionAlgorithm Objects to reconstruct a tomography.\n*/\n\n/**\n \\defgroup CudaImageToImageFilter Filters using the GPU with CUDA.\n*/\n\n/**\n \\defgroup Macro Useful macros for RTK development.\n*/\n\n/**\n \\defgroup Geometry Geometrical computations.\n*/\n"
  },
  {
    "path": "documentation/Doxygen/doxygen.config.in",
    "content": "# Doxyfile 1.8.15\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) for a project.\n#\n# All text after a double hash (##) is considered a comment and is placed in\n# front of the TAG it is preceding.\n#\n# All text after a single hash (#) is considered a comment and will be ignored.\n# The format is:\n# TAG = value [value, ...]\n# For lists, items can also be appended using:\n# TAG += value [value, ...]\n# Values that contain spaces should be placed between quotes (\\\" \\\").\n\n#---------------------------------------------------------------------------\n# Project related configuration options\n#---------------------------------------------------------------------------\n\n# This tag specifies the encoding used for all characters in the configuration\n# file that follow. The default is UTF-8 which is also the encoding used for all\n# text before the first occurrence of this tag. Doxygen uses libiconv (or the\n# iconv built into libc) for the transcoding. See\n# https://www.gnu.org/software/libiconv/ for the list of possible encodings.\n# The default value is: UTF-8.\n\nDOXYFILE_ENCODING      = UTF-8\n\n# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by\n# double-quotes, unless you are using Doxywizard) that should identify the\n# project for which the documentation is generated. This name is used in the\n# title of most generated pages and in a few other places.\n# The default value is: My Project.\n\nPROJECT_NAME           = RTK\n\n# The PROJECT_NUMBER tag can be used to enter a project or revision number. This\n# could be handy for archiving the generated documentation or if some version\n# control system is used.\n\nPROJECT_NUMBER         = @RTK_VERSION_MAJOR@.@RTK_VERSION_MINOR@.@RTK_VERSION_PATCH@\n\n# Using the PROJECT_BRIEF tag one can provide an optional one line description\n# for a project that appears at the top of each page and should give viewer a\n# quick idea about the purpose of the project. Keep the description short.\n\nPROJECT_BRIEF          = \"Reconstruction Toolkit\"\n\n# With the PROJECT_LOGO tag one can specify a logo or an icon that is included\n# in the documentation. The maximum height of the logo should not exceed 55\n# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy\n# the logo to the output directory.\n\nPROJECT_LOGO           = https://www.openrtk.org/opensourcelogos/rtk100.png\n\n# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path\n# into which the generated documentation will be written. If a relative path is\n# entered, it will be relative to the location where doxygen was started. If\n# left blank the current directory will be used.\n\nOUTPUT_DIRECTORY       = @PROJECT_BINARY_DIR@/Doxygen\n\n# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-\n# directories (in 2 levels) under the output directory of each output format and\n# will distribute the generated files over these directories. Enabling this\n# option can be useful when feeding doxygen a huge amount of source files, where\n# putting all generated files in the same directory would otherwise causes\n# performance problems for the file system.\n# The default value is: NO.\n\nCREATE_SUBDIRS         = NO\n\n# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII\n# characters to appear in the names of generated files. If set to NO, non-ASCII\n# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode\n# U+3044.\n# The default value is: NO.\n\nALLOW_UNICODE_NAMES    = NO\n\n# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all constant output in the proper language.\n# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,\n# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),\n# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,\n# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),\n# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,\n# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,\n# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,\n# Ukrainian and Vietnamese.\n# The default value is: English.\n\nOUTPUT_LANGUAGE        = English\n\n# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all\n# documentation generated by doxygen is written. Doxygen will use this\n# information to generate all generated output in the proper direction.\n# Possible values are: None, LTR, RTL and Context.\n# The default value is: None.\n\nOUTPUT_TEXT_DIRECTION  = None\n\n# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member\n# descriptions after the members that are listed in the file and class\n# documentation (similar to Javadoc). Set to NO to disable this.\n# The default value is: YES.\n\nBRIEF_MEMBER_DESC      = NO\n\n# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief\n# description of a member or function before the detailed description\n#\n# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the\n# brief descriptions will be completely suppressed.\n# The default value is: YES.\n\nREPEAT_BRIEF           = YES\n\n# This tag implements a quasi-intelligent brief description abbreviator that is\n# used to form the text in various listings. Each string in this list, if found\n# as the leading text of the brief description, will be stripped from the text\n# and the result, after processing the whole list, is used as the annotated\n# text. Otherwise, the brief description is used as-is. If left blank, the\n# following values are used ($name is automatically replaced with the name of\n# the entity):The $name class, The $name widget, The $name file, is, provides,\n# specifies, contains, represents, a, an and the.\n\nABBREVIATE_BRIEF       = \"The $name class\" \\\n                         \"The $name widget\" \\\n                         \"The $name file\" \\\n                         is \\\n                         provides \\\n                         specifies \\\n                         contains \\\n                         represents \\\n                         a \\\n                         an \\\n                         the\n\n# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then\n# doxygen will generate a detailed section even if there is only a brief\n# description.\n# The default value is: NO.\n\nALWAYS_DETAILED_SEC    = NO\n\n# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all\n# inherited members of a class in the documentation of that class as if those\n# members were ordinary class members. Constructors, destructors and assignment\n# operators of the base classes will not be shown.\n# The default value is: NO.\n\nINLINE_INHERITED_MEMB  = NO\n\n# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path\n# before files name in the file list and in the header files. If set to NO the\n# shortest path that makes the file name unique will be used\n# The default value is: YES.\n\nFULL_PATH_NAMES        = NO\n\n# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.\n# Stripping is only done if one of the specified strings matches the left-hand\n# part of the path. The tag can be used to show relative paths in the file list.\n# If left blank the directory from which doxygen is run is used as the path to\n# strip.\n#\n# Note that you can specify absolute paths here, but also relative paths, which\n# will be relative from the directory where doxygen is started.\n# This tag requires that the tag FULL_PATH_NAMES is set to YES.\n\nSTRIP_FROM_PATH        = @PROJECT_BINARY_DIR@/\n\n# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the\n# path mentioned in the documentation of a class, which tells the reader which\n# header file to include in order to use a class. If left blank only the name of\n# the header file containing the class definition is used. Otherwise one should\n# specify the list of include paths that are normally passed to the compiler\n# using the -I flag.\n\nSTRIP_FROM_INC_PATH    =\n\n# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but\n# less readable) file names. This can be useful is your file systems doesn't\n# support long names like on DOS, Mac, or CD-ROM.\n# The default value is: NO.\n\nSHORT_NAMES            = NO\n\n# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the\n# first line (until the first dot) of a Javadoc-style comment as the brief\n# description. If set to NO, the Javadoc-style will behave just like regular Qt-\n# style comments (thus requiring an explicit @brief command for a brief\n# description.)\n# The default value is: NO.\n\nJAVADOC_AUTOBRIEF      = NO\n\n# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first\n# line (until the first dot) of a Qt-style comment as the brief description. If\n# set to NO, the Qt-style will behave just like regular Qt-style comments (thus\n# requiring an explicit \\brief command for a brief description.)\n# The default value is: NO.\n\nQT_AUTOBRIEF           = NO\n\n# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a\n# multi-line C++ special comment block (i.e. a block of //! or /// comments) as\n# a brief description. This used to be the default behavior. The new default is\n# to treat a multi-line C++ comment block as a detailed description. Set this\n# tag to YES if you prefer the old behavior instead.\n#\n# Note that setting this tag to YES also means that rational rose comments are\n# not recognized any more.\n# The default value is: NO.\n\nMULTILINE_CPP_IS_BRIEF = NO\n\n# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the\n# documentation from any documented member that it re-implements.\n# The default value is: YES.\n\nINHERIT_DOCS           = YES\n\n# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new\n# page for each member. If set to NO, the documentation of a member will be part\n# of the file/class/namespace that contains it.\n# The default value is: NO.\n\nSEPARATE_MEMBER_PAGES  = NO\n\n# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen\n# uses this value to replace tabs by spaces in code fragments.\n# Minimum value: 1, maximum value: 16, default value: 4.\n\nTAB_SIZE               = 2\n\n# This tag can be used to specify a number of aliases that act as commands in\n# the documentation. An alias has the form:\n# name=value\n# For example adding\n# \"sideeffect=@par Side Effects:\\n\"\n# will allow you to put the command \\sideeffect (or @sideeffect) in the\n# documentation, which will result in a user-defined paragraph with heading\n# \"Side Effects:\". You can put \\n's in the value part of an alias to insert\n# newlines (in the resulting output). You can put ^^ in the value part of an\n# alias to insert a newline as if a physical newline was in the original file.\n# When you need a literal { or } or , in the value part of an alias you have to\n# escape them by means of a backslash (\\), this can lead to conflicts with the\n# commands \\{ and \\} for these it is advised to use the version @{ and @} or use\n# a double escape (\\\\{ and \\\\})\n\n# Follow example from https://www.doxygen.nl/manual/custcmd.html\n# Use ^^ instead of \\n in aliases https://sourceforge.net/p/doxygen/mailman/message/36215997/\nALIASES                =\n\n# This tag can be used to specify a number of word-keyword mappings (TCL only).\n# A mapping has the form \"name=value\". For example adding \"class=itcl::class\"\n# will allow you to use the command class in the itcl::class meaning.\n\nTCL_SUBST              =\n\n# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources\n# only. Doxygen will then generate output that is more tailored for C. For\n# instance, some of the names that are used will be different. The list of all\n# members will be omitted, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_FOR_C  = NO\n\n# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or\n# Python sources only. Doxygen will then generate output that is more tailored\n# for that language. For instance, namespaces will be presented as packages,\n# qualified scopes will look different, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_JAVA   = NO\n\n# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran\n# sources. Doxygen will then generate output that is tailored for Fortran.\n# The default value is: NO.\n\nOPTIMIZE_FOR_FORTRAN   = NO\n\n# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL\n# sources. Doxygen will then generate output that is tailored for VHDL.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_VHDL   = NO\n\n# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice\n# sources only. Doxygen will then generate output that is more tailored for that\n# language. For instance, namespaces will be presented as modules, types will be\n# separated into more groups, etc.\n# The default value is: NO.\n\nOPTIMIZE_OUTPUT_SLICE  = NO\n\n# Doxygen selects the parser to use depending on the extension of the files it\n# parses. With this tag you can assign which parser to use for a given\n# extension. Doxygen has a built-in mapping, but you can override or extend it\n# using this tag. The format is ext=language, where ext is a file extension, and\n# language is one of the parsers supported by doxygen: IDL, Java, Javascript,\n# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,\n# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:\n# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser\n# tries to guess whether the code is fixed or free formatted code, this is the\n# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat\n# .inc files as Fortran files (default is PHP), and .f files as C (default is\n# Fortran), use: inc=Fortran f=C.\n#\n# Note: For files without extension you can use no_extension as a placeholder.\n#\n# Note that for custom extensions you also need to set FILE_PATTERNS otherwise\n# the files are not read by doxygen.\n\nEXTENSION_MAPPING      =\n\n# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments\n# according to the Markdown format, which allows for more readable\n# documentation. See https://daringfireball.net/projects/markdown/ for details.\n# The output of markdown processing is further processed by doxygen, so you can\n# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in\n# case of backward compatibilities issues.\n# The default value is: YES.\n\nMARKDOWN_SUPPORT       = YES\n\n# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up\n# to that level are automatically included in the table of contents, even if\n# they do not have an id attribute.\n# Note: This feature currently applies only to Markdown headings.\n# Minimum value: 0, maximum value: 99, default value: 0.\n# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.\n\nTOC_INCLUDE_HEADINGS   = 0\n\n# When enabled doxygen tries to link words that correspond to documented\n# classes, or namespaces to their corresponding documentation. Such a link can\n# be prevented in individual cases by putting a % sign in front of the word or\n# globally by setting AUTOLINK_SUPPORT to NO.\n# The default value is: YES.\n\nAUTOLINK_SUPPORT       = YES\n\n# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want\n# to include (a tag file for) the STL sources as input, then you should set this\n# tag to YES in order to let doxygen match functions declarations and\n# definitions whose arguments contain STL classes (e.g. func(std::string);\n# versus func(std::string) {}). This also make the inheritance and collaboration\n# diagrams that involve STL classes more complete and accurate.\n# The default value is: NO.\n\nBUILTIN_STL_SUPPORT    = YES\n\n# If you use Microsoft's C++/CLI language, you should set this option to YES to\n# enable parsing support.\n# The default value is: NO.\n\nCPP_CLI_SUPPORT        = NO\n\n# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:\n# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen\n# will parse them like normal C++ but will assume all classes use public instead\n# of private inheritance when no explicit protection keyword is present.\n# The default value is: NO.\n\nSIP_SUPPORT            = NO\n\n# For Microsoft's IDL there are propget and propput attributes to indicate\n# getter and setter methods for a property. Setting this option to YES will make\n# doxygen to replace the get and set methods by a property in the documentation.\n# This will only work if the methods are indeed getting or setting a simple\n# type. If this is not the case, or you want to show the methods anyway, you\n# should set this option to NO.\n# The default value is: YES.\n\nIDL_PROPERTY_SUPPORT   = YES\n\n# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC\n# tag is set to YES then doxygen will reuse the documentation of the first\n# member in the group (if any) for the other members of the group. By default\n# all members of a group must be documented explicitly.\n# The default value is: NO.\n\nDISTRIBUTE_GROUP_DOC   = YES\n\n# If one adds a struct or class to a group and this option is enabled, then also\n# any nested class or struct is added to the same group. By default this option\n# is disabled and one has to add nested compounds explicitly via \\ingroup.\n# The default value is: NO.\n\nGROUP_NESTED_COMPOUNDS = NO\n\n# Set the SUBGROUPING tag to YES to allow class member groups of the same type\n# (for instance a group of public functions) to be put as a subgroup of that\n# type (e.g. under the Public Functions section). Set it to NO to prevent\n# subgrouping. Alternatively, this can be done per class using the\n# \\nosubgrouping command.\n# The default value is: YES.\n\nSUBGROUPING            = YES\n\n# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions\n# are shown inside the group in which they are included (e.g. using \\ingroup)\n# instead of on a separate page (for HTML and Man pages) or section (for LaTeX\n# and RTF).\n#\n# Note that this feature does not work in combination with\n# SEPARATE_MEMBER_PAGES.\n# The default value is: NO.\n\nINLINE_GROUPED_CLASSES = NO\n\n# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions\n# with only public data fields or simple typedef fields will be shown inline in\n# the documentation of the scope in which they are defined (i.e. file,\n# namespace, or group documentation), provided this scope is documented. If set\n# to NO, structs, classes, and unions are shown on a separate page (for HTML and\n# Man pages) or section (for LaTeX and RTF).\n# The default value is: NO.\n\nINLINE_SIMPLE_STRUCTS  = NO\n\n# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or\n# enum is documented as struct, union, or enum with the name of the typedef. So\n# typedef struct TypeS {} TypeT, will appear in the documentation as a struct\n# with name TypeT. When disabled the typedef will appear as a member of a file,\n# namespace, or class. And the struct will be named TypeS. This can typically be\n# useful for C code in case the coding convention dictates that all compound\n# types are typedef'ed and only the typedef is referenced, never the tag name.\n# The default value is: NO.\n\nTYPEDEF_HIDES_STRUCT   = NO\n\n# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This\n# cache is used to resolve symbols given their name and scope. Since this can be\n# an expensive process and often the same symbol appears multiple times in the\n# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small\n# doxygen will become slower. If the cache is too large, memory is wasted. The\n# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range\n# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536\n# symbols. At the end of a run doxygen will report the cache usage and suggest\n# the optimal cache size from a speed point of view.\n# Minimum value: 0, maximum value: 9, default value: 0.\n\nLOOKUP_CACHE_SIZE      = 2\n\n#---------------------------------------------------------------------------\n# Build related configuration options\n#---------------------------------------------------------------------------\n\n# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in\n# documentation are documented, even if no documentation was available. Private\n# class members and static file members will be hidden unless the\n# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.\n# Note: This will also disable the warnings about undocumented members that are\n# normally produced when WARNINGS is set to YES.\n# The default value is: NO.\n\nEXTRACT_ALL            = YES\n\n# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will\n# be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PRIVATE        = YES\n\n# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal\n# scope will be included in the documentation.\n# The default value is: NO.\n\nEXTRACT_PACKAGE        = NO\n\n# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be\n# included in the documentation.\n# The default value is: NO.\n\nEXTRACT_STATIC         = YES\n\n# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined\n# locally in source files will be included in the documentation. If set to NO,\n# only classes defined in header files are included. Does not have any effect\n# for Java sources.\n# The default value is: YES.\n\nEXTRACT_LOCAL_CLASSES  = YES\n\n# This flag is only useful for Objective-C code. If set to YES, local methods,\n# which are defined in the implementation section but not in the interface are\n# included in the documentation. If set to NO, only methods in the interface are\n# included.\n# The default value is: NO.\n\nEXTRACT_LOCAL_METHODS  = NO\n\n# If this flag is set to YES, the members of anonymous namespaces will be\n# extracted and appear in the documentation as a namespace called\n# 'anonymous_namespace{file}', where file will be replaced with the base name of\n# the file that contains the anonymous namespace. By default anonymous namespace\n# are hidden.\n# The default value is: NO.\n\nEXTRACT_ANON_NSPACES   = NO\n\n# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all\n# undocumented members inside documented classes or files. If set to NO these\n# members will be included in the various overviews, but no documentation\n# section is generated. This option has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_MEMBERS     = NO\n\n# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all\n# undocumented classes that are normally visible in the class hierarchy. If set\n# to NO, these classes will be included in the various overviews. This option\n# has no effect if EXTRACT_ALL is enabled.\n# The default value is: NO.\n\nHIDE_UNDOC_CLASSES     = NO\n\n# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend\n# (class|struct|union) declarations. If set to NO, these declarations will be\n# included in the documentation.\n# The default value is: NO.\n\nHIDE_FRIEND_COMPOUNDS  = NO\n\n# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any\n# documentation blocks found inside the body of a function. If set to NO, these\n# blocks will be appended to the function's detailed documentation block.\n# The default value is: NO.\n\nHIDE_IN_BODY_DOCS      = NO\n\n# The INTERNAL_DOCS tag determines if documentation that is typed after a\n# \\internal command is included. If the tag is set to NO then the documentation\n# will be excluded. Set it to YES to include the internal documentation.\n# The default value is: NO.\n\nINTERNAL_DOCS          = NO\n\n# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file\n# names in lower-case letters. If set to YES, upper-case letters are also\n# allowed. This is useful if you have classes or files whose names only differ\n# in case and if your file system supports case sensitive file names. Windows\n# and Mac users are advised to set this option to NO.\n# The default value is: system dependent.\n\nCASE_SENSE_NAMES       = YES\n\n# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with\n# their full class and namespace scopes in the documentation. If set to YES, the\n# scope will be hidden.\n# The default value is: NO.\n\nHIDE_SCOPE_NAMES       = NO\n\n# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will\n# append additional text to a page's title, such as Class Reference. If set to\n# YES the compound reference will be hidden.\n# The default value is: NO.\n\nHIDE_COMPOUND_REFERENCE= NO\n\n# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of\n# the files that are included by a file in the documentation of that file.\n# The default value is: YES.\n\nSHOW_INCLUDE_FILES     = YES\n\n# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each\n# grouped member an include statement to the documentation, telling the reader\n# which file to include in order to use the member.\n# The default value is: NO.\n\nSHOW_GROUPED_MEMB_INC  = NO\n\n# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include\n# files with double quotes in the documentation rather than with sharp brackets.\n# The default value is: NO.\n\nFORCE_LOCAL_INCLUDES   = NO\n\n# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the\n# documentation for inline members.\n# The default value is: YES.\n\nINLINE_INFO            = YES\n\n# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the\n# (detailed) documentation of file and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order.\n# The default value is: YES.\n\nSORT_MEMBER_DOCS       = YES\n\n# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief\n# descriptions of file, namespace and class members alphabetically by member\n# name. If set to NO, the members will appear in declaration order. Note that\n# this will also influence the order of the classes in the class list.\n# The default value is: NO.\n\nSORT_BRIEF_DOCS        = YES\n\n# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the\n# (brief and detailed) documentation of class members so that constructors and\n# destructors are listed first. If set to NO the constructors will appear in the\n# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.\n# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief\n# member documentation.\n# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting\n# detailed member documentation.\n# The default value is: NO.\n\nSORT_MEMBERS_CTORS_1ST = NO\n\n# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy\n# of group names into alphabetical order. If set to NO the group names will\n# appear in their defined order.\n# The default value is: NO.\n\nSORT_GROUP_NAMES       = NO\n\n# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by\n# fully-qualified names, including namespaces. If set to NO, the class list will\n# be sorted only by class name, not including the namespace part.\n# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.\n# Note: This option applies only to the class list, not to the alphabetical\n# list.\n# The default value is: NO.\n\nSORT_BY_SCOPE_NAME     = NO\n\n# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper\n# type resolution of all parameters of a function it will reject a match between\n# the prototype and the implementation of a member function even if there is\n# only one candidate or it is obvious which candidate to choose by doing a\n# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still\n# accept a match between prototype and implementation in such cases.\n# The default value is: NO.\n\nSTRICT_PROTO_MATCHING  = NO\n\n# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo\n# list. This list is created by putting \\todo commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TODOLIST      = YES\n\n# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test\n# list. This list is created by putting \\test commands in the documentation.\n# The default value is: YES.\n\nGENERATE_TESTLIST      = YES\n\n# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug\n# list. This list is created by putting \\bug commands in the documentation.\n# The default value is: YES.\n\nGENERATE_BUGLIST       = YES\n\n# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)\n# the deprecated list. This list is created by putting \\deprecated commands in\n# the documentation.\n# The default value is: YES.\n\nGENERATE_DEPRECATEDLIST= YES\n\n# The ENABLED_SECTIONS tag can be used to enable conditional documentation\n# sections, marked by \\if <section_label> ... \\endif and \\cond <section_label>\n# ... \\endcond blocks.\n\nENABLED_SECTIONS       =\n\n# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the\n# initial value of a variable or macro / define can have for it to appear in the\n# documentation. If the initializer consists of more lines than specified here\n# it will be hidden. Use a value of 0 to hide initializers completely. The\n# appearance of the value of individual variables and macros / defines can be\n# controlled using \\showinitializer or \\hideinitializer command in the\n# documentation regardless of this setting.\n# Minimum value: 0, maximum value: 10000, default value: 30.\n\nMAX_INITIALIZER_LINES  = 30\n\n# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at\n# the bottom of the documentation of classes and structs. If set to YES, the\n# list will mention the files that were used to generate the documentation.\n# The default value is: YES.\n\nSHOW_USED_FILES        = YES\n\n# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This\n# will remove the Files entry from the Quick Index and from the Folder Tree View\n# (if specified).\n# The default value is: YES.\n\nSHOW_FILES             = YES\n\n# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces\n# page. This will remove the Namespaces entry from the Quick Index and from the\n# Folder Tree View (if specified).\n# The default value is: YES.\n\nSHOW_NAMESPACES        = YES\n\n# The FILE_VERSION_FILTER tag can be used to specify a program or script that\n# doxygen should invoke to get the current version for each file (typically from\n# the version control system). Doxygen will invoke the program by executing (via\n# popen()) the command command input-file, where command is the value of the\n# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided\n# by doxygen. Whatever the program writes to standard output is used as the file\n# version. For an example see the documentation.\n\nFILE_VERSION_FILTER    =\n\n# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed\n# by doxygen. The layout file controls the global structure of the generated\n# output files in an output format independent way. To create the layout file\n# that represents doxygen's defaults, run doxygen with the -l option. You can\n# optionally specify a file name after the option, if omitted DoxygenLayout.xml\n# will be used as the name of the layout file.\n#\n# Note that if you run doxygen from a directory containing a file called\n# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE\n# tag is left empty.\n\nLAYOUT_FILE            = \"@RTK_SOURCE_DIR@/documentation/Doxygen/DoxygenLayout.xml\"\n\n# The CITE_BIB_FILES tag can be used to specify one or more bib files containing\n# the reference definitions. This must be a list of .bib files. The .bib\n# extension is automatically appended if omitted. This requires the bibtex tool\n# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.\n# For LaTeX the style of the bibliography can be controlled using\n# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the\n# search path. See also \\cite for info how to create references.\n\nCITE_BIB_FILES         =\n\n#---------------------------------------------------------------------------\n# Configuration options related to warning and progress messages\n#---------------------------------------------------------------------------\n\n# The QUIET tag can be used to turn on/off the messages that are generated to\n# standard output by doxygen. If QUIET is set to YES this implies that the\n# messages are off.\n# The default value is: NO.\n\nQUIET                  = NO\n\n# The WARNINGS tag can be used to turn on/off the warning messages that are\n# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES\n# this implies that the warnings are on.\n#\n# Tip: Turn warnings on while writing the documentation.\n# The default value is: YES.\n\nWARNINGS               = YES\n\n# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate\n# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag\n# will automatically be disabled.\n# The default value is: YES.\n\nWARN_IF_UNDOCUMENTED   = YES\n\n# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for\n# potential errors in the documentation, such as not documenting some parameters\n# in a documented function, or documenting parameters that don't exist or using\n# markup commands wrongly.\n# The default value is: YES.\n\nWARN_IF_DOC_ERROR      = YES\n\n# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that\n# are documented, but have no documentation for their parameters or return\n# value. If set to NO, doxygen will only warn about wrong or incomplete\n# parameter documentation, but not about the absence of documentation. If\n# EXTRACT_ALL is set to YES then this flag will automatically be disabled.\n# The default value is: NO.\n\nWARN_NO_PARAMDOC       = NO\n\n# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when\n# a warning is encountered.\n# The default value is: NO.\n\nWARN_AS_ERROR          = NO\n\n# The WARN_FORMAT tag determines the format of the warning messages that doxygen\n# can produce. The string should contain the $file, $line, and $text tags, which\n# will be replaced by the file and line number from which the warning originated\n# and the warning text. Optionally the format may contain $version, which will\n# be replaced by the version of the file (if it could be obtained via\n# FILE_VERSION_FILTER)\n# The default value is: $file:$line: $text.\n\nWARN_FORMAT            = \"$file:$line: $text\"\n\n# The WARN_LOGFILE tag can be used to specify a file to which warning and error\n# messages should be written. If left blank the output is written to standard\n# error (stderr).\n\nWARN_LOGFILE           =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the input files\n#---------------------------------------------------------------------------\n\n# The INPUT tag is used to specify the files and/or directories that contain\n# documented source files. You may enter file names like myfile.cpp or\n# directories like /usr/src/myproject. Separate the files or directories with\n# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING\n# Note: If this tag is empty the current directory is searched.\n\nINPUT                  = \"@PROJECT_SOURCE_DIR@\" \\\n                         \"@PROJECT_SOURCE_DIR@/documentation/Doxygen\"\n\n# This tag can be used to specify the character encoding of the source files\n# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses\n# libiconv (or the iconv built into libc) for the transcoding. See the libiconv\n# documentation (see: https://www.gnu.org/software/libiconv/) for the list of\n# possible encodings.\n# The default value is: UTF-8.\n\nINPUT_ENCODING         = UTF-8\n\n# If the value of the INPUT tag contains directories, you can use the\n# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and\n# *.h) to filter out the source-files in the directories.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# read by doxygen.\n#\n# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,\n# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,\n# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,\n# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,\n# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.\n\nFILE_PATTERNS          = *.h \\\n                         *.dox\n\n# The RECURSIVE tag can be used to specify whether or not subdirectories should\n# be searched for input files as well.\n# The default value is: NO.\n\nRECURSIVE              = YES\n\n# The EXCLUDE tag can be used to specify files and/or directories that should be\n# excluded from the INPUT source files. This way you can easily exclude a\n# subdirectory from a directory tree whose root is specified with the INPUT tag.\n#\n# Note that relative paths are relative to the directory from which doxygen is\n# run.\n\nEXCLUDE                = @PROJECT_SOURCE_DIR@/utilities\n\n# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or\n# directories that are symbolic links (a Unix file system feature) are excluded\n# from the input.\n# The default value is: NO.\n\nEXCLUDE_SYMLINKS       = NO\n\n# If the value of the INPUT tag contains directories, you can use the\n# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n# certain files from those directories.\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories for example use the pattern */test/*\n\nEXCLUDE_PATTERNS       = \"*_ggo.h\"\n\n# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names\n# (namespaces, classes, functions, etc.) that should be excluded from the\n# output. The symbol name can be a fully qualified name, a word, or if the\n# wildcard * is used, a substring. Examples: ANamespace, AClass,\n# AClass::ANamespace, ANamespace::*Test\n#\n# Note that the wildcards are matched against the file with absolute path, so to\n# exclude all test directories use the pattern */test/*\n\nEXCLUDE_SYMBOLS        = \"itk::*\"\n\n# The EXAMPLE_PATH tag can be used to specify one or more files or directories\n# that contain example code fragments that are included (see the \\include\n# command).\n\nEXAMPLE_PATH           =\n\n# If the value of the EXAMPLE_PATH tag contains directories, you can use the\n# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and\n# *.h) to filter out the source-files in the directories. If left blank all\n# files are included.\n\nEXAMPLE_PATTERNS       = *.cxx\n\n# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be\n# searched for input files to be used with the \\include or \\dontinclude commands\n# irrespective of the value of the RECURSIVE tag.\n# The default value is: NO.\n\nEXAMPLE_RECURSIVE      = YES\n\n# The IMAGE_PATH tag can be used to specify one or more files or directories\n# that contain images that are to be included in the documentation (see the\n# \\image command).\n\nIMAGE_PATH             =\n\n# The INPUT_FILTER tag can be used to specify a program that doxygen should\n# invoke to filter for each input file. Doxygen will invoke the filter program\n# by executing (via popen()) the command:\n#\n# <filter> <input-file>\n#\n# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the\n# name of an input file. Doxygen will then use the output that the filter\n# program writes to standard output. If FILTER_PATTERNS is specified, this tag\n# will be ignored.\n#\n# Note that the filter must not add or remove lines; it is applied before the\n# code is scanned, but not when the output code is generated. If lines are added\n# or removed, the anchors will not be placed correctly.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nINPUT_FILTER           = \"perl @PROJECT_BINARY_DIR@/Doxygen/itkdoxygen.pl\"\n\n# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern\n# basis. Doxygen will compare the file name with each pattern and apply the\n# filter if there is a match. The filters are a list of the form: pattern=filter\n# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how\n# filters are used. If the FILTER_PATTERNS tag is empty or if none of the\n# patterns match the file name, INPUT_FILTER is applied.\n#\n# Note that for custom extensions or not directly supported extensions you also\n# need to set EXTENSION_MAPPING for the extension otherwise the files are not\n# properly processed by doxygen.\n\nFILTER_PATTERNS        =\n\n# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using\n# INPUT_FILTER) will also be used to filter the input files that are used for\n# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).\n# The default value is: NO.\n\nFILTER_SOURCE_FILES    = YES\n\n# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file\n# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and\n# it is also possible to disable source filtering for a specific pattern using\n# *.ext= (so without naming a filter).\n# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.\n\nFILTER_SOURCE_PATTERNS =\n\n# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that\n# is part of the input, its contents will be placed on the main page\n# (index.html). This can be useful if you have a project on for instance GitHub\n# and want to reuse the introduction page also for the doxygen output.\n\nUSE_MDFILE_AS_MAINPAGE =\n\n#---------------------------------------------------------------------------\n# Configuration options related to source browsing\n#---------------------------------------------------------------------------\n\n# If the SOURCE_BROWSER tag is set to YES then a list of source files will be\n# generated. Documented entities will be cross-referenced with these sources.\n#\n# Note: To get rid of all source code in the generated output, make sure that\n# also VERBATIM_HEADERS is set to NO.\n# The default value is: NO.\n\nSOURCE_BROWSER         = YES\n\n# Setting the INLINE_SOURCES tag to YES will include the body of functions,\n# classes and enums directly into the documentation.\n# The default value is: NO.\n\nINLINE_SOURCES         = NO\n\n# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any\n# special comment blocks from generated source code fragments. Normal C, C++ and\n# Fortran comments will always remain visible.\n# The default value is: YES.\n\nSTRIP_CODE_COMMENTS    = YES\n\n# If the REFERENCED_BY_RELATION tag is set to YES then for each documented\n# entity all documented functions referencing it will be listed.\n# The default value is: NO.\n\nREFERENCED_BY_RELATION = YES\n\n# If the REFERENCES_RELATION tag is set to YES then for each documented function\n# all documented entities called/used by that function will be listed.\n# The default value is: NO.\n\nREFERENCES_RELATION    = YES\n\n# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set\n# to YES then the hyperlinks from functions in REFERENCES_RELATION and\n# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will\n# link to the documentation.\n# The default value is: YES.\n\nREFERENCES_LINK_SOURCE = YES\n\n# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the\n# source code will show a tooltip with additional information such as prototype,\n# brief description and links to the definition and documentation. Since this\n# will make the HTML file larger and loading of large files a bit slower, you\n# can opt to disable this feature.\n# The default value is: YES.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nSOURCE_TOOLTIPS        = YES\n\n# If the USE_HTAGS tag is set to YES then the references to source code will\n# point to the HTML generated by the htags(1) tool instead of doxygen built-in\n# source browser. The htags tool is part of GNU's global source tagging system\n# (see https://www.gnu.org/software/global/global.html). You will need version\n# 4.8.6 or higher.\n#\n# To use it do the following:\n# - Install the latest version of global\n# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file\n# - Make sure the INPUT points to the root of the source tree\n# - Run doxygen as normal\n#\n# Doxygen will invoke htags (and that will in turn invoke gtags), so these\n# tools must be available from the command line (i.e. in the search path).\n#\n# The result: instead of the source browser generated by doxygen, the links to\n# source code will now point to the output of htags.\n# The default value is: NO.\n# This tag requires that the tag SOURCE_BROWSER is set to YES.\n\nUSE_HTAGS              = NO\n\n# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a\n# verbatim copy of the header file for each class for which an include is\n# specified. Set to NO to disable this.\n# See also: Section \\class.\n# The default value is: YES.\n\nVERBATIM_HEADERS       = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to the alphabetical class index\n#---------------------------------------------------------------------------\n\n# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all\n# compounds will be generated. Enable this if the project contains a lot of\n# classes, structs, unions or interfaces.\n# The default value is: YES.\n\nALPHABETICAL_INDEX     = YES\n\n# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in\n# which the alphabetical index list will be split.\n# Minimum value: 1, maximum value: 20, default value: 5.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nCOLS_IN_ALPHA_INDEX    = 1\n\n# In case all classes in a project start with a common prefix, all classes will\n# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag\n# can be used to specify a prefix (or a list of prefixes) that should be ignored\n# while generating the index headers.\n# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.\n\nIGNORE_PREFIX          =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the HTML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output\n# The default value is: YES.\n\nGENERATE_HTML          = YES\n\n# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_OUTPUT            = html\n\n# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each\n# generated HTML page (for example: .htm, .php, .asp).\n# The default value is: .html.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FILE_EXTENSION    = .html\n\n# The HTML_HEADER tag can be used to specify a user-defined HTML header file for\n# each generated HTML page. If the tag is left blank doxygen will generate a\n# standard header.\n#\n# To get valid HTML the header file that includes any scripts and style sheets\n# that doxygen needs, which is dependent on the configuration options used (e.g.\n# the setting GENERATE_TREEVIEW). It is highly recommended to start with a\n# default header using\n# doxygen -w html new_header.html new_footer.html new_stylesheet.css\n# YourConfigFile\n# and then modify the file new_header.html. See also section \"Doxygen usage\"\n# for information on how to generate the default header that doxygen normally\n# uses.\n# Note: The header is subject to change so you typically have to regenerate the\n# default header when upgrading to a newer version of doxygen. For a description\n# of the possible markers and block names see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_HEADER            = \"@PROJECT_SOURCE_DIR@/documentation/Doxygen/DoxygenHeader.html\"\n\n# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each\n# generated HTML page. If the tag is left blank doxygen will generate a standard\n# footer. See HTML_HEADER for more information on how to generate a default\n# footer and what special commands can be used inside the footer. See also\n# section \"Doxygen usage\" for information on how to generate the default footer\n# that doxygen normally uses.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_FOOTER            = \"@PROJECT_SOURCE_DIR@/documentation/Doxygen/DoxygenFooter.html\"\n\n# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style\n# sheet that is used by each HTML page. It can be used to fine-tune the look of\n# the HTML output. If left blank doxygen will generate a default style sheet.\n# See also section \"Doxygen usage\" for information on how to generate the style\n# sheet that doxygen normally uses.\n# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as\n# it is more robust and this tag (HTML_STYLESHEET) will in the future become\n# obsolete.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_STYLESHEET        =\n\n# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# cascading style sheets that are included after the standard style sheets\n# created by doxygen. Using this option one can overrule certain style aspects.\n# This is preferred over using HTML_STYLESHEET since it does not replace the\n# standard style sheet and is therefore more robust against future updates.\n# Doxygen will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list). For an example see the documentation.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_STYLESHEET  = \"@PROJECT_SOURCE_DIR@/documentation/Doxygen/DoxygenStyle.css\"\n\n# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the HTML output directory. Note\n# that these files will be copied to the base HTML output directory. Use the\n# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these\n# files. In the HTML_STYLESHEET file, use the file name only. Also note that the\n# files will be copied as-is; there are no commands or markers available.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_EXTRA_FILES       =\n\n# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen\n# will adjust the colors in the style sheet and background images according to\n# this color. Hue is specified as an angle on a colorwheel, see\n# https://en.wikipedia.org/wiki/Hue for more information. For instance the value\n# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300\n# purple, and 360 is red again.\n# Minimum value: 0, maximum value: 359, default value: 220.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_HUE    = 220\n\n# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors\n# in the HTML output. For a value of 0 the output will use grayscales only. A\n# value of 255 will produce the most vivid colors.\n# Minimum value: 0, maximum value: 255, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_SAT    = 100\n\n# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the\n# luminance component of the colors in the HTML output. Values below 100\n# gradually make the output lighter, whereas values above 100 make the output\n# darker. The value divided by 100 is the actual gamma applied, so 80 represents\n# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not\n# change the gamma.\n# Minimum value: 40, maximum value: 240, default value: 80.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_COLORSTYLE_GAMMA  = 80\n\n# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML\n# page will contain the date and time when the page was generated. Setting this\n# to YES can help to show when doxygen was last run and thus if the\n# documentation is up to date.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_TIMESTAMP         = YES\n\n# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML\n# documentation will contain a main index with vertical navigation menus that\n# are dynamically created via Javascript. If disabled, the navigation index will\n# consists of multiple levels of tabs that are statically embedded in every HTML\n# page. Disable this option to support browsers that do not have Javascript,\n# like the Qt help browser.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_MENUS     = YES\n\n# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML\n# documentation will contain sections that can be hidden and shown after the\n# page has loaded.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_DYNAMIC_SECTIONS  = YES\n\n# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries\n# shown in the various tree structured indices initially; the user can expand\n# and collapse entries dynamically later on. Doxygen will expand the tree to\n# such a level that at most the specified number of entries are visible (unless\n# a fully collapsed tree already exceeds this amount). So setting the number of\n# entries 1 will produce a full collapsed tree by default. 0 is a special value\n# representing an infinite number of entries and will result in a full expanded\n# tree by default.\n# Minimum value: 0, maximum value: 9999, default value: 100.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nHTML_INDEX_NUM_ENTRIES = 100\n\n# If the GENERATE_DOCSET tag is set to YES, additional index files will be\n# generated that can be used as input for Apple's Xcode 3 integrated development\n# environment (see: https://developer.apple.com/xcode/), introduced with OSX\n# 10.5 (Leopard). To create a documentation set, doxygen will generate a\n# Makefile in the HTML output directory. Running make will produce the docset in\n# that directory and running make install will install the docset in\n# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at\n# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy\n# genXcode/_index.html for more information.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_DOCSET        = NO\n\n# This tag determines the name of the docset feed. A documentation feed provides\n# an umbrella under which multiple documentation sets from a single provider\n# (such as a company or product suite) can be grouped.\n# The default value is: Doxygen generated docs.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_FEEDNAME        = \"RTK Doxygen generated documentation\"\n\n# This tag specifies a string that should uniquely identify the documentation\n# set bundle. This should be a reverse domain-name style string, e.g.\n# com.mycompany.MyDocSet. Doxygen will append .docset to the name.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_BUNDLE_ID       = org.rtk.RTK\n\n# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify\n# the documentation publisher. This should be a reverse domain-name style\n# string, e.g. com.mycompany.MyDocSet.documentation.\n# The default value is: org.doxygen.Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_ID    = org.rtk.RTKConsortium\n\n# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.\n# The default value is: Publisher.\n# This tag requires that the tag GENERATE_DOCSET is set to YES.\n\nDOCSET_PUBLISHER_NAME  = RTKConsortium\n\n# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three\n# additional HTML index files: index.hhp, index.hhc, and index.hhk. The\n# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop\n# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on\n# Windows.\n#\n# The HTML Help Workshop contains a compiler that can convert all HTML output\n# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML\n# files are now used as the Windows 98 help format, and will replace the old\n# Windows help format (.hlp) on all Windows platforms in the future. Compressed\n# HTML files also contain an index, a table of contents, and you can search for\n# words in the documentation. The HTML workshop also contains a viewer for\n# compressed HTML files.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_HTMLHELP      = NO\n\n# The CHM_FILE tag can be used to specify the file name of the resulting .chm\n# file. You can add a path in front of the file if the result should not be\n# written to the html output directory.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_FILE               =\n\n# The HHC_LOCATION tag can be used to specify the location (absolute path\n# including file name) of the HTML help compiler (hhc.exe). If non-empty,\n# doxygen will try to run the HTML help compiler on the generated index.hhp.\n# The file has to be specified with full path.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nHHC_LOCATION           =\n\n# The GENERATE_CHI flag controls if a separate .chi index file is generated\n# (YES) or that it should be included in the master .chm file (NO).\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nGENERATE_CHI           = NO\n\n# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)\n# and project file content.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nCHM_INDEX_ENCODING     =\n\n# The BINARY_TOC flag controls whether a binary table of contents is generated\n# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it\n# enables the Previous and Next buttons.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nBINARY_TOC             = NO\n\n# The TOC_EXPAND flag can be set to YES to add extra items for group members to\n# the table of contents of the HTML help documentation and to the tree view.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTMLHELP is set to YES.\n\nTOC_EXPAND             = NO\n\n# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and\n# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that\n# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help\n# (.qch) of the generated HTML documentation.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_QHP           = NO\n\n# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify\n# the file name of the resulting .qch file. The path specified is relative to\n# the HTML output folder.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQCH_FILE               =\n\n# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help\n# Project output. For more information please see Qt Help Project / Namespace\n# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_NAMESPACE          = org.doxygen.Project\n\n# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt\n# Help Project output. For more information please see Qt Help Project / Virtual\n# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-\n# folders).\n# The default value is: doc.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_VIRTUAL_FOLDER     = doc\n\n# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom\n# filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_NAME   =\n\n# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the\n# custom filter to add. For more information please see Qt Help Project / Custom\n# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-\n# filters).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_CUST_FILTER_ATTRS  =\n\n# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this\n# project's filter section matches. Qt Help Project / Filter Attributes (see:\n# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHP_SECT_FILTER_ATTRS  =\n\n# The QHG_LOCATION tag can be used to specify the location of Qt's\n# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the\n# generated .qhp file.\n# This tag requires that the tag GENERATE_QHP is set to YES.\n\nQHG_LOCATION           =\n\n# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be\n# generated, together with the HTML files, they form an Eclipse help plugin. To\n# install this plugin and make it available under the help contents menu in\n# Eclipse, the contents of the directory containing the HTML and XML files needs\n# to be copied into the plugins directory of eclipse. The name of the directory\n# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.\n# After copying Eclipse needs to be restarted before the help appears.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_ECLIPSEHELP   = @ITK_DOXYGEN_GEN_ECLIPSEHELP@\n\n# A unique identifier for the Eclipse help plugin. When installing the plugin\n# the directory name containing the HTML and XML files should also have this\n# name. Each documentation set should have its own identifier.\n# The default value is: org.doxygen.Project.\n# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.\n\nECLIPSE_DOC_ID         = NO\n\n# If you want full control over the layout of the generated HTML pages it might\n# be necessary to disable the index and replace it with your own. The\n# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top\n# of each HTML page. A value of NO enables the index and the value YES disables\n# it. Since the tabs in the index contain the same information as the navigation\n# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nDISABLE_INDEX          = NO\n\n# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index\n# structure should be generated to display hierarchical information. If the tag\n# value is set to YES, a side panel will be generated containing a tree-like\n# index structure (just like the one that is generated for HTML Help). For this\n# to work a browser that supports JavaScript, DHTML, CSS and frames is required\n# (i.e. any modern browser). Windows users are probably better off using the\n# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can\n# further fine-tune the look of the index. As an example, the default style\n# sheet generated by doxygen has an example that shows how to put an image at\n# the root of the tree instead of the PROJECT_NAME. Since the tree basically has\n# the same information as the tab index, you could consider setting\n# DISABLE_INDEX to YES when enabling this option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nGENERATE_TREEVIEW      = NO\n\n# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that\n# doxygen will group on one line in the generated HTML documentation.\n#\n# Note that a value of 0 will completely suppress the enum values from appearing\n# in the overview section.\n# Minimum value: 0, maximum value: 20, default value: 4.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nENUM_VALUES_PER_LINE   = 1\n\n# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used\n# to set the initial width (in pixels) of the frame in which the tree is shown.\n# Minimum value: 0, maximum value: 1500, default value: 250.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nTREEVIEW_WIDTH         = 250\n\n# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to\n# external symbols imported via tag files in a separate window.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nEXT_LINKS_IN_WINDOW    = NO\n\n# Use this tag to change the font size of LaTeX formulas included as images in\n# the HTML documentation. When you change the font size after a successful\n# doxygen run you need to manually remove any form_*.png images from the HTML\n# output directory to force them to be regenerated.\n# Minimum value: 8, maximum value: 50, default value: 10.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_FONTSIZE       = 10\n\n# Use the FORMULA_TRANSPARENT tag to determine whether or not the images\n# generated for formulas are transparent PNGs. Transparent PNGs are not\n# supported properly for IE 6.0, but are supported on all modern browsers.\n#\n# Note that when changing this option you need to delete any form_*.png files in\n# the HTML output directory before the changes have effect.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nFORMULA_TRANSPARENT    = YES\n\n# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see\n# https://www.mathjax.org) which uses client side Javascript for the rendering\n# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX\n# installed or if you want to formulas look prettier in the HTML output. When\n# enabled you may also need to install MathJax separately and configure the path\n# to it using the MATHJAX_RELPATH option.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nUSE_MATHJAX            = YES\n\n# When MathJax is enabled you can set the default output format to be used for\n# the MathJax output. See the MathJax site (see:\n# https://docs.mathjax.org/en/latest/output.html) for more details.\n# Possible values are: HTML-CSS (which is slower, but has the best\n# compatibility), NativeMML (i.e. MathML) and SVG.\n# The default value is: HTML-CSS.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_FORMAT         = HTML-CSS\n\n# When MathJax is enabled you need to specify the location relative to the HTML\n# output directory using the MATHJAX_RELPATH option. The destination directory\n# should contain the MathJax.js script. For instance, if the mathjax directory\n# is located at the same level as the HTML output directory, then\n# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax\n# Content Delivery Network so you can quickly see the result without installing\n# MathJax. However, it is strongly recommended to install a local copy of\n# MathJax from https://www.mathjax.org before deployment.\n# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_RELPATH        = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/\n\n# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax\n# extension names that should be enabled during MathJax rendering. For example\n# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_EXTENSIONS     =\n\n# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces\n# of code that will be used on startup of the MathJax code. See the MathJax site\n# (see: https://docs.mathjax.org/en/latest/output.html) for more details. For an\n# example see the documentation.\n# This tag requires that the tag USE_MATHJAX is set to YES.\n\nMATHJAX_CODEFILE       =\n\n# When the SEARCHENGINE tag is enabled doxygen will generate a search box for\n# the HTML output. The underlying search engine uses javascript and DHTML and\n# should work on any modern browser. Note that when using HTML help\n# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)\n# there is already a search function so this one should typically be disabled.\n# For large projects the javascript based search engine can be slow, then\n# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to\n# search using the keyboard; to jump to the search box use <access key> + S\n# (what the <access key> is depends on the OS and browser, but it is typically\n# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down\n# key> to jump into the search results window, the results can be navigated\n# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel\n# the search. The filter options can be selected when the cursor is inside the\n# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>\n# to select a filter and <Enter> or <escape> to activate or cancel the filter\n# option.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_HTML is set to YES.\n\nSEARCHENGINE           = YES\n\n# When the SERVER_BASED_SEARCH tag is enabled the search engine will be\n# implemented using a web server instead of a web client using Javascript. There\n# are two flavors of web server based searching depending on the EXTERNAL_SEARCH\n# setting. When disabled, doxygen will generate a PHP script for searching and\n# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing\n# and searching needs to be provided by external tools. See the section\n# \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSERVER_BASED_SEARCH    = YES\n\n# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP\n# script for searching. Instead the search results are written to an XML file\n# which needs to be processed by an external indexer. Doxygen will invoke an\n# external search engine pointed to by the SEARCHENGINE_URL option to obtain the\n# search results.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: https://xapian.org/).\n#\n# See the section \"External Indexing and Searching\" for details.\n# The default value is: NO.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH        = NO\n\n# The SEARCHENGINE_URL should point to a search engine hosted by a web server\n# which will return the search results when EXTERNAL_SEARCH is enabled.\n#\n# Doxygen ships with an example indexer (doxyindexer) and search engine\n# (doxysearch.cgi) which are based on the open source search engine library\n# Xapian (see: https://xapian.org/). See the section \"External Indexing and\n# Searching\" for details.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHENGINE_URL       =\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed\n# search data is written to a file for indexing by an external tool. With the\n# SEARCHDATA_FILE tag the name of this file can be specified.\n# The default file is: searchdata.xml.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nSEARCHDATA_FILE        = searchdata.xml\n\n# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the\n# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is\n# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple\n# projects and redirect the results back to the right project.\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTERNAL_SEARCH_ID     =\n\n# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen\n# projects other than the one defined by this configuration file, but that are\n# all added to the same external search index. Each project needs to have a\n# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of\n# to a relative location where the documentation can be found. The format is:\n# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...\n# This tag requires that the tag SEARCHENGINE is set to YES.\n\nEXTRA_SEARCH_MAPPINGS  =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the LaTeX output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.\n# The default value is: YES.\n\nGENERATE_LATEX         = NO\n\n# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: latex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_OUTPUT           = latex\n\n# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be\n# invoked.\n#\n# Note that when not enabling USE_PDFLATEX the default is latex when enabling\n# USE_PDFLATEX the default is pdflatex and when in the later case latex is\n# chosen this is overwritten by pdflatex. For specific output languages the\n# default can have been set differently, this depends on the implementation of\n# the output language.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_CMD_NAME         = latex\n\n# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate\n# index for LaTeX.\n# Note: This tag is used in the Makefile / make.bat.\n# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file\n# (.tex).\n# The default file is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nMAKEINDEX_CMD_NAME     = makeindex\n\n# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to\n# generate index for LaTeX. In case there is no backslash (\\) as first character\n# it will be automatically added in the LaTeX code.\n# Note: This tag is used in the generated output file (.tex).\n# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.\n# The default value is: makeindex.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_MAKEINDEX_CMD    = makeindex\n\n# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nCOMPACT_LATEX          = NO\n\n# The PAPER_TYPE tag can be used to set the paper type that is used by the\n# printer.\n# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x\n# 14 inches) and executive (7.25 x 10.5 inches).\n# The default value is: a4.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPAPER_TYPE             = letter\n\n# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names\n# that should be included in the LaTeX output. The package can be specified just\n# by its name or with the correct syntax as to be used with the LaTeX\n# \\usepackage command. To get the times font for instance you can specify :\n# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}\n# To use the option intlimits with the amsmath package you can specify:\n# EXTRA_PACKAGES=[intlimits]{amsmath}\n# If left blank no extra packages will be included.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nEXTRA_PACKAGES         = amsmath \\\n                         amsfonts\n\n# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the\n# generated LaTeX document. The header should contain everything until the first\n# chapter. If it is left blank doxygen will generate a standard header. See\n# section \"Doxygen usage\" for information on how to let doxygen write the\n# default header to a separate file.\n#\n# Note: Only use a user-defined header if you know what you are doing! The\n# following commands have a special meaning inside the header: $title,\n# $datetime, $date, $doxygenversion, $projectname, $projectnumber,\n# $projectbrief, $projectlogo. Doxygen will replace $title with the empty\n# string, for the replacement values of the other commands the user is referred\n# to HTML_HEADER.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HEADER           =\n\n# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the\n# generated LaTeX document. The footer should contain everything after the last\n# chapter. If it is left blank doxygen will generate a standard footer. See\n# LATEX_HEADER for more information on how to generate a default footer and what\n# special commands can be used inside the footer.\n#\n# Note: Only use a user-defined footer if you know what you are doing!\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_FOOTER           =\n\n# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined\n# LaTeX style sheets that are included after the standard style sheets created\n# by doxygen. Using this option one can overrule certain style aspects. Doxygen\n# will copy the style sheet files to the output directory.\n# Note: The order of the extra style sheet files is of importance (e.g. the last\n# style sheet in the list overrules the setting of the previous ones in the\n# list).\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_STYLESHEET =\n\n# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or\n# other source files which should be copied to the LATEX_OUTPUT output\n# directory. Note that the files will be copied as-is; there are no commands or\n# markers available.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EXTRA_FILES      =\n\n# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is\n# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will\n# contain links (just like the HTML output) instead of page references. This\n# makes the output suitable for online browsing using a PDF viewer.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nPDF_HYPERLINKS         = YES\n\n# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate\n# the PDF file directly from the LaTeX files. Set this option to YES, to get a\n# higher quality PDF documentation.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nUSE_PDFLATEX           = YES\n\n# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode\n# command to the generated LaTeX files. This will instruct LaTeX to keep running\n# if errors occur, instead of asking the user for help. This option is also used\n# when generating formulas in HTML.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BATCHMODE        = YES\n\n# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the\n# index chapters (such as File Index, Compound Index, etc.) in the output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_HIDE_INDICES     = NO\n\n# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source\n# code with syntax highlighting in the LaTeX output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_SOURCE_CODE      = NO\n\n# The LATEX_BIB_STYLE tag can be used to specify the style to use for the\n# bibliography, e.g. plainnat, or ieeetr. See\n# https://en.wikipedia.org/wiki/BibTeX and \\cite for more info.\n# The default value is: plain.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_BIB_STYLE        = plain\n\n# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated\n# page will contain the date and time when the page was generated. Setting this\n# to NO can help when comparing the output of multiple runs.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_TIMESTAMP        = NO\n\n# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)\n# path from which the emoji images will be read. If a relative path is entered,\n# it will be relative to the LATEX_OUTPUT directory. If left blank the\n# LATEX_OUTPUT directory will be used.\n# This tag requires that the tag GENERATE_LATEX is set to YES.\n\nLATEX_EMOJI_DIRECTORY  =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the RTF output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The\n# RTF output is optimized for Word 97 and may not look too pretty with other RTF\n# readers/editors.\n# The default value is: NO.\n\nGENERATE_RTF           = NO\n\n# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: rtf.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_OUTPUT             = rtf\n\n# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF\n# documents. This may be useful for small projects and may help to save some\n# trees in general.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nCOMPACT_RTF            = NO\n\n# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will\n# contain hyperlink fields. The RTF file will contain links (just like the HTML\n# output) instead of page references. This makes the output suitable for online\n# browsing using Word or some other Word compatible readers that support those\n# fields.\n#\n# Note: WordPad (write) and others do not support links.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_HYPERLINKS         = NO\n\n# Load stylesheet definitions from file. Syntax is similar to doxygen's\n# configuration file, i.e. a series of assignments. You only have to provide\n# replacements, missing definitions are set to their default value.\n#\n# See also section \"Doxygen usage\" for information on how to generate the\n# default style sheet that doxygen normally uses.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_STYLESHEET_FILE    =\n\n# Set optional variables used in the generation of an RTF document. Syntax is\n# similar to doxygen's configuration file. A template extensions file can be\n# generated using doxygen -e rtf extensionFile.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_EXTENSIONS_FILE    =\n\n# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code\n# with syntax highlighting in the RTF output.\n#\n# Note that which sources are shown also depends on other settings such as\n# SOURCE_BROWSER.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_RTF is set to YES.\n\nRTF_SOURCE_CODE        = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the man page output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for\n# classes and files.\n# The default value is: NO.\n\nGENERATE_MAN           = NO\n\n# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it. A directory man3 will be created inside the directory specified by\n# MAN_OUTPUT.\n# The default directory is: man.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_OUTPUT             = man\n\n# The MAN_EXTENSION tag determines the extension that is added to the generated\n# man pages. In case the manual section does not start with a number, the number\n# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is\n# optional.\n# The default value is: .3.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_EXTENSION          = .3\n\n# The MAN_SUBDIR tag determines the name of the directory created within\n# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by\n# MAN_EXTENSION with the initial . removed.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_SUBDIR             =\n\n# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it\n# will generate one additional man file for each entity documented in the real\n# man page(s). These additional files only source the real man page, but without\n# them the man command would be unable to find the correct page.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_MAN is set to YES.\n\nMAN_LINKS              = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the XML output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that\n# captures the structure of the code including all documentation.\n# The default value is: NO.\n\nGENERATE_XML           = NO\n\n# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a\n# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of\n# it.\n# The default directory is: xml.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_OUTPUT             = xml\n\n# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program\n# listings (including syntax highlighting and cross-referencing information) to\n# the XML output. Note that enabling this will significantly increase the size\n# of the XML output.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_PROGRAMLISTING     = YES\n\n# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include\n# namespace members in file scope as well, matching the HTML output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_XML is set to YES.\n\nXML_NS_MEMB_FILE_SCOPE = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the DOCBOOK output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files\n# that can be used to generate PDF.\n# The default value is: NO.\n\nGENERATE_DOCBOOK       = NO\n\n# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.\n# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in\n# front of it.\n# The default directory is: docbook.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_OUTPUT         = docbook\n\n# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the\n# program listings (including syntax highlighting and cross-referencing\n# information) to the DOCBOOK output. Note that enabling this will significantly\n# increase the size of the DOCBOOK output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_DOCBOOK is set to YES.\n\nDOCBOOK_PROGRAMLISTING = NO\n\n#---------------------------------------------------------------------------\n# Configuration options for the AutoGen Definitions output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an\n# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures\n# the structure of the code including all documentation. Note that this feature\n# is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_AUTOGEN_DEF   = NO\n\n#---------------------------------------------------------------------------\n# Configuration options related to the Perl module output\n#---------------------------------------------------------------------------\n\n# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module\n# file that captures the structure of the code including all documentation.\n#\n# Note that this feature is still experimental and incomplete at the moment.\n# The default value is: NO.\n\nGENERATE_PERLMOD       = NO\n\n# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary\n# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI\n# output from the Perl module output.\n# The default value is: NO.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_LATEX          = NO\n\n# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely\n# formatted so it can be parsed by a human reader. This is useful if you want to\n# understand what is going on. On the other hand, if this tag is set to NO, the\n# size of the Perl module output will be much smaller and Perl will parse it\n# just the same.\n# The default value is: YES.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_PRETTY         = YES\n\n# The names of the make variables in the generated doxyrules.make file are\n# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful\n# so different doxyrules.make files included by the same Makefile don't\n# overwrite each other's variables.\n# This tag requires that the tag GENERATE_PERLMOD is set to YES.\n\nPERLMOD_MAKEVAR_PREFIX =\n\n#---------------------------------------------------------------------------\n# Configuration options related to the preprocessor\n#---------------------------------------------------------------------------\n\n# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all\n# C-preprocessor directives found in the sources and include files.\n# The default value is: YES.\n\nENABLE_PREPROCESSING   = YES\n\n# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names\n# in the source code. If set to NO, only conditional compilation will be\n# performed. Macro expansion can be done in a controlled way by setting\n# EXPAND_ONLY_PREDEF to YES.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nMACRO_EXPANSION        = YES\n\n# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then\n# the macro expansion is limited to the macros specified with the PREDEFINED and\n# EXPAND_AS_DEFINED tags.\n# The default value is: NO.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_ONLY_PREDEF     = YES\n\n# If the SEARCH_INCLUDES tag is set to YES, the include files in the\n# INCLUDE_PATH will be searched if a #include is found.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSEARCH_INCLUDES        = NO\n\n# The INCLUDE_PATH tag can be used to specify one or more directories that\n# contain include files that are not input files but should be processed by the\n# preprocessor.\n# This tag requires that the tag SEARCH_INCLUDES is set to YES.\n\nINCLUDE_PATH           =\n\n# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard\n# patterns (like *.h and *.hpp) to filter out the header-files in the\n# directories. If left blank, the patterns specified with FILE_PATTERNS will be\n# used.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nINCLUDE_FILE_PATTERNS  =\n\n# The PREDEFINED tag can be used to specify one or more macro names that are\n# defined before the preprocessor is started (similar to the -D option of e.g.\n# gcc). The argument of the tag is a list of macros of the form: name or\n# name=definition (no spaces). If the definition and the \"=\" are omitted, \"=1\"\n# is assumed. To prevent a macro definition from being undefined via #undef or\n# recursively expanded use the := operator instead of the = operator.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nPREDEFINED             = \"itkNotUsed(x)=\" \\\n                         \"static constexpr type name = value=static constexpr type name = value\" \\\n                         \"itkSetInputMacro(name, type, number)=                   virtual void Set##name##Input(const type *_arg);                   virtual void SetInput##number(const type *_arg);\" \\\n                         \"itkGetInputMacro(name, type, number)=                   virtual const type * Get##name##Input() const;                   virtual const type * GetInput##number() const;\" \\\n                         \"itkSetMacro(name,type)=                   virtual void Set##name (type _arg);\" \\\n                         \"itkGetMacro(name,type)=                   virtual type Get##name ();\" \\\n                         \"itkGetConstMacro(name,type)=                   virtual type Get##name () const;\" \\\n                         \"itkSetStringMacro(name)=                   virtual void Set##name (const char* _arg);\" \\\n                         \"itkGetStringMacro(name)=                   virtual const char* Get##name () const;\" \\\n                         \"itkSetClampMacro(name,type,min,max)=                   virtual void Set##name (type _arg);\" \\\n                         \"itkSetObjectMacro(name,type)=                   virtual void Set##name (type* _arg);\" \\\n                         \"itkSetConstObjectMacro(name,type)=                   virtual void Set##name ( const type* _arg);\" \\\n                         \"itkGetConstObjectMacro(name,type)=      virtual const type* Get##name () const;\" \\\n                         \"itkGetModifiableObjectMacro(name,type)= virtual type* GetModifiable##name ();  virtual const type* Get##name () const;\" \\\n                         \"itkGetConstReferenceMacro(name,type)=                   virtual const type& Get##name () const;\" \\\n                         \"itkSetEnumMacro(name,type)=                   virtual void Set##name (const type _arg);\" \\\n                         \"itkGetEnumMacro(name,type)=                   virtual type Get##name () const;\" \\\n                         \"itkGetConstReferenceObjectMacro(name,type)=                   virtual const type::Pointer& Get##name () const;\" \\\n                         \"itkSetDecoratedInputMacro(name, type)=                   virtual void Set##name##Input(const SimpleDataObjectDecorator<type> *_arg);                   virtual void Set##name(const type &_arg);              void Set##name(const SimpleDataObjectDecorator< type > *_arg)\" \\\n                         \"itkGetDecoratedInputMacro(name, type)= virtual const SimpleDataObjectDecorator< type > * Get##name##Input() const; virtual const type & Get##name() const; \" \\\n                         \"itkSetGetDecoratedInputMacro(name, type)=                   virtual void Set##name##Input(const SimpleDataObjectDecorator< type > *_arg);         virtual void Set##name(const type &_arg);          virtual void Set##name(const SimpleDataObjectDecorator< type > *_arg);        virtual const SimpleDataObjectDecorator< type > * Get##name##Input() const;              virtual const type & Get##name() const;          \" \\\n                         \"itkSetDecoratedObjectInputMacro(name, type, number)=                   virtual void Set##name##Input(const DataObjectDecorator<type> *_arg);                   virtual void SetInput##number(const DataObjectDecorator<type> *_arg);                   virtual const DataObjectDecorator<type> * Get##name##Input() const;                   virtual const DataObjectDecorator<type> * GetInput##number() const;                   virtual void Set##name(const type *_arg);\" \\\n                         \"itkGetDecoratedObjectInputMacro(name, type)= virtual const DataObjectDecorator< type > * Get##name##Input() const; virtual const type * Get##name() const; \" \\\n                         \"itkSetGetDecoratedObjectInputMacro(name, type)= virtual void Set##name##Input(const DataObjectDecorator<type> *_arg);                   virtual void SetInput##number(const DataObjectDecorator<type> *_arg);                   virtual const DataObjectDecorator<type> * Get##name##Input() const;                   virtual const DataObjectDecorator<type> * GetInput##number() const;                   virtual void Set##name(const type *_arg); virtual const DataObjectDecorator< type > * Get##name##Input() const; virtual const type * Get##name() const; \" \\\n                         \"itkSetDecoratedOutputMacro(name, type)=                   virtual void Set##name##Output(const SimpleDataObjectDecorator<type> *_arg);                   virtual void Set##name(const type &_arg);              void Set##name(const SimpleDataObjectDecorator< type > *_arg)\" \\\n                         \"itkGetDecoratedOutputMacro(name, type)= virtual const SimpleDataObjectDecorator< type > * Get##name##Output() const; virtual const type & Get##name() const; \" \\\n                         \"itkBooleanMacro(name)=                   virtual void name##On ();                   virtual void name##Off ();\" \\\n                         \"itkSetVector2Macro(name,type)=                   virtual void Set##name (type _arg1, type _arg2)                   virtual void Set##name (type _arg[2]);\" \\\n                         \"itkGetVector2Macro(name,type)=                   virtual type* Get##name () const;                   virtual void Get##name (type& _arg1, type& _arg2) const;                   virtual void Get##name (type _arg[2]) const;\" \\\n                         \"itkSetVector3Macro(name,type)=                   virtual void Set##name (type _arg1, type _arg2, type _arg3)                   virtual void Set##name (type _arg[3]);\" \\\n                         \"itkGetVector3Macro(name,type)=                   virtual type* Get##name () const;                   virtual void Get##name (type& _arg1, type& _arg2, type& _arg3) const;                   virtual void Get##name (type _arg[3]) const;\" \\\n                         \"itkSetVector4Macro(name,type)=                   virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4)                   virtual void Set##name (type _arg[4]);\" \\\n                         \"itkGetVector4Macro(name,type)=                   virtual type* Get##name () const;                   virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4) const;                   virtual void Get##name (type _arg[4]) const;\" \\\n                         \"itkSetVector6Macro(name,type)=                   virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4, type _arg5, type _arg6)                   virtual void Set##name (type _arg[6]);\" \\\n                         \"itkGetVector6Macro(name,type)=                   virtual type* Get##name () const;                   virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4, type& _arg5, type& _arg6) const;                   virtual void Get##name (type _arg[6]) const;\" \\\n                         \"itkSetVectorMacro(name,type,count)=                   virtual void Set##name(type data[]);\" \\\n                         \"itkGetVectorMacro(name,type,count)=                   virtual type* Get##name () const;\" \\\n                         \"itkSetInputMacro(name,type)=         virtual void Set##name(const type *input);\" \\\n                         \"itkGetInputMacro(name,type)=         virtual const type * Get##name() const;\" \\\n                         \"itkNewMacro(type)=                   static Pointer New();                                                                           virtual::itk::LightObject::Pointer CreateAnother() const;\" \\\n                         \"itkSimpleNewMacro(type)=             static Pointer New();\" \\\n                         \"itkCreateAnotherMacro(type)=         virtual::itk::LightObject::Pointer CreateAnother() const;\" \\\n                         \"itkFactorylessNewMacro(x)=                   static Pointer New();                   virtual ::itk::LightObject::Pointer CreateAnother() const;\" \\\n                         \"itkOverrideGetNameOfClassMacro(thisClass)=         const char * GetNameOfClass() const override;\" \\\n                         \"itkEventMacro(thisClass,superclass)=                   class thisClass : public superclass {};\" \\\n                         \"itkDeclareExceptionMacro(newexcp,parentexcp,whatmessage)=         namespace itk {         class newexcp : public parentexcp {        public:       newexcp( const char *file, unsigned int lineNumber ) :        parentexcp( file, lineNumber )          { this->SetDescription( whatmessage ); }          newexcp( const std::string & file, unsigned int lineNumber ) :          parentexcp( file, lineNumber )          { this->SetDescription( whatmessage ); }          itkOverrideGetNameOfClassMacro( newexcp );         };        }\" \\\n                         \"itkConceptMacro(thisName,thisConcept)=                   /* This class requires thisName                       in the form of thisConcept */\" \\\n                         \"std::numeric_limits=                   std::numeric_limits\" \\\n                         \"ITK_TYPENAME=                   typename\" \\\n                         \"itkTemplateFloatingToIntegerMacro(name)=                   template <TReturn, typename TInput> name( TInput x )\" \\\n                         \"FEM_ABSTRACT_CLASS(thisClass,parentClass)=                   public:                                                                   /** Standard  Self typedef.*/                                          typedef thisClass Self;                                                 /** Standard  Superclass typedef. */                                   typedef parentClass Superclass;                                         /** Pointer or SmartPointer to an object. */                            typedef Self* Pointer;                                                  /** Const pointer or SmartPointer to an object. */                      typedef const Self* ConstPointer;                                     private:\" \\\n                         \"FEM_CLASS(thisClass,parentClass)=                   FEM_ABSTRACT_CLASS(thisClass,parentClass)                               public:                                                                   /** Create a new object from the existing one  */                       virtual Baseclass::Pointer Clone() const;                               /** Class ID for FEM object factory */                                  static const int CLID;                                                  /** Virtual function to access the class ID */                          virtual int ClassID() const                                               { return CLID; }                                                      /** Object creation in an itk compatible way */                         static Self::Pointer New()                                                { return new Self(); }                                              private:\" \\\n                         \"ERROR_CHECKING\" \\\n                         \"VCL_USE_NATIVE_STL=1\" \\\n                         \"VCL_USE_NATIVE_COMPLEX=1\" \\\n                         \"VCL_HAS_BOOL=1\" \\\n                         \"VXL_BIG_ENDIAN=1\" \\\n                         \"VXL_LITTLE_ENDIAN=0\" \\\n                         \"VNL_DLL_DATA=\" \\\n                         \"size_t=vcl_size_t\" \\\n                         \"ITK_USE_FFTWD\" \\\n                         \"ITK_USE_FFTWF\" \\\n                         \"itkMacro_h\" \\\n                         \"ITK_LEGACY_REMOVE\" \\\n                         \"ITK_FUTURE_LEGACY_REMOVE\" \\\n                         \"ITKCommon_EXPORT_EXPLICIT\" \\\n                         \"ITK_OVERRIDE= override \" \\\n                         \"ITK_NULLPTR=  nullptr \" \\\n                         \"ITK_NOEXCEPT= noexcept \" \\\n                         \"ITK_DISALLOW_COPY_AND_MOVE(type)=\" \\\n                         \"ITK_FORCE_EXPORT_MACRO(X)=\" \\\n                         \"RTK_USE_CUDA\"\n\n# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this\n# tag can be used to specify a list of macro names that should be expanded. The\n# macro definition that is found in the sources will be used. Use the PREDEFINED\n# tag if you want to use a different macro definition that overrules the\n# definition found in the source code.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nEXPAND_AS_DEFINED      =\n\n# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will\n# remove all references to function-like macros that are alone on a line, have\n# an all uppercase name, and do not end with a semicolon. Such function macros\n# are typically used for boiler-plate code, and will confuse the parser if not\n# removed.\n# The default value is: YES.\n# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.\n\nSKIP_FUNCTION_MACROS   = YES\n\n#---------------------------------------------------------------------------\n# Configuration options related to external references\n#---------------------------------------------------------------------------\n\n# The TAGFILES tag can be used to specify one or more tag files. For each tag\n# file the location of the external documentation should be added. The format of\n# a tag file without this location is as follows:\n# TAGFILES = file1 file2 ...\n# Adding location for the tag files is done as follows:\n# TAGFILES = file1=loc1 \"file2 = loc2\" ...\n# where loc1 and loc2 can be relative or absolute paths or URLs. See the\n# section \"Linking to external documentation\" for more information about the use\n# of tag files.\n# Note: Each tag file must have a unique name (where the name does NOT include\n# the path). If a tag file is not located in the directory in which doxygen is\n# run, you must also specify the path to the tagfile here.\n\nTAGFILES               = @DOXYGEN_TAGFILES_PARAMETER@\n\n# When a file name is specified after GENERATE_TAGFILE, doxygen will create a\n# tag file that is based on the input files it reads. See section \"Linking to\n# external documentation\" for more information about the usage of tag files.\n\nGENERATE_TAGFILE       = @PROJECT_BINARY_DIR@/Doxygen/RTKDoxygen.tag\n\n# If the ALLEXTERNALS tag is set to YES, all external class will be listed in\n# the class index. If set to NO, only the inherited external classes will be\n# listed.\n# The default value is: NO.\n\nALLEXTERNALS           = NO\n\n# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed\n# in the modules index. If set to NO, only the current project's groups will be\n# listed.\n# The default value is: YES.\n\nEXTERNAL_GROUPS        = YES\n\n# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in\n# the related pages index. If set to NO, only the current project's pages will\n# be listed.\n# The default value is: YES.\n\nEXTERNAL_PAGES         = YES\n\n# The PERL_PATH should be the absolute path and name of the perl script\n# interpreter (i.e. the result of 'which perl').\n# The default file (with absolute path) is: /usr/bin/perl.\n\nPERL_PATH              = \"@PERL_EXECUTABLE@\"\n\n#---------------------------------------------------------------------------\n# Configuration options related to the dot tool\n#---------------------------------------------------------------------------\n\n# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram\n# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to\n# NO turns the diagrams off. Note that this option also works with HAVE_DOT\n# disabled, but it is recommended to install and use dot, since it yields more\n# powerful graphs.\n# The default value is: YES.\n\nCLASS_DIAGRAMS         = YES\n\n# You can define message sequence charts within doxygen comments using the \\msc\n# command. Doxygen will then run the mscgen tool (see:\n# https://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the\n# documentation. The MSCGEN_PATH tag allows you to specify the directory where\n# the mscgen tool resides. If left empty the tool is assumed to be found in the\n# default search path.\n\nMSCGEN_PATH            =\n\n# You can include diagrams made with dia in doxygen documentation. Doxygen will\n# then run dia to produce the diagram and insert it in the documentation. The\n# DIA_PATH tag allows you to specify the directory where the dia binary resides.\n# If left empty dia is assumed to be found in the default search path.\n\nDIA_PATH               =\n\n# If set to YES the inheritance and collaboration graphs will hide inheritance\n# and usage relations if the target is undocumented or is not a class.\n# The default value is: YES.\n\nHIDE_UNDOC_RELATIONS   = YES\n\n# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is\n# available from the path. This tool is part of Graphviz (see:\n# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent\n# Bell Labs. The other options in this section have no effect if this option is\n# set to NO\n# The default value is: NO.\n\nHAVE_DOT               = YES\n\n# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed\n# to run in parallel. When set to 0 doxygen will base this on the number of\n# processors available in the system. You can set it explicitly to a value\n# larger than 0 to get control over the balance between CPU load and processing\n# speed.\n# Minimum value: 0, maximum value: 32, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_NUM_THREADS        = 0\n\n# When you want a differently looking font in the dot files that doxygen\n# generates you can specify the font name using DOT_FONTNAME. You need to make\n# sure dot is able to find the font, which can be done by putting it in a\n# standard location or by setting the DOTFONTPATH environment variable or by\n# setting DOT_FONTPATH to the directory containing the font.\n# The default value is: Helvetica.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTNAME           = Helvetica\n\n# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of\n# dot graphs.\n# Minimum value: 4, maximum value: 24, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTSIZE           = 10\n\n# By default doxygen will tell dot to use the default font as specified with\n# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set\n# the path where dot can find it using this tag.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_FONTPATH           =\n\n# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for\n# each documented class showing the direct and indirect inheritance relations.\n# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCLASS_GRAPH            = YES\n\n# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a\n# graph for each documented class showing the direct and indirect implementation\n# dependencies (inheritance, containment, and class references variables) of the\n# class with other documented classes.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCOLLABORATION_GRAPH    = YES\n\n# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for\n# groups, showing the direct groups dependencies.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGROUP_GRAPHS           = YES\n\n# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and\n# collaboration diagrams in a style similar to the OMG's Unified Modeling\n# Language.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LOOK               = NO\n\n# If the UML_LOOK tag is enabled, the fields and methods are shown inside the\n# class node. If there are many fields or methods and many nodes the graph may\n# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the\n# number of items for each type to make the size more manageable. Set this to 0\n# for no limit. Note that the threshold may be exceeded by 50% before the limit\n# is enforced. So when you set the threshold to 10, up to 15 fields may appear,\n# but if the number exceeds 15, the total amount of fields shown is limited to\n# 10.\n# Minimum value: 0, maximum value: 100, default value: 10.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nUML_LIMIT_NUM_FIELDS   = 10\n\n# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and\n# collaboration graphs will show the relations between templates and their\n# instances.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nTEMPLATE_RELATIONS     = YES\n\n# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to\n# YES then doxygen will generate a graph for each documented file showing the\n# direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDE_GRAPH          = YES\n\n# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are\n# set to YES then doxygen will generate a graph for each documented file showing\n# the direct and indirect include dependencies of the file with other documented\n# files.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINCLUDED_BY_GRAPH      = YES\n\n# If the CALL_GRAPH tag is set to YES then doxygen will generate a call\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable call graphs for selected\n# functions only using the \\callgraph command. Disabling a call graph can be\n# accomplished by means of the command \\hidecallgraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALL_GRAPH             = NO\n\n# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller\n# dependency graph for every global function or class method.\n#\n# Note that enabling this option will significantly increase the time of a run.\n# So in most cases it will be better to enable caller graphs for selected\n# functions only using the \\callergraph command. Disabling a caller graph can be\n# accomplished by means of the command \\hidecallergraph.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nCALLER_GRAPH           = NO\n\n# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical\n# hierarchy of all classes instead of a textual one.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGRAPHICAL_HIERARCHY    = NO\n\n# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the\n# dependencies a directory has on other directories in a graphical way. The\n# dependency relations are determined by the #include relations between the\n# files in the directories.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDIRECTORY_GRAPH        = YES\n\n# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images\n# generated by dot. For an explanation of the image formats see the section\n# output formats in the documentation of the dot tool (Graphviz (see:\n# https://www.graphviz.org/)).\n# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order\n# to make the SVG files visible in IE 9+ (other browsers do not have this\n# requirement).\n# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,\n# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and\n# png:gdiplus:gdiplus.\n# The default value is: png.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_IMAGE_FORMAT       = svg\n\n# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to\n# enable generation of interactive SVG images that allow zooming and panning.\n#\n# Note that this requires a modern browser other than Internet Explorer. Tested\n# and working are Firefox, Chrome, Safari, and Opera.\n# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make\n# the SVG files visible. Older versions of IE do not have SVG support.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nINTERACTIVE_SVG        = NO\n\n# The DOT_PATH tag can be used to specify the path where the dot tool can be\n# found. If left blank, it is assumed the dot tool can be found in the path.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_PATH               =\n\n# The DOTFILE_DIRS tag can be used to specify one or more directories that\n# contain dot files that are included in the documentation (see the \\dotfile\n# command).\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOTFILE_DIRS           =\n\n# The MSCFILE_DIRS tag can be used to specify one or more directories that\n# contain msc files that are included in the documentation (see the \\mscfile\n# command).\n\nMSCFILE_DIRS           =\n\n# The DIAFILE_DIRS tag can be used to specify one or more directories that\n# contain dia files that are included in the documentation (see the \\diafile\n# command).\n\nDIAFILE_DIRS           =\n\n# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the\n# path where java can find the plantuml.jar file. If left blank, it is assumed\n# PlantUML is not used or called during a preprocessing step. Doxygen will\n# generate a warning when it encounters a \\startuml command in this case and\n# will not generate output for the diagram.\n\nPLANTUML_JAR_PATH      =\n\n# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a\n# configuration file for plantuml.\n\nPLANTUML_CFG_FILE      =\n\n# When using plantuml, the specified paths are searched for files specified by\n# the !include statement in a plantuml block.\n\nPLANTUML_INCLUDE_PATH  =\n\n# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes\n# that will be shown in the graph. If the number of nodes in a graph becomes\n# larger than this value, doxygen will truncate the graph, which is visualized\n# by representing a node as a red box. Note that doxygen if the number of direct\n# children of the root node in a graph is already larger than\n# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that\n# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.\n# Minimum value: 0, maximum value: 10000, default value: 50.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_GRAPH_MAX_NODES    = 150\n\n# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs\n# generated by dot. A depth value of 3 means that only nodes reachable from the\n# root by following a path via at most 3 edges will be shown. Nodes that lay\n# further from the root node will be omitted. Note that setting this option to 1\n# or 2 may greatly reduce the computation time needed for large code bases. Also\n# note that the size of a graph can be further restricted by\n# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n# Minimum value: 0, maximum value: 1000, default value: 0.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nMAX_DOT_GRAPH_DEPTH    = 0\n\n# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent\n# background. This is disabled by default, because dot on Windows does not seem\n# to support this out of the box.\n#\n# Warning: Depending on the platform used, enabling this option may lead to\n# badly anti-aliased labels on the edges of a graph (i.e. they become hard to\n# read).\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_TRANSPARENT        = NO\n\n# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output\n# files in one run (i.e. multiple -o and -T options on the command line). This\n# makes dot run faster, but since only newer versions of dot (>1.8.10) support\n# this, this feature is disabled by default.\n# The default value is: NO.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_MULTI_TARGETS      = YES\n\n# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page\n# explaining the meaning of the various boxes and arrows in the dot generated\n# graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nGENERATE_LEGEND        = YES\n\n# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot\n# files that are used to generate the various graphs.\n# The default value is: YES.\n# This tag requires that the tag HAVE_DOT is set to YES.\n\nDOT_CLEANUP            = YES\n"
  },
  {
    "path": "documentation/Doxygen/itkdoxygen.pl.in",
    "content": "# for vxl files run the vxl_doxy.pl script, and use itkgroup.pl for all other files\nif ( $ARGV[0] =~ /(vxl|vcl|vnl)/)\n{\n    system (\"perl @RTK_SOURCE_DIR@/documentation/Doxygen/vxl_doxy.pl $ARGV[0]\");\n}\nelse\n{\n    system (\"perl @RTK_SOURCE_DIR@/documentation/Doxygen/itkgroup.pl $ARGV[0]\");\n}\n"
  },
  {
    "path": "documentation/Doxygen/itkgroup.pl",
    "content": "# if regular doxycomment add a @{\n# at next empty line add a //@}\n\n$ingroup = 0;\n$semicount =0;\n$endbracecount = 0;\n$endparencount = 0;\nwhile(<>)\n{\n    chomp;\n    $line = $_;\n# if the line is not an empty line\n    if( $line =~ /\\S+/ )\n    {\n\tif ( /\\/\\*\\*(.*)/ )\n\t{\n            # I guess it was not a group, dump savebuffer\n            if($ingroup)\n            {\n                print \"/**\" . $savebuffer . \"\\n\";\n            }\n            # if it is a class or brief then output the line but\n            # do not start a group\n\t    if ( /(\\\\class|\\\\brief)/ )\n\t    {\n\t\tprint $line . \"\\n\";\n\t    }\n            # must be a group so start saving\n\t    else\n\t    {\n                $savebuffer = \"$1\" . \"\\n\";\n\t\t$ingroup = 1;\n                $semicount = 0;\n                $endbracecount = 0;\n                $endparencount = 0;\n\t    }\n\t}\n\telse\n\t{\n            # add to save buffer if in group\n            if($ingroup)\n            {\n                $savebuffer = $savebuffer . $_ . \"\\n\";\n            }\n            else\n            {\n                # non empty line that is not the start of a doxy comment\n                print $_ . \"\\n\";\n            }\n\t}\n        if($line =~ /;/ )\n        {\n            $semicount = $semicount + 1;\n        }\n        if($line =~ /\\}/ )\n        {\n            $endbracecount = $endbracecount + 1;\n        }\n        if($line =~ /\\)/ )\n        {\n            $endparencount = $endparencount + 1;\n        }\n    }\n    else\n    {\n\tif($ingroup)\n\t{\n            if($endparencount > 1 && ($semicount > 1 || $endbracecount > 1))\n            {\n                print \"/**@\\{\" . $savebuffer . \"//@}\\n\\n\";\n            }\n            else\n            {\n                print \"/**\" . $savebuffer . \"\\n\";\n            }\n            $savebuffer = \"\";\n\t    $ingroup = 0;\n\t}\n\telse\n\t{\n\t    print $line . \"\\n\";\n\t}\n    }\n}\n"
  },
  {
    "path": "documentation/Doxygen/rtkThreeDCirculationProjectionGeometry.dox",
    "content": "/*!\n * \\page DocGeo3D RTK 3D circular projection geometry\n *\n * This documentation page has been moved to a <a\n * href=\"https://docs.openrtk.org/en/latest/documentation/docs/Geometry.html\">user\n * documentation page</a>.\n * */\n"
  },
  {
    "path": "documentation/Doxygen/vxl_doxy.pl",
    "content": "#!/bin/sh\n# -*- perl -*-\nexec perl -w -x $0 ${1+\"$@\"}\n#!perl\n#line 6\n# If Windows barfs at line 3 here, you will need to run perl -x vxl_doxy.pl\n# You can set up as a permanent file association using the following commands\n#  >assoc .pl-PerlScript\n#  >ftype PerlScript=Perl=C:\\Perl\\bin\\Perl.exe -x \"%1\" %*\n\n# Script to change the perceps documentation format to Doxygen (JavaDoc) format\n# Authors:\n#         Dave Cooper\n#         Maarten Vergauwen\n# Date:\n#      17/02/2000\n# Modified:\n# 11 April 2001 Ian Scott.   Remove support for old perceps commands\n#  5 May   2001 Geoff Cross. Correctly handle end of verbatim blocks. Allow two contiguous comments\n#  10 May  2001 Ian Scott. Merged Geoffs and my changes\n\n\n# patterns to be matched\n$verbpatt = '\\\\\\\\verbatim';\n$endverbpatt = '\\\\\\\\endverbatim';\n$slashslashpatt = '^\\\\s*//';\n$slashslashcolonpatt = '^\\\\s*//:';\n$slashstarstarpatt = '/**';\n$spacespacepatt = '  ';\n$starpatt = '*';\n$starslashpatt = '*/';\n\n# variables that keep state:\n\n# comment found -> first line should start with /**, next lines with *, last line with */\n$comment = 0;\n\n# verbatim found -> lines should not start with * (visible in Doxygen)\n$verbatim = 0;\n# finish verbatim mode at the end of this line.\n$should_end_verbatim = 0;\n\n$debug = 0;\n\n# mainloop\nwhile (<>)\n{\n    # preprocessing\n    s/\\bVCL_SUNPRO_CLASS_SCOPE_HACK\\s*\\([^()]*\\)//g;\n    s/\\bVCL_SUNPRO_ALLOCATOR_HACK\\s*\\(([^()]*)\\)/$1/g;\n    s/\\bVCL_CAN_STATIC_CONST_INIT_(INT|FLOAT)\\b/1/g;\n    s/\\bVCL_STATIC_CONST_INIT_(INT|FLOAT)\\s*\\(([^()]*)\\)/= $2/g;\n    s/\\bVCL_DFL_TYPE_PARAM_STLDECL\\s*\\(([^,()]*),([^,()]*)\\)/class $1 = $2 /g;\n    s/\\bDECLARE_DYNCREATE\\s*\\([^()]*\\)//g; # for MFC\n\n    if ( $should_end_verbatim )\n    {\n        $verbatim = 0;\n        $should_end_verbatim = 0;\n    }\n\n    # found verbatim ?\n    if ( m/$verbpatt/ ) { $verbatim = 1; };\n\n    # found endverbatim ?\n    if ( m/$endverbpatt/ ) { $should_end_verbatim = 1; };\n\n    # found start of comment: \"//:\"  ?\n    if ( s!$slashslashcolonpatt!$slashstarstarpatt! )\n    {\n        chomp; s/\\s*$//;\n        # escape a space following a dot, add a dot at the end,\n#       # and finish brief doc, unless the line is empty or only has '\\file':\n        unless (m!^\\s*\\/\\*\\*\\s*(\\\\file)?\\s*$!) {\n#         s/\\. /.\\\\ /g; s/(\\.)?\\s*$/. \\*\\/\\n\\/\\*/;\n          s/\\. /.\\\\ /g; s/(\\.)?\\s*$/.\\n/;\n        }\n        else { s/$/\\n/; }\n\n        if ($comment)\n        {\n            # Previous comment hasn't ended--two contiguous comment blocks.\n            # (Should not happen.)\n            print STDERR \"Two contiguous comment blocks -- this should not happen\\n\";\n            print \"*/\\n\";\n        }\n        $comment = 1;\n        print; next;\n    }\n\n    # Replace '$' with '\\f$' (TeX math mode)\n    s/(\\\\f)?\\$(.+?)(\\\\f)?\\$/\\\\f\\$$2\\\\f\\$/g if ($comment);\n\n    # found continuation of comment WITH verbatim -> no \"*\"\n    if ( m!$slashslashpatt! && $verbatim && $comment)\n    {\n        s!$slashslashpatt!$spacespacepatt!;\n#       # Make 'Modifications' a section title:\n#       s!\\b(Modifications?)\\b\\:?!\\<H2\\>$1\\<\\/H2\\>!;\n        # remove lines of the form ========= or +-+-+-+-+ or ********* or longer:\n        print unless m/^\\s*[*=+-]{9,}\\s*$/; next;\n    }\n\n    # found continuation of comment WITHOUT verbatim -> start line with \"*\"\n    if ( m!$slashslashpatt! && $comment )\n    {\n        s!$slashslashpatt!$starpatt!;\n        # remove lines of the form ========= or +-+-+-+-+ or ********* or longer:\n        print unless m/^\\s*[*=+-]{9,}\\s*$/; next;\n    }\n\n    # found end of comment -> start line with */\n    # NOTE that *every* line within a comment (also empty lines) *must* start with // !\n    # (In an earlier version of this script, empty lines were allowed inside comments.)\n    if ( $comment && ! m!$slashslashpatt!  )\n    {\n        print \"$starslashpatt\\n\";\n        $comment = 0;\n        print; next;\n    }\n\n    # just print line if not in comment or in file\n    if ( !$comment ) { print; next; }\n\n    # debug - print unprocessed lines (s.b. none)\n    if ($debug) { print \"LNP:\\t\"; print; }\n}\n"
  },
  {
    "path": "documentation/docs/CMakeLists.txt",
    "content": "if(RTK_BUILD_SPHINX)\n\n  # Build sphinx documentation in the build directory\n  set(RTK_DOC_OUTPUT_DIR ${CMAKE_BINARY_DIR}/sphinx)\n\n  # Copy the source tree documentation to the build tree before calling sphinx.\n  # The images are downloaded when conf.py is run by sphinx.\n  add_custom_target(copy_sources ALL\n    COMMAND ${CMAKE_COMMAND}\n               -DRTK_SOURCE_DIR:PATH=\"${RTK_SOURCE_DIR}\"\n               -DRTK_DOC_OUTPUT_DIR:PATH=\"${RTK_DOC_OUTPUT_DIR}\"\n               -P \"${CMAKE_CURRENT_SOURCE_DIR}/copy_and_fetch_sphinx_doc_files.cmake\"\n    COMMENT \"Copying documentation sources\"\n    )\n\n  find_program(SPHINX_EXECUTABLE\n    NAMES sphinx-build sphinx-build.exe\n    DOC \"Sphinx documentation generator\"\n  )\n\n  add_custom_target( sphinx_doc ALL\n    COMMAND ${SPHINX_EXECUTABLE}\n    -c ${RTK_DOC_OUTPUT_DIR}                   # conf.py directory\n    ${RTK_DOC_OUTPUT_DIR}                      # Source directory containing root index.md\n    \"${RTK_DOC_OUTPUT_DIR}/_build\"             # Output directory\n    COMMENT \"Generating sphinx documentation\"\n    DEPENDS copy_sources\n    WORKING_DIRECTORY ${RTK_DOC_OUTPUT_DIR}\n    )\n\n  set_property(\n    DIRECTORY APPEND PROPERTY\n    ADDITIONAL_MAKE_CLEAN_FILES\n    \"${RTK_DOC_OUTPUT_DIR}/_build\"\n    )\n\nendif()\n"
  },
  {
    "path": "documentation/docs/ExternalData/AddNoise.png.sha512",
    "content": "43cd0808d4123fd6cc078367530731d266a6fa986ed26a6ab1cc706fcc48f8d3371611b6fd230d3424370b4fcf4047dea1a636b0cef07005be21d0b1d0181a0c\n"
  },
  {
    "path": "documentation/docs/ExternalData/AdmmWavelets.png.sha512",
    "content": "0cf3987d383f967ce99f01dcbd051944ee23a1fce64263a451b9391a295cf69a8bb670c109aa23ada7c62ce3c78630bcc0afe0669d09fe5f1bfab9544a8e0032"
  },
  {
    "path": "documentation/docs/ExternalData/Admmtv.png.sha512",
    "content": "2551a4bcf95c478d86bb63c37f6cf966640efc015529febc4881959cc9eab3b3aec16c607384f022b81f7f590a533d9c73361659c722c4aa87ea5583c0204b77"
  },
  {
    "path": "documentation/docs/ExternalData/Amsterdam.png.sha512",
    "content": "bf4f5bc8e887d7faf7dc9e835814b123a84dd617ef83343590411651f35a03083cc2d71cff6f7a3d8fd5b4b0fdd517871335650183238814de769f49ca07210e"
  },
  {
    "path": "documentation/docs/ExternalData/Blurred.jpg.sha512",
    "content": "52a2f4d2559e0a60c5af7c50c5969ea4f9649573492df3f25e7e963b408bc25022ea8aec3a661ae1cf6a82119a249ef4c383d97c483371b0a5fa578314457c2d"
  },
  {
    "path": "documentation/docs/ExternalData/Blurred_vs_mc.gif.sha512",
    "content": "2c05f3a1f4c14db8b0280e59640aec0c6a856dbecba1e2d3db3b5db9a202cdfe2f40982531f97174652c210bea120b9867b83ca7e4110a48fe28ecf2f3ce776e"
  },
  {
    "path": "documentation/docs/ExternalData/ConjugateGradient-2D.png.sha512",
    "content": "9b80b5ed103e40f6a1b73ad482be98c75c0f46bd6f4276fe699471ca9cc0692dcffc087ac330ecc86a8bfeec37c8031abf50859cb0ceb6400725fa5168f29473"
  },
  {
    "path": "documentation/docs/ExternalData/ConjugateGradient-3D.png.sha512",
    "content": "7b1756962a167f411b7ad80553498c67d7ac9ef572151fe53756682fc3dc8f9b2d8c053652952c1f2c38d0ec5bd6c8a3197884307e958201ab0a8421802cbf5f"
  },
  {
    "path": "documentation/docs/ExternalData/ConjugateGradient-Sinogram-2D.png.sha512",
    "content": "b62bcfb17c8a841dd72890d82f8a321cd819618fea3cc96bd58a82a349b8a191419db279dce0d194a6168d1744caca6352eae1a950b1efe6a6b2b3adcbf1d4f7"
  },
  {
    "path": "documentation/docs/ExternalData/Elekta.png.sha512",
    "content": "8cb55621686009fb44c03656aa978114ee689ef474afea0bfa20837c8b321eaedc3aebd3c6ba7592d555c215460b3c3a16034568d7c6a5f99352ca5edf65c953"
  },
  {
    "path": "documentation/docs/ExternalData/Fdk-2D.png.sha512",
    "content": "39a1ecdc81a80c4570674d035ffbcd612cf5df4fbc3588cec782b8c57db2b2dd91cfc198fb25669ee9be9a6a7708f2a68781f591b07b69dc1bc5b507ac63969a"
  },
  {
    "path": "documentation/docs/ExternalData/Fdk-3D.png.sha512",
    "content": "2fd7d04586bbe7b3cb0f1463752afb48311e6de67400ad889edd53b7512a34a3b124a1563f42c0f47defa8bf53bb17f6ed6506d742ff28a7d09cb739c7f0df26"
  },
  {
    "path": "documentation/docs/ExternalData/GammexPhantom.png.sha512",
    "content": "51510a6083a3c6dfae0ffa229c0a98ac11f2bea2b14eee814658b5ef47a98ec3545d54951afd57ba103bbaa1db04ff7e7dcddfa862e78111904da7d079ee40bf"
  },
  {
    "path": "documentation/docs/ExternalData/MotionMask.jpg.sha512",
    "content": "13b801ac5e9833613e42abb9d9e7628fcde6f4dcf2d7e6c2a501e61a6b335d7b6766c512db547887a367f280943a9715934f6f21918117942e6e3ea99e39865d"
  },
  {
    "path": "documentation/docs/ExternalData/Moving-Phantom-Sinogram.png.sha512",
    "content": "b31fe75d2f3ef6289e6dbca4bf7dc2675eebd80bfd25d61b167727587b796cf9b371f05db51949904699ceb3bf5cc681265ac7b4aa9b89ab632a2213e7bcca1d"
  },
  {
    "path": "documentation/docs/ExternalData/POPI-Reconstruction.png.sha512",
    "content": "5261406f0891c4141006a4a4f75aaabe81e372dc380c27230b8b7355d13392ab43abc351de028f880c8df2bfdf352a5754bc8f575d6365fb4c9b66b48c547f37"
  },
  {
    "path": "documentation/docs/ExternalData/POPI-Sinogram.png.sha512",
    "content": "72cd6bd4bed25bb626ee5eee5aa142c3514b0ac8346def3887ba8eece4f9fc0379cd6d9a1e085848fb5e7ef2ed3ef9d1c322c9e9cfa14f49986a329956a24289"
  },
  {
    "path": "documentation/docs/ExternalData/SheppLogan-Sinogram-2D.png.sha512",
    "content": "086f1c57c7fe6be7324b0a2a3a68f1f4b15bba502de301208173b76d9fa0a592f1aee410acb7375780c562fc9f57d1767f276da43fb4fc217aaa1c4eec6def9d"
  },
  {
    "path": "documentation/docs/ExternalData/SheppLogan-Sinogram-3D.png.sha512",
    "content": "a77ba17cb7997a7a130b52b1f07d39024f5ddb5c68f1990a7c796f72e07ecedfb28b949b243a983a12b2af90f8ca703f2ee385fcfe15a4b856e68ba490e8bb30"
  },
  {
    "path": "documentation/docs/ExternalData/ShowGeometry.png.sha512",
    "content": "5f4513b8f36d5fef429f7bdb452e55e31f6726b90ea3674029e78c517f2fa2031e7bad0e0d9ec1fcb715798c8f061db761f3ce3fffd70ddb32740fc952b801c1"
  },
  {
    "path": "documentation/docs/ExternalData/Signal.jpg.sha512",
    "content": "7c265ec19e50310585f65ae90147ca1972225f93f35b090e233acfa081b084e329ed5b2d31fad23ec43e64d281937fad213d1229f5b717a98592518f6d56a7c2"
  },
  {
    "path": "documentation/docs/ExternalData/Thorax-Sinogram.png.sha512",
    "content": "363abef4b21fbda556addb6eb2b91a414622e58b4684fe141f71569274f05039e6130b2cf5f363360b3358c33baeb755fa3866fa53ff0934828f2e5a25b41ab1"
  },
  {
    "path": "documentation/docs/ExternalData/Thorax-fdk.png.sha512",
    "content": "b7bca5f09929a2ceedb7b97bc7217e6d20e6931a038fe79e41e39523776b2bc1f4e4655787f528acc0e08aefbfc1a9bac0ae618f9067543d61c121dfe7700073"
  },
  {
    "path": "documentation/docs/ExternalData/Thorax-visualisation.png.sha512",
    "content": "9b49ea1d6739196ea8a9b3bc36f0e647cb247276d87faa69e85c6d4fce8702fb48de3e321632608c2945dbf3254dbfeeeee55edae09f5d2d5d7dbd2fe37e682d\n"
  },
  {
    "path": "documentation/docs/ExternalData/Varian.png.sha512",
    "content": "32682b605de454017def2fd481c13f8f8ad7bf989025f0534538655e39c5e82dda7c41c00e558cfd8399ed15cc899f0dff8f8720b5bffb6a426e5c199ca82d0d"
  },
  {
    "path": "documentation/docs/ExternalData/VarianProBeam.png.sha512",
    "content": "8e0e9cabae8aa32fb54f23e26791133c40766fda48b94c9145a50a4110ae26291f7aca8f1d29699595cdb1199aacb990ddf12d52a674cbbb82e8ef4e043fd0c3"
  },
  {
    "path": "documentation/docs/ExternalData/VectorField.gif.sha512",
    "content": "def878b887fa050f59978b9441050ea177736d1e5a227e8a6f3693ef4f8c9c7175e06cdaf71305958ed8b131686fea184fe2fb6810228fa11d69fa7b99759cb2"
  },
  {
    "path": "documentation/docs/Geometry.md",
    "content": "# 3D projection geometry\n\n## Purpose\n\nThe purpose of this page is to describe the geometry object used in RTK to relate a tomography to projection images. There is currently only one geometry class, `ThreeDCircularProjectionGeometry`. A visual illustration of a given geometry is provided by the command line tool [`rtkshowgeometry`](../../applications/rtkshowgeometry/README.md).\n\n## Units\n\n- Degrees are used in the geometry files and to pass angle values to the `AddProjection` member but they are converted to and stored in radians. Angles are wrapped between 0 and 360 degrees.\n- No unit is enforced for distances but it is the responsibility of the user to have a consistent unit for all distances (pixel and voxel spacings, geometry parameters...). Millimeters are typically used in ITK and DICOM.\n\n## Image Coordinate System\n\nAn `itk::Image<>` contains information to convert voxel indices to physical coordinates using its members `m_Origin`, `m_Spacing`, and `m_Direction`. Voxel coordinates are not used in RTK except for internal computation. The conversion from voxel index coordinates to physical coordinates and the dimensions of the images are out of the scope of this document (see section 4.1.1 of the [ITK software guide](https://itk.org/ITKSoftwareGuide/html/Book1/ITKSoftwareGuide-Book1ch4.html)). In the following, origin refers to point with coordinates $\\vec{0}$ mm (and not to `m_Origin` in ITK).\n\n## Fixed Coordinate System\n\nThe fixed coordinate system $(x,y,z)$ in RTK is the coordinate system of the tomography with the isocenter at the origin $(0,0,0)$.\n\n## ProjectionGeometry\\<TDimension\\>\n\nThis is the mother class for relating a TDimension-D tomography to a (TDimension-1)-D projection image. It holds a vector of (TDimension)x(TDimension+1) projection matrices accessible via `GetMatrices`. The construction of those matrices is geometry dependent.\n\n## ThreeDCircularProjectionGeometry\n\nThis class is meant to define a set of 2D projection images, acquired with a flat panel along a circular trajectory, around a 3D tomography. The trajectory does not have to be strictly circular but it is assumed in some reconstruction algorithms that the rotation axis is y. The description of the geometry is based on the international standard IEC 61217 which has been designed for cone-beam imagers on isocentric radiotherapy systems but it can be used for any 3D circular trajectory. The fixed coordinate system of RTK and the fixed coordinate system of IEC 61217 are the same.\n\n9 parameters are used per projection to define the position of the source and the detector relatively to the fixed coordinate system. The 9 parameters are set with the method `AddProjection`. Default values are provided for the parameters which are not mandatory. Note that explicit names have been used but this does not necessarily correspond to the value returned by the scanner which can use its own parameterization.\n\n### Detector Orientation\n\n#### Initial Detector Orientation\n\nWith all parameters set to 0, the detector is normal to the z direction of the fixed coordinate system, similarly to the x-ray image receptor in the IEC 61217.\n\n#### Rotation Order\n\nThree rotation angles are used to define the orientation of the detector. The ZXY convention of Euler angles is used for detector orientation where `GantryAngle` is the rotation around y, `OutOfPlaneAngle` the rotation around x, and `InPlaneAngle` the rotation around z. These three angles are detailed in the following.\n\n#### GantryAngle\n\nGantry angle of the scanner. It corresponds to $\\phi_g$ in Section 2.3 of IEC 61217:\n\n> The rotation of the \"g\" system is defined by the rotation of coordinate axes Xg, Zg by an angle $\\phi_g$ about axis Yg (therefore about Yf of the \"f\" system).\n>\n> An increase in the value of $\\phi_g$ corresponds to a clockwise rotation of the GANTRY as viewed along the horizontal axis Yf from the ISOCENTER towards the GANTRY.\n\n#### OutOfPlaneAngle\n\nOut of plane rotation of the flat panel complementary to the GantryAngle rotation, i.e., with a rotation axis perpendicular to the gantry rotation axis and parallel to the flat panel. It is optional with a default value equal to 0. There is no corresponding rotation in IEC 61217. After gantry rotation, the rotation is defined by the rotation of the coordinate axes y and z about x. An increase in the value of `OutOfPlaneAngle` corresponds to a counter-clockwise rotation of the flat panel as viewed from a positive value along the x axis towards the isocenter.\n\n#### InPlaneAngle\n\nIn plane rotation of the 2D projection. It is optional with 0 as default value. If `OutOfPlaneAngle` equals 0, it corresponds to $\\theta_r$ in Section 2.6 of IEC 61217:\n\n> The rotation of the \"r\" system is defined by the rotation of the coordinate axes Xr, Yr about Zr (parallel to axis Zg) by an angle $\\theta_r$.\n>\n> An increase in the value of angle $\\theta_r$ corresponds to a counter-clockwise rotation of the X-RAY IMAGE RECEPTOR as viewed from the RADIATION SOURCE.\n\n#### Rotation Matrix\n\nThe rotation matrix in homogeneous coordinates is then (constructed with `itk::Euler3DTransform<double>::ComputeMatrix()` with opposite angles because we rotate the volume coordinates instead of the scanner):\n\n$$\n\\begin{split}\nM_R = &\n\\begin{pmatrix}\n\\cos(-InPlaneAngle) & -\\sin(-InPlaneAngle) & 0 & 0\\\\\n\\sin(-InPlaneAngle) & \\cos(-InPlaneAngle) & 0 & 0\\\\\n0 & 0 & 1 & 0\\\\\n0 & 0 & 0 & 1\n\\end{pmatrix}\\\\\n&\\times\n\\begin{pmatrix}\n1 & 0 & 0 & 0\\\\\n0 & \\cos(-OutOfPlaneAngle) & -\\sin(-OutOfPlaneAngle) & 0\\\\\n0 & \\sin(-OutOfPlaneAngle) & \\cos(-OutOfPlaneAngle) & 0\\\\\n0 & 0 & 0 & 1\n\\end{pmatrix}\\\\\n&\\times\n\\begin{pmatrix}\n\\cos(-GantryAngle) & 0 & \\sin(-GantryAngle) & 0 \\\\\n0 & 1 & 0 & 0 \\\\\n-\\sin(-GantryAngle) & 0 & \\cos(-GantryAngle) & 0 \\\\\n0 & 0 & 0 & 1\n\\end{pmatrix}\n\\end{split}\n$$\n\n### Drawings\n\nThe following drawing describes the parameters of the source and the detector positions in the rotated coordinate system $(Rx,Ry,Rz)$ (i.e., oriented according to the detector orientation), with its origin at the isocenter, when all values are positive (but all distances can be negative in this geometry):\n\n![Drawing](https://www.openrtk.org/RTK/img/ThreeDCircularProjectionGeometry.svg)\n\nThese 6 parameters are used to describe any source and detector positions. It is simpler to understand the circular geometry when all Offset values equal 0:\n\n![Drawing](https://www.openrtk.org/RTK/img/ThreeDCircularProjectionGeometry_aligned.svg)\n\n### Source Position\n\nThe source position is defined with respect to the isocenter with three parameters, `SourceOffsetX`, `SourceOffsetY`, and `SourceToIsocenterDistance`. `(SourceOffsetX, SourceOffsetY, SourceToIsocenterDistance)` are the coordinates of the source in the rotated coordinated system. In IEC 61217, `SourceToIsocenterDistance` is the RADIATION SOURCE axis distance, SAD. `SourceOffsetX` and `SourceOffsetY` are optional and zero by default.\n\n### Detector Position\n\nThe detector position is defined with respect to the source with three parameters: `ProjectionOffsetX`, `ProjectionOffsetY`, and `SourceToDetectorDistance`. `(ProjectionOffsetX, ProjectionOffsetY, SourceToIsocenterDistance - SourceToDetectorDistance)` are the coordinates of the detector origin $(0,0)$ in the rotated coordinated system. In IEC 61217, `SourceToDetectorDistance` is the RADIATION SOURCE to IMAGE RECEPTION AREA distance, SID. `ProjectionOffsetX` and `ProjectionOffsetY` are optional and zero by default.\n\n### Final Matrix\n\nEach matrix, accessible via `GetMatrices`, is constructed with:\n\n$$\n \\begin{split}\n  M_P =\n  &\\begin{pmatrix}\n    1 & 0 & SourceOffsetX-ProjectionOffsetX  \\\\\n    0 & 1 & SourceOffsetY-ProjectionOffsetY  \\\\\n    0 & 0 & 1\n  \\end{pmatrix}\\\\\n  &\\times\n  \\begin{pmatrix}\n    -SourceToDetectorDistance & 0 & 0 & 0  \\\\\n    0 & -SourceToDetectorDistance & 0 & 0  \\\\\n    0 & 0 & 1 & -SourceToIsocenterDistance\n  \\end{pmatrix}\\\\\n  &\\times\n  \\begin{pmatrix}\n    1 & 0 & 0 & -SourceOffsetX  \\\\\n    0 & 1 & 0 & -SourceOffsetY  \\\\\n    0 & 0 & 1 & 0 \\\\\n    0 & 0 & 0 & 1\n  \\end{pmatrix}\\\\\n  &\\times\n  M_R\n  \\end{split}\n$$\n\n### Detector Radius\n\nIn addition to flat panel detectors, some of the forward and back projectors in\nRTK can handle cylindrical detectors. The radius of the cylindrical detector is\nstored only once, as the variable `RadiusCylindricalDetector`. The default value\nfor `RadiusCylindricalDetector` is 0, and indicates that the detector is a flat\npanel (i.e. infinite radius, but 0 is easier to deal with). When the value is\nnon-zero, then the flat detector is curved according to the radius and remain\ntangent to the corresponding flat detector along the line defined by the\ndetector origin `(0,0)` and second axis of the detector without accouting\nfor the parameters `ProjectionOffsetX` and `ProjectionOffsetY`. The latter two\nallow to modify the Origin of each projection as is the case for a flat panel.\nThe cylindrical detector geometry is illustrated in the following scheme:\n\n![Drawing](https://www.openrtk.org/RTK/img/ThreeDCircularProjectionGeometry_cylindrical.svg)\n\nThis scheme is based on the previous one with all offsets equal 0 but this is not required.\n\n### Parallel Geometry\n\nWhen `SourceToDetectorDistance` is set to 0, the geometry is assumed to be\nparallel (i.e. infinite distance, but 0 is easier to deal with). The detector\nis then flat. The rays are perpendicular to the detector plane which is\noriented similarly to the divergent geometry.  The (plane) source is actually\nplaced at a distance `SourceToIsocenterDistance` from the isocenter and the\ndetector is placed symetrically around the origin `(0,0,0)` at the same\n`SourceToIsocenterDistance`. This is summarized in the following scheme:\n\n![Drawing](https://www.openrtk.org/RTK/img/ThreeDCircularProjectionGeometry_parallel.svg)\n\nIn this case, the projection matrix becomes:\n\n$$\n  M_P =\n  \\begin{pmatrix}\n    1 & 0 & 0 & -ProjectionOffsetX  \\\\\n    0 & 1 & 0 & -ProjectionOffsetY  \\\\\n    0 & 0 & 0 & 1\n  \\end{pmatrix}\n  \\times M_R.\n$$\n\n### XML File\n\n`ThreeDCircularProjectionGeometry` can be saved and loaded from an XML file\nwith\n[rtk::ThreeDCircularProjectionGeometryXMLFileReader](http://www.openrtk.org/Doxygen/classrtk_1_1ThreeDCircularProjectionGeometryXMLFileReader.html)\nand\n[rtk::ThreeDCircularProjectionGeometryXMLFileWriter](http://www.openrtk.org/Doxygen/classrtk_1_1ThreeDCircularProjectionGeometryXMLFileWriter.html),\nrespectivey. If the parameter is equal to the default value for all\nprojections, it is not stored in the file. If it is equal for all projections\nbut different from the default value, it is stored once. Otherwise, it is\nstored for each projection.  The matrix is given for information. It is read\nand checked to be consistent with the parameters but a manual modification of\nthe file must consistently modify both the parameters and the matrix. An\nexample is given hereafter:\n\n```xml\n<?xml version=\"1.0\"?>\n<!DOCTYPE RTKGEOMETRY>\n<RTKThreeDCircularGeometry version=\"3\">\n  <SourceToIsocenterDistance>1000</SourceToIsocenterDistance>\n  <SourceToDetectorDistance>1536</SourceToDetectorDistance>\n  <RadiusCylindricalDetector>1536</RadiusCylindricalDetector>\n  <Projection>\n    <GantryAngle>271.847274780273</GantryAngle>\n    <ProjectionOffsetX>-117.056503295898</ProjectionOffsetX>\n    <ProjectionOffsetY>-1.01195001602173</ProjectionOffsetY>\n    <Matrix>\n          -166.5093078829                   0   -1531.42837748039   -117056.503295898\n        -1.01142410874151               -1536  0.0326206557691505   -1011.95001602173\n       -0.999480303105996                   0  0.0322354417240802               -1000\n    </Matrix>\n  </Projection>\n  <Projection>\n    <GantryAngle>271.852905273438</GantryAngle>\n    <ProjectionOffsetX>-117.056831359863</ProjectionOffsetX>\n    <ProjectionOffsetY>-1.01187002658844</ProjectionOffsetY>\n    <Matrix>\n        -166.660129424325                   0   -1531.41199650136   -117056.831359863\n        -1.01134095059569               -1536  0.0327174625589984   -1011.87002658844\n       -0.999477130482326                   0  0.0323336611415466               -1000\n    </Matrix>\n  </Projection>\n</RTKThreeDCircularGeometry>\n"
  },
  {
    "path": "documentation/docs/Phantom.md",
    "content": "# Phantom definition\n\nThis page, adapted from the original [Forbild's syntax explanation](https://www.dkfz.de/en/roentgenbildgebung/ct/CT_Phantoms/Head_Phantom/How-to-define-a-phantom.pdf), provides instructions for defining a phantom in the Forbild format in RTK.\n\n- Each shape is defined in a block enclosed in curly brackets `{}`.\n- Each shape is specified in square brackets `[type : commands]`\nwith **type** in the list below (e.g., sphere, box) and **commands** the parameters of the shape.\n\n- Each block must specify the function (attenuation, emission, etc. depending on the context) value of the material with `rho`.\n\n**Example**:\n```\n{\n    [Sphere: x=0 y=0 z=0 r=5]\n    rho = 1.0\n}\n```\n- Clip planes and unions (see below) are optional.\n\n## Volumes\n\nVolumes are the building blocks of phantom objects. These represent solid shapes with parameters that define their size, orientation and position.\n**All parameter values are zero by default**.\n\n1. **Sphere**\n- Parameters: center (`x`,`y`,`z`), radius (`r`).\n- **Example**:\n    ```\n    {\n        [Sphere: x=0 y=0 z=0 r=100]\n        rho = 1.0\n    }\n    ```\n\n2. **Box**\n- Also known as rectangular cuboid.\n- Parameters: center (`x`,`y`,`z`), edge lengths (`dx`,`dy`,`dz`).\n- **Example**:\n    ```\n    {\n        [Box: x=0 y=0 z=0 dx=100 dy=100 dz=100]\n        rho = 1.5\n    }\n    ```\n\n3. **Cylinder_x, Cylinder_y, Cylinder_z**\n- Cylinder parallel to the x, y or z axis, respectively.\n- Parameters: center (`x`,`y`,`z`), radius (`r`), length (`l`).\n- **Example**:\n    ```\n    {\n        [Cylinder_y: x=0 y=0 z=0 r=50 l=200]\n        rho = 2.0\n    }\n    ```\n\n4. **Cylinder**\n- Parameters: center (`x`,`y`,`z`), radius (`r`), length (`l`), axis vector (`axis`).\n- **Example**:\n    ```\n    {\n        [Cylinder: x=0 y=0 z=0 r=50 l=200 axis(1,1,0)]\n        rho = 2.5\n    }\n    ```\n\n5. **Ellipsoid**\n- Parameters: center (`x`,`y`,`z`), half-axes (`dx`,`dy`,`dz`).\n- **Example**:\n    ```\n    {\n        [Ellipsoid: x=0 y=0 z=0 dx=100 dy=75 dz=50]\n        rho = 3.0\n    }\n    ```\n\n6. **Ellipsoid_free**\n- Parameters: center (`x`,`y`,`z`), half-axes (`dx`,`dy`,`dz`), orthogonal orientation vectors (`a_x`,`a_y`,`a_z`).\n- **Example**:\n    ```\n    {\n        [Ellipsoid_free: x=0 y=0 z=0 dx=100 dy=75 dz=50 a_x(1,0,0) a_y(0,1,0) a_z(0,0,1)]\n        rho = 1.8\n    }\n    ```\n\n7. **Ellipt_Cyl**\n- Cylinder with an elliptical cross-section.\n- Parameters: center (`x`,`y`,`z`), half-axes (`dx`,`dy`,`dz`), length (`l`), orientation vectors (`a_x`,`a_y`) and principal direction (`axis`).\n- **Example**:\n    ```\n    {\n        [Ellipt_Cyl: x=0 y=0 z=0 l=150 dx=75 dy=50 dz=30 axis(0,1,1) a_x(1,0,0) a_y(0,1,0)]\n        rho = 3.0\n    }\n    ```\n\n8. **Cone**\n- Parameters: center (`x`,`y`,`z`), length (`l`), radii at the base and tip (`r1`,`r2`), axis vector (`axis`).\n- **Example**:\n    ```\n    {\n        [Cone: x=0 y=0 z=0 l=150 r1=75 r2=30 axis(0,0,1)]\n        rho = 2.2\n    }\n    ```\n\n9. **Cone_x, Cone_y, Cone_z**\n- Cone parallel to the x, y or z axis, respectively.\n- Parameters: center of the base (`x`,`y`,`z`), length along the axis (`l`), radii at the base and tip (`r1`,`r2`).\n- **Example**:\n    ```\n    {\n        [Cone_y: x=1 y=1 z=1 l=120 r1=40 r2=0]\n        rho = 2.2\n    }\n    ```\n\n## Clip Planes\n\nClip planes can be applied to any volume to restrict their extents.\n- Coordinate-based: `x<value`, `y>value`.\n- Plane-based: `r(x,y,z)<value`.\n\n**Example**:\n```\n{\n    [Sphere: x=0 y=0 z=0 r=100 x<50 z>0]\n    rho = 1.0\n}\n```\n\n## Function value `rho`\n\nThe function (attenuation, emission, etc. depending on the context) value `rho` is defined absolutely in the shape. RTK automatically deduces how much must be added to the current background based on the center (`x`,`y`,`z`) of the shape (e.g. 0.5 if one adds a shape with `rho=1.5` in a shape with `rho=1`). This is order dependent so the same phantom shapes defined in different orders might result in different results. The background of a shape must be defined first. \n\n## Union\n\nThe `union` parameter allows taking the union of two shapes. The second shape takes a negative integer value (`union=-N`), representing an index offset between the current shape and the shape it is being united with.\nThe `union` parameter is valid only when the two shapes share the same density (`rho`).\n\n**Example**:\n```\n{\n    [Sphere: x=100 y=0 z=0 r=50]\n    rho = 1.0\n}\n{\n    [Box: x=0 y=0 z=0 dx=100 dy=100 dz=100]\n    rho = 1.0\n    union=-1\n}\n```\n"
  },
  {
    "path": "documentation/docs/Projectors.md",
    "content": "# Forward and backprojectors\n\nIn cone-beam computed tomography (CBCT), forward and backprojectors are crucial components of the reconstruction algorithms. RTK implements multiple forward and backprojectors, each tailored to different purposes.\n\nAll projector classes in RTK are implemented as ITK filters. They inherit from either [`rtk::ForwardProjectionImageFilter`](https://www.openrtk.org/Doxygen/classrtk_1_1ForwardProjectionImageFilter.html) or [`rtk::BackProjectionImageFilter`](https://www.openrtk.org/Doxygen/classrtk_1_1BackProjectionImageFilter.html), both inheriting from [`itk::InPlaceImageFilter`](https://itk.org/Doxygen/html/classitk_1_1InPlaceImageFilter.html).\n\n## Forward projectors\n\nAn intuitive design for a forward projector would be:\n\n```{eval-rst}\n.. graphviz::\n  :align: center\n\n  digraph IntuitiveDesign {\n    node [shape=box];\n    Input [ label=\"Input (Volume)\" ];\n    Input [shape=Mdiamond];\n    ForwardProject [ label=\"rtk::ForwardProjectionImageFilter\" ];\n    Output [ label=\"Output (Projections)\"];\n    Output [shape=Mdiamond];\n    Input -> ForwardProject;\n    ForwardProject -> Output;\n  }\n```\n\nbut ITK's filter output has the same information (size, spacing, direction, ...) by default as the first input. This could be changed but it was deemed simpler to chose the following design:\n\n```{eval-rst}\n.. graphviz::\n  :align: center\n\n  digraph IntuitiveDesign {\n    node [shape=box];\n    Input0 [ label=\"Input (Projections)\" ];\n    Input0 [ shape=Mdiamond ];\n    Input1 [ label=\"Input (Volume)\" ];\n    Input1 [ shape=Mdiamond ];\n    ForwardProject [ label=\"rtk::ForwardProjectionImageFilter\" href=\"https://www.openrtk.org/Doxygen/classrtk_1_1ForwardProjectionImageFilter.html\" target=\"_top\"];\n    Output [ label=\"Output (Projections)\"];\n    Output [ shape=Mdiamond ];\n    Input0 -> ForwardProject;\n    Input1 -> ForwardProject;\n    ForwardProject -> Output;\n  }\n```\n\nForward projections of the second input are then added to the first input. Because forward projectors inherit from [`itk::InplaceImageFilter`](https://docs.itk.org/projects/doxygen/en/stable/classitk_1_1InPlaceImageFilter.html), there is still a single memory buffer for the projections. Projections filled with a constant, 0 by default, can be generated with [`rtk::ConstantImageSource`](http://www.openrtk.org/Doxygen/classrtk_1_1ConstantImageSource.html) which only generates the requested part in the memory buffer.\n\nRTK supports the following forward projector implementations :\n\n- [Joseph](https://www.openrtk.org/Doxygen/classrtk_1_1JosephForwardProjectionImageFilter.html)\n- [JosephAttenuated](https://www.openrtk.org/Doxygen/classrtk_1_1JosephForwardAttenuatedProjectionImageFilter.html)\n- [Zeng](https://www.openrtk.org/Doxygen/classrtk_1_1ZengForwardProjectionImageFilter.html)\n- [MIP](https://www.openrtk.org/Doxygen/classrtk_1_1MaximumIntensityProjectionImageFilter.html)\n\nCuda based projector:\n- [CudaRayCast](https://www.openrtk.org/Doxygen/classrtk_1_1CudaForwardProjectionImageFilter.html)\n- [CudaWarpRayCast](https://www.openrtk.org/Doxygen/classrtk_1_1CudaWarpForwardProjectionImageFilter.html)\n\n## Back projectors\n\nSimilarly, the design chosen for RTK back projectors is:\n\n```{eval-rst}\n.. graphviz::\n  :align: center\n\n  digraph IntuitiveDesign {\n    node [shape=box];\n    Input0 [ label=\"Input (Volume)\" ];\n    Input0 [ shape=Mdiamond ];\n    Input1 [ label=\"Input (Projections)\" ];\n    Input1 [ shape=Mdiamond ];\n    BackProject [ label=\"rtk::BackProjectionImageFilter\" href=\"https://www.openrtk.org/Doxygen/classrtk_1_1BackProjectionImageFilter.html\" target=\"_top\"];\n    Output [ label=\"Output (Volume)\"];\n    Output [ shape=Mdiamond ];\n    Input0 -> BackProject;\n    Input1 -> BackProject;\n    BackProject -> Output;\n  }\n```\n\nRTK supports the following back projector implementations :\n\n- [VoxelBasedBackProjection](https://www.openrtk.org/Doxygen/classrtk_1_1BackProjectionImageFilter.html)\n- [FDKBackProjection](https://www.openrtk.org/Doxygen/classrtk_1_1FDKBackProjectionImageFilter.html)\n- [FDKWarpBackProjection](https://www.openrtk.org/Doxygen/classrtk_1_1FDKWarpBackProjectionImageFilter.html)\n- [Joseph](https://www.openrtk.org/Doxygen/classrtk_1_1JosephBackProjectionImageFilter.html)\n- [JosephAttenuated](https://www.openrtk.org/Doxygen/classrtk_1_1JosephBackAttenuatedProjectionImageFilter.html)\n- [Zeng](https://www.openrtk.org/Doxygen/classrtk_1_1ZengBackProjectionImageFilter.html)\n\nCuda based projector:\n- [CudaBackProjection](https://www.openrtk.org/Doxygen/classrtk_1_1CudaBackProjectionImageFilter.html)\n- [CudaFDKBackProjection](https://www.openrtk.org/Doxygen/classrtk_1_1CudaFDKBackProjectionImageFilter.html)\n- [CudaRayCast](https://www.openrtk.org/Doxygen/classrtk_1_1CudaRayCastBackProjectionImageFilter.html)\n- [CudaWarpBackProjection](https://www.openrtk.org/Doxygen/classrtk_1_1CudaWarpBackProjectionImageFilter.html)\n"
  },
  {
    "path": "documentation/docs/README.md",
    "content": "# Contribute documentation improvements\n\nThank you for improving our documentation!\n\nThe sources of the RTK documentation are spread across the RTK source tree in multiple markdown (.md) files.\nEdit existing documentation files, add new examples or documentation files, and open a merge request on the RTK repository.\n\n## Add a new documentation page\nTo add a new page to the documentation, create a new .md file in the RTK source tree.\nWrite plain markdown text or use the [MyST](https://myst-parser.readthedocs.io/en/latest/index.html) syntax to include technical and scientific content.\nAdditional MyST syntax extensions can be enabled by adding them to the `myst_enable_extensions` variable in the sphinx `conf.py` configuration file.\n\nThe new documentation page will appear in the documentation after being referenced in a `toctree` element of an `index.md` file.\nIndex files are markdown files using [TOC tree](https://sphinx-doc-zh.readthedocs.io/en/latest/markup/toctree.html) elements to define the table of content and sections of the documentation.\nAdd a reference to your new page in an existing section by adding the path to your file, relative to the `index.md` file, in an existing TOC tree element.\nYou may also add new `toctree` elements and new `index.md` file as needed.\n\n### Inline images\nImages can be referenced with their URL in markdown, but this can delay their presentation in the page.\nAnother option is to store the images in the [RTK collection](https://data.kitware.com/?#collection/5a7706878d777f0649e04776/folder/5eaeaa2f9014a6d84e47adb3) on data.kitware.com and to push their content file (SHA512) to the RTK source tree.\nSuch images will be automatically downloaded when building the documentation and served as static files when navigating.\nTo add a new image:\n1. Go to the [RTKDocumentationData](https://data.kitware.com/?#collection/5a7706878d777f0649e04776/folder/5eaeaa2f9014a6d84e47adb3) folder on data.kitware.com\n2. Choose a folder or create a new one and click the \"Upload here\" button to drag & drop your images.\n3. Once uploaded, click on the file to open its information page.\n4. Under the \"Files & Links\" section click the information icon (\"Show info\") next to the file name\n5. Download the key file from the SHA-512 section by pressing the key icon\n6. Place this file in the RTK source tree next to the .md file that uses it\n\nThe image can be referenced in markdown, e.g. `![img_2D](SheppLogan-2D.png){w=200px alt=\"Shepp-Logan 2D image\"}`\n\n### Inline code\nCode blocks from external files can also be included in the documentation pages using the [literalinclude](https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-literalinclude) directive.\n~~~\n```{literalinclude} code.py\n```\n~~~\n\n### Add an example\nCreate a new directory in the examples directory to place the example scripts.\nThen add the content link files of the screenshots to presented in the documentation by following the instructions from the \"Inline images\" section above.\nInclude the images and scripts in a `README.md` file describing the example.\nAdd a reference to the README file in the `examples/index.md` to add the new example page to the documentation\n\n### Graphs\n\nITK's pipeline mechanism, described in their [software guide](https://itk.org/ITKSoftwareGuide/html/Book1/ITKSoftwareGuide-Book1ch3.html#x39-420003.5), is described in the documention with [Graphviz](https://graphviz.org), both in the Sphinx doc (e.g. in [Projectors.md](Projectors.md)) and in the Doxygen doc (e.g. in the [ProjectionsReader](https://www.openrtk.org/Doxygen/classrtk_1_1ProjectionsReader.html)).\n\n## Preview changes\n\nTo preview documentation changes, build and serve the documentation locally:\n\n1. Install sphinx and the required packages:\n```bash\ncd RTK/documentation/docs\npip install -r requirements.txt\n```\n2. Configure RTK with the CMake option `RTK_BUILD_SPHINX` turned on\n3. Build the `sphinx_doc` target and open the `index.html` file generated in `RTK-build/sphinx/sphinx_build`\n\nThe documentation is generated in the RTK build tree by first copying the documentation sources. To make sure new files are included in the local documentation builds, check that they belong to the list of files and directories copied by the `copy_sources` target in `documentation/docs/CMakeLists.txt`.\n"
  },
  {
    "path": "documentation/docs/Release.md",
    "content": "\n# How to prepare an RTK release\n\nCheck ITK's instructions and update this wiki page accordingly.\n\n## Prepare release message\n\nBased on previous messages (`git show tags`).\n\n```\ngit log --no-merges $(git describe --tags --abbrev=0)..HEAD --pretty=format:\"%h; %an; %ad: %s\" >release_notes.txt\ngit log --no-merges $(git describe --tags --abbrev=0)..HEAD --pretty=format:\"%an\" | sort -u >contributors.txt\n```\n\n## Prepare repository\n\n* Modify the RTK release number(s) in `CMakeLists.txt`,\n* Modify the RTK release number, the required `itk` package version in `pyproject.toml` and the required `itk-cudacommon` version in `.github/workflows/build-test-package-python-cuda.yml`.\n* Commit these changes and tag the commit. Push and release via GitHub when the Python packages have been compiled and uploaded.\n\n## Backup Doxygen documentation\n\n```\nctest -S /home/srit/src/rtk/rtk-dashboard/russula_doxygen.cmake -V\ncd /home/srit/src/rtk/RTK-website/\nmv  /home/srit/src/rtk/dashboard_tests/RTK-Doxygen/Doxygen/html Doxygen250\n./sync.sh\n```\n\n## Prepare website\n\nCreate news message in `RTK/news`, update `rtkindex.html` and `RTK/news/lefthand.html` accordingly.\n\nUpdate page `RTK/resources/software.html`.\n\n## Advertise\n\nPost message on the mailing list [`rtk-users@openrtk.org`](mailto:rtk-users@openrtk.org).\n\n## Verify binaries\n\nBinaries will now be posted by GitHub actions when tagging the repository, simply verify that the Github action goes well and that the packages have been posted once it is over.\n"
  },
  {
    "path": "documentation/docs/copy_and_fetch_sphinx_doc_files.cmake",
    "content": "# List of files to be copied to RTK_DOC_OUTPUT_DIR\nlist(APPEND DOCSRCFILES\n      \"conf.py\"\n      \"index.md\"\n      \"GettingStarted.md\"\n      \"INSTALLATION.md\"\n      \"CodeContribution.md\"\n    )\n\n# List of subdirectories to be copied to RTK_DOC_OUTPUT_DIR\nset(DOCSUBDIRS\n      \"examples\"\n      \"applications\"\n      \"documentation\"\n   )\n\n# Append the files in the subdirectories\nforeach(subdir ${DOCSUBDIRS})\n  file(GLOB_RECURSE SUBSUBDIR LIST_DIRECTORIES false RELATIVE \"${RTK_SOURCE_DIR}\" \"${RTK_SOURCE_DIR}/${subdir}/*\")\n  list(APPEND DOCSRCFILES ${SUBSUBDIR})\nendforeach()\n\n# Make the directory and copy the file if they are different\nforeach(file ${DOCSRCFILES})\n  get_filename_component(dir \"${RTK_DOC_OUTPUT_DIR}/${file}\" DIRECTORY)\n  file(MAKE_DIRECTORY ${dir})\n  file(COPY_FILE \"${RTK_SOURCE_DIR}/${file}\" \"${RTK_DOC_OUTPUT_DIR}/${file}\" ONLY_IF_DIFFERENT)\nendforeach()\n\n# Fetch external data from https://data.kitware.com\n# Used by Sphinx conf.py during setup.\n#\nif(POLICY CMP0009)\n    cmake_policy(SET CMP0009 NEW)\nendif()\nset(link_content sha512)\nfile(GLOB_RECURSE content_files\n  \"${RTK_DOC_OUTPUT_DIR}/*${link_content}\")\nforeach(content_file ${content_files})\n  file(RELATIVE_PATH content_file_rel_path ${RTK_DOC_OUTPUT_DIR} ${content_file})\n  get_filename_component(last_ext \"${content_file_rel_path}\" LAST_EXT)\n  string(REPLACE \"${last_ext}\" \"\" content_file_rel_path \"${content_file_rel_path}\")\n\n  if(NOT EXISTS \"${RTK_DOC_OUTPUT_DIR}/${content_file_rel_path}\" OR\n     NOT \"${RTK_DOC_OUTPUT_DIR}/${content_file_rel_path}\" IS_NEWER_THAN \"${content_file}\")\n    file(READ \"${content_file}\" hash)\n    set(URL \"https://data.kitware.com:443/api/v1/file/hashsum/${link_content}/${hash}/download\")\n    string(REGEX REPLACE \"\\n\" \"\" URL \"${URL}\")\n    file(DOWNLOAD \"${URL}\" \"${RTK_DOC_OUTPUT_DIR}/${content_file_rel_path}\")\n  endif()\n  list(APPEND DOCSRCFILES \"${content_file_rel_path}\")\nendforeach()\n\n# Clean-up: remove all files which are not in the input files or in the _build and documentation/docs/ExternalData/ subfolders\nfile(GLOB_RECURSE filesInOutput LIST_DIRECTORIES false RELATIVE \"${RTK_DOC_OUTPUT_DIR}\" \"${RTK_DOC_OUTPUT_DIR}/*\")\nlist(REMOVE_ITEM filesInOutput ${DOCSRCFILES})\nfile(GLOB_RECURSE filesInOutputBuild LIST_DIRECTORIES false RELATIVE \"${RTK_DOC_OUTPUT_DIR}\" \"${RTK_DOC_OUTPUT_DIR}/_build/*\")\nlist(REMOVE_ITEM filesInOutput ${filesInOutputBuild})\nforeach(file ${filesInOutput})\n  file(REMOVE \"${RTK_DOC_OUTPUT_DIR}/${file}\")\nendforeach()\n"
  },
  {
    "path": "documentation/docs/requirements.txt",
    "content": "cmake\nfuro\nmyst-parser[linkify]\nsphinx>=7.2.6\nsphinx-copybutton\nsphinx-design\n"
  },
  {
    "path": "documentation/docs/rtk_3_migration_guide.md",
    "content": "# RTK v3 migration guide\n\n## Use `--size` instead of `--dimension`\n\nAs of RTK 3.0, the `--dimension` argument in applications is deprecated and\nwill be removed in a future release.  Please use the `--size` argument instead.\nThis update aligns RTK with upstream ITK's member name, where `--size` more\naccurately reflects the expected parameter (e.g., image size) and avoids\nconfusion with spatial dimensions (e.g., 2D vs 3D).\n\n## Forbild phantom file format only\n\nThe legacy `rtk::GeometricPhantomFileReader` has been removed starting with RTK\n3.0. This handcrafted file format was not documented and everything it could do\nis also achievable with the only file format for geometric phantoms accepted in\nRTK 3.0, the [Forbild phantom file format](Phantom.md). The flag `--forbild`\nhas also been removed from command line tools as it is now the default and only\noption.\n\n## Remove config option from c++ applications\n\nThe `--config` command-line option has been removed from all RTK ggo-based\napplications as it was not known to be used in practice.\n\n## Default branch renamed from master to main\n\nThe InsightSoftwareConsortium has decided to rename its default branches from `master` to `main` (https://github.com/InsightSoftwareConsortium/ITK/issues/4732) following [GitHub's move](https://github.com/github/renaming). RTK's default branch has been renamed from `master` to `main` too. Here is what to do:\n\n- GitHub forks: see [Matt McCormick's post](https://discourse.itk.org/t/itk-git-repository-primary-branch-name-transition-from-master-to-main/7569) to change your fork's default repository.\n- Your local clones should be updated as suggested by GitHub (if `origin` is the name of https://github.com/RTKConsortium/RTK.git):\n\n```\ngit branch -m master main\ngit fetch origin\ngit branch -u origin/main main\ngit remote set-head origin -a\n```\n"
  },
  {
    "path": "examples/AddNoise/AddNoise.cxx",
    "content": "#include <itkImageFileWriter.h>\n#include <itkMultiplyImageFilter.h>\n#include <itkExpImageFilter.h>\n#include <itkShotNoiseImageFilter.h>\n#include <itkThresholdImageFilter.h>\n#include <itkLogImageFilter.h>\n\n#include <rtkConstantImageSource.h>\n#include <rtkSheppLoganPhantomFilter.h>\n\nusing ImageType = itk::Image<float, 3>;\n\n// Constant parameters\nconst float I0 = 1e4;     // Number of photons before attenuation\nconst float mu = 0.01879; // mm^-1, attenuation coefficient of water at 75 keV\n\nint\nmain()\n{\n  // Simulate a Shepp Logan projection\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  geometry->AddProjection(1000., 0., 0.);\n\n  auto source = rtk::ConstantImageSource<ImageType>::New();\n  source->SetSize(itk::MakeSize(64, 64, 1));\n  source->SetSpacing(itk::MakeVector(2., 2., 2.));\n  source->SetOrigin(itk::MakePoint(-63., -63., 0.));\n\n  auto shepp = rtk::SheppLoganPhantomFilter<ImageType, ImageType>::New();\n  shepp->SetInput(source->GetOutput());\n  shepp->SetGeometry(geometry);\n  shepp->SetPhantomScale(70.);\n\n  // Use ITK to add pre-log Poisson noise\n  auto multiply = itk::MultiplyImageFilter<ImageType>::New();\n  multiply->SetInput(shepp->GetOutput());\n  multiply->SetConstant(-mu);\n\n  auto exp = itk::ExpImageFilter<ImageType, ImageType>::New();\n  exp->SetInput(multiply->GetOutput());\n\n  auto multiply2 = itk::MultiplyImageFilter<ImageType>::New();\n  multiply2->SetInput(exp->GetOutput());\n  multiply2->SetConstant(I0);\n\n  auto poisson = itk::ShotNoiseImageFilter<ImageType>::New();\n  poisson->SetInput(multiply2->GetOutput());\n\n  auto threshold = itk::ThresholdImageFilter<ImageType>::New();\n  threshold->SetInput(poisson->GetOutput());\n  threshold->SetLower(1.);\n  threshold->SetOutsideValue(1.);\n\n  auto multiply3 = itk::MultiplyImageFilter<ImageType>::New();\n  multiply3->SetInput(threshold->GetOutput());\n  multiply3->SetConstant(1. / I0);\n\n  auto log = itk::LogImageFilter<ImageType, ImageType>::New();\n  log->SetInput(multiply3->GetOutput());\n\n  auto multiply4 = itk::MultiplyImageFilter<ImageType>::New();\n  multiply4->SetInput(log->GetOutput());\n  multiply4->SetConstant(-1. / mu);\n\n  itk::WriteImage(multiply4->GetOutput(), \"projection.mha\");\n\n  return 0;\n}\n"
  },
  {
    "path": "examples/AddNoise/AddNoise.py",
    "content": "import itk\nfrom itk import RTK as rtk\n\n# Constant values of the script\nI0 = 1e4  # Number of photons before attenuation\nmu = 0.01879  # mm^-1 (attenuation coefficient of water at 75 keV)\n\n# Simulate a Shepp Logan projection\nImageType = itk.Image[itk.F, 3]\ngeometry = rtk.ThreeDCircularProjectionGeometry.New()\ngeometry.AddProjection(1000.0, 0.0, 0)\nprojection = rtk.constant_image_source(\n    size=[64, 64, 1], spacing=[2.0] * 3, ttype=[ImageType], origin=[-63.0, -63.0, 0]\n)\nprojection = rtk.shepp_logan_phantom_filter(\n    projection, geometry=geometry, phantom_scale=70\n)\nitk.imwrite(projection, \"projection.mha\")\n\n# Use ITK to add pre-log Poisson noise\nnoisy_projection = itk.multiply_image_filter(projection, constant=-mu)\nnoisy_projection = itk.exp_image_filter(noisy_projection)\nnoisy_projection = itk.multiply_image_filter(noisy_projection, constant=I0)\nnoisy_projection = itk.shot_noise_image_filter(noisy_projection)\nnoisy_projection = itk.threshold_image_filter(\n    noisy_projection, lower=1.0, outside_value=1.0\n)\nnoisy_projection = itk.multiply_image_filter(noisy_projection, constant=1.0 / I0)\nnoisy_projection = itk.log_image_filter(noisy_projection)\nnoisy_projection = itk.multiply_image_filter(noisy_projection, constant=-1.0 / mu)\nitk.imwrite(noisy_projection, \"noisy_projection.mha\")\n\n# Alternative NumPy implementation\n# projection = rtk.constant_image_source(size=[64,64,1],spacing=[2.]*3, ttype=[ImageType], origin=[-63.,-63.,0])\n# projection = rtk.shepp_logan_phantom_filter(projection, geometry=geometry, phantom_scale=70)\n# import numpy as np\n# proj_array = itk.array_view_from_image(projection)\n# proj_array = I0*np.exp(-1.*mu*proj_array)\n# proj_array = np.maximum(np.random.poisson(proj_array), 1)\n# proj_array = np.log(I0/proj_array)/mu\n# projection_noisy = itk.image_view_from_array(proj_array)\n# projection_noisy.CopyInformation(projection)\n# itk.imwrite(projection_noisy, 'projection.mha')\n\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(14, 4))\nplt.subplot(131)\nplt.title(\"Noiseless projection\")\nplt.imshow(\n    itk.array_view_from_image(projection)[0, :, :],\n    cmap=plt.cm.gray,\n    origin=\"lower\",\n    clim=[0, 140],\n)\nplt.xlabel(\"u pixel index\")\nplt.ylabel(\"v pixel index\")\nplt.subplot(132)\nplt.title(\"Noisy projection\")\nplt.imshow(\n    itk.array_view_from_image(noisy_projection)[0, :, :],\n    cmap=plt.cm.gray,\n    origin=\"lower\",\n    clim=[0, 140],\n)\nplt.xlabel(\"u pixel index\")\nplt.subplot(133)\nplt.title(\"Central vertical profile\")\nplt.plot(itk.array_view_from_image(projection)[0, :, 32], label=\"Noiseless\")\nplt.plot(itk.array_view_from_image(noisy_projection)[0, :, 32], label=\"Noisy\")\nplt.xlabel(\"v pixel index\")\nplt.ylabel(\"Pixel intensity\")\nplt.legend()\nplt.savefig(\"AddNoise.png\", bbox_inches=\"tight\")\n"
  },
  {
    "path": "examples/AddNoise/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.9.5 FATAL_ERROR)\n\n# This project is designed to be built outside the RTK source tree.\nproject(AddNoise)\n\n# Find ITK with RTK\nfind_package(ITK REQUIRED COMPONENTS RTK)\ninclude(${ITK_USE_FILE})\n\n# Executable(s)\nadd_executable(AddNoise AddNoise.cxx)\ntarget_link_libraries(AddNoise ${ITK_LIBRARIES})\n"
  },
  {
    "path": "examples/AddNoise/README.md",
    "content": "# Add Poisson noise\n\nAddNoise illustrates how one can add pre-log Poisson noise to RTK-simulated projections. This simulation has been used in previous articles, e.g.[\\[Rit et al, Med Phys, 2016\\]](https://doi.org/10.1118/1.4945418) and described as *The same simulations were repeated with Poisson noise. The Shepp Logan densities were weighted by 0.01879 mm$^{−1}$, i.e., the linear attenuation coefficient of water at 75 keV. The number of photons received per detector pixel without object in the beam was constant (...) and equal to $10^4$.*\n`````{tab-set}\n\n````{tab-item} C++\n\n```{literalinclude} ./AddNoise.cxx\n:language: c++\n```\n````\n\n````{tab-item} Python\n\n```{literalinclude} ./AddNoise.py\n:language: python\n```\n\n````\n`````\nThe plot resulting from the Python version is\n\n![AddNoise](../../documentation/docs/ExternalData/AddNoise.png){w=800px alt=\"Profile\"}\n"
  },
  {
    "path": "examples/ConjugateGradient/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.9.5 FATAL_ERROR)\n\n# This project is designed to be built outside the RTK source tree.\nproject(ConjugateGradient)\n\n# Find ITK with RTK\nfind_package(ITK REQUIRED COMPONENTS RTK)\ninclude(${ITK_USE_FILE})\n\n# Executable(s)\nadd_executable(ConjugateGradient ConjugateGradient.cxx)\ntarget_link_libraries(ConjugateGradient ${ITK_LIBRARIES})\n"
  },
  {
    "path": "examples/ConjugateGradient/ConjugateGradient.cxx",
    "content": "#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkConjugateGradientConeBeamReconstructionFilter.h\"\n#include \"rtkIterationCommands.h\"\n#include \"rtkProjectGeometricPhantomImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include <itkCudaImage.h>\n#endif\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char * argv[])\n{\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef RTK_USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  constexpr unsigned int numberOfProjections = 180;\n  constexpr double       angularArc = 360.;\n  constexpr unsigned int sid = 600;  // source to isocenter distance\n  constexpr unsigned int sdd = 1200; // source to detector distance\n  constexpr double       scale = 2.;\n  std::string            configFileName = \"Thorax\";\n  if (argc > 1 && argv[1] && argv[1][0] != '\\0')\n  {\n    configFileName = argv[1];\n  }\n  constexpr unsigned int niterations = 10;\n\n  itk::Matrix<double, Dimension, Dimension> rotation;\n  rotation[0][0] = 1.;\n  rotation[1][2] = 1.;\n  rotation[2][1] = 1.;\n\n\n  // Set up the geometry for the projections\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int x = 0; x < numberOfProjections; x++)\n  {\n    geometry->AddProjection(sid, sdd, x * angularArc / numberOfProjections);\n  }\n  rtk::WriteGeometry(geometry, \"geometry.xml\");\n\n  // Create a constant image source for the projections\n  auto projectionsSource = rtk::ConstantImageSource<OutputImageType>::New();\n  projectionsSource->SetOrigin(itk::MakePoint(-127., -127., -127.));\n  projectionsSource->SetSpacing(itk::MakeVector(2., 2., 2.));\n  projectionsSource->SetSize(itk::MakeSize(128, 128, numberOfProjections));\n\n  // Project the geometric phantom image\n  auto pgp = rtk::ProjectGeometricPhantomImageFilter<OutputImageType, OutputImageType>::New();\n  pgp->SetInput(projectionsSource->GetOutput());\n  pgp->SetGeometry(geometry);\n  pgp->SetPhantomScale(scale);\n  pgp->SetConfigFile(configFileName);\n  pgp->SetRotationMatrix(rotation);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(pgp->GetOutput(), \"projections.mha\"));\n\n  // Create new empty volume\n  auto conjugateGradientSource = rtk::ConstantImageSource<OutputImageType>::New();\n  conjugateGradientSource->SetOrigin(itk::MakePoint(-127., -127., -127.));\n  conjugateGradientSource->SetSpacing(itk::MakeVector(2., 2., 2.));\n  conjugateGradientSource->SetSize(itk::MakeSize(128, 128, 128));\n\n  // Set the forward and back projection filters to be used\n  using ConjugateGradientFilterType = rtk::ConjugateGradientConeBeamReconstructionFilter<OutputImageType>;\n  auto conjugategradient = ConjugateGradientFilterType::New();\n\n  conjugategradient->SetInputVolume(conjugateGradientSource->GetOutput());\n  conjugategradient->SetInputProjectionStack(pgp->GetOutput());\n  conjugategradient->SetGeometry(geometry);\n  conjugategradient->SetNumberOfIterations(niterations);\n#ifdef RTK_USE_CUDA\n  conjugategradient->SetCudaConjugateGradient(true);\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientFilterType::FP_CUDARAYCAST);\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientFilterType::BP_CUDAVOXELBASED);\n#else\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientFilterType::FP_JOSEPH);\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientFilterType::BP_VOXELBASED);\n#endif\n\n  using VerboseIterationCommandType = rtk::VerboseIterationCommand<ConjugateGradientFilterType>;\n  auto verboseIterationCommand = rtk::VerboseIterationCommand<ConjugateGradientFilterType>::New();\n  conjugategradient->AddObserver(itk::AnyEvent(), verboseIterationCommand);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update())\n\n  // Write\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(conjugategradient->GetOutput(), \"conjugategradient.mha\"));\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "examples/ConjugateGradient/ConjugateGradient.py",
    "content": "import itk\nfrom itk import RTK as rtk\n\nDimension = 3\nOutputPixelType = itk.F\nOutputImageType = itk.Image[OutputPixelType, Dimension]\n\nniterations = 10\nnumberOfProjections = 180\nangularArc = 360.0\nsid = 600\nsdd = 1200\nscale = 2.0\n\n# Using RTK applications python APIs to create the geometry and projections\nrtk.rtksimulatedgeometry(\n    nproj=numberOfProjections,\n    arc=angularArc,\n    sid=sid,\n    sdd=sdd,\n    output=\"geometry.xml\",\n)\nrtk.rtkprojectgeometricphantom(\n    geometry=\"geometry.xml\",\n    output=\"projections.mha\",\n    phantomfile=\"Thorax\",\n    phantomscale=scale,\n    rotation=\"1,0,0,0,0,-1,0,1,0\",\n    spacing=2,\n    size=128,\n)\n\nprojections = itk.imread(\"projections.mha\")\ngeometry = rtk.read_geometry(\"geometry.xml\")\n\n# Create a constant image source to initialize the reconstruction\nconjugate_gradient_source = rtk.constant_image_source(\n    ttype=[OutputImageType],\n    origin=[-127.0, -127.0, -127.0],\n    size=[128, 128, 128],\n    spacing=[2.0] * 3,\n)\n\n# Set the forward and back projection filters to be used\nif hasattr(itk, \"CudaImage\"):\n    OutputCudaImageType = itk.CudaImage[itk.F, Dimension]\n    ConjugateGradientFilterType = rtk.ConjugateGradientConeBeamReconstructionFilter[\n        OutputCudaImageType\n    ]\n    conjugategradient = ConjugateGradientFilterType.New()\n    conjugategradient.SetCudaConjugateGradient(True)\n    conjugategradient.SetInput(itk.cuda_image_from_image(conjugate_gradient_source))\n    conjugategradient.SetInput(1, itk.cuda_image_from_image(projections))\n    conjugategradient.SetBackProjectionFilter(\n        ConjugateGradientFilterType.BackProjectionType_BP_CUDAVOXELBASED\n    )\n    conjugategradient.SetForwardProjectionFilter(\n        ConjugateGradientFilterType.ForwardProjectionType_FP_CUDARAYCAST\n    )\n\nelse:\n    ConjugateGradientFilterType = rtk.ConjugateGradientConeBeamReconstructionFilter[\n        OutputImageType\n    ]\n    conjugategradient = ConjugateGradientFilterType.New()\n    conjugategradient.SetInput(conjugate_gradient_source)\n    conjugategradient.SetInput(1, projections)\n    conjugategradient.SetBackProjectionFilter(\n        ConjugateGradientFilterType.BackProjectionType_BP_VOXELBASED\n    )\n    conjugategradient.SetForwardProjectionFilter(\n        ConjugateGradientFilterType.ForwardProjectionType_FP_JOSEPH\n    )\n\nconjugategradient.SetGeometry(geometry)\nconjugategradient.SetNumberOfIterations(niterations)\n\n\n# Create a command to observe the iterations\nclass VerboseIterationCommand:\n    def __init__(self):\n        self.count = 0\n\n    def callback(self):\n        self.count = self.count + 1\n        print(f\"Iteration {self.count}\", end=\"\\r\")\n\n\nclass VerboseEndCommand:\n    def callback(self):\n        print(\"\")\n\n\ncmd = VerboseIterationCommand()\nconjugategradient.AddObserver(itk.IterationEvent(), cmd.callback)\ncmd = VerboseEndCommand()\nconjugategradient.AddObserver(itk.EndEvent(), cmd.callback)\nconjugategradient.Update()\n\n# Write\nwriter = itk.ImageFileWriter[OutputImageType].New()\nwriter.SetFileName(\"conjugategradient.mha\")\nwriter.SetInput(conjugategradient.GetOutput())\nwriter.Update()\n"
  },
  {
    "path": "examples/ConjugateGradient/README.md",
    "content": "#   Conjugate Gradient\n\nConjugateGradient shows how to perform iterative cone-beam CT reconstruction using either CPU and GPU resources.\nYou can refere to the [projectors documentation](https://docs.openrtk.org/en/latest/documentation/docs/Projectors.html) to see all options available for the back and forwardprojections.\n\nThis example uses the [Thorax](https://raw.githubusercontent.com/RTKConsortium/Forbild/refs/heads/main/Thorax) Forbild phantom, available in the [dedicated GitHub repository](https://github.com/RTKConsortium/Forbild) for Forbild phantom files compatible with RTK.\n\n`````{tab-set}\n\n````{tab-item} C++\n\n```{literalinclude} ./ConjugateGradient.cxx\n:language: c++\n```\n````\n\n````{tab-item} Python\n\n```{literalinclude} ./ConjugateGradient.py\n:language: python\n```\n\n````\n`````\n\nThe results displayed with [rtkshowgeometry](../../applications/rtkshowgeometry/README.md) are:\n\n![visu](../../documentation/docs/ExternalData/Thorax-visualisation.png){alt=\"Visualisation\"}\n"
  },
  {
    "path": "examples/FirstReconstruction/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.9.5 FATAL_ERROR)\n\n# This project is designed to be built outside the RTK source tree.\nproject(FirstReconstruction)\n\n# Find ITK with RTK\nfind_package(ITK REQUIRED COMPONENTS RTK)\ninclude(${ITK_USE_FILE})\n\n# Executable(s)\nadd_executable(FirstReconstruction FirstReconstruction.cxx )\ntarget_link_libraries(FirstReconstruction ${ITK_LIBRARIES})\nif(${RTK_USE_CUDA})\n  add_executable(FirstCudaReconstruction FirstCudaReconstruction.cxx )\n  target_link_libraries(FirstCudaReconstruction ${ITK_LIBRARIES})\nendif()\n"
  },
  {
    "path": "examples/FirstReconstruction/FirstCudaReconstruction.cxx",
    "content": "// RTK includes\n#include <rtkConstantImageSource.h>\n#include <rtkThreeDCircularProjectionGeometryXMLFileWriter.h>\n#include <rtkRayEllipsoidIntersectionImageFilter.h>\n#include <rtkCudaFDKConeBeamReconstructionFilter.h>\n#include <rtkFieldOfViewImageFilter.h>\n\n// ITK includes\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char ** argv)\n{\n  if (argc < 3)\n  {\n    std::cout << \"Usage: FirstReconstruction <outputimage> <outputgeometry>\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Defines the image type\n  using ImageType = itk::CudaImage<float, 3>;\n\n  // Defines the RTK geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  GeometryType::Pointer geometry = GeometryType::New();\n  unsigned int          numberOfProjections = 360;\n  double                firstAngle = 0;\n  double                angularArc = 360;\n  unsigned int          sid = 600;  // source to isocenter distance\n  unsigned int          sdd = 1200; // source to detector distance\n  for (unsigned int noProj = 0; noProj < numberOfProjections; noProj++)\n  {\n    double angle = firstAngle + noProj * angularArc / numberOfProjections;\n    geometry->AddProjection(sid, sdd, angle);\n  }\n\n  // Write the geometry to disk\n  rtk::ThreeDCircularProjectionGeometryXMLFileWriter::Pointer xmlWriter;\n  xmlWriter = rtk::ThreeDCircularProjectionGeometryXMLFileWriter::New();\n  xmlWriter->SetFilename(argv[2]);\n  xmlWriter->SetObject(geometry);\n  xmlWriter->WriteFile();\n\n  // Create a stack of empty projection images\n  using ConstantImageSourceType = rtk::ConstantImageSource<ImageType>;\n  ConstantImageSourceType::Pointer constantImageSource = ConstantImageSourceType::New();\n  constantImageSource->SetOrigin(itk::MakePoint(-127., -127., 0.));\n  constantImageSource->SetSpacing(itk::MakeVector(2., 2., 2.));\n  constantImageSource->SetSize(itk::MakeSize(128, 128, numberOfProjections));\n  constantImageSource->SetConstant(0.);\n\n  // Create projections of an ellipse\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<ImageType, ImageType>;\n  REIType::Pointer rei = REIType::New();\n  rei->SetDensity(2.);\n  rei->SetAngle(0.);\n  rei->SetCenter(itk::MakeVector(0., 0., 10.));\n  rei->SetAxis(itk::MakeVector(50., 50., 50.));\n  rei->SetGeometry(geometry);\n  rei->SetInput(constantImageSource->GetOutput());\n\n  // Create reconstructed image\n  ConstantImageSourceType::Pointer constantImageSource2 = ConstantImageSourceType::New();\n  constantImageSource2->SetOrigin(itk::MakePoint(-63.5, -63.5, -63.5));\n  constantImageSource2->SetSpacing(itk::MakeVector(1., 1., 1.));\n  constantImageSource2->SetSize(itk::MakeSize(128, 128, 128));\n  constantImageSource2->SetConstant(0.);\n\n  // FDK reconstruction\n  std::cout << \"Reconstructing...\" << std::endl;\n  using FDKGPUType = rtk::CudaFDKConeBeamReconstructionFilter;\n  FDKGPUType::Pointer feldkamp = FDKGPUType::New();\n  feldkamp->SetInput(0, constantImageSource2->GetOutput());\n  feldkamp->SetInput(1, rei->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  feldkamp->GetRampFilter()->SetTruncationCorrection(0.);\n  feldkamp->GetRampFilter()->SetHannCutFrequency(0.0);\n\n  // Field-of-view masking\n  using FOVFilterType = rtk::FieldOfViewImageFilter<ImageType, ImageType>;\n  FOVFilterType::Pointer fieldofview = FOVFilterType::New();\n  fieldofview->SetInput(0, feldkamp->GetOutput());\n  fieldofview->SetProjectionsStack(rei->GetOutput());\n  fieldofview->SetGeometry(geometry);\n\n  // Writer\n  std::cout << \"Writing output image...\" << std::endl;\n  using WriterType = itk::ImageFileWriter<ImageType>;\n  WriterType::Pointer writer = WriterType::New();\n  writer->SetFileName(argv[1]);\n  writer->SetInput(fieldofview->GetOutput());\n  writer->Update();\n\n  std::cout << \"Done!\" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "examples/FirstReconstruction/FirstCudaReconstruction.py",
    "content": "#!/usr/bin/env python\nimport os\nimport sys\nimport itk\nfrom itk import RTK as rtk\n\nif len(sys.argv) < 3:\n    print(\"Usage: FirstReconstruction <outputimage> <outputgeometry>\")\n    sys.exit(1)\n\n# Import Windows CUDA_PATH for dll (required for some Python versions,\n# https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew)\nif sys.platform == \"win32\":\n    os.add_dll_directory(os.path.join(os.environ[\"CUDA_PATH\"], \"bin\"))\n\n# Defines the image type\nGPUImageType = rtk.CudaImage[itk.F, 3]\nCPUImageType = rtk.Image[itk.F, 3]\n\n# Defines the RTK geometry object\ngeometry = rtk.ThreeDCircularProjectionGeometry.New()\nnumberOfProjections = 360\nfirstAngle = 0.0\nangularArc = 360.0\nsid = 600  # source to isocenter distance\nsdd = 1200  # source to detector distance\nfor x in range(0, numberOfProjections):\n    angle = firstAngle + x * angularArc / numberOfProjections\n    geometry.AddProjection(sid, sdd, angle)\n\n# Writing the geometry to disk\nrtk.write_geometry(geometry, sys.argv[2])\n\n# Create a stack of empty projection images\nConstantImageSourceType = rtk.ConstantImageSource[GPUImageType]\nconstantImageSource = ConstantImageSourceType.New()\norigin = [-127, -127, 0.0]\nsizeOutput = [128, 128, numberOfProjections]\nspacing = [2.0, 2.0, 2.0]\nconstantImageSource.SetOrigin(origin)\nconstantImageSource.SetSpacing(spacing)\nconstantImageSource.SetSize(sizeOutput)\nconstantImageSource.SetConstant(0.0)\n\nREIType = rtk.RayEllipsoidIntersectionImageFilter[CPUImageType, CPUImageType]\nrei = REIType.New()\nsemiprincipalaxis = [50, 50, 50]\ncenter = [0, 0, 10]\n# Set GrayScale value, axes, center...\nrei.SetDensity(2)\nrei.SetAngle(0)\nrei.SetCenter(center)\nrei.SetAxis(semiprincipalaxis)\nrei.SetGeometry(geometry)\nrei.SetInput(constantImageSource.GetOutput())\n\n# Create reconstructed image\nconstantImageSource2 = ConstantImageSourceType.New()\nsizeOutput = [128, 128, 128]\norigin = [-63.5, -63.5, -63.5]\nspacing = [1.0, 1.0, 1.0]\nconstantImageSource2.SetOrigin(origin)\nconstantImageSource2.SetSpacing(spacing)\nconstantImageSource2.SetSize(sizeOutput)\nconstantImageSource2.SetConstant(0.0)\n\n# Graft the projections to an itk::CudaImage\nprojections = GPUImageType.New()\nrei.Update()\nprojections.SetPixelContainer(rei.GetOutput().GetPixelContainer())\nprojections.CopyInformation(rei.GetOutput())\nprojections.SetBufferedRegion(rei.GetOutput().GetBufferedRegion())\nprojections.SetRequestedRegion(rei.GetOutput().GetRequestedRegion())\n\n# FDK reconstruction\nprint(\"Reconstructing...\")\nFDKGPUType = rtk.CudaFDKConeBeamReconstructionFilter\nfeldkamp = FDKGPUType.New()\nfeldkamp.SetInput(0, constantImageSource2.GetOutput())\nfeldkamp.SetInput(1, projections)\nfeldkamp.SetGeometry(geometry)\nfeldkamp.GetRampFilter().SetTruncationCorrection(0.0)\nfeldkamp.GetRampFilter().SetHannCutFrequency(0.0)\n\n# Field-of-view masking\nFOVFilterType = rtk.FieldOfViewImageFilter[CPUImageType, CPUImageType]\nfieldofview = FOVFilterType.New()\nfieldofview.SetInput(0, feldkamp.GetOutput())\nfieldofview.SetProjectionsStack(rei.GetOutput())\nfieldofview.SetGeometry(geometry)\n\n# Writer\nprint(\"Writing output image...\")\nWriterType = rtk.ImageFileWriter[CPUImageType]\nwriter = WriterType.New()\nwriter.SetFileName(sys.argv[1])\nwriter.SetInput(fieldofview.GetOutput())\nwriter.Update()\n\nprint(\"Done!\")\n"
  },
  {
    "path": "examples/FirstReconstruction/FirstReconstruction.cxx",
    "content": "// RTK includes\n#include <rtkConstantImageSource.h>\n#include <rtkThreeDCircularProjectionGeometryXMLFileWriter.h>\n#include <rtkRayEllipsoidIntersectionImageFilter.h>\n#include <rtkFDKConeBeamReconstructionFilter.h>\n#include <rtkFieldOfViewImageFilter.h>\n\n// ITK includes\n#include <itkImageFileWriter.h>\n\nint\nmain(int argc, char ** argv)\n{\n  if (argc < 3)\n  {\n    std::cout << \"Usage: FirstReconstruction <outputimage> <outputgeometry>\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Defines the image type\n  using ImageType = itk::Image<float, 3>;\n\n  // Defines the RTK geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  GeometryType::Pointer geometry = GeometryType::New();\n  unsigned int          numberOfProjections = 360;\n  double                firstAngle = 0;\n  double                angularArc = 360;\n  unsigned int          sid = 600;  // source to isocenter distance\n  unsigned int          sdd = 1200; // source to detector distance\n  for (unsigned int noProj = 0; noProj < numberOfProjections; noProj++)\n  {\n    double angle = firstAngle + noProj * angularArc / numberOfProjections;\n    geometry->AddProjection(sid, sdd, angle);\n  }\n\n  // Write the geometry to disk\n  rtk::ThreeDCircularProjectionGeometryXMLFileWriter::Pointer xmlWriter;\n  xmlWriter = rtk::ThreeDCircularProjectionGeometryXMLFileWriter::New();\n  xmlWriter->SetFilename(argv[2]);\n  xmlWriter->SetObject(geometry);\n  xmlWriter->WriteFile();\n\n  // Create a stack of empty projection images\n  using ConstantImageSourceType = rtk::ConstantImageSource<ImageType>;\n  ConstantImageSourceType::Pointer constantImageSource = ConstantImageSourceType::New();\n  constantImageSource->SetOrigin(itk::MakePoint(-127., -127., 0.));\n  constantImageSource->SetSpacing(itk::MakeVector(2., 2., 2.));\n  constantImageSource->SetSize(itk::MakeSize(128, 128, numberOfProjections));\n\n  // Create projections of an ellipse\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<ImageType, ImageType>;\n  REIType::Pointer rei = REIType::New();\n  rei->SetDensity(2.);\n  rei->SetAngle(0.);\n  rei->SetCenter(itk::MakeVector(0., 0., 10.));\n  rei->SetAxis(itk::MakeVector(50., 50., 50.));\n  rei->SetGeometry(geometry);\n  rei->SetInput(constantImageSource->GetOutput());\n\n  // Create reconstructed image\n  ConstantImageSourceType::Pointer constantImageSource2 = ConstantImageSourceType::New();\n  constantImageSource2->SetOrigin(itk::MakePoint(-63.5, -63.5, -63.5));\n  constantImageSource2->SetSpacing(itk::MakeVector(1., 1., 1.));\n  constantImageSource2->SetSize(itk::MakeSize(128, 128, 128));\n  constantImageSource2->SetConstant(0.);\n\n  // FDK reconstruction\n  std::cout << \"Reconstructing...\" << std::endl;\n  using FDKCPUType = rtk::FDKConeBeamReconstructionFilter<ImageType>;\n  FDKCPUType::Pointer feldkamp = FDKCPUType::New();\n  feldkamp->SetInput(0, constantImageSource2->GetOutput());\n  feldkamp->SetInput(1, rei->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  feldkamp->GetRampFilter()->SetTruncationCorrection(0.);\n  feldkamp->GetRampFilter()->SetHannCutFrequency(0.0);\n\n  // Field-of-view masking\n  using FOVFilterType = rtk::FieldOfViewImageFilter<ImageType, ImageType>;\n  FOVFilterType::Pointer fieldofview = FOVFilterType::New();\n  fieldofview->SetInput(0, feldkamp->GetOutput());\n  fieldofview->SetProjectionsStack(rei->GetOutput());\n  fieldofview->SetGeometry(geometry);\n\n  // Writer\n  std::cout << \"Writing output image...\" << std::endl;\n  using WriterType = itk::ImageFileWriter<ImageType>;\n  WriterType::Pointer writer = WriterType::New();\n  writer->SetFileName(argv[1]);\n  writer->SetInput(fieldofview->GetOutput());\n  writer->Update();\n\n  std::cout << \"Done!\" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "examples/FirstReconstruction/FirstReconstruction.py",
    "content": "#!/usr/bin/env python\nimport sys\nimport itk\nfrom itk import RTK as rtk\n\nif len(sys.argv) < 3:\n    print(\"Usage: FirstReconstruction <outputimage> <outputgeometry>\")\n    sys.exit(1)\n\n# Defines the image type\nImageType = itk.Image[itk.F, 3]\n\n# Defines the RTK geometry object\ngeometry = rtk.ThreeDCircularProjectionGeometry.New()\nnumberOfProjections = 360\nfirstAngle = 0.0\nangularArc = 360.0\nsid = 600  # source to isocenter distance\nsdd = 1200  # source to detector distance\nfor x in range(0, numberOfProjections):\n    angle = firstAngle + x * angularArc / numberOfProjections\n    geometry.AddProjection(sid, sdd, angle)\n\n# Writing the geometry to disk\nrtk.write_geometry(geometry, sys.argv[2])\n\n# Create a stack of empty projection images\nConstantImageSourceType = rtk.ConstantImageSource[ImageType]\nconstantImageSource = ConstantImageSourceType.New()\norigin = [-127, -127, 0.0]\nsizeOutput = [128, 128, numberOfProjections]\nspacing = [2.0, 2.0, 2.0]\nconstantImageSource.SetOrigin(origin)\nconstantImageSource.SetSpacing(spacing)\nconstantImageSource.SetSize(sizeOutput)\nconstantImageSource.SetConstant(0.0)\n\nREIType = rtk.RayEllipsoidIntersectionImageFilter[ImageType, ImageType]\nrei = REIType.New()\nsemiprincipalaxis = [50, 50, 50]\ncenter = [0, 0, 10]\n# Set GrayScale value, axes, center...\nrei.SetDensity(2)\nrei.SetAngle(0)\nrei.SetCenter(center)\nrei.SetAxis(semiprincipalaxis)\nrei.SetGeometry(geometry)\nrei.SetInput(constantImageSource.GetOutput())\n\n# Create reconstructed image\nconstantImageSource2 = ConstantImageSourceType.New()\nsizeOutput = [128, 128, 128]\norigin = [-63.5, -63.5, -63.5]\nspacing = [1.0, 1.0, 1.0]\nconstantImageSource2.SetOrigin(origin)\nconstantImageSource2.SetSpacing(spacing)\nconstantImageSource2.SetSize(sizeOutput)\nconstantImageSource2.SetConstant(0.0)\n\n# FDK reconstruction\nprint(\"Reconstructing...\")\nFDKCPUType = rtk.FDKConeBeamReconstructionFilter[ImageType]\nfeldkamp = FDKCPUType.New()\nfeldkamp.SetInput(0, constantImageSource2.GetOutput())\nfeldkamp.SetInput(1, rei.GetOutput())\nfeldkamp.SetGeometry(geometry)\nfeldkamp.GetRampFilter().SetTruncationCorrection(0.0)\nfeldkamp.GetRampFilter().SetHannCutFrequency(0.0)\n\n# Field-of-view masking\nFOVFilterType = rtk.FieldOfViewImageFilter[ImageType, ImageType]\nfieldofview = FOVFilterType.New()\nfieldofview.SetInput(0, feldkamp.GetOutput())\nfieldofview.SetProjectionsStack(rei.GetOutput())\nfieldofview.SetGeometry(geometry)\n\n# Writer\nprint(\"Writing output image...\")\nWriterType = rtk.ImageFileWriter[ImageType]\nwriter = WriterType.New()\nwriter.SetFileName(sys.argv[1])\nwriter.SetInput(fieldofview.GetOutput())\nwriter.Update()\n\nprint(\"Done!\")\n"
  },
  {
    "path": "examples/FirstReconstruction/README.md",
    "content": "# First reconstruction\n\nRTK is a library, therefore it's meant to be integrated into application. This tutorial shows how to create a simple FirstReconstruction project that links with RTK. The source code for this tutorial is located in [RTK/examples/FirstReconstruction](https://github.com/RTKConsortium/RTK/blob/master/examples/FirstReconstruction).\n\n\n`````{tab-set}\n\n````{tab-item} C++\n\n## CMakeLists\n\n*   First you need to create a [CMakeLists.txt](https://github.com/RTKConsortium/RTK/blob/master/examples/FirstReconstruction/CMakeLists.txt)\n\n```{literalinclude} ./CMakeLists.txt\n:language: cmake\n```\n\n*   Run CMake on the FirstReconstruction directory and create a FirstReconstruction-bin,\n*   Configure and build the project using your favorite compiler,\n*   Run `FirstReconstruction image.mha geometry.xml`. If everything runs correctly, you should see a few messages ending with `Done!` and two new files in the current directory, image.mha and geometry.xml. image.mha is the reconstruction of a sphere from 360 projections and geometry.xml is the geometry file in [RTK's geometry format](../../documentation/docs/Geometry.md).\n\n## Code\n\n```{literalinclude} ./FirstReconstruction.cxx\n:language: c++\n```\n````\n\n````{tab-item} C++ Cuda\n\n## CMakeLists\n\n*   First you need to create a [CMakeLists.txt](https://github.com/RTKConsortium/RTK/blob/master/examples/FirstReconstruction/CMakeLists.txt)\n\n```{literalinclude} ./CMakeLists.txt\n:language: cmake\n```\n\n*   Run CMake on the FirstReconstruction directory and create a FirstReconstruction-bin,\n*   Configure and build the project using your favorite compiler,\n*   Run `FirstReconstruction image.mha geometry.xml`. If everything runs correctly, you should see a few messages ending with `Done!` and two new files in the current directory, image.mha and geometry.xml. image.mha is the reconstruction of a sphere from 360 projections and geometry.xml is the geometry file in [RTK's geometry format](../../documentation/docs/Geometry.md).\n\n## Code\n\n```{literalinclude} ./FirstCudaReconstruction.cxx\n:language: c++\n```\n\n````\n\n````{tab-item} Python\n\n## Code\n\n```{literalinclude} ./FirstReconstruction.py\n:language: python\n```\n\n````\n\n````{tab-item} Python Cuda\n\n## Code\n\n```{literalinclude} ./FirstCudaReconstruction.py\n:language: python\n```\n````\n`````"
  },
  {
    "path": "examples/GeometricPhantom/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.9.5 FATAL_ERROR)\n\n# This project is designed to be built outside the RTK source tree.\nproject(GeometricPhantom)\n\n# Find ITK with RTK\nfind_package(ITK REQUIRED COMPONENTS RTK)\ninclude(${ITK_USE_FILE})\n\n# Executable(s)\nadd_executable(GeometricPhantom GeometricPhantom.cxx )\ntarget_link_libraries(GeometricPhantom ${ITK_LIBRARIES})\n"
  },
  {
    "path": "examples/GeometricPhantom/GeometricPhantom.cxx",
    "content": "#include \"rtkDrawGeometricPhantomImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkProjectGeometricPhantomImageFilter.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFileWriter.h\"\n\nint\nmain(int argc, char ** argv)\n{\n  if (argc < 2)\n  {\n    std::cout << \"Usage: GeometricPhantom <phantomfile>\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n\n  constexpr unsigned int numberOfProjections = 180;\n  constexpr double       angularArc = 360.;\n  constexpr unsigned int sid = 600;  // source to isocenter distance\n  constexpr unsigned int sdd = 1200; // source to detector distance\n  constexpr double       scale = 2.;\n\n  itk::Matrix<double, Dimension, Dimension> rotation;\n  rotation[0][0] = 1.;\n  rotation[1][2] = 1.;\n  rotation[2][1] = 1.;\n\n  // Set up the geometry for the projections\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int x = 0; x < numberOfProjections; x++)\n  {\n    geometry->AddProjection(sid, sdd, x * angularArc / numberOfProjections);\n  }\n  rtk::WriteGeometry(geometry, \"geometry.xml\");\n\n  // Create a constant image source for the tomography\n  auto tomographySource = rtk::ConstantImageSource<OutputImageType>::New();\n  tomographySource->SetOrigin(itk::MakePoint(-63.5, -63.5, -63.5));\n  tomographySource->SetSize(itk::MakeSize(128, 128, 128));\n\n  // Create a constant image source for the projections\n  auto projectionsSource = rtk::ConstantImageSource<OutputImageType>::New();\n  projectionsSource->SetOrigin(itk::MakePoint(-127., -127., -127.));\n  projectionsSource->SetSpacing(itk::MakeVector(2., 2., 2.));\n  projectionsSource->SetSize(itk::MakeSize(128, 128, numberOfProjections));\n\n  // Project the geometric phantom image\n  auto pgp = rtk::ProjectGeometricPhantomImageFilter<OutputImageType, OutputImageType>::New();\n  pgp->SetInput(projectionsSource->GetOutput());\n  pgp->SetGeometry(geometry);\n  pgp->SetPhantomScale(scale);\n  pgp->SetRotationMatrix(rotation);\n  pgp->SetConfigFile(argv[1]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(pgp->GetOutput(), \"projections.mha\"));\n\n  // Draw the geometric phantom image\n  auto dgp = rtk::DrawGeometricPhantomImageFilter<OutputImageType, OutputImageType>::New();\n  dgp->SetInput(tomographySource->GetOutput());\n  dgp->SetPhantomScale(scale);\n  dgp->SetRotationMatrix(rotation);\n  dgp->SetConfigFile(argv[1]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(dgp->GetOutput(), \"ref.mha\"));\n\n  // Perform FDK reconstruction filtering\n  auto feldkamp = rtk::FDKConeBeamReconstructionFilter<OutputImageType>::New();\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, pgp->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(itk::WriteImage(feldkamp->GetOutput(), \"fdk.mha\"));\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "examples/GeometricPhantom/GeometricPhantom.py",
    "content": "import itk\nfrom itk import RTK as rtk\n\nDimension = 3\nOutputPixelType = itk.F\nOutputImageType = itk.Image[OutputPixelType, Dimension]\n\nnumberOfProjections = 180\nangularArc = 360.0\nsid = 600\nsdd = 1200\nscale = 2.0\nconfig_file_name = \"Thorax\"\nrotation = itk.matrix_from_array([[1.0, 0.0, 0.0], [0.0, 0.0, -1.0], [0.0, 1.0, 0.0]])\n\n# Set up the geometry for the projections\ngeometry = rtk.ThreeDCircularProjectionGeometry.New()\nfor x in range(0, numberOfProjections):\n    angle = x * angularArc / numberOfProjections\n    geometry.AddProjection(sid, sdd, angle)\nrtk.write_geometry(geometry, \"geometry.xml\")\n\n# Project the geometric phantom image\nprojections_source = rtk.constant_image_source(\n    ttype=[OutputImageType],\n    origin=[-127.0, -127.0, 0.0],\n    size=[128, 128, numberOfProjections],\n    spacing=[2.0] * 3,\n)\npgp = rtk.project_geometric_phantom_image_filter(\n    projections_source,\n    geometry=geometry,\n    phantom_scale=scale,\n    rotation_matrix=rotation,\n    config_file=config_file_name,\n)\nitk.imwrite(pgp, \"projections.mha\")\n\n# Draw the geometric phantom image\nref_source = rtk.constant_image_source(\n    ttype=[OutputImageType], origin=[-63.5] * 3, size=[128] * 3\n)\ndgp = rtk.draw_geometric_phantom_image_filter(\n    ref_source,\n    phantom_scale=scale,\n    rotation_matrix=rotation,\n    config_file=config_file_name,\n)\nitk.imwrite(dgp, \"ref.mha\")\n\n# Perform FDK reconstruction filtering\nfdk_source = rtk.constant_image_source(\n    ttype=[OutputImageType],\n    origin=[-63.5] * 3,\n    size=[128] * 3,\n    spacing=[1.0] * 3,\n    constant=0.0,\n)\nfeldkamp = rtk.fdk_cone_beam_reconstruction_filter(fdk_source, pgp, geometry=geometry)\nitk.imwrite(feldkamp, \"fdk.mha\")\n"
  },
  {
    "path": "examples/GeometricPhantom/README.md",
    "content": "# Project, draw and reconstruct geometric phantom\n\nGeometricPhantom demonstrates how to create 2D projections of a Forbild phantom, draw a reference 3D image and reconstruct from the projections with [FDK](http://www.openrtk.org/Doxygen/classrtk_1_1FDKConeBeamReconstructionFilter.html). You can find how to create your own phantom file in the [phantom definition page](../../documentation/docs/Phantom.md).\n\nThis example uses the [Thorax](https://raw.githubusercontent.com/RTKConsortium/Forbild/refs/heads/main/Thorax) Forbild phantom, available in the [dedicated GitHub repository](https://github.com/RTKConsortium/Forbild) for Forbild phantom files compatible with RTK.\n\n`````{tab-set}\n\n````{tab-item} C++\n\n```{literalinclude} ./GeometricPhantom.cxx\n:language: c++\n```\n````\n\n````{tab-item} Python\n\n```{literalinclude} ./GeometricPhantom.py\n:language: python\n```\n\n````\n`````\n\nThe results displayed with [rtkshowgeometry](../../applications/rtkshowgeometry/README.md) are:\n\n![visu](../../documentation/docs/ExternalData/Thorax-visualisation.png){alt=\"Visualisation\"}\n"
  },
  {
    "path": "examples/InlineReconstruction/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.9.5 FATAL_ERROR)\n\n# This project is designed to be built outside the RTK source tree.\nproject(InlineReconstruction)\n\n# Find ITK with RTK\nfind_package(ITK REQUIRED COMPONENTS RTK)\ninclude(${ITK_USE_FILE})\n\n# Executable(s)\nadd_executable(InlineReconstruction InlineReconstruction.cxx)\ntarget_link_libraries(AddNoise ${ITK_LIBRARIES})\n"
  },
  {
    "path": "examples/InlineReconstruction/InlineReconstruction.cxx",
    "content": "#include <iostream>\n#include <thread>\n#include <chrono>\n#include <vector>\n#include <iomanip>\n#include <sstream>\n#include <atomic>\n\n#include <itkImageFileWriter.h>\n#include <itkExtractImageFilter.h>\n\n#include <rtkFDKConeBeamReconstructionFilter.h>\n#include <rtkParkerShortScanImageFilter.h>\n#include <rtkProjectionsReader.h>\n#include <rtkSheppLoganPhantomFilter.h>\n#include <rtkConstantImageSource.h>\n\n// CUDA headers (if available)\n#ifdef RTK_USE_CUDA\n#  include <rtkCudaFDKConeBeamReconstructionFilter.h>\n#  include <rtkCudaParkerShortScanImageFilter.h>\n#  include <itkCudaImage.h>\n#endif\n\n// Type definitions\nusing ImageType = itk::Image<float, 3>;\n\n// Constants for acquisition and reconstruction\nconst int                       numProjections = 64;\nconst double                    sid = 1000.0;\nconst double                    sdd = 1500.0;\nconst double                    arc = 200.0;\nconst double                    spacing = 1.0;\nconst int                       imageSize = 256;\nconst double                    origin = -0.5 * (imageSize - 1);\nconst std::chrono::milliseconds acquisitionSleepDuration(100);\n\nstd::atomic<int> AcquiredProjectionsCount(0);\n\n// Function for the thread simulating an acquisition\n// Simulates and writes a projection every 100 ms.\nvoid\nAcquisition()\n{\n  for (int i = 0; i < numProjections; ++i)\n  {\n    // Create geometry for the acquisition\n    auto geometryAcq = rtk::ThreeDCircularProjectionGeometry::New();\n    geometryAcq->AddProjection(sid, sdd, i * arc / numProjections);\n\n    // Create a constant image source for the projection\n    auto projection = rtk::ConstantImageSource<ImageType>::New();\n    projection->SetOrigin(itk::MakePoint(origin, origin, 0.0));\n    projection->SetSize(itk::MakeSize(imageSize, imageSize, 1));\n    projection->SetSpacing(itk::MakeVector(spacing, spacing, spacing));\n    projection->Update();\n\n    // Create Shepp-Logan phantom filter\n    auto phantom = rtk::SheppLoganPhantomFilter<ImageType, ImageType>::New();\n    phantom->SetInput(projection->GetOutput());\n    phantom->SetGeometry(geometryAcq);\n    phantom->SetPhantomScale(100);\n\n    // Create filename for the output projection\n    std::ostringstream filename;\n    filename << \"projection_\" << std::setw(3) << std::setfill('0') << i << \".mha\";\n    phantom->Update();\n\n    // Write the projection image to file\n    itk::WriteImage(phantom->GetOutput(), filename.str());\n    AcquiredProjectionsCount++;\n    std::this_thread::sleep_for(acquisitionSleepDuration);\n  }\n}\n\nint\nmain()\n{\n  // Launch the simulated acquisition\n  std::thread acquisitionThread(Acquisition);\n\n  // Create the geometry for reconstruction\n  auto geometryRec = rtk::ThreeDCircularProjectionGeometry::New();\n  for (int i = 0; i < numProjections; ++i)\n  {\n    geometryRec->AddProjection(sid, sdd, i * arc / numProjections);\n  }\n\n  // Create the reconstruction pipeline\n  auto reader = rtk::ProjectionsReader<ImageType>::New();\n  auto extractor = itk::ExtractImageFilter<ImageType, ImageType>::New();\n  extractor->SetInput(reader->GetOutput());\n\n  double originValue = origin * sid / sdd;\n  double spacingValue = spacing * sid / sdd;\n\n#ifdef RTK_USE_CUDA\n  using CudaImageType = itk::CudaImage<float, 3>;\n  // Use CUDA for Parker short scan image filter\n  auto parker = rtk::CudaParkerShortScanImageFilter::New();\n  parker->SetGeometry(geometryRec);\n\n  auto reconstructionSource = rtk::ConstantImageSource<CudaImageType>::New();\n  reconstructionSource->SetOrigin(itk::MakePoint(originValue, originValue, originValue));\n  reconstructionSource->SetSpacing(itk::MakeVector(spacingValue, spacingValue, spacingValue));\n  reconstructionSource->SetSize(itk::MakeSize(imageSize, imageSize, imageSize));\n  auto fdk = rtk::CudaFDKConeBeamReconstructionFilter::New();\n#else\n  // Use CPU for Parker short scan image filter\n  auto parker = rtk::ParkerShortScanImageFilter<ImageType>::New();\n  parker->SetInput(extractor->GetOutput());\n  parker->SetGeometry(geometryRec);\n\n  auto reconstructionSource = rtk::ConstantImageSource<ImageType>::New();\n  reconstructionSource->SetOrigin(itk::MakePoint(originValue, originValue, originValue));\n  reconstructionSource->SetSpacing(itk::MakeVector(spacingValue, spacingValue, spacingValue));\n  reconstructionSource->SetSize(itk::MakeSize(imageSize, imageSize, imageSize));\n  auto fdk = rtk::FDKConeBeamReconstructionFilter<ImageType>::New();\n#endif\n\n  fdk->SetGeometry(geometryRec);\n  fdk->SetInput(0, reconstructionSource->GetOutput());\n  fdk->SetInput(1, parker->GetOutput());\n\n  // Online reconstruction loop\n  int                      reconstructedProjectionsCount = 0;\n  std::vector<std::string> projectionFileNames(numProjections, \"projection_000.mha\");\n\n  while (reconstructedProjectionsCount != numProjections)\n  {\n    if (reconstructedProjectionsCount < AcquiredProjectionsCount)\n    {\n      std::cout << \"Processing projection #\" << reconstructedProjectionsCount << \"\\r\";\n\n      if (reconstructedProjectionsCount == 0)\n      {\n        reader->SetFileNames(projectionFileNames);\n        reader->UpdateOutputInformation();\n      }\n      else\n      {\n        // Create filename for the next projection\n        std::ostringstream filename;\n        filename << \"projection_\" << std::setw(3) << std::setfill('0') << reconstructedProjectionsCount << \".mha\";\n        projectionFileNames[reconstructedProjectionsCount] = filename.str();\n        reader->SetFileNames(projectionFileNames);\n\n        // Disconnect the pipeline to allow for proper reconstruction\n        ImageType::Pointer reconstructedImage = fdk->GetOutput();\n        reconstructedImage->DisconnectPipeline();\n\n        fdk->SetInput(0, reconstructionSource->GetOutput());\n      }\n\n      // Extract and read the new projection\n      auto extractedRegion = reader->GetOutput()->GetLargestPossibleRegion();\n      extractedRegion.SetIndex(2, reconstructedProjectionsCount);\n      extractedRegion.SetSize(2, 1);\n      extractor->SetExtractionRegion(extractedRegion);\n      extractor->UpdateLargestPossibleRegion();\n\n#ifdef RTK_USE_CUDA\n      // Prepare projection for CUDA processing\n      auto projection = CudaImageType::New();\n      projection->SetPixelContainer(extractor->GetOutput()->GetPixelContainer());\n      projection->CopyInformation(extractor->GetOutput());\n      projection->SetBufferedRegion(extractor->GetOutput()->GetBufferedRegion());\n      projection->SetRequestedRegion(extractor->GetOutput()->GetRequestedRegion());\n      parker->SetInput(projection);\n#endif\n\n      fdk->Update();\n      reconstructedProjectionsCount++;\n    }\n    else\n    {\n      // Sleep briefly to avoid busy waiting\n      std::this_thread::sleep_for(std::chrono::milliseconds(10));\n    }\n  }\n\n  acquisitionThread.join();\n  itk::WriteImage(fdk->GetOutput(), \"fdk.mha\");\n\n  return 0;\n}\n"
  },
  {
    "path": "examples/InlineReconstruction/InlineReconstruction.py",
    "content": "import sys\nimport os\nimport time\nimport threading\nimport itk\nfrom itk import RTK as rtk\n\n# Parameters controlling the geometry of the simulated acquisition\nimage_type = itk.Image[itk.F, 3]\nhas_gpu_capability = hasattr(itk, \"CudaImage\")\nif has_gpu_capability:\n    cuda_image_type = itk.CudaImage[itk.F, 3]\nnproj = 64\nsid = 1000\nsdd = 1500\narc = 200\nspacing = 1\nsize = 256\norigin = -0.5 * (size - 1)\nnumber_of_acquired_projections = 0\n\n# Function for the thread simulating an acquisition: simulates and writes a\n# projection every 100 ms.\ndef acquisition():\n    global number_of_acquired_projections\n    for i in range(nproj):\n        geometry_acq = rtk.ThreeDCircularProjectionGeometry.New()\n        geometry_acq.AddProjection(sid, sdd, i * arc / nproj)\n        projection = rtk.constant_image_source(\n            origin=[origin, origin, 0.0],\n            size=[size, size, 1],\n            spacing=[spacing] * 3,\n            ttype=image_type,\n        )\n        projection = rtk.shepp_logan_phantom_filter(\n            projection,\n            geometry=geometry_acq,\n            phantom_scale=100,\n        )\n        itk.imwrite(projection, f\"projection_{i:03d}.mha\")\n\n        # The code assumes that incrementing an integer is thread safe, which\n        # is the case with CPython\n        # https://docs.python.org/3/library/threading.html\n        number_of_acquired_projections += 1\n        time.sleep(0.1)\n\n\n\n# Launches the acquisition thread, then waits for new projections and reconstructs inline / on-the-fly\n# Launch the simulated acquisition\nthread = threading.Thread(target=acquisition)\nthread.start()\n\n# Create the (expected) geometry and filenames\ngeometry_rec = rtk.ThreeDCircularProjectionGeometry.New()\nfor i in range(nproj):\n    geometry_rec.AddProjection(sid, sdd, i * arc / nproj)\n\n# Create the reconstruction pipeline\nreader = rtk.ProjectionsReader[image_type].New()\nextractor = itk.ExtractImageFilter[image_type, image_type].New(\n    Input=reader.GetOutput()\n)\nif has_gpu_capability:\n    parker = rtk.CudaParkerShortScanImageFilter.New(Geometry=geometry_rec)\n    reconstruction_source = rtk.ConstantImageSource[cuda_image_type].New(\n        Origin=[origin * sid / sdd] * 3,\n        Spacing=[spacing * sid / sdd] * 3,\n        Size=[size] * 3,\n    )\n    fdk = rtk.CudaFDKConeBeamReconstructionFilter.New(Geometry=geometry_rec)\nelse:\n    parker = rtk.ParkerShortScanImageFilter[image_type].New(\n        Input=extractor.GetOutput(), Geometry=geometry_rec\n    )\n    reconstruction_source = rtk.ConstantImageSource[image_type].New(\n        Origin=[origin * sid / sdd] * 3,\n        Spacing=[spacing * sid / sdd] * 3,\n        Size=[size] * 3,\n    )\n    fdk = rtk.FDKConeBeamReconstructionFilter[image_type].New(Geometry=geometry_rec)\nfdk.SetInput(0, reconstruction_source.GetOutput())\nfdk.SetInput(1, parker.GetOutput())\n\n# Do the online / on-the-fly reconstruction: wait for acquired projections\n# and use them as soon as a new one is available\nnumber_of_reconstructed_projections = 0\nwhile number_of_reconstructed_projections != nproj:\n    new_projection_available = bool(\n        number_of_reconstructed_projections < number_of_acquired_projections\n    )\n    if not new_projection_available:\n        time.sleep(0.01)\n    else:\n        print(\n            f\"Processing projection #{number_of_reconstructed_projections}\",\n            end=\"\\r\",\n        )\n        if number_of_reconstructed_projections == 0:\n            # First projection, mimick a stack from one file and prepare extracted region\n            projection_file_names = [\"projection_000.mha\"] * nproj\n            reader.SetFileNames(projection_file_names)\n            reader.UpdateOutputInformation()\n            extracted_region = reader.GetOutput().GetLargestPossibleRegion()\n            extracted_region.SetSize(2, 1)\n        else:\n            # Update file name list with the new projection\n            projection_file_names[\n                number_of_reconstructed_projections\n            ] = f\"projection_{number_of_reconstructed_projections:03d}.mha\"\n            reader.SetFileNames(projection_file_names)\n\n            # Reconnect FDK output to\n            reconstructed_image = fdk.GetOutput()\n            reconstructed_image.DisconnectPipeline()\n            fdk.SetInput(reconstructed_image)\n\n        # Only extract and read the new projection\n        extracted_region.SetIndex(2, number_of_reconstructed_projections)\n        extractor.SetExtractionRegion(extracted_region)\n        extractor.UpdateLargestPossibleRegion()\n        if has_gpu_capability:\n            projection = cuda_image_type.New()\n            projection.SetPixelContainer(extractor.GetOutput().GetPixelContainer())\n            projection.CopyInformation(extractor.GetOutput())\n            projection.SetBufferedRegion(extractor.GetOutput().GetBufferedRegion())\n            projection.SetRequestedRegion(\n                extractor.GetOutput().GetRequestedRegion()\n            )\n            parker.SetInput(projection)\n        fdk.Update()\n        number_of_reconstructed_projections += 1\nthread.join()\nwriter = itk.ImageFileWriter[image_type].New(\n    Input=fdk.GetOutput(), FileName=\"fdk.mha\"\n)\nwriter.Update()\n"
  },
  {
    "path": "examples/InlineReconstruction/README.md",
    "content": "# Inline Reconstruction\n\nInlineReconstruction demonstrates how to perform cone-beam CT reconstruction using\nRTK's implementation of [FDK](https://doi.org/10.1364/JOSAA.1.000612) while\nprojections are being acquired.\n\nThe program simulates the acquisition of X-ray projections in a separate thread,  \ngradually reconstructing the 3D volume as new projections become available.\n\n\n`````{tab-set}\n\n````{tab-item} C++\n\n```{literalinclude} ./InlineReconstruction.cxx\n:language: c++\n```\n````\n\n````{tab-item} Python\n\n```{literalinclude} ./InlineReconstruction.py\n:language: python\n```\n\n````\n`````\n\n"
  },
  {
    "path": "examples/README.md",
    "content": "C++ / Python examples\n========\n\nThis section provides a collection of C++ and Python code examples \nto demonstrate how to effectively use RTK in various applications.\n\nA key example is [FirstReconstruction](./FirstReconstruction/README.md), \na generic starting point for users new to RTK. This example demonstrates \nthe fundamental steps of performing a reconstruction, making it an ideal \nentry point for those beginning with RTK.\nIt showcases how to set up an RTK pipeline, configure parameters, \nand execute a basic reconstruction process.\n\nAdditionally, there are examples which use CUDA for GPU-accelerated computations, \nproviding efficient implementations for high-performance applications.\n\n```{toctree}\n:maxdepth: 1\n\n./FirstReconstruction/README.md\n./ConjugateGradient/README.md\n./WaterPreCorrection/README.md\n./InlineReconstruction/README.md\n./AddNoise/README.md\n./GeometricPhantom/README.md\n```\n"
  },
  {
    "path": "examples/WaterPreCorrection/Profile.png.sha512",
    "content": "0722bc916860fca6a98ebaff9bb064d9153336f7fc18746329c557514f88450242361476075b1df296ac870ea966df7db825665fb8dc51f629650e0013d0b027"
  },
  {
    "path": "examples/WaterPreCorrection/README.md",
    "content": "# Cupping correction\n\nThis example illustrates how to apply empirical cupping correction using the [algorithm of Kachelriess et al.](https://www.doi.org/doi/10.1118/1.2188076/abstract) named [WaterPrecorrection](https://www.openrtk.org/Doxygen/classrtk_1_1WaterPrecorrectionImageFilter.html) in RTK. The example uses a Gate simulation using the [fixed forced detection actor](https://opengate.readthedocs.io/en/latest/tools_to_interact_with_the_simulation_actors.html#fixed-forced-detection-ct).\n\nThe simulation implements a 120 kV beam, a detector with 512x3 pixels and an energy response curve. Only the primary beam is simulated.\n\nThe simulation files, the output projections and the processing script are available [here](https://data.kitware.com/api/v1/file/5d394cea877dfcc9022c922b/download).\n\n```{literalinclude} WaterPreCorrection.py\n```\nThe resulting central profiles are\n\n![Profile](Profile.png){w=800px alt=\"Profile\"}\n"
  },
  {
    "path": "examples/WaterPreCorrection/WaterPreCorrection.py",
    "content": "#!/usr/bin/env python\n\nimport itk\nfrom itk import RTK as rtk\nimport os\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport scipy.optimize\nimport glob\n\n# Script parameters\ndirectory = \"output/\"\nspacing = [0.5] * 3\nsize = [512, 1, 512]\norder = 6\nreference_attenuation = 0.02\norigin = [-(size[0] / 2 + 0.5) * spacing[0], 0.0, -(size[2] / 2 + 0.5) * spacing[2]]\n\n# List of filenames\nfile_names = list()\nfor file in os.listdir(directory):\n    if file.startswith(\"attenuation\") and file.endswith(\".mha\"):\n        file_names.append(directory + file)\n\n# Read in full geometry\ngeometry = rtk.read_geometry(\"output/geometry.xml\")\n\n# Crate template image\nImageType = itk.Image[itk.F, 3]\nprojections_reader = rtk.ProjectionsReader[ImageType].New(file_names=file_names)\nprojections = projections_reader.GetOutput()\nconstant_image_filter = rtk.ConstantImageSource[ImageType].New(\n    origin=origin, spacing=spacing, size=size\n)\nconstant_image = constant_image_filter.GetOutput()\ntemplate = rtk.draw_ellipsoid_image_filter(\n    constant_image, density=reference_attenuation, axis=[100, 0, 100]\n)\nitk.imwrite(template, \"template.mha\")\ntemplate = itk.array_from_image(template).flatten()\n\n# Create weights (where the template should match)\nweights = rtk.draw_ellipsoid_image_filter(\n    constant_image, density=1.0, axis=[125, 0, 125]\n)\nweights = rtk.draw_ellipsoid_image_filter(weights, density=-1.0, axis=[102, 0, 102])\nweights = rtk.draw_ellipsoid_image_filter(weights, density=1.0, axis=[98, 0, 98])\nitk.imwrite(weights, \"weights.mha\")\nweights = itk.array_from_image(weights).flatten()\n\n# Create reconstructed images\nwpcoeffs = np.zeros((order + 1))\nfdks = [None] * (order + 1)\nfor o in range(0, order + 1):\n    wpcoeffs[o - 1] = 0.0\n    wpcoeffs[o] = 1.0\n    water_precorrection = rtk.water_precorrection_image_filter(\n        projections, coefficients=wpcoeffs, in_place=False\n    )\n    fdk = rtk.fdk_cone_beam_reconstruction_filter(\n        constant_image, water_precorrection, geometry=geometry\n    )\n    itk.imwrite(fdk, f\"fdk{o}.mha\")\n    fdks[o] = itk.array_from_image(fdk).flatten()\n\n# Create and solve the linear system of equation B.c= a to find the coeffs c\na = np.zeros((order + 1))\nB = np.zeros((order + 1, order + 1))\nfor i in range(0, order + 1):\n    a[i] = np.sum(weights * fdks[i] * template)\n    for j in np.arange(i, order + 1):\n        B[i, j] = np.sum(weights * fdks[i] * fdks[j])\n        B[j, i] = B[i, j]\nc = np.linalg.solve(B, a)\n\nwater_precorrection = rtk.water_precorrection_image_filter(projections, coefficients=c)\nfdk = rtk.fdk_cone_beam_reconstruction_filter(\n    constant_image, water_precorrection, geometry=geometry\n)\nitk.imwrite(fdk, \"fdk.mha\")\n\nfdk = itk.imread(\"fdk.mha\")\nfdk1 = itk.imread(\"fdk1.mha\")\n\nplt.plot(itk.array_from_image(fdk)[:, 0, 256], label=\"Corrected\")\nplt.plot(itk.array_from_image(fdk1)[:, 0, 256], label=\"Uncorrected\")\nplt.legend()\nplt.xlabel(\"Pixel number\")\nplt.ylabel(\"Attenuation\")\nplt.xlim(0, 512)\nplt.savefig(\"profile.png\")\n"
  },
  {
    "path": "include/rtkADMMTotalVariationConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkADMMTotalVariationConeBeamReconstructionFilter_h\n#define rtkADMMTotalVariationConeBeamReconstructionFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkAddImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n\n#include \"rtkConjugateGradientImageFilter.h\"\n#include \"rtkSoftThresholdTVImageFilter.h\"\n#include \"rtkADMMTotalVariationConjugateGradientOperator.h\"\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n#include \"rtkMultiplyByVectorImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class ADMMTotalVariationConeBeamReconstructionFilter\n * \\brief Implements the ADMM reconstruction with total variation regularization\n *\n * This filter implements a reconstruction method based on compressed sensing.\n * The method attempts to find the f that minimizes\n * || sqrt(D) (Rf -p) ||_2^2 + alpha * TV(f),\n * with R the forward projection operator, p the measured projections,\n * D the displaced detector weighting matrix, and TV the total variation.\n * Details on the method and the calculations can be found on page 48 of\n *\n * Mory, C. \"Cardiac C-Arm Computed Tomography\", PhD thesis, 2014.\n * https://hal.inria.fr/tel-00985728/document\n *\n * \\f$ f_{k+1} \\f$ is obtained by linear conjugate solving the following:\n * \\f[ ( R^T R + \\beta \\nabla^T \\nabla ) f = R^T p + \\beta \\nabla^T ( g_k + d_k ) \\f]\n *\n * \\f$ g_{k+1} \\f$ is obtained by soft thresholding:\n * \\f[ g_{k+1} = ST_{ \\frac{\\alpha}{2 \\beta} } ( \\nabla f_{k+1} - d_k ) \\f]\n *\n * \\f$ d_{k+1} \\f$ is a simple subtraction:\n * \\f[ d_{k+1} = g_{k+1} - ( \\nabla f_{k+1} - d_k) \\f]\n *\n * \\dot\n * digraph ADMMTotalVariationConeBeamReconstructionFilter {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Volume)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * ZeroMultiplyVolume [label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * ZeroMultiplyGradient [label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * BeforeZeroMultiplyVolume [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterGradient [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterZeroMultiplyGradient [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Gradient [ label=\"rtk::ForwardDifferenceGradientImageFilter\" URL=\"\\ref rtk::ForwardDifferenceGradientImageFilter\"];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n * BackProjection [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * AddGradient [ label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n * Divergence [ label=\"rtk::BackwardDifferenceDivergenceImageFilter\"\n *              URL=\"\\ref rtk::BackwardDifferenceDivergenceImageFilter\"];\n * Multiply [ label=\"itk::MultiplyImageFilter (by beta)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * SubtractVolume [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * ConjugateGradient[ label=\"rtk::ConjugateGradientImageFilter\" URL=\"\\ref rtk::ConjugateGradientImageFilter\"];\n * AfterConjugateGradient [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * GradientTwo [ label=\"rtk::ForwardDifferenceGradientImageFilter\"\n *               URL=\"\\ref rtk::ForwardDifferenceGradientImageFilter\"];\n * Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * TVSoftThreshold [ label=\"rtk::SoftThresholdTVImageFilter\" URL=\"\\ref rtk::SoftThresholdTVImageFilter\"];\n * BeforeTVSoftThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterTVSoftThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * SubtractTwo [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n *\n * Input0 -> BeforeZeroMultiplyVolume [arrowhead=none, label=\"f_0\"];\n * BeforeZeroMultiplyVolume -> ZeroMultiplyVolume;\n * BeforeZeroMultiplyVolume -> Gradient;\n * BeforeZeroMultiplyVolume -> ConjugateGradient;\n * ZeroMultiplyVolume -> BackProjection;\n * Input1 -> Displaced [label=\"p\"];\n * Displaced -> BackProjection;\n * Gradient -> AfterGradient [arrowhead=none, label=\"g_0\"];\n * AfterGradient -> AddGradient;\n * AfterGradient -> ZeroMultiplyGradient;\n * ZeroMultiplyGradient -> AfterZeroMultiplyGradient [arrowhead=none, label=\"d_0\"];\n * AfterZeroMultiplyGradient -> AddGradient;\n * AfterZeroMultiplyGradient -> Subtract;\n * AddGradient -> Divergence [label=\"g_0 + d_0\"];\n * Divergence -> Multiply [label=\"-nabla_t(g_0 + d_0)\"];\n * Multiply -> SubtractVolume [label=\"-beta *nabla_t(g_0 + d_0)\"];\n * BackProjection -> SubtractVolume [label=\"R_t p\"];\n * SubtractVolume -> ConjugateGradient [label=\"b\"];\n * ConjugateGradient -> AfterConjugateGradient [label=\"f_k+1\"];\n * AfterConjugateGradient -> GradientTwo;\n * GradientTwo -> Subtract [label=\"nabla(f_k+1)\"];\n * Subtract -> BeforeTVSoftThreshold [arrowhead=none, label=\"nabla(f_k+1) - d_k\"];\n * BeforeTVSoftThreshold -> TVSoftThreshold;\n * BeforeTVSoftThreshold -> SubtractTwo;\n * TVSoftThreshold -> AfterTVSoftThreshold [arrowhead=none];\n * AfterTVSoftThreshold -> SubtractTwo [label=\"g_k+1\"];\n * AfterTVSoftThreshold -> AfterGradient [style=dashed];\n * SubtractTwo -> AfterZeroMultiplyGradient [style=dashed, label=\"d_k+1\"];\n * AfterConjugateGradient -> BeforeZeroMultiplyVolume [style=dashed];\n * AfterConjugateGradient -> Output [style=dashed];\n * }\n * \\enddot\n *\n * \\test rtkadmmtotalvariationtest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\n\ntemplate <typename TOutputImage>\nclass ITK_TEMPLATE_EXPORT ADMMTotalVariationConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<TOutputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ADMMTotalVariationConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = ADMMTotalVariationConeBeamReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<TOutputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ADMMTotalVariationConeBeamReconstructionFilter);\n\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<TOutputImage, TOutputImage>;\n  using ForwardProjectionFilterPointer = typename ForwardProjectionFilterType::Pointer;\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<TOutputImage, TOutputImage>;\n  using BackProjectionFilterPointer = typename BackProjectionFilterType::Pointer;\n  using ConjugateGradientFilterType = rtk::ConjugateGradientImageFilter<TOutputImage>;\n  using VectorPixelType = itk::CovariantVector<typename TOutputImage::ValueType, TOutputImage::ImageDimension>;\n  using CPUImageType = itk::Image<typename TOutputImage::PixelType, TOutputImage::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  typedef\n    typename std::conditional<std::is_same<TOutputImage, CPUImageType>::value,\n                              itk::Image<VectorPixelType, TOutputImage::ImageDimension>,\n                              itk::CudaImage<VectorPixelType, TOutputImage::ImageDimension>>::type GradientImageType;\n#else\n  using GradientImageType = itk::Image<VectorPixelType, TOutputImage::ImageDimension>;\n#endif\n  using ImageGradientFilterType = ForwardDifferenceGradientImageFilter<TOutputImage,\n                                                                       typename TOutputImage::ValueType,\n                                                                       typename TOutputImage::ValueType,\n                                                                       GradientImageType>;\n  using ImageDivergenceFilterType = rtk::BackwardDifferenceDivergenceImageFilter<GradientImageType, TOutputImage>;\n  typedef rtk::SoftThresholdTVImageFilter<GradientImageType> SoftThresholdTVFilterType;\n  using SubtractVolumeFilterType = itk::SubtractImageFilter<TOutputImage>;\n  using AddGradientsFilterType = itk::AddImageFilter<GradientImageType>;\n  using MultiplyVolumeFilterType = itk::MultiplyImageFilter<TOutputImage>;\n  using MultiplyGradientFilterType = itk::MultiplyImageFilter<GradientImageType>;\n  using SubtractGradientsFilterType = itk::SubtractImageFilter<GradientImageType>;\n  using CGOperatorFilterType = rtk::ADMMTotalVariationConjugateGradientOperator<TOutputImage>;\n  using DisplacedDetectorFilterType = rtk::DisplacedDetectorImageFilter<TOutputImage>;\n  using GatingWeightsFilterType = rtk::MultiplyByVectorImageFilter<TOutputImage>;\n\n  /** Pass the geometry to all filters needing it */\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Increase the value of Beta at each iteration */\n  void\n  SetBetaForCurrentIteration(int iter);\n\n  /** In the case of a gated reconstruction, set the gating weights */\n  void\n  SetGatingWeights(std::vector<float> weights);\n\n  itkSetMacro(Alpha, float);\n  itkGetMacro(Alpha, float);\n\n  itkSetMacro(Beta, float);\n  itkGetMacro(Beta, float);\n\n  itkSetMacro(AL_iterations, float);\n  itkGetMacro(AL_iterations, float);\n\n  itkSetMacro(CG_iterations, float);\n  itkGetMacro(CG_iterations, float);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  ADMMTotalVariationConeBeamReconstructionFilter();\n  ~ADMMTotalVariationConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename SubtractGradientsFilterType::Pointer                              m_SubtractFilter1;\n  typename SubtractGradientsFilterType::Pointer                              m_SubtractFilter2;\n  typename MultiplyVolumeFilterType::Pointer                                 m_MultiplyFilter;\n  typename MultiplyVolumeFilterType::Pointer                                 m_ZeroMultiplyVolumeFilter;\n  typename MultiplyGradientFilterType::Pointer                               m_ZeroMultiplyGradientFilter;\n  typename ImageGradientFilterType::Pointer                                  m_GradientFilter1;\n  typename ImageGradientFilterType::Pointer                                  m_GradientFilter2;\n  typename SubtractVolumeFilterType::Pointer                                 m_SubtractVolumeFilter;\n  typename AddGradientsFilterType::Pointer                                   m_AddGradientsFilter;\n  typename ImageDivergenceFilterType::Pointer                                m_DivergenceFilter;\n  typename ConjugateGradientFilterType::Pointer                              m_ConjugateGradientFilter;\n  typename SoftThresholdTVFilterType::Pointer                                m_SoftThresholdFilter;\n  typename CGOperatorFilterType::Pointer                                     m_CGOperator;\n  typename ForwardProjectionImageFilter<TOutputImage, TOutputImage>::Pointer m_ForwardProjectionFilter;\n  typename BackProjectionImageFilter<TOutputImage, TOutputImage>::Pointer    m_BackProjectionFilterForConjugateGradient;\n  typename BackProjectionImageFilter<TOutputImage, TOutputImage>::Pointer    m_BackProjectionFilter;\n  typename DisplacedDetectorFilterType::Pointer                              m_DisplacedDetectorFilter;\n  typename GatingWeightsFilterType::Pointer                                  m_GatingWeightsFilter;\n\n  /** The inputs of this filter have the same type (float, 3) but not the same meaning\n   * It is normal that they do not occupy the same physical space. Therefore this check\n   * must be removed */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n\n  /** Have gating weights been set ? If so, apply them, otherwise ignore\n   * the gating weights filter */\n  bool               m_IsGated;\n  std::vector<float> m_GatingWeights;\n  bool               m_DisableDisplacedDetectorFilter;\n\nprivate:\n  float        m_Alpha;\n  float        m_Beta;\n  unsigned int m_AL_iterations;\n  unsigned int m_CG_iterations;\n\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkADMMTotalVariationConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkADMMTotalVariationConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkADMMTotalVariationConeBeamReconstructionFilter_hxx\n#define rtkADMMTotalVariationConeBeamReconstructionFilter_hxx\n\n\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage>\nADMMTotalVariationConeBeamReconstructionFilter<TOutputImage>::ADMMTotalVariationConeBeamReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set the default values of member parameters\n  m_Alpha = 1;\n  m_Beta = 1;\n  m_AL_iterations = 10;\n  m_CG_iterations = 3;\n  m_IsGated = false;\n\n  // Create the filters\n  m_ZeroMultiplyVolumeFilter = MultiplyVolumeFilterType::New();\n  m_ZeroMultiplyGradientFilter = MultiplyGradientFilterType::New();\n  m_SubtractFilter1 = SubtractGradientsFilterType::New();\n  m_SubtractFilter2 = SubtractGradientsFilterType::New();\n  m_MultiplyFilter = MultiplyVolumeFilterType::New();\n  m_GradientFilter1 = ImageGradientFilterType::New();\n  m_GradientFilter2 = ImageGradientFilterType::New();\n  m_SubtractVolumeFilter = SubtractVolumeFilterType::New();\n  m_AddGradientsFilter = AddGradientsFilterType::New();\n  m_DivergenceFilter = ImageDivergenceFilterType::New();\n  m_ConjugateGradientFilter = ConjugateGradientFilterType::New();\n  m_SoftThresholdFilter = SoftThresholdTVFilterType::New();\n  m_CGOperator = CGOperatorFilterType::New();\n  m_ConjugateGradientFilter->SetA(m_CGOperator.GetPointer());\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n  m_GatingWeightsFilter = GatingWeightsFilterType::New();\n\n  // Set permanent connections\n  m_ZeroMultiplyGradientFilter->SetInput1(m_GradientFilter1->GetOutput());\n  m_AddGradientsFilter->SetInput1(m_ZeroMultiplyGradientFilter->GetOutput());\n  m_AddGradientsFilter->SetInput2(m_GradientFilter1->GetOutput());\n  m_DivergenceFilter->SetInput(m_AddGradientsFilter->GetOutput());\n  m_MultiplyFilter->SetInput1(m_DivergenceFilter->GetOutput());\n  m_SubtractVolumeFilter->SetInput2(m_MultiplyFilter->GetOutput());\n  m_ConjugateGradientFilter->SetB(m_SubtractVolumeFilter->GetOutput());\n  m_ConjugateGradientFilter->SetNumberOfIterations(m_CG_iterations);\n  m_GradientFilter2->SetInput(m_ConjugateGradientFilter->GetOutput());\n  m_SubtractFilter1->SetInput1(m_GradientFilter2->GetOutput());\n  m_SubtractFilter1->SetInput2(m_ZeroMultiplyGradientFilter->GetOutput());\n  m_SoftThresholdFilter->SetInput(m_SubtractFilter1->GetOutput());\n  m_SubtractFilter2->SetInput1(m_SoftThresholdFilter->GetOutput());\n  m_SubtractFilter2->SetInput2(m_SubtractFilter1->GetOutput());\n\n  // Set permanent parameters\n  m_ZeroMultiplyVolumeFilter->SetConstant2(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_ZeroMultiplyGradientFilter->SetConstant2(itk::NumericTraits<typename GradientImageType::PixelType>::ZeroValue());\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n  m_DisableDisplacedDetectorFilter = false;\n  // Not in place to avoid reading the projections twice\n  m_DisplacedDetectorFilter->SetInPlace(false);\n\n  // Set memory management parameters\n  m_ZeroMultiplyVolumeFilter->ReleaseDataFlagOn();\n  m_ZeroMultiplyGradientFilter->ReleaseDataFlagOn();\n  m_GradientFilter1->ReleaseDataFlagOn();\n  m_AddGradientsFilter->ReleaseDataFlagOn();\n  m_DivergenceFilter->ReleaseDataFlagOn();\n  m_MultiplyFilter->ReleaseDataFlagOn();\n  m_SubtractVolumeFilter->ReleaseDataFlagOn();\n  m_ConjugateGradientFilter->ReleaseDataFlagOff(); // Output is f_k+1\n  m_GradientFilter2->ReleaseDataFlagOn();\n  m_SubtractFilter1->ReleaseDataFlagOff();     // Output used in two filters\n  m_SoftThresholdFilter->ReleaseDataFlagOff(); // Output is g_k+1\n  m_SubtractFilter2->ReleaseDataFlagOff();     // Output is d_k+1\n  m_DisplacedDetectorFilter->ReleaseDataFlagOn();\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConeBeamReconstructionFilter<TOutputImage>::SetBetaForCurrentIteration(int iter)\n{\n  float currentBeta = m_Beta * (iter + 1) / (float)m_AL_iterations;\n\n  m_CGOperator->SetBeta(currentBeta);\n  m_SoftThresholdFilter->SetThreshold(m_Alpha / (2 * currentBeta));\n  m_MultiplyFilter->SetConstant2((const float)currentBeta);\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConeBeamReconstructionFilter<TOutputImage>::SetGatingWeights(std::vector<float> weights)\n{\n  m_GatingWeights = weights;\n  m_IsGated = true;\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConeBeamReconstructionFilter<TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the volume we update\n  typename Superclass::InputImagePointer inputPtr0 = const_cast<TOutputImage *>(this->GetInput(0));\n  if (!inputPtr0)\n  {\n    return;\n  }\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the stack of projections to backproject\n  typename Superclass::InputImagePointer inputPtr1 = const_cast<TOutputImage *>(this->GetInput(1));\n  if (!inputPtr1)\n  {\n    return;\n  }\n  inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n}\n\ntemplate <class TOutputImage>\nvoid\nADMMTotalVariationConeBeamReconstructionFilter<TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConeBeamReconstructionFilter<TOutputImage>::GenerateOutputInformation()\n{\n  // Set forward projection filter\n  m_ForwardProjectionFilter = this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n  // Pass the ForwardProjection filter to the conjugate gradient operator\n  m_CGOperator->SetForwardProjectionFilter(m_ForwardProjectionFilter);\n\n  // Set back projection filter\n  m_BackProjectionFilter = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  // Pass the backprojection filter to the conjugate gradient operator and to the back projection filter generating the\n  // B of AX=B\n  m_BackProjectionFilterForConjugateGradient =\n    this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  m_CGOperator->SetBackProjectionFilter(m_BackProjectionFilterForConjugateGradient);\n\n  // Set runtime connections\n  m_GradientFilter1->SetInput(this->GetInput(0));\n  m_ZeroMultiplyVolumeFilter->SetInput1(this->GetInput(0));\n  m_CGOperator->SetInput(1, this->GetInput(1));\n  m_ConjugateGradientFilter->SetX(this->GetInput(0));\n  m_MultiplyFilter->SetConstant2(m_Beta);\n  if (m_IsGated)\n  {\n    // Insert the gating filter into the pipeline\n    m_GatingWeightsFilter->SetInput(this->GetInput(1));\n    m_GatingWeightsFilter->SetVector(m_GatingWeights);\n    m_DisplacedDetectorFilter->SetInput(m_GatingWeightsFilter->GetOutput());\n\n    // Also perform gating in the conjugate gradient operator\n    m_CGOperator->SetGatingWeights(m_GatingWeights);\n  }\n  else\n  {\n    m_DisplacedDetectorFilter->SetInput(this->GetInput(1));\n  }\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n  m_CGOperator->SetDisableDisplacedDetectorFilter(m_DisableDisplacedDetectorFilter);\n\n  // Links with the m_BackProjectionFilter should be set here and not\n  // in the constructor, as m_BackProjectionFilter is set at runtime\n  m_BackProjectionFilter->SetInput(0, m_ZeroMultiplyVolumeFilter->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_DisplacedDetectorFilter->GetOutput());\n  m_SubtractVolumeFilter->SetInput1(m_BackProjectionFilter->GetOutput());\n\n  // For the same reason, set geometry now\n  m_CGOperator->SetGeometry(this->m_Geometry);\n  m_BackProjectionFilter->SetGeometry(this->m_Geometry.GetPointer());\n  m_DisplacedDetectorFilter->SetGeometry(this->m_Geometry);\n\n  // Set runtime parameters\n  m_ConjugateGradientFilter->SetNumberOfIterations(this->m_CG_iterations);\n\n  // Have the last filter calculate its output information\n  m_SubtractFilter2->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_SubtractFilter2->GetOutput());\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConeBeamReconstructionFilter<TOutputImage>::GenerateData()\n{\n  itk::IterationReporter iterationReporter(this, 0, 1);\n  for (unsigned int iter = 0; iter < m_AL_iterations; iter++)\n  {\n    SetBetaForCurrentIteration(iter);\n\n    // After the first update, we need to use some outputs as inputs\n    if (iter > 0)\n    {\n      typename TOutputImage::Pointer f_k_plus_one = m_ConjugateGradientFilter->GetOutput();\n      f_k_plus_one->DisconnectPipeline();\n      m_ConjugateGradientFilter->SetX(f_k_plus_one);\n\n      typename ImageGradientFilterType::OutputImageType::Pointer g_k_plus_one = m_SoftThresholdFilter->GetOutput();\n      g_k_plus_one->DisconnectPipeline();\n      m_AddGradientsFilter->SetInput2(g_k_plus_one);\n\n      typename ImageGradientFilterType::OutputImageType::Pointer d_k_plus_one = m_SubtractFilter2->GetOutput();\n      d_k_plus_one->DisconnectPipeline();\n      m_AddGradientsFilter->SetInput1(d_k_plus_one);\n      m_SubtractFilter1->SetInput2(d_k_plus_one);\n\n      // Recreate the links destroyed by DisconnectPipeline\n      m_GradientFilter2->SetInput(m_ConjugateGradientFilter->GetOutput());\n      m_SubtractFilter2->SetInput1(m_SoftThresholdFilter->GetOutput());\n    }\n    m_SubtractFilter2->Update();\n    this->GraftOutput(m_ConjugateGradientFilter->GetOutput());\n    iterationReporter.CompletedStep();\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkADMMTotalVariationConjugateGradientOperator.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkADMMTotalVariationConjugateGradientOperator_h\n#define rtkADMMTotalVariationConjugateGradientOperator_h\n\n#include <itkMultiplyImageFilter.h>\n#include <itkSubtractImageFilter.h>\n\n#include \"rtkConjugateGradientOperator.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkForwardDifferenceGradientImageFilter.h\"\n#include \"rtkBackwardDifferenceDivergenceImageFilter.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n#include \"rtkMultiplyByVectorImageFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\n#ifdef RTK_USE_CUDA\n#  include <itkCudaImage.h>\n#endif\n\nnamespace rtk\n{\n\n/** \\class ADMMTotalVariationConjugateGradientOperator\n * \\brief Implements the operator A used in the conjugate gradient step\n * of ADMM reconstruction with total variation regularization\n *\n * This filter implements the operator A used in the conjugate gradient step\n * of a reconstruction method based on compressed sensing.\n * The method attempts to find the f that minimizes\n * || sqrt(D) (Rf -p) ||_2^2 + alpha * TV(f),\n * with R the forward projection operator, p the measured projections,\n * D the displaced detector weighting matrix, and TV the total variation.\n * Details on the method and the calculations can be found in\n *\n * Mory, C., B. Zhang, V. Auvray, M. Grass, D. Schafer, F. Peyrin, S. Rit, P. Douek,\n * and L. Boussel. \"ECG-Gated C-Arm Computed Tomography Using L1 Regularization.\"\n * In Proceedings of the 20th European Signal Processing Conference (EUSIPCO), 2728-32, 2012.\n *\n * This filter takes in input f and outputs R_t D R f - beta div(grad(f)).\n *\n * \\dot\n * digraph ADMMTotalVariationConjugateGradientOperator {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Volume)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * ZeroMultiplyVolume [label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * ZeroMultiplyProjections [label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * BeforeZeroMultiplyVolume [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * Multiply [ label=\"itk::MultiplyImageFilter (by lambda)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * Gradient [ label=\"rtk::ForwardDifferenceGradientImageFilter\" URL=\"\\ref rtk::ForwardDifferenceGradientImageFilter\"];\n * Divergence [ label=\"rtk::BackwardDifferenceDivergenceImageFilter\"\n *              URL=\"\\ref rtk::BackwardDifferenceDivergenceImageFilter\"];\n * BackProjection [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * ForwardProjection [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n *\n * Input0 -> BeforeZeroMultiplyVolume [arrowhead=none];\n * BeforeZeroMultiplyVolume -> ZeroMultiplyVolume;\n * BeforeZeroMultiplyVolume -> ForwardProjection;\n * BeforeZeroMultiplyVolume -> Gradient;\n * Input1 -> ZeroMultiplyProjections;\n * ZeroMultiplyProjections -> ForwardProjection;\n * ZeroMultiplyVolume -> BackProjection;\n * ForwardProjection -> Displaced;\n * Displaced -> BackProjection;\n * BackProjection -> Subtract;\n * Gradient -> Divergence;\n * Divergence -> Multiply;\n * Multiply -> Subtract;\n * Subtract -> Output;\n *\n * }\n * \\enddot\n *\n * \\test rtkadmmtotalvariationtest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TOutputImage>\nclass ITK_TEMPLATE_EXPORT ADMMTotalVariationConjugateGradientOperator : public ConjugateGradientOperator<TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ADMMTotalVariationConjugateGradientOperator);\n\n  /** Standard class type alias. */\n  using Self = ADMMTotalVariationConjugateGradientOperator;\n  using Superclass = ConjugateGradientOperator<TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ADMMTotalVariationConjugateGradientOperator);\n\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<TOutputImage, TOutputImage>;\n  using BackProjectionFilterPointer = typename BackProjectionFilterType::Pointer;\n\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<TOutputImage, TOutputImage>;\n  using ForwardProjectionFilterPointer = typename ForwardProjectionFilterType::Pointer;\n\n  using MultiplyFilterType = itk::MultiplyImageFilter<TOutputImage>;\n  using SubtractFilterType = itk::SubtractImageFilter<TOutputImage>;\n\n  using VectorPixelType = itk::CovariantVector<typename TOutputImage::ValueType, TOutputImage::ImageDimension>;\n  using CPUImageType = itk::Image<typename TOutputImage::PixelType, TOutputImage::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  typedef\n    typename std::conditional<std::is_same<TOutputImage, CPUImageType>::value,\n                              itk::Image<VectorPixelType, TOutputImage::ImageDimension>,\n                              itk::CudaImage<VectorPixelType, TOutputImage::ImageDimension>>::type GradientImageType;\n#else\n  using GradientImageType = itk::Image<VectorPixelType, TOutputImage::ImageDimension>;\n#endif\n\n  using GradientFilterType = ForwardDifferenceGradientImageFilter<TOutputImage,\n                                                                  typename TOutputImage::ValueType,\n                                                                  typename TOutputImage::ValueType,\n                                                                  GradientImageType>;\n  using DivergenceFilterType = rtk::BackwardDifferenceDivergenceImageFilter<GradientImageType, TOutputImage>;\n  using DisplacedDetectorFilterType = rtk::DisplacedDetectorImageFilter<TOutputImage>;\n  using GatingWeightsFilterType = rtk::MultiplyByVectorImageFilter<TOutputImage>;\n\n  /** Set the backprojection filter*/\n  void\n  SetBackProjectionFilter(BackProjectionFilterType * _arg);\n\n  /** Set the forward projection filter*/\n  void\n  SetForwardProjectionFilter(ForwardProjectionFilterType * _arg);\n\n  /** Pass the geometry to all filters needing it */\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Set the regularization parameter */\n  itkSetMacro(Beta, float);\n\n  /** In the case of a gated reconstruction, set the gating weights */\n  void\n  SetGatingWeights(std::vector<float> weights);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  ADMMTotalVariationConjugateGradientOperator();\n  ~ADMMTotalVariationConjugateGradientOperator() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  BackProjectionFilterPointer    m_BackProjectionFilter;\n  ForwardProjectionFilterPointer m_ForwardProjectionFilter;\n\n  typename SubtractFilterType::Pointer          m_SubtractFilter;\n  typename MultiplyFilterType::Pointer          m_MultiplyFilter;\n  typename MultiplyFilterType::Pointer          m_ZeroMultiplyProjectionFilter;\n  typename MultiplyFilterType::Pointer          m_ZeroMultiplyVolumeFilter;\n  typename DivergenceFilterType::Pointer        m_DivergenceFilter;\n  typename GradientFilterType::Pointer          m_GradientFilter;\n  typename DisplacedDetectorFilterType::Pointer m_DisplacedDetectorFilter;\n  typename GatingWeightsFilterType::Pointer     m_GatingWeightsFilter;\n\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n  float                                     m_Beta;\n  bool                                      m_DisableDisplacedDetectorFilter;\n\n  /** Have gating weights been set ? If so, apply them, otherwise ignore\n   * the gating weights filter */\n  bool               m_IsGated;\n  std::vector<float> m_GatingWeights;\n\n  /** When the inputs have the same type, ITK checks whether they occupy the\n   * same physical space or not. Obviously they dont, so we have to remove this check\n   */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkADMMTotalVariationConjugateGradientOperator.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkADMMTotalVariationConjugateGradientOperator.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkADMMTotalVariationConjugateGradientOperator_hxx\n#define rtkADMMTotalVariationConjugateGradientOperator_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage>\nADMMTotalVariationConjugateGradientOperator<TOutputImage>::ADMMTotalVariationConjugateGradientOperator()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set default parameters\n  m_Beta = 0;\n  m_IsGated = false;\n\n  // Create filters\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_ZeroMultiplyProjectionFilter = MultiplyFilterType::New();\n  m_ZeroMultiplyVolumeFilter = MultiplyFilterType::New();\n  m_SubtractFilter = SubtractFilterType::New();\n  m_DivergenceFilter = DivergenceFilterType::New();\n  m_GradientFilter = GradientFilterType::New();\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n  m_GatingWeightsFilter = GatingWeightsFilterType::New();\n\n  // Set permanent connections\n  m_DivergenceFilter->SetInput(m_GradientFilter->GetOutput());\n  m_MultiplyFilter->SetInput1(m_DivergenceFilter->GetOutput());\n  m_SubtractFilter->SetInput2(m_MultiplyFilter->GetOutput());\n\n  // Set permanent parameters\n  m_ZeroMultiplyProjectionFilter->SetConstant2(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_ZeroMultiplyVolumeFilter->SetConstant2(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n  m_DisableDisplacedDetectorFilter = false;\n\n  // Set memory management options\n  m_ZeroMultiplyProjectionFilter->ReleaseDataFlagOn();\n  m_ZeroMultiplyVolumeFilter->ReleaseDataFlagOn();\n  m_DivergenceFilter->ReleaseDataFlagOn();\n  m_GradientFilter->ReleaseDataFlagOn();\n  m_MultiplyFilter->ReleaseDataFlagOn();\n  m_SubtractFilter->ReleaseDataFlagOff();\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConjugateGradientOperator<TOutputImage>::SetBackProjectionFilter(BackProjectionFilterType * _arg)\n{\n  if (m_BackProjectionFilter != _arg)\n    this->Modified();\n  m_BackProjectionFilter = _arg;\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConjugateGradientOperator<TOutputImage>::SetForwardProjectionFilter(\n  ForwardProjectionFilterType * _arg)\n{\n  if (m_ForwardProjectionFilter != _arg)\n    this->Modified();\n  m_ForwardProjectionFilter = _arg;\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConjugateGradientOperator<TOutputImage>::SetGatingWeights(std::vector<float> weights)\n{\n  m_GatingWeights = weights;\n  m_IsGated = true;\n  this->Modified();\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConjugateGradientOperator<TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConjugateGradientOperator<TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the volume in which we backproject\n  typename Superclass::InputImagePointer inputPtr0 = const_cast<TOutputImage *>(this->GetInput(0));\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the stack of projections to backproject\n  typename Superclass::InputImagePointer inputPtr1 = const_cast<TOutputImage *>(this->GetInput(1));\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConjugateGradientOperator<TOutputImage>::GenerateOutputInformation()\n{\n  // Set runtime connections, and connections with\n  // forward and back projection filters, which are set\n  // at runtime\n  m_ForwardProjectionFilter->SetInput(0, m_ZeroMultiplyProjectionFilter->GetOutput());\n  m_BackProjectionFilter->SetInput(0, m_ZeroMultiplyVolumeFilter->GetOutput());\n  if (m_IsGated)\n  {\n    // Insert the gating filter into the pipeline\n    m_GatingWeightsFilter->SetInput(m_ForwardProjectionFilter->GetOutput());\n    m_GatingWeightsFilter->SetVector(m_GatingWeights);\n    m_DisplacedDetectorFilter->SetInput(m_GatingWeightsFilter->GetOutput());\n  }\n  else\n  {\n    m_DisplacedDetectorFilter->SetInput(m_ForwardProjectionFilter->GetOutput());\n  }\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n  m_BackProjectionFilter->SetInput(1, m_DisplacedDetectorFilter->GetOutput());\n  m_SubtractFilter->SetInput1(m_BackProjectionFilter->GetOutput());\n  m_ZeroMultiplyVolumeFilter->SetInput1(this->GetInput(0));\n  m_ZeroMultiplyProjectionFilter->SetInput1(this->GetInput(1));\n  m_ForwardProjectionFilter->SetInput(1, this->GetInput(0));\n  m_GradientFilter->SetInput(this->GetInput(0));\n\n  // Set geometry\n  m_BackProjectionFilter->SetGeometry(this->m_Geometry.GetPointer());\n  m_ForwardProjectionFilter->SetGeometry(this->m_Geometry);\n  m_DisplacedDetectorFilter->SetGeometry(this->m_Geometry);\n\n  // Set runtime parameters\n  m_MultiplyFilter->SetConstant2(m_Beta);\n\n  // Set memory management parameters for forward\n  // and back projection filters\n  m_ForwardProjectionFilter->ReleaseDataFlagOn();\n  m_BackProjectionFilter->ReleaseDataFlagOn();\n\n  // Have the last filter calculate its output information\n  m_SubtractFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_SubtractFilter->GetOutput());\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMTotalVariationConjugateGradientOperator<TOutputImage>::GenerateData()\n{\n  // Execute Pipeline\n  m_SubtractFilter->Update();\n\n  // Get the output\n  this->GraftOutput(m_SubtractFilter->GetOutput());\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkADMMWaveletsConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkADMMWaveletsConeBeamReconstructionFilter_h\n#define rtkADMMWaveletsConeBeamReconstructionFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkAddImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n\n#include \"rtkConjugateGradientImageFilter.h\"\n#include \"rtkDeconstructSoftThresholdReconstructImageFilter.h\"\n#include \"rtkADMMWaveletsConjugateGradientOperator.h\"\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class ADMMWaveletsConeBeamReconstructionFilter\n * \\brief Implements the ADMM reconstruction with wavelets regularization\n *\n * This filter implements the operator A used in the conjugate gradient step\n * of a reconstruction method based on compressed sensing. The method attempts\n * to find the f that minimizes || Rf -p ||_2^2 + alpha * || W(f) ||_1, with R the\n * forward projection operator, p the measured projections, and W the\n * Daubechies wavelets transform. Note that since Daubechies wavelets are orthogonal,\n * \\f$ W^{T} = W^{-1} \\f$\n * Details on the method and the calculations can be found on page 53 of\n *\n * Mory, C. \"Cardiac C-Arm Computed Tomography\", PhD thesis, 2014.\n * https://hal.inria.fr/tel-00985728/document\n *\n * \\f$ f_{k+1} \\f$ is obtained by linear conjugate solving the following:\n * \\f[ ( R^T R + \\beta I ) f = R^T p + \\beta W^{-1} ( g_k + d_k ) \\f]\n *\n * \\f$ g_{k+1} \\f$ is obtained by soft thresholding:\n * \\f[ g_{k+1} = ST_{ \\frac{\\alpha}{2 \\beta} } ( W f_{k+1} - d_k ) \\f]\n *\n * \\f$ d_{k+1} \\f$ is a simple subtraction:\n * \\f[ d_{k+1} = g_{k+1} - ( W f_{k+1} - d_k) \\f]\n *\n * In ITK, it is much easier to store a volume than its wavelets decomposition.\n * Therefore, we store \\f$ g'_k = W^{-1} g_k \\f$ and \\f$ d'_k = W^{-1} d_k \\f$\n * instead of \\f$ g_k \\f$ and \\f$ d_k \\f$. The above algorithm can therefore be re-written as follows:\n *\n * \\f$ f_{k+1} \\f$ is obtained by linear conjugate solving the following:\n * \\f[ ( R^T R + \\beta I ) f = R^T p + \\beta ( g'_k + d'_k ) \\f]\n *\n * \\f$ g'_{k+1} \\f$ is obtained by soft thresholding:\n * \\f[ g'_{k+1} = W^{-1} ( ST_{ \\frac{\\alpha}{2 \\beta} } W( f_{k+1} - d'_k )) \\f]\n *\n * \\f$ d'_{k+1} \\f$ is a simple subtraction:\n * \\f[ d'_{k+1} = g'_{k+1} - ( f_{k+1} - d'_k) \\f]\n *\n * The wavelet decomposition and reconstruction steps are therefore performed only for\n * soft thresholding.\n *\n * \\dot\n * digraph ADMMWaveletsConeBeamReconstructionFilter {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Volume)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * ZeroMultiply [label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * BeforeZeroMultiply [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterZeroMultiply [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * D [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * G [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * BackProjection [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * Add [ label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n * Multiply [ label=\"itk::MultiplyImageFilter (by beta)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * AddTwo [ label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n * ConjugateGradient[ label=\"rtk::ConjugateGradientImageFilter\" URL=\"\\ref rtk::ConjugateGradientImageFilter\"];\n * AfterConjugateGradient [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * SoftThreshold [ label=\"rtk::DeconstructSoftThresholdReconstructImageFilter\"\n *                 URL=\"\\ref rtk::DeconstructSoftThresholdReconstructImageFilter\"];\n * BeforeSoftThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterSoftThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * SubtractTwo [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n *\n * Input0 -> BeforeZeroMultiply [arrowhead=none];\n * BeforeZeroMultiply -> ZeroMultiply;\n * BeforeZeroMultiply -> G [label=\"g'_0\"];\n * ZeroMultiply -> AfterZeroMultiply;\n * BeforeZeroMultiply -> ConjugateGradient [label=\"f_0\"];\n * Input1 -> Displaced;\n * Displaced -> BackProjection;\n * AfterZeroMultiply -> D [label=\"d'_0\"];\n * AfterZeroMultiply -> BackProjection;\n * D -> Add;\n * G -> Add;\n * D -> Subtract;\n * Add -> Multiply [label=\"d'_k + g'_k\"];\n * Multiply -> AddTwo [label=\"beta (d'_k + g'_k)\"];\n * BackProjection -> AddTwo;\n * AddTwo -> ConjugateGradient [label=\"b\"];\n * ConjugateGradient -> AfterConjugateGradient [label=\"f_k+1\"];\n * AfterConjugateGradient -> Subtract;\n * Subtract -> BeforeSoftThreshold [arrowhead=none, label=\"f_k+1 - d'k\"];\n * BeforeSoftThreshold -> SoftThreshold;\n * BeforeSoftThreshold -> SubtractTwo;\n * SoftThreshold -> AfterSoftThreshold [arrowhead=none];\n * AfterSoftThreshold -> SubtractTwo [label=\"g'_k+1\"];\n * AfterSoftThreshold -> G [style=dashed, constraint=false];\n * SubtractTwo -> D [style=dashed, label=\"d'_k+1\"];\n * AfterConjugateGradient -> BeforeZeroMultiply [style=dashed];\n * AfterConjugateGradient -> Output [style=dashed];\n * }\n * \\enddot\n *\n * \\test rtkadmmwaveletstest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TOutputImage>\nclass ITK_TEMPLATE_EXPORT ADMMWaveletsConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<TOutputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ADMMWaveletsConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = ADMMWaveletsConeBeamReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<TOutputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ADMMWaveletsConeBeamReconstructionFilter);\n\n  //    /** The 3D image to be updated */\n  //    void SetInputVolume(const TOutputImage* Volume);\n\n  //    /** The gated measured projections */\n  //    void SetInputProjectionStack(const TOutputImage* Projection);\n\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<TOutputImage, TOutputImage>;\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<TOutputImage, TOutputImage>;\n  using ConjugateGradientFilterType = rtk::ConjugateGradientImageFilter<TOutputImage>;\n  using SubtractFilterType = itk::SubtractImageFilter<TOutputImage>;\n  using AddFilterType = itk::AddImageFilter<TOutputImage>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<TOutputImage>;\n  using CGOperatorFilterType = rtk::ADMMWaveletsConjugateGradientOperator<TOutputImage>;\n  using SoftThresholdFilterType = rtk::DeconstructSoftThresholdReconstructImageFilter<TOutputImage>;\n  using DisplacedDetectorFilterType = rtk::DisplacedDetectorImageFilter<TOutputImage>;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** Pass the geometry to all filters needing it */\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  itkSetMacro(Alpha, float);\n  itkGetMacro(Alpha, float);\n\n  itkSetMacro(Beta, float);\n  itkGetMacro(Beta, float);\n\n  itkSetMacro(AL_iterations, float);\n  itkGetMacro(AL_iterations, float);\n\n  itkSetMacro(CG_iterations, float);\n  itkGetMacro(CG_iterations, float);\n\n  itkSetMacro(Order, unsigned int);\n  itkGetMacro(Order, unsigned int);\n\n  itkSetMacro(NumberOfLevels, unsigned int);\n  itkGetMacro(NumberOfLevels, unsigned int);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  ADMMWaveletsConeBeamReconstructionFilter();\n  ~ADMMWaveletsConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename SubtractFilterType::Pointer          m_SubtractFilter1;\n  typename SubtractFilterType::Pointer          m_SubtractFilter2;\n  typename MultiplyFilterType::Pointer          m_MultiplyFilter;\n  typename MultiplyFilterType::Pointer          m_ZeroMultiplyFilter;\n  typename AddFilterType::Pointer               m_AddFilter1;\n  typename AddFilterType::Pointer               m_AddFilter2;\n  typename ConjugateGradientFilterType::Pointer m_ConjugateGradientFilter;\n  typename SoftThresholdFilterType::Pointer     m_SoftThresholdFilter;\n  typename CGOperatorFilterType::Pointer        m_CGOperator;\n  typename ForwardProjectionImageFilter<TOutputImage, TOutputImage>::Pointer\n                                                                          m_ForwardProjectionFilterForConjugateGradient;\n  typename BackProjectionImageFilter<TOutputImage, TOutputImage>::Pointer m_BackProjectionFilterForConjugateGradient;\n  typename BackProjectionImageFilter<TOutputImage, TOutputImage>::Pointer m_BackProjectionFilter;\n  typename DisplacedDetectorFilterType::Pointer                           m_DisplacedDetectorFilter;\n\n  /** The inputs of this filter have the same type (float, 3) but not the same meaning\n   * It is normal that they do not occupy the same physical space. Therefore this check\n   * must be removed */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n\nprivate:\n  float        m_Alpha{ 1 };\n  float        m_Beta{ 1 };\n  unsigned int m_AL_iterations{ 10 };\n  unsigned int m_CG_iterations{ 3 };\n  unsigned int m_Order{ 3 };\n  unsigned int m_NumberOfLevels{ 5 };\n  bool         m_DisableDisplacedDetectorFilter;\n\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkADMMWaveletsConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkADMMWaveletsConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkADMMWaveletsConeBeamReconstructionFilter_hxx\n#define rtkADMMWaveletsConeBeamReconstructionFilter_hxx\n\n\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage>\nADMMWaveletsConeBeamReconstructionFilter<TOutputImage>::ADMMWaveletsConeBeamReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Create the filters\n  m_ZeroMultiplyFilter = MultiplyFilterType::New();\n  m_SubtractFilter1 = SubtractFilterType::New();\n  m_SubtractFilter2 = SubtractFilterType::New();\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_AddFilter1 = AddFilterType::New();\n  m_AddFilter2 = AddFilterType::New();\n  m_ConjugateGradientFilter = ConjugateGradientFilterType::New();\n  m_SoftThresholdFilter = SoftThresholdFilterType::New();\n  m_CGOperator = CGOperatorFilterType::New();\n  m_ConjugateGradientFilter->SetA(m_CGOperator.GetPointer());\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n\n  // Set permanent connections\n  m_AddFilter1->SetInput2(m_ZeroMultiplyFilter->GetOutput());\n  m_MultiplyFilter->SetInput1(m_AddFilter1->GetOutput());\n  m_AddFilter2->SetInput1(m_MultiplyFilter->GetOutput());\n  m_ConjugateGradientFilter->SetB(m_AddFilter2->GetOutput());\n  m_SubtractFilter1->SetInput1(m_ConjugateGradientFilter->GetOutput());\n  m_SubtractFilter1->SetInput2(m_ZeroMultiplyFilter->GetOutput());\n  m_SoftThresholdFilter->SetInput(m_SubtractFilter1->GetOutput());\n  m_SubtractFilter2->SetInput1(m_SoftThresholdFilter->GetOutput());\n  m_SubtractFilter2->SetInput2(m_SubtractFilter1->GetOutput());\n\n  // Set permanent parameters\n  m_ZeroMultiplyFilter->SetConstant2(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n  m_DisableDisplacedDetectorFilter = false;\n  // Not in place to avoid reading the projections twice\n  m_DisplacedDetectorFilter->SetInPlace(false);\n\n  // Set memory management parameters\n  m_ZeroMultiplyFilter->ReleaseDataFlagOn();\n  m_AddFilter1->ReleaseDataFlagOn();\n  m_AddFilter2->ReleaseDataFlagOn();\n  m_MultiplyFilter->ReleaseDataFlagOn();\n  m_ConjugateGradientFilter->ReleaseDataFlagOff(); // Output is f_k+1\n  m_SubtractFilter1->ReleaseDataFlagOff();         // Output used in two filters\n  m_SoftThresholdFilter->ReleaseDataFlagOff();     // Output is g_k+1\n  m_SubtractFilter2->ReleaseDataFlagOff();         // Output is d_k+1\n  m_DisplacedDetectorFilter->ReleaseDataFlagOn();\n}\n\ntemplate <class TOutputImage>\nvoid\nADMMWaveletsConeBeamReconstructionFilter<TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConeBeamReconstructionFilter<TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the volume we update\n  typename Superclass::InputImagePointer inputPtr0 = const_cast<TOutputImage *>(this->GetInput(0));\n  if (!inputPtr0)\n  {\n    return;\n  }\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the stack of projections to backproject\n  typename Superclass::InputImagePointer inputPtr1 = const_cast<TOutputImage *>(this->GetInput(1));\n  if (!inputPtr1)\n  {\n    return;\n  }\n  inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConeBeamReconstructionFilter<TOutputImage>::GenerateOutputInformation()\n{\n  // Set forward projection filter\n  m_ForwardProjectionFilterForConjugateGradient =\n    this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n  // Pass the ForwardProjection filter to the conjugate gradient operator\n  m_CGOperator->SetForwardProjectionFilter(m_ForwardProjectionFilterForConjugateGradient);\n\n  // Set back projection filter\n  m_BackProjectionFilter = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  // Pass the backprojection filter to the conjugate gradient operator and to the back projection filter generating the\n  // B of AX=B\n  m_BackProjectionFilterForConjugateGradient =\n    this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  m_CGOperator->SetBackProjectionFilter(m_BackProjectionFilterForConjugateGradient);\n\n  // Set runtime connections\n  m_ZeroMultiplyFilter->SetInput1(this->GetInput(0));\n  m_CGOperator->SetInput(1, this->GetInput(1)); // The projections (the conjugate gradient operator needs them)\n  m_CGOperator->SetBeta(m_Beta);\n  m_ConjugateGradientFilter->SetX(this->GetInput(0));\n  m_MultiplyFilter->SetConstant2(m_Beta);\n  m_DisplacedDetectorFilter->SetInput(this->GetInput(1));\n\n  // Links with the m_BackProjectionFilter should be set here and not\n  // in the constructor, as m_BackProjectionFilter is set at runtime\n  m_BackProjectionFilter->SetInput(0, m_ZeroMultiplyFilter->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_DisplacedDetectorFilter->GetOutput());\n  m_AddFilter1->SetInput1(this->GetInput(0));\n  m_AddFilter2->SetInput2(m_BackProjectionFilter->GetOutput());\n\n  // For the same reason, set geometry now\n  m_CGOperator->SetGeometry(this->m_Geometry);\n  m_BackProjectionFilter->SetGeometry(this->m_Geometry.GetPointer());\n  m_DisplacedDetectorFilter->SetGeometry(this->m_Geometry);\n\n  // Set runtime parameters\n  m_ConjugateGradientFilter->SetNumberOfIterations(this->m_CG_iterations);\n  m_SoftThresholdFilter->SetNumberOfLevels(this->GetNumberOfLevels());\n  m_SoftThresholdFilter->SetOrder(this->GetOrder());\n  m_SoftThresholdFilter->SetThreshold(m_Alpha / (2 * m_Beta));\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n  m_CGOperator->SetDisableDisplacedDetectorFilter(m_DisableDisplacedDetectorFilter);\n\n  // Have the last filter calculate its output information\n  m_SubtractFilter2->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_SubtractFilter2->GetOutput());\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConeBeamReconstructionFilter<TOutputImage>::GenerateData()\n{\n  typename TOutputImage::Pointer f_k_plus_one;\n  typename TOutputImage::Pointer W_t_G_k_plus_one;\n  typename TOutputImage::Pointer W_t_D_k_plus_one;\n\n  itk::IterationReporter iterationReporter(this, 0, 1);\n\n  for (unsigned int iter = 0; iter < m_AL_iterations; iter++)\n  {\n    // After the first update, we need to use some outputs as inputs\n    if (iter > 0)\n    {\n      f_k_plus_one = m_ConjugateGradientFilter->GetOutput();\n      f_k_plus_one->DisconnectPipeline();\n      m_ConjugateGradientFilter->SetX(f_k_plus_one);\n\n      W_t_G_k_plus_one = m_SoftThresholdFilter->GetOutput();\n      W_t_G_k_plus_one->DisconnectPipeline();\n      m_AddFilter1->SetInput1(W_t_G_k_plus_one);\n\n      W_t_D_k_plus_one = m_SubtractFilter2->GetOutput();\n      W_t_D_k_plus_one->DisconnectPipeline();\n      m_AddFilter1->SetInput2(W_t_D_k_plus_one);\n      m_SubtractFilter1->SetInput2(W_t_D_k_plus_one);\n\n      // Recreate the links destroyed by DisconnectPipeline\n      m_SubtractFilter1->SetInput1(m_ConjugateGradientFilter->GetOutput());\n      m_SubtractFilter2->SetInput1(m_SoftThresholdFilter->GetOutput());\n    }\n    m_SubtractFilter2->Update();\n    this->GraftOutput(m_ConjugateGradientFilter->GetOutput());\n    iterationReporter.CompletedStep();\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkADMMWaveletsConjugateGradientOperator.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkADMMWaveletsConjugateGradientOperator_h\n#define rtkADMMWaveletsConjugateGradientOperator_h\n\n#include <itkMultiplyImageFilter.h>\n#include <itkAddImageFilter.h>\n\n#include \"rtkConjugateGradientOperator.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class ADMMWaveletsConjugateGradientOperator\n * \\brief Implements the operator A used in the conjugate gradient step\n * of ADMM reconstruction with wavelets regularization\n *\n * This filter implements the operator A used in the conjugate gradient step\n * of a reconstruction method based on compressed sensing. The method attempts\n * to find the f that minimizes || Rf -p ||_2^2 + alpha * || W(f) ||_1, with R the\n * forward projection operator, p the measured projections, and W the\n * Daubechies wavelets transform.\n * Details on the method and the calculations can be found in\n *\n * Mory, C., B. Zhang, V. Auvray, M. Grass, D. Schafer, F. Peyrin, S. Rit, P. Douek,\n * and L. Boussel. \"ECG-Gated C-Arm Computed Tomography Using L1 Regularization.\"\n * In Proceedings of the 20th European Signal Processing Conference (EUSIPCO), 2728-32, 2012.\n *\n * This filter takes in input f and outputs R_t R f + beta * W_t W f. The Daubechies\n * wavelets being orthogonal, W_t happens to be the inverse of W, and therefore\n * the filter outputs R_t R f + beta * f\n *\n * \\dot\n * digraph ADMMWaveletsConjugateGradientOperator {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Volume)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * ZeroMultiplyVolume [label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * ZeroMultiplyProjections [label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * BeforeZeroMultiplyVolume [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Add [ label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n * Multiply [ label=\"itk::MultiplyImageFilter (by lambda)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * BackProjection [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * ForwardProjection [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n *\n * Input0 -> BeforeZeroMultiplyVolume [arrowhead=none];\n * BeforeZeroMultiplyVolume -> ZeroMultiplyVolume;\n * BeforeZeroMultiplyVolume -> ForwardProjection;\n * BeforeZeroMultiplyVolume -> Multiply;\n * Input1 -> ZeroMultiplyProjections;\n * ZeroMultiplyProjections -> ForwardProjection;\n * ZeroMultiplyVolume -> BackProjection;\n * ForwardProjection -> Displaced;\n * Displaced -> BackProjection;\n * BackProjection -> Add;\n * Multiply -> Add;\n * Add -> Output;\n *\n * }\n * \\enddot\n *\n * \\test rtkadmmWaveletstest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TOutputImage>\nclass ITK_TEMPLATE_EXPORT ADMMWaveletsConjugateGradientOperator : public ConjugateGradientOperator<TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ADMMWaveletsConjugateGradientOperator);\n\n  /** Standard class type alias. */\n  using Self = ADMMWaveletsConjugateGradientOperator;\n  using Superclass = ConjugateGradientOperator<TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ADMMWaveletsConjugateGradientOperator);\n\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<TOutputImage, TOutputImage>;\n  using BackProjectionFilterPointer = typename BackProjectionFilterType::Pointer;\n\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<TOutputImage, TOutputImage>;\n  using ForwardProjectionFilterPointer = typename ForwardProjectionFilterType::Pointer;\n\n  using MultiplyFilterType = itk::MultiplyImageFilter<TOutputImage>;\n  using AddFilterType = itk::AddImageFilter<TOutputImage>;\n\n  using DisplacedDetectorFilterType = rtk::DisplacedDetectorImageFilter<TOutputImage>;\n\n  /** Set the backprojection filter*/\n  void\n  SetBackProjectionFilter(BackProjectionFilterType * _arg);\n\n  /** Set the forward projection filter*/\n  void\n  SetForwardProjectionFilter(ForwardProjectionFilterType * _arg);\n\n  /** Set the geometry of both m_BackProjectionFilter and m_ForwardProjectionFilter */\n  void\n  SetGeometry(ThreeDCircularProjectionGeometry * _arg);\n\n  /** Set the regularization parameter */\n  itkSetMacro(Beta, float);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  ADMMWaveletsConjugateGradientOperator();\n  ~ADMMWaveletsConjugateGradientOperator() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  BackProjectionFilterPointer    m_BackProjectionFilter;\n  ForwardProjectionFilterPointer m_ForwardProjectionFilter;\n\n  typename AddFilterType::Pointer               m_AddFilter;\n  typename MultiplyFilterType::Pointer          m_MultiplyFilter;\n  typename MultiplyFilterType::Pointer          m_ZeroMultiplyProjectionFilter;\n  typename MultiplyFilterType::Pointer          m_ZeroMultiplyVolumeFilter;\n  typename DisplacedDetectorFilterType::Pointer m_DisplacedDetectorFilter;\n\n  float m_Beta;\n  bool  m_DisableDisplacedDetectorFilter;\n\n  /** When the inputs have the same type, ITK checks whether they occupy the\n   * same physical space or not. Obviously they dont, so we have to remove this check\n   */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkADMMWaveletsConjugateGradientOperator.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkADMMWaveletsConjugateGradientOperator.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkADMMWaveletsConjugateGradientOperator_hxx\n#define rtkADMMWaveletsConjugateGradientOperator_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage>\nADMMWaveletsConjugateGradientOperator<TOutputImage>::ADMMWaveletsConjugateGradientOperator()\n{\n  this->SetNumberOfRequiredInputs(2);\n  this->m_Beta = 0;\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_ZeroMultiplyProjectionFilter = MultiplyFilterType::New();\n  m_ZeroMultiplyVolumeFilter = MultiplyFilterType::New();\n  m_AddFilter = AddFilterType::New();\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n\n  // Set permanent connections\n  m_AddFilter->SetInput2(m_MultiplyFilter->GetOutput());\n\n  // Set permanent parameters\n  m_ZeroMultiplyProjectionFilter->SetConstant2(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_ZeroMultiplyVolumeFilter->SetConstant2(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n  m_DisableDisplacedDetectorFilter = false;\n\n  // Set memory management options\n  m_ZeroMultiplyProjectionFilter->ReleaseDataFlagOn();\n  m_ZeroMultiplyVolumeFilter->ReleaseDataFlagOn();\n  m_MultiplyFilter->ReleaseDataFlagOn();\n  m_AddFilter->ReleaseDataFlagOff();\n  m_DisplacedDetectorFilter->ReleaseDataFlagOn();\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConjugateGradientOperator<TOutputImage>::SetBackProjectionFilter(BackProjectionFilterType * _arg)\n{\n  if (m_BackProjectionFilter != _arg)\n    this->Modified();\n  m_BackProjectionFilter = _arg;\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConjugateGradientOperator<TOutputImage>::SetForwardProjectionFilter(ForwardProjectionFilterType * _arg)\n{\n  if (m_ForwardProjectionFilter != _arg)\n    this->Modified();\n  m_ForwardProjectionFilter = _arg;\n}\n\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConjugateGradientOperator<TOutputImage>::SetGeometry(ThreeDCircularProjectionGeometry * _arg)\n{\n  m_BackProjectionFilter->SetGeometry(_arg);\n  m_ForwardProjectionFilter->SetGeometry(_arg);\n  m_DisplacedDetectorFilter->SetGeometry(_arg);\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConjugateGradientOperator<TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the volume in which we backproject\n  typename Superclass::InputImagePointer inputPtr0 = const_cast<TOutputImage *>(this->GetInput(0));\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the stack of projections to backproject\n  typename Superclass::InputImagePointer inputPtr1 = const_cast<TOutputImage *>(this->GetInput(1));\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConjugateGradientOperator<TOutputImage>::GenerateOutputInformation()\n{\n  // Set runtime connections, and connections with\n  // forward and back projection filters, which are set\n  // at runtime\n  m_ForwardProjectionFilter->SetInput(0, m_ZeroMultiplyProjectionFilter->GetOutput());\n  m_DisplacedDetectorFilter->SetInput(m_ForwardProjectionFilter->GetOutput());\n  m_BackProjectionFilter->SetInput(0, m_ZeroMultiplyVolumeFilter->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_DisplacedDetectorFilter->GetOutput());\n  m_AddFilter->SetInput1(m_BackProjectionFilter->GetOutput());\n  m_ZeroMultiplyVolumeFilter->SetInput1(this->GetInput(0));\n  m_ZeroMultiplyProjectionFilter->SetInput1(this->GetInput(1));\n  m_ForwardProjectionFilter->SetInput(1, this->GetInput(0));\n  m_MultiplyFilter->SetInput1(this->GetInput(0));\n\n  // Set runtime parameters\n  m_MultiplyFilter->SetConstant2(m_Beta);\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n\n  // Set memory management parameters for forward\n  // and back projection filters\n  m_ForwardProjectionFilter->ReleaseDataFlagOn();\n  m_BackProjectionFilter->ReleaseDataFlagOn();\n\n  // Have the last filter calculate its output information\n  m_AddFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_AddFilter->GetOutput());\n}\n\ntemplate <typename TOutputImage>\nvoid\nADMMWaveletsConjugateGradientOperator<TOutputImage>::GenerateData()\n{\n  // Execute Pipeline\n  m_AddFilter->Update();\n\n  // Get the output\n  this->GraftOutput(m_AddFilter->GetOutput());\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkAddMatrixAndDiagonalImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkAddMatrixAndDiagonalImageFilter_h\n#define rtkAddMatrixAndDiagonalImageFilter_h\n\n#include \"itkImageToImageFilter.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class AddMatrixAndDiagonalImageFilter\n * \\brief For each vector-valued pixel, adds a vector to the diagonal of a matrix\n *\n * This filter takes in input an image of vectors of length n (input 1)\n * and an image of vectors of length n*n (input 2). The vectors in input 2\n * are used as n*n matrices, and those in input 1 are assumed to be a compact\n * representation of diagonal matrices of size n*n (thus with only n non-null\n * values).\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <class TDiagonal,\n          class TMatrix = itk::Image<itk::Vector<typename TDiagonal::PixelType::ValueType,\n                                                 TDiagonal::PixelType::Dimension * TDiagonal::PixelType::Dimension>,\n                                     TDiagonal::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT AddMatrixAndDiagonalImageFilter : public itk::ImageToImageFilter<TMatrix, TMatrix>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(AddMatrixAndDiagonalImageFilter);\n\n  /** Standard class type alias. */\n  using Self = AddMatrixAndDiagonalImageFilter;\n  using Superclass = itk::ImageToImageFilter<TMatrix, TMatrix>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(AddMatrixAndDiagonalImageFilter);\n\n  /** Convenient parameters extracted from template types */\n  static constexpr unsigned int nChannels = TDiagonal::PixelType::Dimension;\n\n  /** Convenient type alias */\n  using dataType = typename TDiagonal::PixelType::ValueType;\n\n  /** Set methods for all inputs, since they have different types */\n  void\n  SetInputDiagonal(const TDiagonal * gradient);\n  void\n  SetInputMatrix(const TMatrix * hessian);\n\nprotected:\n  AddMatrixAndDiagonalImageFilter();\n  ~AddMatrixAndDiagonalImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  DynamicThreadedGenerateData(const typename TDiagonal::RegionType & outputRegionForThread) override;\n\n  /** Getters for the inputs */\n  typename TDiagonal::ConstPointer\n  GetInputDiagonal();\n  typename TMatrix::ConstPointer\n  GetInputMatrix();\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkAddMatrixAndDiagonalImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkAddMatrixAndDiagonalImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkAddMatrixAndDiagonalImageFilter_hxx\n#define rtkAddMatrixAndDiagonalImageFilter_hxx\n\n#include \"itkImageRegionIteratorWithIndex.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"vnl/vnl_inverse.h\"\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <class TDiagonal, class TMatrix>\nAddMatrixAndDiagonalImageFilter<TDiagonal, TMatrix>::AddMatrixAndDiagonalImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n}\n\ntemplate <class TDiagonal, class TMatrix>\nvoid\nAddMatrixAndDiagonalImageFilter<TDiagonal, TMatrix>::SetInputMatrix(const TMatrix * hessian)\n{\n  this->SetNthInput(0, const_cast<TMatrix *>(hessian));\n}\n\ntemplate <class TDiagonal, class TMatrix>\nvoid\nAddMatrixAndDiagonalImageFilter<TDiagonal, TMatrix>::SetInputDiagonal(const TDiagonal * gradient)\n{\n  this->SetNthInput(1, const_cast<TDiagonal *>(gradient));\n}\n\ntemplate <class TDiagonal, class TMatrix>\ntypename TMatrix::ConstPointer\nAddMatrixAndDiagonalImageFilter<TDiagonal, TMatrix>::GetInputMatrix()\n{\n  return static_cast<const TMatrix *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <class TDiagonal, class TMatrix>\ntypename TDiagonal::ConstPointer\nAddMatrixAndDiagonalImageFilter<TDiagonal, TMatrix>::GetInputDiagonal()\n{\n  return static_cast<const TDiagonal *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <class TDiagonal, class TMatrix>\nvoid\nAddMatrixAndDiagonalImageFilter<TDiagonal, TMatrix>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get the requested regions on both outputs (should be identical)\n  typename TDiagonal::RegionType outputRequested = this->GetOutput()->GetRequestedRegion();\n\n  // Get pointers to the inputs\n  typename TMatrix::Pointer   input0Ptr = const_cast<TMatrix *>(this->GetInputMatrix().GetPointer());\n  typename TDiagonal::Pointer input1Ptr = const_cast<TDiagonal *>(this->GetInputDiagonal().GetPointer());\n\n  // The first and second input must have the same requested region as the outputs\n  input1Ptr->SetRequestedRegion(outputRequested);\n  input0Ptr->SetRequestedRegion(outputRequested);\n}\n\ntemplate <class TDiagonal, class TMatrix>\nvoid\nAddMatrixAndDiagonalImageFilter<TDiagonal, TMatrix>::DynamicThreadedGenerateData(\n  const typename TDiagonal::RegionType & outputRegionForThread)\n{\n  // Create iterators for all inputs and outputs\n  itk::ImageRegionIterator<TMatrix>        outIt(this->GetOutput(), outputRegionForThread);\n  itk::ImageRegionConstIterator<TDiagonal> diagIt(this->GetInputDiagonal(), outputRegionForThread);\n  itk::ImageRegionConstIterator<TMatrix>   matIt(this->GetInputMatrix(), outputRegionForThread);\n\n  itk::Vector<dataType, nChannels * nChannels> forOutput;\n\n  while (!outIt.IsAtEnd())\n  {\n    // Make a vnl matrix out of the values read in input 2 (the hessian, but stored in a vector)\n    forOutput = matIt.Get();\n    for (unsigned int i = 0; i < nChannels; i++)\n      forOutput[i * (nChannels + 1)] += diagIt.Get()[i];\n\n    outIt.Set(forOutput);\n\n    ++outIt;\n    ++diagIt;\n    ++matIt;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkAdditiveGaussianNoiseImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/*=========================================================================\n *\n *  Copyright NumFOCUS\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkAdditiveGaussianNoiseImageFilter_h\n#define rtkAdditiveGaussianNoiseImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkNormalVariateGenerator.h>\n#include <itkUnaryFunctorImageFilter.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class NormalVariateNoiseFunctor\n *\n * \\brief Pixel functor that adds Gaussian noise.\n *\n * \\author Gavin Baker: gavinb at cs_mu_oz_au\n *\n * \\ingroup RTK\n */\ntemplate <class TPixel>\nclass ITK_TEMPLATE_EXPORT NormalVariateNoiseFunctor\n{\npublic:\n  NormalVariateNoiseFunctor()\n  {\n    m_Mean = 0.0;\n    m_StandardDeviation = 1.0;\n\n    m_Generator = itk::Statistics::NormalVariateGenerator::New();\n\n    this->SetSeed(42);\n  }\n\n  float\n  GetMean() const\n  {\n    return m_Mean;\n  }\n\n  void\n  SetMean(float mean)\n  {\n    m_Mean = mean;\n  }\n\n  float\n  GetStandardDeviation() const\n  {\n    return m_StandardDeviation;\n  }\n\n  void\n  SetStandardDeviation(float stddev)\n  {\n    m_StandardDeviation = stddev;\n  }\n\n  void\n  SetSeed(unsigned long seed)\n  {\n    m_Generator->Initialize(seed);\n  }\n\n  void\n  SetOutputMinimum(TPixel min)\n  {\n    m_OutputMinimum = min;\n  }\n\n  void\n  SetOutputMaximum(TPixel max)\n  {\n    m_OutputMaximum = max;\n  }\n\n  TPixel\n  GetOutputMinimum() const\n  {\n    return m_OutputMinimum;\n  }\n\n  TPixel\n  GetOutputMaximum() const\n  {\n    return m_OutputMaximum;\n  }\n\n  TPixel\n  operator()(TPixel input)\n  {\n    // Get the minimum and maximum output values\n    static const auto min = static_cast<float>(m_OutputMinimum);\n    static const auto max = static_cast<float>(m_OutputMaximum);\n\n    // Compute the output\n    float output = static_cast<float>(input) + m_Mean + m_StandardDeviation * m_Generator->GetVariate();\n\n    // Clamp the output value in valid range\n    output = (output < min ? min : output);\n    output = (output > max ? max : output);\n\n    return static_cast<TPixel>(output);\n  }\n\nprivate:\n  TPixel                                           m_OutputMinimum;\n  TPixel                                           m_OutputMaximum;\n  float                                            m_Mean;\n  float                                            m_StandardDeviation;\n  itk::Statistics::NormalVariateGenerator::Pointer m_Generator;\n};\n\n\n/** \\class AdditiveGaussianNoiseImageFilter\n * \\brief Adds Gaussian noise to the input image\n *\n * Adds noise to the input image according to a Gaussian normal variate\n * distribution.  The user supplies the mean \\f$\\bar{x}\\f$ and standard\n * deviation \\f$\\sigma\\f$, such that the output is given by:\n *\n * \\f[\n *     v_{out} = v_{in} + \\bar{x} + \\sigma * G(d)\n * \\f]\n *\n * where G() is the Gaussian generator and d is the seed.  A particular seed\n * can be specified in order to perform repeatable tests.\n *\n * \\test rtkrampfiltertest.cxx\n *\n * \\author Gavin Baker: gavinb at cs_mu_oz_au\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage>\nclass ITK_TEMPLATE_EXPORT AdditiveGaussianNoiseImageFilter : public itk::ImageToImageFilter<TInputImage, TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(AdditiveGaussianNoiseImageFilter);\n\n  /** Standard class type alias. */\n  using Self = AdditiveGaussianNoiseImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(AdditiveGaussianNoiseImageFilter);\n\n  /** Superclass type alias. */\n  using OutputImageRegionType = typename Superclass::OutputImageRegionType;\n  using OutputImagePointer = typename Superclass::OutputImagePointer;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using InputImageConstPointer = typename InputImageType::ConstPointer;\n  using InputImageRegionType = typename InputImageType::RegionType;\n  using InputImagePixelType = typename InputImageType::PixelType;\n  using InputPixelType = typename InputImageType::PixelType;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n\n  // virtual void GenerateOutputInformation();\n\n  void\n  GenerateData() override;\n\n  // Accessor & Mutator methods\n\n  /**\n   *    Specifies the average noise added to the image per pixel.\n   *    The default is 0.\n   */\n  void\n  SetMean(float mean)\n  {\n    m_NoiseFilter->GetFunctor().SetMean(mean);\n    this->Modified();\n  }\n\n  /**\n   *    Returns the average noise added to the image per pixel.\n   *    The default is 0.\n   */\n  float\n  GetMean() const\n  {\n    return m_NoiseFilter->GetFunctor().GetMean();\n  }\n\n  /**\n   *    Specifies the standard deviation of the noise added to the image.\n   *    The default is 1.\n   */\n  void\n  SetStandardDeviation(float stddev)\n  {\n    m_NoiseFilter->GetFunctor().SetStandardDeviation(stddev);\n    this->Modified();\n  }\n\n  /**\n   *    Returns the standard deviation of the noise added to the image.\n   *    The default is 1.\n   */\n  float\n  GetStandardDeviation() const\n  {\n    return m_NoiseFilter->GetFunctor().GetStandardDeviation();\n  }\n\n  /**\n   *    Specifies the seed for the normal variate generator.  The same seed\n   *    will produce the same pseduo-random sequence, which can be used to\n   *    reproduce results.  For a higher dose of entropy, initialise with\n   *    the current system time (in ms).\n   */\n  void\n  SetSeed(unsigned long seed)\n  {\n    m_NoiseFilter->GetFunctor().SetSeed(seed);\n    this->Modified();\n  }\n\n  /** Set the minimum output value. */\n  void\n  SetOutputMinimum(InputImagePixelType min)\n  {\n    if (min == m_NoiseFilter->GetFunctor().GetOutputMinimum())\n    {\n      return;\n    }\n    m_NoiseFilter->GetFunctor().SetOutputMinimum(min);\n    this->Modified();\n  }\n\n  /** Get the minimum output value. */\n  InputImagePixelType\n  GetOutputMinimum()\n  {\n    return m_NoiseFilter->GetFunctor().GetOutputMinimum();\n  }\n\n  /** Set the maximum output value. */\n  void\n  SetOutputMaximum(InputImagePixelType max)\n  {\n    if (max == m_NoiseFilter->GetFunctor().GetOutputMaximum())\n    {\n      return;\n    }\n    m_NoiseFilter->GetFunctor().SetOutputMaximum(max);\n    this->Modified();\n  }\n\n  /** Get the maximum output value. */\n  InputImagePixelType\n  GetOutputMaximum()\n  {\n    return m_NoiseFilter->GetFunctor().GetOutputMaximum();\n  }\n\nprotected:\n  AdditiveGaussianNoiseImageFilter();\n\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\npublic:\n  using NoiseFilterType = itk::UnaryFunctorImageFilter<InputImageType,\n                                                       InputImageType,\n                                                       NormalVariateNoiseFunctor<typename InputImageType::PixelType>>;\n\nprivate:\n  typename NoiseFilterType::Pointer m_NoiseFilter;\n};\n\n} /* end namespace rtk */\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkAdditiveGaussianNoiseImageFilter.hxx\"\n#endif\n\n#endif /* rtkAdditiveGaussianNoiseImageFilter_h */\n"
  },
  {
    "path": "include/rtkAdditiveGaussianNoiseImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/*=========================================================================\n *\n *  Copyright NumFOCUS\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkAdditiveGaussianNoiseImageFilter_hxx\n#define rtkAdditiveGaussianNoiseImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <class TInputImage>\nAdditiveGaussianNoiseImageFilter<TInputImage>::AdditiveGaussianNoiseImageFilter()\n{\n  m_NoiseFilter = NoiseFilterType::New();\n  m_NoiseFilter->GetFunctor().SetOutputMinimum(itk::NumericTraits<InputPixelType>::NonpositiveMin());\n  m_NoiseFilter->GetFunctor().SetOutputMaximum(itk::NumericTraits<InputPixelType>::max());\n}\n\n\ntemplate <class TInputImage>\nvoid\nAdditiveGaussianNoiseImageFilter<TInputImage>::GenerateData()\n{\n  this->AllocateOutputs();\n\n  // Set the global max number of threads to 1\n  // NOTE: This is required because there is a bug with this filter,\n  // it appears the NormalVariateGenerate is single threaded only.\n  m_NoiseFilter->SetNumberOfWorkUnits(1);\n\n  // Setup grafted pipeline for composite filter\n  m_NoiseFilter->SetInput(this->GetInput());\n  m_NoiseFilter->Update();\n  this->GraftOutput(m_NoiseFilter->GetOutput());\n}\n\ntemplate <class TInputImage>\nvoid\nAdditiveGaussianNoiseImageFilter<TInputImage>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  os << indent << \"AdditiveGaussianNoiseImageFilter\"\n     << \"\\n Mean: \" << this->GetMean() << \"\\n StandardDeviation: \" << this->GetStandardDeviation() << std::endl;\n}\n\n} /* namespace rtk */\n\n#endif // rtkAdditiveGaussianNoiseImageFilter_hxx\n"
  },
  {
    "path": "include/rtkAmsterdamShroudImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkAmsterdamShroudImageFilter_h\n#define rtkAmsterdamShroudImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkRecursiveGaussianImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n#include <itkThresholdImageFilter.h>\n#include <itkSumProjectionImageFilter.h>\n#include <itkConvolutionImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkPermuteAxesImageFilter.h>\n#include <itkCropImageFilter.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class AmsterdamShroudImageFilter\n * \\brief Compute the Amsterdam shroud image for respiratory signal extraction.\n *\n * The Amsterdam shroud is an image that is used to extract a respiratory\n * signal from cone-beam projection images. The Y-axis is time and the X-axis\n * is the cranio-caudal position. More information is available in\n * [Zijp, ICCR, 2004], [Sonke, Med Phys, 2005] and [Rit, IJROBP, 2012].\n *\n * The following mini-pipeline of ITK filters is used for its RTK implementation:\n *\n * \\dot\n * digraph AmsterdamShroud {\n *\n * Input [label=\"Input (Projections)\", shape=Mdiamond];\n * Output [label=\"Output (Amsterdam Shroud)\", shape=Mdiamond];\n *\n * node [shape=box];\n *\n * Derivative [label=\"itk::RecursiveGaussianImageFilter\" URL=\"\\ref itk::RecursiveGaussianImageFilter\"];\n * Negative [label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * Threshold [label=\"itk::ThresholdImageFilter\" URL=\"\\ref itk::ThresholdImageFilter\"];\n * Sum [label=\"itk::SumProjectionImageFilter\" URL=\"\\ref itk::SumProjectionImageFilter\"];\n * Convolution [label=\"itk::ConvolutionImageFilter\" URL=\"\\ref itk::ConvolutionImageFilter\"];\n * Subtract [label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * Permute [label=\"itk::PermuteAxesImageFilter\" URL=\"\\ref itk::PermuteAxesImageFilter\"];\n *\n * Input->Derivative\n * Derivative->Negative\n * Negative->Threshold\n * Threshold->Sum\n * Sum->Subtract\n * Sum->Convolution\n * Convolution->Subtract\n * Subtract->Permute\n * Permute->Output\n * }\n * \\enddot\n *\n * \\test rtkamsterdamshroudtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage>\nclass ITK_TEMPLATE_EXPORT AmsterdamShroudImageFilter\n  : public itk::ImageToImageFilter<TInputImage, itk::Image<double, TInputImage::ImageDimension - 1>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(AmsterdamShroudImageFilter);\n\n  /** Standard class type alias. */\n  using Self = AmsterdamShroudImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, itk::Image<double, TInputImage::ImageDimension - 1>>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using TOutputImage = itk::Image<double, TInputImage::ImageDimension - 1>;\n  using PointType = itk::Point<double, 3>;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryPointer = typename GeometryType::Pointer;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n  static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension;\n  static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Size parameter of the unsharp mask. This is the number of pixels along the\n   * time direction (X) along which it averages. The unsharp mask allows after\n   * computation of the shroud to enhance fast varying motions, e.g., breathing,\n   * and remove slow varying motions, e.g., rotation around the table. The default\n   * value is 17 pixels. */\n  itkGetMacro(UnsharpMaskSize, unsigned int);\n  itkSetMacro(UnsharpMaskSize, unsigned int);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, GeometryType);\n  itkSetObjectMacro(Geometry, GeometryType);\n\n  /** 3D clipbox corners for selecting part of the projections. Each corner is\n   * projected and rounded to the nearest 2D pixel and only those pixels within\n   * the two pixels are kept. */\n  itkGetMacro(Corner1, PointType);\n  itkSetMacro(Corner1, PointType);\n  itkGetMacro(Corner2, PointType);\n  itkSetMacro(Corner2, PointType);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(AmsterdamShroudImageFilter);\n\nprotected:\n  AmsterdamShroudImageFilter();\n  ~AmsterdamShroudImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  UpdateUnsharpMaskKernel();\n\n  /** Single-threaded version of GenerateData.  This filter delegates\n   * to other filters. */\n  void\n  GenerateData() override;\n\n  /** Function that actually projects the 3D box defined by m_Corner1 and\n   * m_Corner2 and set everything outside to 0. */\n  virtual void\n  CropOutsideProjectedBox();\n\nprivate:\n  using DerivativeType = itk::RecursiveGaussianImageFilter<TInputImage, TInputImage>;\n  using NegativeType = itk::MultiplyImageFilter<TInputImage, TInputImage, TInputImage>;\n  using ThresholdType = itk::ThresholdImageFilter<TInputImage>;\n  using SumType = itk::SumProjectionImageFilter<TInputImage, TOutputImage>;\n  using ConvolutionType = itk::ConvolutionImageFilter<TOutputImage, TOutputImage>;\n  using SubtractType = itk::SubtractImageFilter<TOutputImage, TOutputImage>;\n  using PermuteType = itk::PermuteAxesImageFilter<TOutputImage>;\n\n  typename DerivativeType::Pointer  m_DerivativeFilter;\n  typename NegativeType::Pointer    m_NegativeFilter;\n  typename ThresholdType::Pointer   m_ThresholdFilter;\n  typename SumType::Pointer         m_SumFilter;\n  typename ConvolutionType::Pointer m_ConvolutionFilter;\n  typename SubtractType::Pointer    m_SubtractFilter;\n  typename PermuteType::Pointer     m_PermuteFilter;\n  unsigned int                      m_UnsharpMaskSize{ 17 };\n  GeometryPointer                   m_Geometry{ nullptr };\n  PointType                         m_Corner1{ 0. };\n  PointType                         m_Corner2{ 0. };\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkAmsterdamShroudImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkAmsterdamShroudImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkAmsterdamShroudImageFilter_hxx\n#define rtkAmsterdamShroudImageFilter_hxx\n\n#include \"rtkHomogeneousMatrix.h\"\n\n#include <itkImageFileWriter.h>\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage>\nAmsterdamShroudImageFilter<TInputImage>::AmsterdamShroudImageFilter()\n{\n  m_DerivativeFilter = DerivativeType::New();\n  m_NegativeFilter = NegativeType::New();\n  m_ThresholdFilter = ThresholdType::New();\n  m_SumFilter = SumType::New();\n  m_ConvolutionFilter = ConvolutionType::New();\n  m_SubtractFilter = SubtractType::New();\n  m_PermuteFilter = PermuteType::New();\n\n  m_NegativeFilter->SetInput(m_DerivativeFilter->GetOutput());\n  m_ThresholdFilter->SetInput(m_NegativeFilter->GetOutput());\n  m_SumFilter->SetInput(m_ThresholdFilter->GetOutput());\n  m_ConvolutionFilter->SetInput(m_SumFilter->GetOutput());\n  m_SubtractFilter->SetInput1(m_SumFilter->GetOutput());\n  m_SubtractFilter->SetInput2(m_ConvolutionFilter->GetOutput());\n  m_PermuteFilter->SetInput(m_SubtractFilter->GetOutput());\n\n  m_DerivativeFilter->SetOrder(itk::GaussianOrderEnum::FirstOrder);\n  m_DerivativeFilter->SetDirection(1);\n  m_DerivativeFilter->SetSigma(4);\n\n  m_NegativeFilter->SetConstant(-1.0);\n  m_NegativeFilter->InPlaceOn();\n\n  m_ThresholdFilter->SetUpper(0.0);\n  m_ThresholdFilter->SetOutsideValue(0.0);\n  m_ThresholdFilter->InPlaceOn();\n\n  m_SumFilter->SetProjectionDimension(0);\n\n  // The permute filter is used to allow streaming because ITK splits the output image in the last direction\n  typename PermuteType::PermuteOrderArrayType order;\n  order[0] = 1;\n  order[1] = 0;\n  m_PermuteFilter->SetOrder(order);\n\n  // Create default kernel\n  UpdateUnsharpMaskKernel();\n}\n\ntemplate <class TInputImage>\nvoid\nAmsterdamShroudImageFilter<TInputImage>::GenerateOutputInformation()\n{\n  // get pointers to the input and output\n  typename Superclass::InputImageConstPointer inputPtr = this->GetInput();\n  typename Superclass::OutputImagePointer     outputPtr = this->GetOutput();\n\n  if (!outputPtr || !inputPtr)\n  {\n    return;\n  }\n\n  m_DerivativeFilter->SetInput(this->GetInput());\n  m_PermuteFilter->UpdateOutputInformation();\n  outputPtr->CopyInformation(m_PermuteFilter->GetOutput());\n}\n\ntemplate <class TInputImage>\nvoid\nAmsterdamShroudImageFilter<TInputImage>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput());\n  if (!inputPtr)\n  {\n    return;\n  }\n  m_DerivativeFilter->SetInput(this->GetInput());\n  m_PermuteFilter->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  m_PermuteFilter->GetOutput()->PropagateRequestedRegion();\n}\n\ntemplate <class TInputImage>\nvoid\nAmsterdamShroudImageFilter<TInputImage>::GenerateData()\n{\n  // If there is a geometry set, use it to crop the projections\n  if (m_Geometry.GetPointer())\n    CropOutsideProjectedBox();\n\n  unsigned int kernelWidth = 0;\n  kernelWidth = m_ConvolutionFilter->GetKernelImage()->GetLargestPossibleRegion().GetSize()[1];\n  if (kernelWidth != m_UnsharpMaskSize)\n    UpdateUnsharpMaskKernel();\n\n  // If the convolution filter is not updated independently of the rest of the\n  // pipeline, there is a bug in the streaming and it does not behave as\n  // expected: the largest possible region is modified of the output of the\n  // convolution filter is modified! I don't have an explanation for this but\n  // this seems to fix the problem (SR).\n  m_ConvolutionFilter->Update();\n\n  m_PermuteFilter->Update();\n  this->GraftOutput(m_PermuteFilter->GetOutput());\n}\n\ntemplate <class TInputImage>\nvoid\nAmsterdamShroudImageFilter<TInputImage>::UpdateUnsharpMaskKernel()\n{\n  // Unsharp mask: difference between image and moving average\n  // m_ConvolutionFilter computes the moving average\n  auto                              kernel = TOutputImage::New();\n  typename TOutputImage::RegionType region;\n  region.SetIndex(0, 0);\n  region.SetIndex(1, (int)m_UnsharpMaskSize / -2);\n  region.SetSize(0, 1);\n  region.SetSize(1, m_UnsharpMaskSize);\n  kernel->SetRegions(region);\n  kernel->Allocate();\n  kernel->FillBuffer(1. / m_UnsharpMaskSize);\n  m_ConvolutionFilter->SetKernelImage(kernel);\n}\n\ntemplate <class TInputImage>\nvoid\nAmsterdamShroudImageFilter<TInputImage>::CropOutsideProjectedBox()\n{\n  // The crop is performed after derivation for the sake of simplicity\n  m_DerivativeFilter->Update();\n\n  typename TInputImage::RegionType reg;\n  reg = m_DerivativeFilter->GetOutput()->GetRequestedRegion();\n\n  typename itk::ImageRegionIterator<TInputImage> it(m_DerivativeFilter->GetOutput(), reg);\n\n  // Prepare the 8 corners of the box\n  std::vector<GeometryType::HomogeneousVectorType> corners;\n  for (unsigned int i = 0; i < 8; i++)\n  {\n    GeometryType::HomogeneousVectorType corner;\n    if (i / 4 == 0)\n      corner[2] = m_Corner1[2];\n    else\n      corner[2] = m_Corner2[2];\n    if ((i / 2) % 2 == 0)\n      corner[1] = m_Corner1[1];\n    else\n      corner[1] = m_Corner2[1];\n    if (i % 2 == 0)\n      corner[0] = m_Corner1[0];\n    else\n      corner[0] = m_Corner2[0];\n    corner[3] = 1.;\n    corners.push_back(corner);\n  }\n\n  for (int iProj = reg.GetIndex(2); iProj < reg.GetIndex(2) + (int)reg.GetSize(2); iProj++)\n  {\n    // Project and keep the inferior and superior 2d corner\n    itk::ContinuousIndex<double, 3> pCornerInf, pCornerSup;\n    pCornerInf.Fill(0.); // Useless but removes warning\n    pCornerSup.Fill(0.); // Useless but removes warning\n    GeometryType::MatrixType matrix;\n    matrix = m_Geometry->GetMatrices()[iProj].GetVnlMatrix();\n    for (unsigned int ci = 0; ci < 8; ci++)\n    {\n      typename TInputImage::PointType pCorner(0.);\n      vnl_vector<double> pCornerVnl = m_Geometry->GetMatrices()[iProj].GetVnlMatrix() * corners[ci].GetVnlVector();\n      for (unsigned int i = 0; i < 2; i++)\n        pCorner[i] = pCornerVnl[i] / pCornerVnl[2];\n      const itk::ContinuousIndex<double, 3> pCornerI =\n        this->GetInput()\n          ->template TransformPhysicalPointToContinuousIndex<typename TInputImage::PointType::ValueType, double>(\n            pCorner);\n      if (ci == 0)\n      {\n        pCornerInf = pCornerI;\n        pCornerSup = pCornerI;\n      }\n      else\n      {\n        for (int i = 0; i < 2; i++)\n        {\n          pCornerInf[i] = std::min(pCornerInf[i], pCornerI[i]);\n          pCornerSup[i] = std::max(pCornerSup[i], pCornerI[i]);\n        }\n      }\n    }\n\n    // Set to 0 all pixels outside 2D projected box\n    for (unsigned int j = 0; j < reg.GetSize(1); j++)\n    {\n      for (unsigned int i = 0; i < reg.GetSize(0); i++, ++it)\n      {\n        if (i < pCornerInf[0] || i > pCornerSup[0] || j < pCornerInf[1] || j > pCornerSup[1])\n          it.Set(0);\n      }\n    }\n  }\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkAverageOutOfROIImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkAverageOutOfROIImageFilter_h\n#define rtkAverageOutOfROIImageFilter_h\n\n#include \"itkInPlaceImageFilter.h\"\n\n#include <itkImageRegionSplitterDirection.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class AverageOutOfROIImageFilter\n * \\brief Averages along the last dimension if the pixel is outside ROI\n *\n * This filter takes in input a n-D image and an (n-1)D binary image\n * representing a region of interest (1 inside the ROI, 0 outside).\n * The filter walks through the ROI image, and :\n * - if it contains 0, pixels in the n-D image a replaced with their\n * average along the last dimension\n * - if it contains 1, nothing happens\n *\n * This filter is used in rtk4DROOSTERConeBeamReconstructionFilter in\n * order to average along time between phases, everywhere except where\n * movement is expected to occur.\n *\n * \\test rtkfourdroostertest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <class TInputImage, class TROI = itk::Image<typename TInputImage::PixelType, TInputImage::ImageDimension - 1>>\n\nclass ITK_TEMPLATE_EXPORT AverageOutOfROIImageFilter : public itk::InPlaceImageFilter<TInputImage, TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(AverageOutOfROIImageFilter);\n\n  /** Standard class type alias. */\n  using Self = AverageOutOfROIImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using LowerDimImage = itk::Image<typename TInputImage::PixelType, TInputImage::ImageDimension - 1>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(AverageOutOfROIImageFilter);\n\n  /** The image containing the weights applied to the temporal components */\n  void\n  SetROI(const TROI * Map);\n\nprotected:\n  AverageOutOfROIImageFilter();\n  ~AverageOutOfROIImageFilter() override = default;\n\n  typename TROI::Pointer\n  GetROI();\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  ThreadedGenerateData(const typename TInputImage::RegionType & outputRegionForThread,\n                       itk::ThreadIdType                        itkNotUsed(threadId)) override;\n\n  /** Splits the OutputRequestedRegion along the first direction, not the last */\n  const itk::ImageRegionSplitterBase *\n                                             GetImageRegionSplitter() const override;\n  itk::ImageRegionSplitterDirection::Pointer m_Splitter;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkAverageOutOfROIImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkAverageOutOfROIImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkAverageOutOfROIImageFilter_hxx\n#define rtkAverageOutOfROIImageFilter_hxx\n\n#include \"itkImageRegionIteratorWithIndex.h\"\n#include \"itkImageRegionIterator.h\"\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <class TInputImage, class TROI>\nAverageOutOfROIImageFilter<TInputImage, TROI>::AverageOutOfROIImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set the direction along which the output requested region should NOT be split\n  m_Splitter = itk::ImageRegionSplitterDirection::New();\n  m_Splitter->SetDirection(TInputImage::ImageDimension - 1);\n}\n\ntemplate <class TInputImage, class TROI>\nvoid\nAverageOutOfROIImageFilter<TInputImage, TROI>::SetROI(const TROI * Map)\n{\n  this->SetNthInput(1, const_cast<TROI *>(Map));\n}\n\ntemplate <class TInputImage, class TROI>\ntypename TROI::Pointer\nAverageOutOfROIImageFilter<TInputImage, TROI>::GetROI()\n{\n  return static_cast<TROI *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <class TInputImage, class TROI>\nconst itk::ImageRegionSplitterBase *\nAverageOutOfROIImageFilter<TInputImage, TROI>::GetImageRegionSplitter() const\n{\n  return m_Splitter;\n}\n\ntemplate <class TInputImage, class TROI>\nvoid\nAverageOutOfROIImageFilter<TInputImage, TROI>::GenerateOutputInformation()\n{\n  Superclass::GenerateOutputInformation();\n\n  // Check whether the ROI has the same information as the input image\n  typename TROI::SizeType      ROISize = this->GetROI()->GetLargestPossibleRegion().GetSize();\n  typename TROI::SpacingType   ROISpacing = this->GetROI()->GetSpacing();\n  typename TROI::PointType     ROIOrigin = this->GetROI()->GetOrigin();\n  typename TROI::DirectionType ROIDirection = this->GetROI()->GetDirection();\n\n  bool isInformationInconsistent = false;\n  isInformationInconsistent = false;\n\n  for (unsigned int dim = 0; dim < TROI::ImageDimension; dim++)\n  {\n    if (ROISize[dim] != this->GetInput(0)->GetLargestPossibleRegion().GetSize()[dim])\n      isInformationInconsistent = true;\n    if (ROISpacing[dim] != this->GetInput(0)->GetSpacing()[dim])\n      isInformationInconsistent = true;\n    if (ROIOrigin[dim] != this->GetInput(0)->GetOrigin()[dim])\n      isInformationInconsistent = true;\n    for (unsigned int i = 0; i < TROI::ImageDimension; i++)\n    {\n      if (ROIDirection(dim, i) != this->GetInput(0)->GetDirection()(dim, i))\n        isInformationInconsistent = true;\n    }\n  }\n\n  if (isInformationInconsistent)\n    itkGenericExceptionMacro(<< \"In AverageOutOfROIImageFilter: information of ROI image does not match input image\");\n\n  this->GetOutput()->SetLargestPossibleRegion(this->GetInput(0)->GetLargestPossibleRegion());\n}\n\ntemplate <class TInputImage, class TROI>\nvoid\nAverageOutOfROIImageFilter<TInputImage, TROI>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Compute the requested regions on input and ROI from the output's requested region\n  typename TInputImage::RegionType outputRequested = this->GetOutput()->GetRequestedRegion();\n\n  typename TInputImage::RegionType inputRequested = outputRequested;\n  inputRequested.SetSize(TInputImage::ImageDimension - 1,\n                         this->GetInput(0)->GetLargestPossibleRegion().GetSize(TInputImage::ImageDimension - 1));\n  inputRequested.SetIndex(TInputImage::ImageDimension - 1,\n                          this->GetInput(0)->GetLargestPossibleRegion().GetIndex(TInputImage::ImageDimension - 1));\n\n  typename TROI::RegionType ROIRequested;\n  //  for (unsigned int dim = 0; dim<TROI::ImageDimension; dim++)\n  //    {\n  //    ROIRequested.SetSize(dim, outputRequested.GetSize(dim));\n  //    ROIRequested.SetIndex(dim, outputRequested.GetSize(dim));\n  //    }\n  ROIRequested = outputRequested.Slice(TInputImage::ImageDimension - 1);\n\n  // Get pointers to the input and ROI\n  typename TInputImage::Pointer inputPtr = const_cast<TInputImage *>(this->GetInput(0));\n  inputPtr->SetRequestedRegion(inputRequested);\n\n  typename TROI::Pointer ROIPtr = this->GetROI();\n  ROIPtr->SetRequestedRegion(ROIRequested);\n}\n\ntemplate <class TInputImage, class TROI>\nvoid\nAverageOutOfROIImageFilter<TInputImage, TROI>::ThreadedGenerateData(\n  const typename TInputImage::RegionType & outputRegionForThread,\n  itk::ThreadIdType                        itkNotUsed(threadId))\n{\n  // Walks the first frame of the outputRegionForThread\n  // For each voxel, creates an input iterator that walks\n  // the last dimension and computes the average, and\n  // a similar output iterator that replaces the output\n  // by their average along last dimension if ROI=1\n\n  // Create a region containing only the first frame of outputRegionForThread\n  typename TInputImage::RegionType FirstFrameRegion = outputRegionForThread;\n  FirstFrameRegion.SetSize(TInputImage::ImageDimension - 1, 1);\n\n  // Create a similar region with TROI image type (last dimension removed)\n  typename TROI::RegionType SingleFrameRegion = this->GetROI()->GetLargestPossibleRegion();\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension - 1; dim++)\n  {\n    SingleFrameRegion.SetSize(dim, FirstFrameRegion.GetSize(dim));\n    SingleFrameRegion.SetIndex(dim, FirstFrameRegion.GetIndex(dim));\n  }\n\n  // Iterate on these regions\n  itk::ImageRegionIteratorWithIndex<TInputImage> FakeIterator(this->GetOutput(), FirstFrameRegion);\n  itk::ImageRegionIterator<TROI>                 ROIIterator(this->GetROI(), SingleFrameRegion);\n\n  // Create a single-voxel region traversing last dimension\n  typename TInputImage::RegionType SingleVoxelRegion = outputRegionForThread;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension - 1; dim++)\n    SingleVoxelRegion.SetSize(dim, 1);\n\n  // Create a variable to store the average value\n  typename TInputImage::PixelType avg;\n\n  while (!ROIIterator.IsAtEnd())\n  {\n    // Configure the SingleVoxelRegion correctly to follow the FakeIterator\n    // It is the only purpose of this FakeIterator\n    SingleVoxelRegion.SetIndex(FakeIterator.GetIndex());\n\n    // Walk the input along last dimension for this voxel, averaging along the way\n    itk::ImageRegionConstIterator<TInputImage> inputIterator(this->GetInput(), SingleVoxelRegion);\n    avg = 0;\n    while (!inputIterator.IsAtEnd())\n    {\n      avg += inputIterator.Get();\n      ++inputIterator;\n    }\n    avg /= SingleVoxelRegion.GetSize(TInputImage::ImageDimension - 1);\n\n    // Walk the output along last dimension for this voxel,\n    // replacing voxel values with their average, if indicated by the value in ROI\n    itk::ImageRegionIterator<TInputImage> outputIterator(this->GetOutput(), SingleVoxelRegion);\n    while (!outputIterator.IsAtEnd())\n    {\n      outputIterator.Set(ROIIterator.Get() * outputIterator.Get() + avg * (1 - ROIIterator.Get()));\n      ++outputIterator;\n    }\n\n    ++FakeIterator;\n    ++ROIIterator;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBackProjectionImageFilter_h\n#define rtkBackProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n\n#include <itkInPlaceImageFilter.h>\n#include <itkConceptChecking.h>\n\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\n#include <type_traits>\n#include <typeinfo>\n\nnamespace rtk\n{\n\n/** \\class BackProjectionImageFilter\n * \\brief 3D backprojection\n *\n * Backprojects a stack of projection images (input 1) in a 3D volume (input 0)\n * using linear interpolation according to a specified geometry. The operation\n * is voxel-based, meaning that the center of each voxel is projected in the\n * projection images to determine the interpolation location.\n *\n * \\test rtkfovtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Projector\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT BackProjectionImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(BackProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = BackProjectionImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using InputPixelType = typename TInputImage::PixelType;\n  using InternalInputPixelType = typename TInputImage::InternalPixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryConstPointer = typename GeometryType::ConstPointer;\n  using ProjectionMatrixType = typename GeometryType::MatrixType;\n  using ProjectionImageType = itk::Image<InputPixelType, TInputImage::ImageDimension - 1>;\n  using ProjectionImagePointer = typename ProjectionImageType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(BackProjectionImageFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetConstObjectMacro(Geometry, GeometryType);\n  itkSetConstObjectMacro(Geometry, GeometryType);\n\n  /** Get / Set the transpose flag for 2D projections (optimization trick) */\n  itkGetMacro(Transpose, bool);\n  itkSetMacro(Transpose, bool);\n\nprotected:\n  BackProjectionImageFilter()\n    : m_Geometry(nullptr)\n  {\n    this->SetNumberOfRequiredInputs(2);\n    this->SetInPlace(true);\n  };\n  ~BackProjectionImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Apply changes to the input image requested region. */\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  /** Special case when the detector is cylindrical and centered on source */\n  virtual void\n  CylindricalDetectorCenteredOnSourceBackprojection(\n    const OutputImageRegionType &                                                         region,\n    const ProjectionMatrixType &                                                          volIndexToProjPP,\n    const itk::Matrix<double, TInputImage::ImageDimension, TInputImage::ImageDimension> & projPPToProjIndex,\n    const ProjectionImagePointer                                                          projection);\n\n  /** Optimized version when the rotation is parallel to X, i.e. matrix[1][0]\n    and matrix[2][0] are zeros. */\n  virtual void\n  OptimizedBackprojectionX(const OutputImageRegionType & region,\n                           const ProjectionMatrixType &  matrix,\n                           const ProjectionImagePointer  projection);\n\n  /** Optimized version when the rotation is parallel to Y, i.e. matrix[1][1]\n    and matrix[2][1] are zeros. */\n  virtual void\n  OptimizedBackprojectionY(const OutputImageRegionType & region,\n                           const ProjectionMatrixType &  matrix,\n                           const ProjectionImagePointer  projection);\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The input is a stack of projections, we need to interpolate in one projection\n      for efficiency during interpolation. Use of itk::ExtractImageFilter is\n      not threadsafe in ThreadedGenerateData, this one is. The output can be multiplied by a constant.\n      The function is templated to allow getting an itk::CudaImage. */\n  template <class TProjectionImage>\n  typename TProjectionImage::Pointer\n  GetProjection(const unsigned int iProj);\n\n  /** Creates iProj index to index projection matrices with current inputs\n      instead of the physical point to physical point projection matrix provided by Geometry */\n  ProjectionMatrixType\n  GetIndexToIndexProjectionMatrix(const unsigned int iProj);\n\n  ProjectionMatrixType\n  GetVolumeIndexToProjectionPhysicalPointMatrix(const unsigned int iProj);\n\n  itk::Matrix<double, TInputImage::ImageDimension, TInputImage::ImageDimension>\n  GetProjectionPhysicalPointToProjectionIndexMatrix(const unsigned int iProj);\n\n  /** RTK geometry object */\n  GeometryConstPointer m_Geometry;\n\nprivate:\n  /** Flip projection flag: infludences GetProjection and\n    GetIndexToIndexProjectionMatrix for optimization */\n  bool m_Transpose{ false };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkBackProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkBackProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBackProjectionImageFilter_hxx\n#define rtkBackProjectionImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include \"rtkHomogeneousMatrix.h\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkLinearInterpolateImageFunction.h>\n#include <itkPixelTraits.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackProjectionImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the volume in which we backproject\n  typename Superclass::InputImagePointer inputPtr0 = const_cast<TInputImage *>(this->GetInput(0));\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the stack of projections to backproject\n  typename Superclass::InputImagePointer inputPtr1 = const_cast<TInputImage *>(this->GetInput(1));\n  if (!inputPtr1)\n    return;\n\n  // Geometry size check\n  const unsigned int Dimension = TInputImage::ImageDimension;\n  const int          lastProjIndex = this->GetInput(1)->GetLargestPossibleRegion().GetIndex(Dimension - 1) +\n                            this->GetInput(1)->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  if ((int)this->m_Geometry->GetMatrices().size() < lastProjIndex)\n  {\n    itkExceptionMacro(<< \"Mismatch between the number of projections and the geometry entries. \"\n                      << \"Geometry has \" << this->m_Geometry->GetMatrices().size()\n                      << \" entries, which is less than the \"\n                      << \"last index of the projections stack, i.e., \" << lastProjIndex << \".\");\n  }\n\n  typename TInputImage::RegionType reqRegion = inputPtr1->GetLargestPossibleRegion();\n  if (m_Geometry.GetPointer() == nullptr || m_Geometry->GetRadiusCylindricalDetector() != 0)\n  {\n    inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n    return;\n  }\n\n  itk::ContinuousIndex<double, Dimension> cornerInf;\n  itk::ContinuousIndex<double, Dimension> cornerSup;\n  cornerInf[0] = itk::NumericTraits<double>::max();\n  cornerSup[0] = itk::NumericTraits<double>::NonpositiveMin();\n  cornerInf[1] = itk::NumericTraits<double>::max();\n  cornerSup[1] = itk::NumericTraits<double>::NonpositiveMin();\n  cornerInf[2] = reqRegion.GetIndex(2);\n  cornerSup[2] = reqRegion.GetIndex(2) + reqRegion.GetSize(2);\n\n  // Go over each projection\n  const unsigned int nProj = this->GetInput(1)->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  const unsigned int iFirstProj = this->GetInput(1)->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n  this->SetTranspose(false);\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    // Extract the current slice\n    ProjectionMatrixType matrix = GetIndexToIndexProjectionMatrix(iProj);\n\n    // Check which part of the projection image will be backprojected in the\n    // volume.\n    double firstPerspFactor = 0.;\n    int    c[Dimension] = { 0 };\n    for (c[2] = 0; c[2] < 2; c[2]++)\n      for (c[1] = 0; c[1] < 2; c[1]++)\n        for (c[0] = 0; c[0] < 2; c[0]++)\n        {\n          // Compute corner index\n          const double                            eps = 1e-4;\n          itk::ContinuousIndex<double, Dimension> index;\n          for (unsigned int i = 0; i < Dimension; i++)\n          {\n            index[i] = this->GetOutput()->GetRequestedRegion().GetIndex()[i] - eps;\n            index[i] += c[i] * (this->GetOutput()->GetRequestedRegion().GetSize(i) - 1 + 2 * eps);\n          }\n\n          // Compute projection index\n          itk::ContinuousIndex<double, Dimension - 1> point;\n          for (unsigned int i = 0; i < Dimension - 1; i++)\n          {\n            point[i] = matrix[i][Dimension];\n            for (unsigned int j = 0; j < Dimension; j++)\n              point[i] += matrix[i][j] * index[j];\n          }\n\n          // Apply perspective\n          double perspFactor = matrix[Dimension - 1][Dimension];\n          for (unsigned int j = 0; j < Dimension; j++)\n            perspFactor += matrix[Dimension - 1][j] * index[j];\n          perspFactor = 1 / perspFactor;\n          for (unsigned int i = 0; i < Dimension - 1; i++)\n            point[i] = point[i] * perspFactor;\n\n          // Check if corners all have the same perspective factor sign.\n          // If not, source is too close for easily computing a smaller requested\n          // region than the largest possible one.\n          if (c[0] + c[1] + c[2] == 0)\n            firstPerspFactor = perspFactor;\n          if (perspFactor * firstPerspFactor < 0.) // Change of sign\n          {\n            inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n            return;\n          }\n\n          // Look for extremas on projection to calculate requested region\n          for (int i = 0; i < 2; i++)\n          {\n            cornerInf[i] = std::min(cornerInf[i], point[i]);\n            cornerSup[i] = std::max(cornerSup[i], point[i]);\n          }\n        }\n  }\n  reqRegion.SetIndex(0, itk::Math::floor(cornerInf[0]));\n  reqRegion.SetIndex(1, itk::Math::floor(cornerInf[1]));\n  reqRegion.SetSize(0, itk::Math::ceil(cornerSup[0] - reqRegion.GetIndex(0)) + 1);\n  reqRegion.SetSize(1, itk::Math::ceil(cornerSup[1] - reqRegion.GetIndex(1)) + 1);\n\n  if (reqRegion.Crop(inputPtr1->GetLargestPossibleRegion()))\n    inputPtr1->SetRequestedRegion(reqRegion);\n  else\n  {\n    inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackProjectionImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackProjectionImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  this->SetTranspose(true);\n\n  // Check if detector is cylindrical\n  double radius = m_Geometry->GetRadiusCylindricalDetector();\n  if ((radius != 0) && (radius != this->m_Geometry->GetSourceToDetectorDistances()[0]))\n  {\n    itkGenericExceptionMacro(<< \"Voxel-based back projector can currently handle a cylindrical detector only when it \"\n                                \"is centered on the source. \"\n                             << \"Detector radius is \" << radius << \", should be \"\n                             << this->m_Geometry->GetSourceToDetectorDistances()[0]);\n  }\n}\n\n/**\n * GenerateData performs the accumulation\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackProjectionImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  const unsigned int Dimension = TInputImage::ImageDimension;\n  const unsigned int nProj = this->GetInput(1)->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  const unsigned int iFirstProj = this->GetInput(1)->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n\n  // Create interpolator, could be any interpolation\n  using InterpolatorType = itk::LinearInterpolateImageFunction<ProjectionImageType, double>;\n  auto interpolator = InterpolatorType::New();\n\n  // Iterators on volume input and output\n  itk::ImageRegionConstIterator<TInputImage> itIn(this->GetInput(), outputRegionForThread);\n  using OutputRegionIterator = itk::ImageRegionIteratorWithIndex<TOutputImage>;\n  OutputRegionIterator itOut(this->GetOutput(), outputRegionForThread);\n\n  // Initialize output region with input region in case the filter is not in\n  // place\n  if (this->GetInput() != this->GetOutput())\n  {\n    itIn.GoToBegin();\n    while (!itIn.IsAtEnd())\n    {\n      itOut.Set(itIn.Get());\n      ++itIn;\n      ++itOut;\n    }\n  }\n\n  // Continuous index at which we interpolate\n  itk::ContinuousIndex<double, Dimension - 1> pointProj;\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    // Extract the current slice\n    ProjectionImagePointer projection = GetProjection<ProjectionImageType>(iProj);\n\n    ProjectionMatrixType matrix = GetIndexToIndexProjectionMatrix(iProj);\n    interpolator->SetInputImage(projection);\n\n    // Cylindrical detector centered on source case\n    if (m_Geometry->GetRadiusCylindricalDetector() != 0)\n    {\n      ProjectionMatrixType volIndexToProjPP = GetVolumeIndexToProjectionPhysicalPointMatrix(iProj);\n      itk::Matrix<double, TInputImage::ImageDimension, TInputImage::ImageDimension> projPPToProjIndex =\n        GetProjectionPhysicalPointToProjectionIndexMatrix(iProj);\n      CylindricalDetectorCenteredOnSourceBackprojection(\n        outputRegionForThread, volIndexToProjPP, projPPToProjIndex, projection);\n      continue;\n    }\n\n    // Optimized version\n    if (itk::Math::abs(matrix[1][0]) < 1e-10 && itk::Math::abs(matrix[2][0]) < 1e-10)\n    {\n      OptimizedBackprojectionX(outputRegionForThread, matrix, projection);\n      continue;\n    }\n    if (itk::Math::abs(matrix[1][1]) < 1e-10 && itk::Math::abs(matrix[2][1]) < 1e-10)\n    {\n      OptimizedBackprojectionY(outputRegionForThread, matrix, projection);\n      continue;\n    }\n\n    // Go over each voxel\n    itOut.GoToBegin();\n    while (!itOut.IsAtEnd())\n    {\n      // Compute projection index\n      for (unsigned int i = 0; i < Dimension - 1; i++)\n      {\n        pointProj[i] = matrix[i][Dimension];\n        for (unsigned int j = 0; j < Dimension; j++)\n          pointProj[i] += matrix[i][j] * itOut.GetIndex()[j];\n      }\n\n      // Apply perspective\n      double perspFactor = matrix[Dimension - 1][Dimension];\n      for (unsigned int j = 0; j < Dimension; j++)\n        perspFactor += matrix[Dimension - 1][j] * itOut.GetIndex()[j];\n      perspFactor = 1 / perspFactor;\n      for (unsigned int i = 0; i < Dimension - 1; i++)\n        pointProj[i] = pointProj[i] * perspFactor;\n\n      // Interpolate if in projection\n      if (interpolator->IsInsideBuffer(pointProj))\n      {\n        typename TOutputImage::PixelType v = interpolator->EvaluateAtContinuousIndex(pointProj);\n        itOut.Set(itOut.Get() + v);\n      }\n\n      ++itOut;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackProjectionImageFilter<TInputImage, TOutputImage>::CylindricalDetectorCenteredOnSourceBackprojection(\n  const OutputImageRegionType &                                                         region,\n  const ProjectionMatrixType &                                                          volIndexToProjPP,\n  const itk::Matrix<double, TInputImage::ImageDimension, TInputImage::ImageDimension> & projPPToProjIndex,\n  const ProjectionImagePointer                                                          projection)\n{\n  using OutputRegionIterator = itk::ImageRegionIteratorWithIndex<TOutputImage>;\n  OutputRegionIterator itOut(this->GetOutput(), region);\n\n  const unsigned int Dimension = TInputImage::ImageDimension;\n\n  // Create interpolator, could be any interpolation\n  using InterpolatorType = itk::LinearInterpolateImageFunction<ProjectionImageType, double>;\n  auto interpolator = InterpolatorType::New();\n  interpolator->SetInputImage(projection);\n\n  // Get radius of the cylindrical detector\n  double radius = m_Geometry->GetRadiusCylindricalDetector();\n\n  // Continuous index at which we interpolate\n  itk::ContinuousIndex<double, Dimension - 1> pointProj, pointProjIdx;\n\n  // Go over each voxel\n  itOut.GoToBegin();\n  while (!itOut.IsAtEnd())\n  {\n    // Compute projection index\n    for (unsigned int i = 0; i < Dimension - 1; i++)\n    {\n      pointProj[i] = volIndexToProjPP[i][Dimension];\n      for (unsigned int j = 0; j < Dimension; j++)\n        pointProj[i] += volIndexToProjPP[i][j] * itOut.GetIndex()[j];\n    }\n\n    // Apply perspective\n    double perspFactor = volIndexToProjPP[Dimension - 1][Dimension];\n    for (unsigned int j = 0; j < Dimension; j++)\n      perspFactor += volIndexToProjPP[Dimension - 1][j] * itOut.GetIndex()[j];\n    perspFactor = 1 / perspFactor;\n    for (unsigned int i = 0; i < Dimension - 1; i++)\n      pointProj[i] = pointProj[i] * perspFactor;\n\n    // Apply correction for cylindrical centered on source\n    const double u = pointProj[0];\n    pointProj[0] = radius * atan2(u, radius);\n    pointProj[1] = pointProj[1] * radius / sqrt(radius * radius + u * u);\n\n    // Convert to projection index\n    for (unsigned int i = 0; i < Dimension - 1; i++)\n    {\n      pointProjIdx[i] = projPPToProjIndex[i][Dimension - 1];\n      for (unsigned int j = 0; j < Dimension - 1; j++)\n        pointProjIdx[i] += projPPToProjIndex[i][j] * pointProj[j];\n    }\n\n    // Interpolate if in projection\n    if (interpolator->IsInsideBuffer(pointProjIdx))\n    {\n      typename TOutputImage::PixelType v = interpolator->EvaluateAtContinuousIndex(pointProjIdx);\n      itOut.Set(itOut.Get() + v);\n    }\n\n    ++itOut;\n  }\n}\n\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackProjectionImageFilter<TInputImage, TOutputImage>::OptimizedBackprojectionX(const OutputImageRegionType & region,\n                                                                               const ProjectionMatrixType &  matrix,\n                                                                               const ProjectionImagePointer  projection)\n{\n  typename ProjectionImageType::SizeType    pSize = projection->GetBufferedRegion().GetSize();\n  typename ProjectionImageType::IndexType   pIndex = projection->GetBufferedRegion().GetIndex();\n  typename TOutputImage::SizeType           vBufferSize = this->GetOutput()->GetBufferedRegion().GetSize();\n  typename TOutputImage::IndexType          vBufferIndex = this->GetOutput()->GetBufferedRegion().GetIndex();\n  typename TInputImage::InternalPixelType * pProj = nullptr;\n  typename TOutputImage::InternalPixelType *pVol = nullptr, *pVolZeroPointer = nullptr;\n\n  // Pointers in memory to index (0,0,0) which do not necessarily exist\n  pVolZeroPointer = this->GetOutput()->GetBufferPointer();\n  pVolZeroPointer -= vBufferIndex[0] + vBufferSize[0] * (vBufferIndex[1] + vBufferSize[1] * vBufferIndex[2]);\n\n  // Continuous index at which we interpolate\n  double u = NAN, v = NAN, w = NAN;\n  int    ui = 0, vi = 0;\n  double du = NAN;\n\n  for (int k = region.GetIndex(2); k < region.GetIndex(2) + (int)region.GetSize(2); k++)\n  {\n    for (int j = region.GetIndex(1); j < region.GetIndex(1) + (int)region.GetSize(1); j++)\n    {\n      int i = region.GetIndex(0);\n      u = matrix[0][0] * i + matrix[0][1] * j + matrix[0][2] * k + matrix[0][3];\n      v = matrix[1][1] * j + matrix[1][2] * k + matrix[1][3];\n      w = matrix[2][1] * j + matrix[2][2] * k + matrix[2][3];\n\n      // Apply perspective\n      w = 1 / w;\n      u = u * w - pIndex[0];\n      v = v * w - pIndex[1];\n      du = w * matrix[0][0];\n\n      using ComponentType = typename itk::PixelTraits<typename TInputImage::PixelType>::ValueType;\n      ComponentType u1, u2, v1, v2;\n      vi = itk::Math::floor(v);\n      if (vi >= 0 && vi < (int)pSize[1] - 1)\n      {\n        v1 = v - vi;\n        v2 = 1.0 - v1;\n\n        pProj = projection->GetBufferPointer() + vi * pSize[0];\n        pVol = pVolZeroPointer + i + vBufferSize[0] * (j + k * vBufferSize[1]);\n\n        // Innermost loop\n        for (; i < (region.GetIndex(0) + (int)region.GetSize(0)); i++, u += du, pVol++)\n        {\n          ui = itk::Math::floor(u);\n          if (ui >= 0 && ui < (int)pSize[0] - 1)\n          {\n            u1 = u - ui;\n            u2 = 1.0 - u1;\n            *pVol += v2 * (u2 * *(pProj + ui) + u1 * *(pProj + ui + 1)) +\n                     v1 * (u2 * *(pProj + ui + pSize[0]) + u1 * *(pProj + ui + pSize[0] + 1));\n          }\n        } // i\n      }\n    } // j\n  } // k\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackProjectionImageFilter<TInputImage, TOutputImage>::OptimizedBackprojectionY(const OutputImageRegionType & region,\n                                                                               const ProjectionMatrixType &  matrix,\n                                                                               const ProjectionImagePointer  projection)\n{\n  typename ProjectionImageType::SizeType    pSize = projection->GetBufferedRegion().GetSize();\n  typename ProjectionImageType::IndexType   pIndex = projection->GetBufferedRegion().GetIndex();\n  typename TOutputImage::SizeType           vBufferSize = this->GetOutput()->GetBufferedRegion().GetSize();\n  typename TOutputImage::IndexType          vBufferIndex = this->GetOutput()->GetBufferedRegion().GetIndex();\n  typename TInputImage::InternalPixelType * pProj = nullptr;\n  typename TOutputImage::InternalPixelType *pVol = nullptr, *pVolZeroPointer = nullptr;\n\n  // Pointers in memory to index (0,0,0) which do not necessarily exist\n  pVolZeroPointer = this->GetOutput()->GetBufferPointer();\n  pVolZeroPointer -= vBufferIndex[0] + vBufferSize[0] * (vBufferIndex[1] + vBufferSize[1] * vBufferIndex[2]);\n\n  // Continuous index at which we interpolate\n  double u = NAN, v = NAN, w = NAN;\n  int    ui = 0, vi = 0;\n  double du = NAN;\n\n  for (int k = region.GetIndex(2); k < region.GetIndex(2) + (int)region.GetSize(2); k++)\n  {\n    for (int i = region.GetIndex(0); i < region.GetIndex(0) + (int)region.GetSize(0); i++)\n    {\n      int j = region.GetIndex(1);\n      u = matrix[0][0] * i + matrix[0][1] * j + matrix[0][2] * k + matrix[0][3];\n      v = matrix[1][0] * i + matrix[1][2] * k + matrix[1][3];\n      w = matrix[2][0] * i + matrix[2][2] * k + matrix[2][3];\n\n      // Apply perspective\n      w = 1 / w;\n      u = u * w - pIndex[0];\n      v = v * w - pIndex[1];\n      du = w * matrix[0][1];\n\n      vi = itk::Math::floor(v);\n      if (vi >= 0 && vi < (int)pSize[1] - 1)\n      {\n        pVol = pVolZeroPointer + i + vBufferSize[0] * (j + k * vBufferSize[1]);\n        for (; j < (region.GetIndex(1) + (int)region.GetSize(1)); j++, pVol += vBufferSize[0], u += du)\n        {\n          ui = itk::Math::floor(u);\n          if (ui >= 0 && ui < (int)pSize[0] - 1)\n          {\n            using ComponentType = typename itk::PixelTraits<typename TInputImage::PixelType>::ValueType;\n            ComponentType u1, u2, v1, v2;\n            pProj = projection->GetBufferPointer() + vi * pSize[0] + ui;\n            v1 = v - vi;\n            v2 = 1.0 - v1;\n            u1 = u - ui;\n            u2 = 1.0 - u1;\n            *pVol +=\n              v2 * (u2 * *(pProj) + u1 * *(pProj + 1)) + v1 * (u2 * *(pProj + pSize[0]) + u1 * *(pProj + pSize[0] + 1));\n          }\n        } // j\n      }\n    } // i\n  } // k\n}\n\ntemplate <class TInputImage, class TOutputImage>\ntemplate <class TProjectionImage>\ntypename TProjectionImage::Pointer\nBackProjectionImageFilter<TInputImage, TOutputImage>::GetProjection(const unsigned int iProj)\n{\n\n  typename Superclass::InputImagePointer stack = const_cast<TInputImage *>(this->GetInput(1));\n\n  const int iProjBuff = stack->GetBufferedRegion().GetIndex(ProjectionImageType::ImageDimension);\n\n  auto                                   projection = TProjectionImage::New();\n  typename TProjectionImage::RegionType  region;\n  typename TProjectionImage::SpacingType spacing;\n  typename TProjectionImage::PointType   origin;\n\n  for (unsigned int i = 0; i < TProjectionImage::ImageDimension; i++)\n  {\n    origin[i] = stack->GetOrigin()[i];\n    spacing[i] = stack->GetSpacing()[i];\n    region.SetSize(i, stack->GetBufferedRegion().GetSize()[i]);\n    region.SetIndex(i, stack->GetBufferedRegion().GetIndex()[i]);\n  }\n  if (this->GetTranspose())\n  {\n    typename TProjectionImage::SizeType  size = region.GetSize();\n    typename TProjectionImage::IndexType index = region.GetIndex();\n    std::swap(size[0], size[1]);\n    std::swap(index[0], index[1]);\n    std::swap(origin[0], origin[1]);\n    std::swap(spacing[0], spacing[1]);\n    region.SetSize(size);\n    region.SetIndex(index);\n  }\n  projection->SetSpacing(spacing);\n  projection->SetOrigin(origin);\n  projection->SetRegions(region);\n  projection->Allocate();\n\n  const unsigned int             npixels = projection->GetBufferedRegion().GetNumberOfPixels();\n  const InternalInputPixelType * pi = stack->GetBufferPointer() + (iProj - iProjBuff) * npixels;\n  InternalInputPixelType *       po = projection->GetBufferPointer();\n\n  // Transpose projection for optimization\n  if (this->GetTranspose())\n  {\n    for (unsigned int j = 0; j < region.GetSize(0); j++, po -= npixels - 1)\n      for (unsigned int i = 0; i < region.GetSize(1); i++, po += region.GetSize(0))\n        *po = *pi++;\n  }\n  else\n    for (unsigned int i = 0; i < npixels; i++)\n      *po++ = *pi++;\n\n  return projection;\n}\n\ntemplate <class TInputImage, class TOutputImage>\ntypename BackProjectionImageFilter<TInputImage, TOutputImage>::ProjectionMatrixType\nBackProjectionImageFilter<TInputImage, TOutputImage>::GetIndexToIndexProjectionMatrix(const unsigned int iProj)\n{\n  const unsigned int Dimension = TInputImage::ImageDimension;\n\n  ProjectionMatrixType VolumeIndexToProjectionPhysicalPointMatrix =\n    GetVolumeIndexToProjectionPhysicalPointMatrix(iProj);\n\n  itk::Matrix<double, Dimension, Dimension> ProjectionPhysicalPointToProjectionIndexMatrix =\n    GetProjectionPhysicalPointToProjectionIndexMatrix(iProj);\n\n  return ProjectionMatrixType(ProjectionPhysicalPointToProjectionIndexMatrix.GetVnlMatrix() *\n                              VolumeIndexToProjectionPhysicalPointMatrix.GetVnlMatrix());\n}\n\ntemplate <class TInputImage, class TOutputImage>\ntypename BackProjectionImageFilter<TInputImage, TOutputImage>::ProjectionMatrixType\nBackProjectionImageFilter<TInputImage, TOutputImage>::GetVolumeIndexToProjectionPhysicalPointMatrix(\n  const unsigned int iProj)\n{\n  const unsigned int Dimension = TInputImage::ImageDimension;\n\n  itk::Matrix<double, Dimension + 1, Dimension + 1> matrixVol =\n    GetIndexToPhysicalPointMatrix<TOutputImage>(this->GetOutput());\n\n  return ProjectionMatrixType(this->m_Geometry->GetMagnificationMatrices()[iProj].GetVnlMatrix() *\n                              this->m_Geometry->GetSourceTranslationMatrices()[iProj].GetVnlMatrix() *\n                              this->m_Geometry->GetRotationMatrices()[iProj].GetVnlMatrix() * matrixVol.GetVnlMatrix());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nitk::Matrix<double, TInputImage::ImageDimension, TInputImage::ImageDimension>\nBackProjectionImageFilter<TInputImage, TOutputImage>::GetProjectionPhysicalPointToProjectionIndexMatrix(\n  const unsigned int iProj)\n{\n  const unsigned int Dimension = TInputImage::ImageDimension;\n\n  itk::Matrix<double, Dimension + 1, Dimension + 1> matrixStackProj =\n    GetPhysicalPointToIndexMatrix<TOutputImage>(this->GetInput(1));\n\n  itk::Matrix<double, Dimension, Dimension> matrixProj;\n  matrixProj.SetIdentity();\n  for (unsigned int i = 0; i < Dimension - 1; i++)\n  {\n    matrixProj[i][Dimension - 1] = matrixStackProj[i][Dimension];\n    for (unsigned int j = 0; j < Dimension - 1; j++)\n      matrixProj[i][j] = matrixStackProj[i][j];\n  }\n\n  // Transpose projection for optimization\n  itk::Matrix<double, Dimension, Dimension> matrixFlip;\n  matrixFlip.SetIdentity();\n  if (this->GetTranspose())\n  {\n    std::swap(matrixFlip[0][0], matrixFlip[0][1]);\n    std::swap(matrixFlip[1][0], matrixFlip[1][1]);\n  }\n\n  return itk::Matrix<double, TInputImage::ImageDimension, TInputImage::ImageDimension>(\n    matrixFlip.GetVnlMatrix() * matrixProj.GetVnlMatrix() *\n    this->m_Geometry->GetProjectionTranslationMatrices()[iProj].GetVnlMatrix());\n}\n\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkBackwardDifferenceDivergenceImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBackwardDifferenceDivergenceImageFilter_h\n#define rtkBackwardDifferenceDivergenceImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkCastImageFilter.h>\n\nnamespace rtk\n{\n/** \\class BackwardDifferenceDivergenceImageFilter\n * \\brief Computes the backward differences divergence\n * (adjoint of the forward differences gradient) of the input image\n *\n * The exact definition of the desired divergence filter can\n * be found in Chambolle, Antonin. \"An Algorithm for Total\n * Variation Minimization and Applications.\" J. Math. Imaging Vis. 20,\n * no. 1-2 (January 2004): 89-97.\n *\n * \\ingroup RTK IntensityImageFilters\n */\n\ntemplate <typename TInputImage, typename TOutputImage = itk::Image<float, TInputImage::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT BackwardDifferenceDivergenceImageFilter\n  : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(BackwardDifferenceDivergenceImageFilter);\n\n  /** Extract dimension from input and output image. */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n\n  /** Convenient type alias for simplifying declarations. */\n  using InputImageType = TInputImage;\n\n  /** Standard class type alias. */\n  using Self = BackwardDifferenceDivergenceImageFilter;\n  using Superclass = itk::ImageToImageFilter<InputImageType, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(BackwardDifferenceDivergenceImageFilter);\n\n  /** Use the image spacing information in calculations. Use this option if you\n   *  want derivatives in physical space. Default is UseImageSpacingOn. */\n  void\n  SetUseImageSpacingOn()\n  {\n    this->SetUseImageSpacing(true);\n  }\n\n  /** Ignore the image spacing. Use this option if you want derivatives in\n      isotropic pixel space.  Default is UseImageSpacingOn. */\n  void\n  SetUseImageSpacingOff()\n  {\n    this->SetUseImageSpacing(false);\n  }\n\n  /** Set/Get whether or not the filter will use the spacing of the input\n      image in its calculations */\n  itkSetMacro(UseImageSpacing, bool);\n  itkGetConstMacro(UseImageSpacing, bool);\n\n  /** Set along which dimensions the gradient computation should be\n      performed. The vector components at unprocessed dimensions are ignored */\n  void\n  SetDimensionsProcessed(bool * DimensionsProcessed);\n\n  /** Allows to change the default boundary condition */\n  void\n  OverrideBoundaryCondition(itk::ImageBoundaryCondition<TInputImage> * boundaryCondition);\n\n  /** Image type alias support. */\n  using InputPixelType = typename InputImageType::PixelType;\n  using InputImageRegionType = typename InputImageType::RegionType;\n  using InputSizeType = typename InputImageType::SizeType;\n  using CovariantVectorType = itk::CovariantVector<InputPixelType, InputImageDimension>;\n\nprotected:\n  BackwardDifferenceDivergenceImageFilter();\n  ~BackwardDifferenceDivergenceImageFilter() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  void\n  DynamicThreadedGenerateData(const typename InputImageType::RegionType & outputRegionForThread) override;\n\n  void\n  AfterThreadedGenerateData() override;\n\nprivate:\n  bool                              m_UseImageSpacing;\n  typename TInputImage::SpacingType m_InvSpacingCoeffs;\n\n  // list of the dimensions along which the divergence has\n  // to be computed. The components on other dimensions\n  // are ignored for performance, but the gradient filter\n  // sets them to zero anyway\n  bool m_DimensionsProcessed[TInputImage::ImageDimension];\n\n  // The default is ConstantBoundaryCondition, but this behavior sometimes needs to be overriden\n  itk::ImageBoundaryCondition<TInputImage, TInputImage> * m_BoundaryCondition;\n  // If so, do not perform boundary processing in AfterThreadedGenerateData\n  bool m_IsBoundaryConditionOverriden;\n};\n\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkBackwardDifferenceDivergenceImageFilter.hxx\"\n#endif\n\n#endif //__rtkBackwardDifferenceDivergenceImageFilter__\n"
  },
  {
    "path": "include/rtkBackwardDifferenceDivergenceImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBackwardDifferenceDivergenceImageFilter_hxx\n#define rtkBackwardDifferenceDivergenceImageFilter_hxx\n\n#include <itkConstShapedNeighborhoodIterator.h>\n#include <itkNeighborhoodInnerProduct.h>\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkNeighborhoodAlgorithm.h>\n#include <itkConstantBoundaryCondition.h>\n#include <itkOffset.h>\n#include <itkProgressReporter.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nBackwardDifferenceDivergenceImageFilter<TInputImage, TOutputImage>::BackwardDifferenceDivergenceImageFilter()\n{\n  m_UseImageSpacing = true;\n\n  // default boundary condition\n  m_BoundaryCondition = new itk::ConstantBoundaryCondition<TInputImage>();\n  m_IsBoundaryConditionOverriden = false;\n\n  // default behaviour is to process all dimensions\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    m_DimensionsProcessed[dim] = true;\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nBackwardDifferenceDivergenceImageFilter<TInputImage, TOutputImage>::~BackwardDifferenceDivergenceImageFilter()\n{\n  delete m_BoundaryCondition;\n}\n\n// This should be handled by an itkMacro, but it doesn't seem to work with pointer types\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackwardDifferenceDivergenceImageFilter<TInputImage, TOutputImage>::SetDimensionsProcessed(bool * DimensionsProcessed)\n{\n  bool bModif = false;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    if (m_DimensionsProcessed[dim] != DimensionsProcessed[dim])\n    {\n      m_DimensionsProcessed[dim] = DimensionsProcessed[dim];\n      bModif = true;\n    }\n  }\n  if (bModif)\n    this->Modified();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackwardDifferenceDivergenceImageFilter<TInputImage, TOutputImage>::OverrideBoundaryCondition(\n  itk::ImageBoundaryCondition<TInputImage> * boundaryCondition)\n{\n  delete m_BoundaryCondition;\n  m_BoundaryCondition = boundaryCondition;\n  m_IsBoundaryConditionOverriden = true;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackwardDifferenceDivergenceImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  // call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // get pointers to the input and output\n  typename TInputImage::Pointer  inputPtr = const_cast<TInputImage *>(this->GetInput());\n  typename TOutputImage::Pointer outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n  {\n    return;\n  }\n\n  // get a copy of the input requested region (should equal the output\n  // requested region)\n  typename TInputImage::RegionType inputRequestedRegion;\n  inputRequestedRegion = inputPtr->GetRequestedRegion();\n\n  // pad the input requested region by the operator radius\n  inputRequestedRegion.PadByRadius(1);\n\n  // crop the input requested region at the input's largest possible region\n  if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))\n  {\n    inputPtr->SetRequestedRegion(inputRequestedRegion);\n    return;\n  }\n  else\n  {\n    // Couldn't crop the region (requested region is outside the largest\n    // possible region).  Throw an exception.\n\n    // store what we tried to request (prior to trying to crop)\n    inputPtr->SetRequestedRegion(inputRequestedRegion);\n\n    // build an exception\n    itk::InvalidRequestedRegionError e(__FILE__, __LINE__);\n    e.SetLocation(ITK_LOCATION);\n    e.SetDescription(\"Requested region is (at least partially) outside the largest possible region.\");\n    e.SetDataObject(inputPtr);\n    throw e;\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackwardDifferenceDivergenceImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (m_UseImageSpacing == false)\n  {\n    m_InvSpacingCoeffs.Fill(1.0);\n  }\n  else\n  {\n    m_InvSpacingCoeffs = this->GetInput()->GetSpacing();\n    for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n    {\n      m_InvSpacingCoeffs[dim] = 1.0 / m_InvSpacingCoeffs[dim];\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackwardDifferenceDivergenceImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const typename TInputImage::RegionType & outputRegionForThread)\n{\n  // Generate a list of indices of the dimensions to process\n  std::vector<int> dimsToProcess;\n  dimsToProcess.reserve(TInputImage::ImageDimension);\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    if (m_DimensionsProcessed[dim])\n      dimsToProcess.push_back(dim);\n  }\n\n  typename TOutputImage::Pointer     output = this->GetOutput();\n  typename TInputImage::ConstPointer input = this->GetInput();\n\n  itk::ImageRegionIterator<TOutputImage> oit(output, outputRegionForThread);\n  oit.GoToBegin();\n\n  itk::Size<InputImageDimension> radius;\n  radius.Fill(1);\n\n  itk::ConstNeighborhoodIterator<TInputImage> iit(radius, input, outputRegionForThread);\n  iit.GoToBegin();\n  iit.OverrideBoundaryCondition(m_BoundaryCondition);\n\n  const auto         c = (itk::SizeValueType)(iit.Size() / 2); // get offset of center pixel\n  itk::SizeValueType strides[TOutputImage::ImageDimension];    // get offsets to access neighboring pixels\n  for (unsigned int dim = 0; dim < TOutputImage::ImageDimension; dim++)\n  {\n    strides[dim] = iit.GetStride(dim);\n  }\n\n  while (!oit.IsAtEnd())\n  {\n    typename TOutputImage::PixelType div = 0.0F;\n    // Compute the local differences around the central pixel\n    for (unsigned int k = 0; k < dimsToProcess.size(); k++)\n    {\n      div +=\n        (iit.GetPixel(c)[k] - iit.GetPixel(c - strides[dimsToProcess[k]])[k]) * m_InvSpacingCoeffs[dimsToProcess[k]];\n    }\n    oit.Set(div);\n    ++oit;\n    ++iit;\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBackwardDifferenceDivergenceImageFilter<TInputImage, TOutputImage>::AfterThreadedGenerateData()\n{\n  if (m_IsBoundaryConditionOverriden)\n    return;\n\n  std::vector<int> dimsToProcess;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    if (m_DimensionsProcessed[dim])\n      dimsToProcess.push_back(dim);\n  }\n\n  // The conditions on the borders this filter requires are very specific\n  // Some must be enforced explicitely as they do not correspond to any of the\n  // padding styles available in ITK.\n  // This needs to be performed only if the output requested region contains\n  // the borders of the image.\n  // It is ignored if the boundary condition has been overriden (this function returns before)\n\n  typename TOutputImage::RegionType largest = this->GetOutput()->GetLargestPossibleRegion();\n\n  for (unsigned int k = 0; k < dimsToProcess.size(); k++)\n  {\n    // Create a slice region at the border of the largest possible region\n    typename TOutputImage::RegionType slice = largest;\n    slice.SetSize(dimsToProcess[k], 1);\n    slice.SetIndex(dimsToProcess[k], largest.GetSize()[dimsToProcess[k]] - 1);\n\n    // If it overlaps the output buffered region, enforce boundary condition\n    // on the overlap\n    if (slice.Crop(this->GetOutput()->GetBufferedRegion()))\n    {\n      itk::ImageRegionIterator<TOutputImage>     oit(this->GetOutput(), slice);\n      itk::ImageRegionConstIterator<TInputImage> iit(this->GetInput(), slice);\n\n      oit.Set(oit.Get() - iit.Get()[k] * m_InvSpacingCoeffs[dimsToProcess[k]]);\n      ++oit;\n      ++iit;\n    }\n  }\n}\n\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkBioscanGeometryReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBioscanGeometryReader_h\n#define rtkBioscanGeometryReader_h\n\n#include <itkLightProcessObject.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"RTKExport.h\"\n\n// Trick KWStyle with a first declaration of namespace RTK. Style test would\n// not pass otherwise on the gdcm namespace.\nnamespace rtk\n{}\n\n// Forward declare class Dataset. This is done to avoid define conflicts in\n// GDCM with lp_solve\nnamespace gdcm\n{\nclass DataSet;\n}\n\nnamespace rtk\n{\n\n/** \\class BioscanGeometryReader\n *\n * Creates a 3D circular geometry from a Bioscan NanoSPECT/CT.\n *\n * \\test rtkbioscantest\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\n\nclass RTK_EXPORT BioscanGeometryReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(BioscanGeometryReader);\n\n  /** Standard type alias */\n  using Self = BioscanGeometryReader;\n  using Superclass = itk::LightProcessObject;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using GeometryPointer = GeometryType::Pointer;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(BioscanGeometryReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Get the pointer to the generated geometry object. */\n  itkGetModifiableObjectMacro(Geometry, GeometryType);\n\n  /** Some convenient type alias. */\n  using FileNamesContainer = std::vector<std::string>;\n\n  /** Set the vector of strings that contains the projection file names. Files\n   * are processed in sequential order. */\n  void\n  SetProjectionsFileNames(const FileNamesContainer & name)\n  {\n    if (m_ProjectionsFileNames != name)\n    {\n      m_ProjectionsFileNames = name;\n      this->Modified();\n    }\n  }\n  const FileNamesContainer &\n  GetProjectionsFileNames() const\n  {\n    return m_ProjectionsFileNames;\n  }\n\nprotected:\n  std::vector<float>\n  GetVectorTagValue(const gdcm::DataSet & ds, itk::uint16_t group, itk::uint16_t element) const;\n  std::string\n  GetStringTagValue(const gdcm::DataSet & ds, itk::uint16_t group, itk::uint16_t element) const;\n  double\n  GetFloatTagValue(const gdcm::DataSet & ds, itk::uint16_t group, itk::uint16_t element) const;\n\n  BioscanGeometryReader()\n    : m_Geometry(nullptr) {};\n  ~BioscanGeometryReader() override = default;\n\nprivate:\n  void\n  GenerateData() override;\n\n  GeometryPointer    m_Geometry;\n  FileNamesContainer m_ProjectionsFileNames;\n};\n\n} // namespace rtk\n\n#endif // rtkBioscanGeometryReader_h\n"
  },
  {
    "path": "include/rtkBlockDiagonalMatrixVectorMultiplyImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkBlockDiagonalMatrixVectorMultiplyImageFilter_h\n#define rtkBlockDiagonalMatrixVectorMultiplyImageFilter_h\n\n#include \"itkImageToImageFilter.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class BlockDiagonalMatrixVectorMultiplyImageFilter\n * \\brief Multiplies matrix by vector\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <class TVectorImage,\n          class TMatrixImage =\n            itk::Image<itk::Vector<typename TVectorImage::PixelType::ValueType,\n                                   TVectorImage::PixelType::Dimension * TVectorImage::PixelType::Dimension>,\n                       TVectorImage::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT BlockDiagonalMatrixVectorMultiplyImageFilter\n  : public itk::ImageToImageFilter<TVectorImage, TVectorImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(BlockDiagonalMatrixVectorMultiplyImageFilter);\n\n  /** Standard class type alias. */\n  using Self = BlockDiagonalMatrixVectorMultiplyImageFilter;\n  using Superclass = itk::ImageToImageFilter<TVectorImage, TVectorImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(BlockDiagonalMatrixVectorMultiplyImageFilter);\n\n  /** Convenient parameters extracted from template types */\n  static constexpr unsigned int nChannels = TVectorImage::PixelType::Dimension;\n\n  /** Convenient type alias */\n  using dataType = typename TVectorImage::PixelType::ValueType;\n\n  /** Set methods for all inputs, since they have different types */\n  void\n  SetInput1(const TVectorImage * vector);\n  void\n  SetInput2(const TMatrixImage * matrix);\n\nprotected:\n  BlockDiagonalMatrixVectorMultiplyImageFilter();\n  ~BlockDiagonalMatrixVectorMultiplyImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  DynamicThreadedGenerateData(const typename TVectorImage::RegionType & outputRegionForThread) override;\n\n  /** Getters for the inputs */\n  typename TVectorImage::ConstPointer\n  GetInput1();\n  typename TMatrixImage::ConstPointer\n  GetInput2();\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkBlockDiagonalMatrixVectorMultiplyImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkBlockDiagonalMatrixVectorMultiplyImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkBlockDiagonalMatrixVectorMultiplyImageFilter_hxx\n#define rtkBlockDiagonalMatrixVectorMultiplyImageFilter_hxx\n\n#include \"itkImageRegionIteratorWithIndex.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"vnl/vnl_inverse.h\"\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <class TVectorImage, class TMatrixImage>\nBlockDiagonalMatrixVectorMultiplyImageFilter<TVectorImage, TMatrixImage>::BlockDiagonalMatrixVectorMultiplyImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n}\n\ntemplate <class TVectorImage, class TMatrixImage>\nvoid\nBlockDiagonalMatrixVectorMultiplyImageFilter<TVectorImage, TMatrixImage>::SetInput1(const TVectorImage * vector)\n{\n  this->SetNthInput(0, const_cast<TVectorImage *>(vector));\n}\n\ntemplate <class TVectorImage, class TMatrixImage>\nvoid\nBlockDiagonalMatrixVectorMultiplyImageFilter<TVectorImage, TMatrixImage>::SetInput2(const TMatrixImage * matrix)\n{\n  this->SetNthInput(1, const_cast<TMatrixImage *>(matrix));\n}\n\ntemplate <class TVectorImage, class TMatrixImage>\ntypename TVectorImage::ConstPointer\nBlockDiagonalMatrixVectorMultiplyImageFilter<TVectorImage, TMatrixImage>::GetInput1()\n{\n  return static_cast<const TVectorImage *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <class TVectorImage, class TMatrixImage>\ntypename TMatrixImage::ConstPointer\nBlockDiagonalMatrixVectorMultiplyImageFilter<TVectorImage, TMatrixImage>::GetInput2()\n{\n  return static_cast<const TMatrixImage *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <class TVectorImage, class TMatrixImage>\nvoid\nBlockDiagonalMatrixVectorMultiplyImageFilter<TVectorImage, TMatrixImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get the requested regions on both outputs (should be identical)\n  typename TVectorImage::RegionType outputRequested = this->GetOutput()->GetRequestedRegion();\n\n  // Get pointers to the inputs\n  typename TVectorImage::Pointer input1Ptr = const_cast<TVectorImage *>(this->GetInput1().GetPointer());\n  typename TMatrixImage::Pointer input2Ptr = const_cast<TMatrixImage *>(this->GetInput2().GetPointer());\n\n  // The first and second input must have the same requested region as the outputs\n  input1Ptr->SetRequestedRegion(outputRequested);\n  input2Ptr->SetRequestedRegion(outputRequested);\n}\n\ntemplate <class TVectorImage, class TMatrixImage>\nvoid\nBlockDiagonalMatrixVectorMultiplyImageFilter<TVectorImage, TMatrixImage>::DynamicThreadedGenerateData(\n  const typename TVectorImage::RegionType & outputRegionForThread)\n{\n  // Create iterators for all inputs and outputs\n  itk::ImageRegionIterator<TVectorImage>      outIt(this->GetOutput(), outputRegionForThread);\n  itk::ImageRegionConstIterator<TVectorImage> vectorIt(this->GetInput1(), outputRegionForThread);\n  itk::ImageRegionConstIterator<TMatrixImage> matrixIt(this->GetInput2(), outputRegionForThread);\n\n  itk::Vector<dataType, nChannels> forOutput;\n\n  while (!outIt.IsAtEnd())\n  {\n    // Make a vnl matrix out of the values read in input 2 (the matrix mat, but stored in a vector)\n    vnl_matrix<dataType> mat = vnl_matrix<dataType>(matrixIt.Get().GetDataPointer(), nChannels, nChannels);\n\n    // Invert the mat, multiply by the vector, and write it in output\n    forOutput.SetVnlVector(mat * vectorIt.Get().GetVnlVector());\n    outIt.Set(forOutput);\n\n    ++outIt;\n    ++vectorIt;\n    ++matrixIt;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkBoellaardScatterCorrectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBoellaardScatterCorrectionImageFilter_h\n#define rtkBoellaardScatterCorrectionImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class BoellaardScatterCorrectionImageFilter\n * \\brief Scatter correction for cone-beam CT reconstruction.\n *\n * The scatter correction algorithm is based on the work of [Boellaard, Med\n * Phys, 1997] which has been used to implement the first scatter correction\n * algorithm of Elekta's cone-beam CT reconstruction software developed at the\n * Netherlands cancer institute by Marcel van Herk's group. The algorithm is\n * applied to raw projections, before computing the log. The algorithm assumes\n * that scatter adds a constant to all pixels of each projection. It does the\n * following steps for each projection:\n * 1. Mask out pixels above m_AirThreshold and record the smallest value sv.\n * 2. Compute the average value over all pixels of the resulting projection avg.\n * 3. Subtract min(m_ScatterToPrimaryRatio*avg, sv-m_NonNegativityConstraintThreshold).\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT BoellaardScatterCorrectionImageFilter\n  : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(BoellaardScatterCorrectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = BoellaardScatterCorrectionImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(BoellaardScatterCorrectionImageFilter);\n\n  /** Get / Set the air threshold on projection images. The threshold is used to\n   ** evaluate which part of the x-rays have traversed the patient. */\n  itkGetMacro(AirThreshold, double);\n  itkSetMacro(AirThreshold, double);\n\n  /** Get / Set the scatter-to-primary ratio on projection images. This is used\n   ** to measure the scatter level on the projection image from the total measure\n   ** signal. */\n  itkGetMacro(ScatterToPrimaryRatio, double);\n  itkSetMacro(ScatterToPrimaryRatio, double);\n\n  /** Get / Set the non-negativity constraint threshold. The pixels values will\n  ** no be alowed below this signal to avoid nan when computing the log. */\n  itkGetMacro(NonNegativityConstraintThreshold, double);\n  itkSetMacro(NonNegativityConstraintThreshold, double);\n\nprotected:\n  BoellaardScatterCorrectionImageFilter();\n  ~BoellaardScatterCorrectionImageFilter() override = default;\n\n  /** Requires full projection images to estimate scatter */\n  void\n  EnlargeOutputRequestedRegion(itk::DataObject * itkNotUsed(output)) override;\n  void\n  ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, ThreadIdType threadId) override;\n\n  /** Split the output's RequestedRegion into \"num\" pieces, returning\n   * region \"i\" as \"splitRegion\". Reimplemented from ImageSource to ensure\n   * that each thread covers entire projections. */\n  unsigned int\n  SplitRequestedRegion(unsigned int i, unsigned int num, OutputImageRegionType & splitRegion) override;\n  virtual int\n  SplitRequestedRegion(int i, int num, OutputImageRegionType & splitRegion);\n\nprivate:\n  /** Air threshold on projection images. */\n  double m_AirThreshold{ 32000 };\n\n  /** Scatter to primary ratio */\n  double m_ScatterToPrimaryRatio{ 0. };\n\n  /** Non-negativity constraint threshold */\n  double m_NonNegativityConstraintThreshold{ 20 };\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkBoellaardScatterCorrectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkBoellaardScatterCorrectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBoellaardScatterCorrectionImageFilter_hxx\n#define rtkBoellaardScatterCorrectionImageFilter_hxx\n\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nBoellaardScatterCorrectionImageFilter<TInputImage, TOutputImage>::BoellaardScatterCorrectionImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n}\n\n// Requires full projection images to estimate scatter.\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBoellaardScatterCorrectionImageFilter<TInputImage, TOutputImage>::EnlargeOutputRequestedRegion(itk::DataObject *)\n{\n  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();\n  if (!outputPtr)\n    return;\n\n  const unsigned int                Dimension = TInputImage::ImageDimension;\n  typename TOutputImage::RegionType orr = outputPtr->GetRequestedRegion();\n  typename TOutputImage::RegionType lpr = outputPtr->GetLargestPossibleRegion();\n\n  for (unsigned int i = 0; i < Dimension - 1; i++)\n  {\n    orr.SetIndex(i, lpr.GetIndex(i));\n    orr.SetSize(i, lpr.GetSize(i));\n  }\n\n  outputPtr->SetRequestedRegion(orr);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nBoellaardScatterCorrectionImageFilter<TInputImage, TOutputImage>::ThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread,\n  ThreadIdType                  itkNotUsed(threadId))\n{\n  // Input / ouput iterators\n  itk::ImageRegionConstIterator<InputImageType> itIn(this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<OutputImageType>     itOut(this->GetOutput(), outputRegionForThread);\n\n  const unsigned int Dimension = TInputImage::ImageDimension;\n  unsigned int       npixelPerSlice = 1;\n  for (unsigned int i = 0; i < Dimension - 1; i++)\n    npixelPerSlice *= outputRegionForThread.GetSize(i);\n\n  unsigned int start = outputRegionForThread.GetIndex(Dimension - 1);\n  unsigned int stop = start + outputRegionForThread.GetSize(Dimension - 1);\n  for (unsigned int slice = start; slice < stop; slice++)\n  {\n    itk::ImageRegionConstIterator<InputImageType> itInSlice = itIn;\n\n    // Retrieve useful characteristics of current slice\n    double averageBehindPatient = 0.;\n    double smallestValue = itk::NumericTraits<double>::max();\n    for (unsigned int i = 0; i < npixelPerSlice; i++)\n    {\n      smallestValue = std::min(smallestValue, (double)itInSlice.Get());\n      if (itInSlice.Get() <= m_AirThreshold)\n      {\n        averageBehindPatient += itInSlice.Get();\n      }\n      ++itInSlice;\n    }\n    averageBehindPatient /= npixelPerSlice;\n\n    // Compute constant correction\n    double correction = averageBehindPatient * m_ScatterToPrimaryRatio;\n\n    // Apply non-negativity constraint\n    if (smallestValue - correction < m_NonNegativityConstraintThreshold)\n      correction = smallestValue - m_NonNegativityConstraintThreshold;\n\n    // Remove constant factor\n    for (unsigned int i = 0; i < npixelPerSlice; i++)\n    {\n      itOut.Set(itIn.Get() - correction);\n      ++itIn;\n      ++itOut;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nunsigned int\nBoellaardScatterCorrectionImageFilter<TInputImage, TOutputImage>::SplitRequestedRegion(\n  unsigned int            i,\n  unsigned int            num,\n  OutputImageRegionType & splitRegion)\n{\n  return SplitRequestedRegion((int)i, (int)num, splitRegion);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nint\nBoellaardScatterCorrectionImageFilter<TInputImage, TOutputImage>::SplitRequestedRegion(\n  int                     i,\n  int                     num,\n  OutputImageRegionType & splitRegion)\n{\n  // Get the output pointer\n  OutputImageType *                       outputPtr = this->GetOutput();\n  const typename TOutputImage::SizeType & requestedRegionSize = outputPtr->GetRequestedRegion().GetSize();\n\n  int                              splitAxis = 0;\n  typename TOutputImage::IndexType splitIndex;\n  typename TOutputImage::SizeType  splitSize;\n\n  // Initialize the splitRegion to the output requested region\n  splitRegion = outputPtr->GetRequestedRegion();\n  splitIndex = splitRegion.GetIndex();\n  splitSize = splitRegion.GetSize();\n\n  // split on the outermost dimension available\n  splitAxis = outputPtr->GetImageDimension() - 1;\n  if (requestedRegionSize[splitAxis] == 1)\n  { // cannot split\n    itkDebugMacro(\"  Cannot Split\");\n    return 1;\n  }\n\n  // determine the actual number of pieces that will be generated\n  typename TOutputImage::SizeType::SizeValueType range = requestedRegionSize[splitAxis];\n  int                                            valuesPerThread = itk::Math::Ceil<int>(range / (double)num);\n  int maxThreadIdUsed = itk::Math::Ceil<int>(range / (double)valuesPerThread) - 1;\n\n  // Split the region\n  if (i < maxThreadIdUsed)\n  {\n    splitIndex[splitAxis] += i * valuesPerThread;\n    splitSize[splitAxis] = valuesPerThread;\n  }\n  if (i == maxThreadIdUsed)\n  {\n    splitIndex[splitAxis] += i * valuesPerThread;\n    // last thread needs to process the \"rest\" dimension being split\n    splitSize[splitAxis] = splitSize[splitAxis] - i * valuesPerThread;\n  }\n\n  // set the split region ivars\n  splitRegion.SetIndex(splitIndex);\n  splitRegion.SetSize(splitSize);\n\n  itkDebugMacro(\"  Split Piece: \" << splitRegion);\n\n  return maxThreadIdUsed + 1;\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkBoxShape.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBoxShape_h\n#define rtkBoxShape_h\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n#include \"rtkConvexShape.h\"\n\n#include <itkImageBase.h>\n\nnamespace rtk\n{\n\n/** \\class BoxShape\n * \\brief BoxShape defines a paralleliped.\n * The box is defined by its two opposite corners, BoxMin and BoxMax, and a\n * rotation matrix Direction. The box corresponding to an Image can be set\n * using the function SetBoxShapeFromImage.\n *\n * \\test rtkforbildtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n *\n */\nclass RTK_EXPORT BoxShape : public ConvexShape\n{\npublic:\n  /** Standard class type alias. */\n  using Self = BoxShape;\n  using Superclass = ConvexShape;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  static constexpr unsigned int Dimension = Superclass::Dimension;\n  using ScalarType = Superclass::ScalarType;\n  using PointType = Superclass::PointType;\n  using VectorType = Superclass::VectorType;\n  using RotationMatrixType = Superclass::RotationMatrixType;\n  using ImageBaseType = itk::ImageBase<Dimension>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(BoxShape);\n\n  /** See rtk::ConvexShape::IsInside. */\n  bool\n  IsInside(const PointType & point) const override;\n\n  /** See rtk::ConvexShape::IsIntersectedByRay for the goal and\n   * https://education.siggraph.org/static/HyperGraph/raytrace/rtinter4.htm\n   * for the computation. */\n  bool\n  IsIntersectedByRay(const PointType &  rayOrigin,\n                     const VectorType & rayDirection,\n                     double &           nearDist,\n                     double &           farDist) const override;\n\n  /** Rescale object along each direction by a 3D vector. */\n  void\n  Rescale(const VectorType & r) override;\n\n  /** Translate object by a given 3D vector. */\n  void\n  Translate(const VectorType & t) override;\n\n  /** Translate object by a given 3D vector. */\n  void\n  Rotate(const RotationMatrixType & r) override;\n\n  /** Get / Set the box inferior corner. Every corner coordinate must be\n   * inferior to those of the superior corner. */\n  itkGetConstMacro(BoxMin, PointType);\n  itkSetMacro(BoxMin, PointType);\n\n  /** Get / Set the box superior corner. Every corner coordinate must be\n   * superior to those of the inferior corner. */\n  itkGetConstMacro(BoxMax, PointType);\n  itkSetMacro(BoxMax, PointType);\n\n  /** Direction is the direction of the box, defined in the same sense as in\n   * itk::ImageBase. */\n  itkGetConstMacro(Direction, RotationMatrixType);\n  itkSetMacro(Direction, RotationMatrixType);\n\n  itk::LightObject::Pointer\n  InternalClone() const override;\n\n  /** Set the 3D box is the portion of space defined by the LargestPossibleRegion.\n   * bWithExternalHalfPixelBorder can be used to include or exclude a half voxel\n   * border. */\n  void\n  SetBoxFromImage(const ImageBaseType * img, bool bWithExternalHalfPixelBorder = true);\n\nprivate:\n  BoxShape();\n\n  PointType          m_BoxMin;\n  PointType          m_BoxMax;\n  RotationMatrixType m_Direction;\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkConditionalMedianImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkConditionalMedianImageFilter_h\n#define rtkConditionalMedianImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include <itkConstNeighborhoodIterator.h>\n#include <itkVectorImage.h>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class ConditionalMedianImageFilter\n * \\brief Performs a median filtering on outlier pixels\n *\n * ConditionalMedianImageFilter computes the median of the pixel values\n * in a neighborhood around each pixel. If the input pixel value is close\n * to the computed median, it is kept unchanged and copied to the output.\n * Otherwise it is replaced by the computed median.\n * Note that if m_ThresholdMultiplier = 0, this filter behaves like a usual\n * median filter, and if m_Radius = [0, 0, ..., 0], the image passes through\n * unchanged.\n *\n * \\test TODO\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <typename TInputImage>\nclass ITK_TEMPLATE_EXPORT ConditionalMedianImageFilter : public itk::InPlaceImageFilter<TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConditionalMedianImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ConditionalMedianImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using MedianRadiusType = typename itk::ConstNeighborhoodIterator<TInputImage>::RadiusType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConditionalMedianImageFilter);\n\n  /** Set/Get neighborhood radius */\n  itkSetMacro(Radius, MedianRadiusType);\n  itkGetMacro(Radius, MedianRadiusType);\n\n  /** Set/Get neighborhood radius */\n  itkSetMacro(ThresholdMultiplier, double);\n  itkGetMacro(ThresholdMultiplier, double);\n\nprotected:\n  ConditionalMedianImageFilter();\n  ~ConditionalMedianImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  DynamicThreadedGenerateData(const typename TInputImage::RegionType & outputRegionForThread) override;\n\n  MedianRadiusType m_Radius;\n  double           m_ThresholdMultiplier;\n};\n\ntemplate <>\nRTK_EXPORT void\nConditionalMedianImageFilter<itk::VectorImage<float, 3>>::DynamicThreadedGenerateData(\n  const itk::VectorImage<float, 3>::RegionType & outputRegionForThread);\n\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkConditionalMedianImageFilter.hxx\"\n#endif\n\n#endif // rtkConditionalMedianImageFilter_h\n"
  },
  {
    "path": "include/rtkConditionalMedianImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkConditionalMedianImageFilter_hxx\n#define rtkConditionalMedianImageFilter_hxx\n\n#include <itkImageRegionIterator.h>\n#include <numeric>\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <typename TInputImage>\nConditionalMedianImageFilter<TInputImage>::ConditionalMedianImageFilter()\n{\n  // Default parameters\n  m_Radius.Fill(1);\n  m_ThresholdMultiplier = 1;\n}\n\n\ntemplate <typename TInputImage>\nvoid\nConditionalMedianImageFilter<TInputImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Compute the requested region\n  typename TInputImage::RegionType inputRequested = this->GetOutput()->GetRequestedRegion();\n  typename TInputImage::SizeType   requestedSize = inputRequested.GetSize();\n  typename TInputImage::IndexType  requestedIndex = inputRequested.GetIndex();\n\n  // We need the previous projection to extract the noise,\n  // and the neighboring pixels to compute its variance\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    requestedSize[dim] += 2 * m_Radius[dim];\n    requestedIndex[dim] -= m_Radius[dim];\n  }\n  inputRequested.SetSize(requestedSize);\n  inputRequested.SetIndex(requestedIndex);\n\n  // Crop the requested region to the LargestPossibleRegion\n  inputRequested.Crop(this->GetInput()->GetLargestPossibleRegion());\n\n  // Get a pointer to the input and set the requested region\n  typename TInputImage::Pointer inputPtr = const_cast<TInputImage *>(this->GetInput());\n  inputPtr->SetRequestedRegion(inputRequested);\n}\n\ntemplate <typename TInputImage>\nvoid\nConditionalMedianImageFilter<TInputImage>::DynamicThreadedGenerateData(\n  const typename TInputImage::RegionType & outputRegionForThread)\n{\n  // Compute the centered difference with the previous and next frames, store it into the intermediate image\n  itk::ConstNeighborhoodIterator<TInputImage> nIt(m_Radius, this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<TInputImage>       outIt(this->GetOutput(), outputRegionForThread);\n\n  // Build a vector in which all pixel of the neighborhood will be temporarily stored\n  std::vector<typename TInputImage::PixelType> pixels;\n  pixels.resize(nIt.Size());\n\n  // Walk the output image\n  while (!outIt.IsAtEnd())\n  {\n    // Walk the neighborhood in the input image, store the pixels into a vector\n    for (unsigned int i = 0; i < nIt.Size(); i++)\n      pixels[i] = nIt.GetPixel(i);\n\n    // Compute the standard deviation\n    double sum = std::accumulate(pixels.begin(), pixels.end(), 0.0);\n    double mean = sum / pixels.size();\n    double sq_sum = std::inner_product(pixels.begin(), pixels.end(), pixels.begin(), 0.0);\n    double stdev = std::sqrt(sq_sum / pixels.size() - mean * mean);\n\n    // Compute the median of the neighborhood\n    std::nth_element(pixels.begin(), pixels.begin() + pixels.size() / 2, pixels.end());\n\n    // If the pixel value is too far from the median, replace it by the median\n    if (itk::Math::abs(pixels[pixels.size() / 2] - nIt.GetCenterPixel()) > (m_ThresholdMultiplier * stdev))\n      outIt.Set(pixels[pixels.size() / 2]);\n    else // Otherwise, leave it as is\n      outIt.Set(nIt.GetCenterPixel());\n\n    ++nIt;\n    ++outIt;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientConeBeamReconstructionFilter_h\n#define rtkConjugateGradientConeBeamReconstructionFilter_h\n\n#include <itkMultiplyImageFilter.h>\n#include <itkDivideOrZeroOutImageFilter.h>\n#include <itkProcessObject.h>\n#include <itkObject.h>\n#include <itkCommand.h>\n#include <itkIterationReporter.h>\n\n#include \"rtkConjugateGradientImageFilter.h\"\n#include \"rtkReconstructionConjugateGradientOperator.h\"\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkLaplacianImageFilter.h\"\n#include \"rtkBlockDiagonalMatrixVectorMultiplyImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaConjugateGradientImageFilter.h\"\n#  include \"rtkCudaDisplacedDetectorImageFilter.h\"\n#  include \"rtkCudaConstantVolumeSource.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class ConjugateGradientConeBeamReconstructionFilter\n * \\brief Implements ConjugateGradient\n *\n * This filter implements the ConjugateGradient method.\n * ConjugateGradient attempts to find the f that minimizes\n * (1/2).|| sqrt(D) (Rf -p) ||_2^2 + (1/2).gamma.|| grad f ||_2^2 + (1/2).Tikhonov || f ||_2^2\n * with R the forward projection operator,\n * p the measured projections, and D the displaced detector weighting operator.\n *\n * With gamma=0, this it is similar to the ART and SART methods. The difference lies\n * in the algorithm employed to minimize this cost function. ART uses the\n * Kaczmarz method (projects and back projects one ray at a time),\n * SART the block-Kaczmarz method (projects and back projects one projection\n * at a time), and ConjugateGradient a conjugate gradient method\n * (projects and back projects all projections together).\n *\n * With gamma > 0, a regularization is applied.\n *\n * \\dot\n * digraph ConjugateGradientConeBeamReconstructionFilter {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (Weights)\"];\n * Input2 [shape=Mdiamond];\n * Input3 [label=\"Input Support mask\"];\n * Input3 [shape=Mdiamond];\n * Output [label=\"Output (Volume)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * MultiplyProjections [label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * MultiplyVolumes [label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * MultiplyOutput [label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * BackProjection [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n * ConjugateGradient[ label=\"rtk::ConjugateGradientImageFilter\" URL=\"\\ref rtk::ConjugateGradientImageFilter\"];\n * VolumeSource [ label=\"rtk::ConstantImageSource (Volume)\" URL=\"\\ref rtk::ConstantImageSource\"];\n\n * Input0 -> ConjugateGradient;\n * Input1 -> MultiplyProjections;\n * Input2 -> Displaced;\n * Displaced -> MultiplyProjections;\n * MultiplyProjections -> BackProjection;\n * VolumeSource -> BackProjection;\n * Input3 -> MultiplyVolumes;\n * Input3 -> MultiplyOutput;\n * BackProjection -> MultiplyVolumes;\n * MultiplyVolumes -> ConjugateGradient;\n * ConjugateGradient -> MultiplyOutput;\n * MultiplyOutput -> Output;\n * }\n * \\enddot\n *\n * \\test rtkconjugategradientreconstructiontest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TOutputImage, typename TSingleComponentImage = TOutputImage, typename TWeightsImage = TOutputImage>\nclass ITK_TEMPLATE_EXPORT ConjugateGradientConeBeamReconstructionFilter\n  : public IterativeConeBeamReconstructionFilter<TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConjugateGradientConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = ConjugateGradientConeBeamReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConjugateGradientConeBeamReconstructionFilter);\n\n  /** Setters for the inputs */\n  void\n  SetInputVolume(const TOutputImage * vol);\n  void\n  SetInputProjectionStack(const TOutputImage * projs);\n  void\n  SetInputWeights(const TWeightsImage * weights);\n  void\n  SetLocalRegularizationWeights(const TSingleComponentImage * weights);\n\n  using ForwardProjectionFilterType = ForwardProjectionImageFilter<TOutputImage, TOutputImage>;\n  using ForwardProjectionFilterPointer = typename ForwardProjectionFilterType::Pointer;\n  using BackProjectionFilterType = BackProjectionImageFilter<TOutputImage, TOutputImage>;\n  using ConjugateGradientFilterType = ConjugateGradientImageFilter<TOutputImage>;\n  using ConjugateGradientFilterPointer = typename ConjugateGradientFilterType::Pointer;\n  using MultiplyFilterType = itk::MultiplyImageFilter<TOutputImage, TSingleComponentImage, TOutputImage>;\n  using CGOperatorFilterType =\n    ReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>;\n  using DivideFilterType = itk::DivideOrZeroOutImageFilter<TOutputImage>;\n  using StatisticsImageFilterType = itk::StatisticsImageFilter<TOutputImage>;\n  using OutputImagePointer = typename TOutputImage::Pointer;\n  using StatisticsFilterType = itk::StatisticsImageFilter<TSingleComponentImage>;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  // If TOutputImage is an itk::Image of floats or double, so are the weights, and a simple Multiply filter is required\n  // If TOutputImage is an itk::Image of itk::Vector<float (or double)>, a BlockDiagonalMatrixVectorMultiply filter\n  // is needed. Thus the meta-programming construct\n  using MatrixVectorMultiplyFilterType = BlockDiagonalMatrixVectorMultiplyImageFilter<TOutputImage, TWeightsImage>;\n  using PlainMultiplyFilterType = itk::MultiplyImageFilter<TOutputImage, TOutputImage, TOutputImage>;\n  using MultiplyWithWeightsFilterType = typename std::conditional_t<std::is_same_v<TSingleComponentImage, TOutputImage>,\n                                                                    PlainMultiplyFilterType,\n                                                                    MatrixVectorMultiplyFilterType>;\n  using CPUOutputImageType = typename itk::Image<typename TOutputImage::PixelType, TOutputImage::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using DisplacedDetectorFilterType = typename std::conditional_t<!std::is_same_v<TOutputImage, CPUOutputImageType> &&\n                                                                    std::is_same_v<TSingleComponentImage, TOutputImage>,\n                                                                  CudaDisplacedDetectorImageFilter,\n                                                                  DisplacedDetectorImageFilter<TWeightsImage>>;\n  using ConstantImageSourceType = typename std::conditional_t<!std::is_same_v<TOutputImage, CPUOutputImageType> &&\n                                                                std::is_same_v<TSingleComponentImage, TOutputImage>,\n                                                              CudaConstantVolumeSource,\n                                                              ConstantImageSource<TOutputImage>>;\n  using ConstantWeightSourceType = typename std::conditional_t<!std::is_same_v<TOutputImage, CPUOutputImageType> &&\n                                                                 std::is_same_v<TSingleComponentImage, TOutputImage>,\n                                                               CudaConstantVolumeSource,\n                                                               ConstantImageSource<TWeightsImage>>;\n#else\n  using DisplacedDetectorFilterType = DisplacedDetectorImageFilter<TWeightsImage>;\n  using ConstantImageSourceType = ConstantImageSource<TOutputImage>;\n  using ConstantWeightSourceType = ConstantImageSource<TWeightsImage>;\n#endif\n\n  /** Set the support mask, if any, for support constraint in reconstruction */\n  void\n  SetSupportMask(const TSingleComponentImage * SupportMask);\n  typename TSingleComponentImage::ConstPointer\n  GetSupportMask();\n\n  /** Pass the geometry to all filters needing it */\n  itkSetConstObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  itkSetMacro(NumberOfIterations, int);\n  itkGetMacro(NumberOfIterations, int);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\n  /** If Regularized, perform Tikhonov regularization during\n   *  reconstruction: (1/2).Tikhonov || f ||_2^2 */\n  itkSetMacro(Tikhonov, float);\n  itkGetMacro(Tikhonov, float);\n\n  /** If Regularized, perform laplacian-based regularization during\n   *  reconstruction: (1/2).gamma.|| grad f ||_2^2 (gamma is the strength of\n   *  the regularization). */\n  itkSetMacro(Gamma, float);\n  itkGetMacro(Gamma, float);\n\n  /** Get / Set whether conjugate gradient should be performed on GPU */\n  itkGetMacro(CudaConjugateGradient, bool);\n  itkSetMacro(CudaConjugateGradient, bool);\n\nprotected:\n  ConjugateGradientConeBeamReconstructionFilter();\n  ~ConjugateGradientConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename MultiplyFilterType::Pointer                                       m_MultiplyProjectionsFilter;\n  typename MultiplyFilterType::Pointer                                       m_MultiplyVolumeFilter;\n  typename MultiplyFilterType::Pointer                                       m_MultiplyOutputFilter;\n  ConjugateGradientFilterPointer                                             m_ConjugateGradientFilter;\n  typename CGOperatorFilterType::Pointer                                     m_CGOperator;\n  typename ForwardProjectionImageFilter<TOutputImage, TOutputImage>::Pointer m_ForwardProjectionFilter;\n  typename BackProjectionImageFilter<TOutputImage, TOutputImage>::Pointer    m_BackProjectionFilter;\n  typename BackProjectionImageFilter<TOutputImage, TOutputImage>::Pointer    m_BackProjectionFilterForB;\n  typename DisplacedDetectorFilterType::Pointer                              m_DisplacedDetectorFilter;\n  typename ConstantImageSourceType::Pointer                                  m_ConstantVolumeSource;\n  typename MultiplyWithWeightsFilterType::Pointer                            m_MultiplyWithWeightsFilter;\n\n  /** The inputs of this filter have the same type (float, 3) but not the same meaning\n   * It is normal that they do not occupy the same physical space. Therefore this check\n   * must be removed */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n\n  /** Getters for the inputs */\n  typename TOutputImage::ConstPointer\n  GetInputVolume();\n  typename TOutputImage::ConstPointer\n  GetInputProjectionStack();\n  typename TWeightsImage::ConstPointer\n  GetInputWeights();\n  typename TSingleComponentImage::ConstPointer\n  GetLocalRegularizationWeights();\n\n  template <typename ImageType,\n            typename IterativeConeBeamReconstructionFilter<TOutputImage>::template EnableCudaScalarAndVectorType<\n              ImageType> * = nullptr>\n  ConjugateGradientFilterPointer\n  InstantiateCudaConjugateGradientImageFilter();\n\n  template <typename ImageType,\n            typename IterativeConeBeamReconstructionFilter<TOutputImage>::template DisableCudaScalarAndVectorType<\n              ImageType> * = nullptr>\n  ConjugateGradientFilterPointer\n  InstantiateCudaConjugateGradientImageFilter();\n\n  /** Iteration reporter */\n  void\n  ReportProgress(itk::Object *, const itk::EventObject &);\n\nprivate:\n  ThreeDCircularProjectionGeometry::ConstPointer m_Geometry;\n\n  int   m_NumberOfIterations;\n  float m_Gamma;\n  float m_Tikhonov;\n  bool  m_CudaConjugateGradient;\n  bool  m_DisableDisplacedDetectorFilter;\n\n  // Iteration reporting\n  itk::IterationReporter m_IterationReporter;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkConjugateGradientConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientConeBeamReconstructionFilter_hxx\n#define rtkConjugateGradientConeBeamReconstructionFilter_hxx\n\n#include <itkProgressAccumulator.h>\n#include <itkPixelTraits.h>\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  ConjugateGradientConeBeamReconstructionFilter()\n  : m_IterationReporter(this, 0, 1) // report every iteration\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set the default values of member parameters\n  m_NumberOfIterations = 3;\n\n  m_Gamma = 0;\n  m_Tikhonov = 0;\n  m_CudaConjugateGradient = true;\n  m_DisableDisplacedDetectorFilter = false;\n\n  // Create the filters\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n  m_ConstantVolumeSource = ConstantImageSourceType::New();\n  m_CGOperator = CGOperatorFilterType::New();\n  m_MultiplyVolumeFilter = MultiplyFilterType::New();\n  m_MultiplyProjectionsFilter = MultiplyFilterType::New();\n  m_MultiplyOutputFilter = MultiplyFilterType::New();\n  m_MultiplyWithWeightsFilter = MultiplyWithWeightsFilterType::New();\n\n  // Set permanent parameters\n  m_ConstantVolumeSource->SetConstant(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::SetInputVolume(\n  const TOutputImage * vol)\n{\n  this->SetNthInput(0, const_cast<TOutputImage *>(vol));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  SetInputProjectionStack(const TOutputImage * projs)\n{\n  this->SetNthInput(1, const_cast<TOutputImage *>(projs));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::SetInputWeights(\n  const TWeightsImage * weights)\n{\n  this->SetInput(\"InputWeights\", const_cast<TWeightsImage *>(weights));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  SetLocalRegularizationWeights(const TSingleComponentImage * weights)\n{\n  this->SetInput(\"LocalRegularizationWeights\", const_cast<TSingleComponentImage *>(weights));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::SetSupportMask(\n  const TSingleComponentImage * SupportMask)\n{\n  this->SetInput(\"SupportMask\", const_cast<TSingleComponentImage *>(SupportMask));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TOutputImage::ConstPointer\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::GetInputVolume()\n{\n  return static_cast<const TOutputImage *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TOutputImage::ConstPointer\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  GetInputProjectionStack()\n{\n  return static_cast<const TOutputImage *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TWeightsImage::ConstPointer\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::GetInputWeights()\n{\n  return static_cast<const TWeightsImage *>(this->itk::ProcessObject::GetInput(\"InputWeights\"));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TSingleComponentImage::ConstPointer\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  GetLocalRegularizationWeights()\n{\n  return static_cast<const TSingleComponentImage *>(this->itk::ProcessObject::GetInput(\"LocalRegularizationWeights\"));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TSingleComponentImage::ConstPointer\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::GetSupportMask()\n{\n  return static_cast<const TSingleComponentImage *>(this->itk::ProcessObject::GetInput(\"SupportMask\"));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::VerifyPreconditions()\n  const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  GenerateInputRequestedRegion()\n{\n  // Input 0 is the volume we update\n  typename TOutputImage::Pointer inputPtr0 = const_cast<TOutputImage *>(this->GetInputVolume().GetPointer());\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the stack of projections to backproject\n  typename TOutputImage::Pointer inputPtr1 = const_cast<TOutputImage *>(this->GetInputProjectionStack().GetPointer());\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n\n  // Input \"InputWeights\" is the weights map on projections, either user-defined or filled with ones (default)\n  if (this->GetInputWeights().IsNotNull())\n  {\n    typename TWeightsImage::Pointer inputWeights = const_cast<TWeightsImage *>(this->GetInputWeights().GetPointer());\n    if (!inputWeights)\n      return;\n    inputWeights->SetRequestedRegion(inputWeights->GetLargestPossibleRegion());\n  }\n\n  // Input LocalRegularizationWeights is the optional weights map on regularization\n  if (this->GetLocalRegularizationWeights().IsNotNull())\n  {\n    typename TSingleComponentImage::Pointer localRegWeights =\n      const_cast<TSingleComponentImage *>(this->GetLocalRegularizationWeights().GetPointer());\n    if (!localRegWeights)\n      return;\n    localRegWeights->SetRequestedRegion(localRegWeights->GetLargestPossibleRegion());\n  }\n\n  // Input \"SupportMask\" is the support constraint mask on volume, if any\n  if (this->GetSupportMask().IsNotNull())\n  {\n    typename TSingleComponentImage::Pointer inputSupportMaskPtr =\n      const_cast<TSingleComponentImage *>(this->GetSupportMask().GetPointer());\n    if (!inputSupportMaskPtr)\n      return;\n    inputSupportMaskPtr->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  }\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  GenerateOutputInformation()\n{\n  // Choose between cuda or non-cuda conjugate gradient filter\n  m_ConjugateGradientFilter = ConjugateGradientFilterType::New();\n#ifdef RTK_USE_CUDA\n  if (m_CudaConjugateGradient)\n    m_ConjugateGradientFilter = InstantiateCudaConjugateGradientImageFilter<TOutputImage>();\n#endif\n  m_ConjugateGradientFilter->SetA(m_CGOperator.GetPointer());\n\n  // Set forward projection filter\n  m_ForwardProjectionFilter = this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n  // Pass the ForwardProjection filter to the conjugate gradient operator\n  m_CGOperator->SetForwardProjectionFilter(m_ForwardProjectionFilter);\n\n  // Set back projection filter\n  m_BackProjectionFilter = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  // Pass the backprojection filter to the conjugate gradient operator and to the back projection filter generating the\n  // B of AX=B\n  m_BackProjectionFilterForB = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  m_CGOperator->SetBackProjectionFilter(m_BackProjectionFilter);\n\n  // Set runtime connections\n  m_ConstantVolumeSource->SetInformationFromImage(this->GetInputVolume());\n  m_CGOperator->SetInputProjectionStack(this->GetInputProjectionStack());\n  m_CGOperator->SetSupportMask(this->GetSupportMask());\n  m_ConjugateGradientFilter->SetX(this->GetInputVolume());\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n  if (this->GetInputWeights().IsNull())\n  {\n    using PixelType = typename TWeightsImage::PixelType;\n    auto ones = ConstantWeightSourceType::New();\n    ones->SetInformationFromImage(this->GetInputProjectionStack());\n    ones->SetConstant(PixelType(itk::NumericTraits<typename itk::PixelTraits<PixelType>::ValueType>::One));\n    ones->Update();\n    this->SetInputWeights(ones->GetOutput());\n  }\n  m_DisplacedDetectorFilter->SetInput(this->GetInputWeights());\n\n  // Links with the m_BackProjectionFilter should be set here and not\n  // in the constructor, as m_BackProjectionFilter is set at runtime\n  m_BackProjectionFilterForB->SetInput(0, m_ConstantVolumeSource->GetOutput());\n  m_ConjugateGradientFilter->SetB(m_BackProjectionFilterForB->GetOutput());\n\n  // Multiply the projections by the weights map\n  m_MultiplyWithWeightsFilter->SetInput1(this->GetInputProjectionStack());\n  m_MultiplyWithWeightsFilter->SetInput2(m_DisplacedDetectorFilter->GetOutput());\n  m_CGOperator->SetInputWeights(m_DisplacedDetectorFilter->GetOutput());\n  m_CGOperator->SetLocalRegularizationWeights(this->GetLocalRegularizationWeights());\n  m_BackProjectionFilterForB->SetInput(1, m_MultiplyWithWeightsFilter->GetOutput());\n\n  // If a support mask is used, it serves as preconditioning weights\n  if (this->GetSupportMask().IsNotNull())\n  {\n    // Multiply the volume by support mask, and pass it to the conjugate gradient operator\n    m_MultiplyVolumeFilter->SetInput1(m_BackProjectionFilterForB->GetOutput());\n    m_MultiplyVolumeFilter->SetInput2(this->GetSupportMask());\n    m_CGOperator->SetSupportMask(this->GetSupportMask());\n    m_ConjugateGradientFilter->SetB(m_MultiplyVolumeFilter->GetOutput());\n\n    // Multiply the output by the support mask\n    m_MultiplyOutputFilter->SetInput1(m_ConjugateGradientFilter->GetOutput());\n    m_MultiplyOutputFilter->SetInput2(this->GetSupportMask());\n  }\n\n  // For the same reason, set geometry now\n  m_CGOperator->SetGeometry(this->m_Geometry);\n  m_BackProjectionFilterForB->SetGeometry(this->m_Geometry.GetPointer());\n  m_DisplacedDetectorFilter->SetGeometry(this->m_Geometry);\n\n  // Set runtime parameters\n  m_ConjugateGradientFilter->SetNumberOfIterations(this->m_NumberOfIterations);\n  m_CGOperator->SetGamma(m_Gamma);\n  m_CGOperator->SetTikhonov(m_Tikhonov);\n\n  // Set memory management parameters\n  m_MultiplyProjectionsFilter->ReleaseDataFlagOn();\n  m_BackProjectionFilterForB->ReleaseDataFlagOn();\n  if (this->GetSupportMask().IsNotNull())\n  {\n    m_MultiplyVolumeFilter->ReleaseDataFlagOn();\n    m_MultiplyOutputFilter->ReleaseDataFlagOn();\n  }\n\n  // Have the last filter calculate its output information\n  m_ConjugateGradientFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_ConjugateGradientFilter->GetOutput());\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::GenerateData()\n{\n  auto callbackCommand = itk::MemberCommand<Self>::New();\n  callbackCommand->SetCallbackFunction(this, &Self::ReportProgress);\n  m_ConjugateGradientFilter->AddObserver(itk::IterationEvent(), callbackCommand);\n\n  m_ConjugateGradientFilter->Update();\n\n  if (this->GetSupportMask())\n  {\n    m_MultiplyOutputFilter->Update();\n    this->GraftOutput(m_MultiplyOutputFilter->GetOutput());\n  }\n  else\n  {\n    this->GraftOutput(m_ConjugateGradientFilter->GetOutput());\n  }\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntemplate <\n  typename ImageType,\n  typename IterativeConeBeamReconstructionFilter<TOutputImage>::template EnableCudaScalarAndVectorType<ImageType> *>\ntypename ConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  ConjugateGradientFilterPointer\n  ConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n    InstantiateCudaConjugateGradientImageFilter()\n{\n  ConjugateGradientFilterPointer cg;\n#ifdef RTK_USE_CUDA\n  cg = CudaConjugateGradientImageFilter<TOutputImage>::New();\n#endif\n  return cg;\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntemplate <\n  typename ImageType,\n  typename IterativeConeBeamReconstructionFilter<TOutputImage>::template DisableCudaScalarAndVectorType<ImageType> *>\ntypename ConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  ConjugateGradientFilterPointer\n  ConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::\n    InstantiateCudaConjugateGradientImageFilter()\n{\n  itkGenericExceptionMacro(\n    << \"CudaConjugateGradientImageFilter only available with 3D CudaImage of float or itk::Vector<float,3>.\");\n  return nullptr;\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nConjugateGradientConeBeamReconstructionFilter<TOutputImage, TSingleComponentImage, TWeightsImage>::ReportProgress(\n  itk::Object *            caller,\n  const itk::EventObject & event)\n{\n  if (!itk::IterationEvent().CheckEvent(&event))\n  {\n    return;\n  }\n  auto * cgCaller = dynamic_cast<rtk::ConjugateGradientImageFilter<TOutputImage> *>(caller);\n  if (cgCaller)\n  {\n    this->GraftOutput(cgCaller->GetOutput());\n    m_IterationReporter.CompletedStep();\n  }\n}\n\n} // end namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientGetP_kPlusOneImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientGetP_kPlusOneImageFilter_h\n#define rtkConjugateGradientGetP_kPlusOneImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkAddImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n\nnamespace rtk\n{\n/** \\class ConjugateGradientGetP_kPlusOneImageFilter\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <typename TInputImage>\nclass ITK_TEMPLATE_EXPORT ConjugateGradientGetP_kPlusOneImageFilter\n  : public itk::ImageToImageFilter<TInputImage, TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConjugateGradientGetP_kPlusOneImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ConjugateGradientGetP_kPlusOneImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using OutputImageRegionType = typename TInputImage::RegionType;\n  using BetaImage = itk::Image<typename TInputImage::InternalPixelType, TInputImage::ImageDimension>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConjugateGradientGetP_kPlusOneImageFilter);\n\n  /** Functions to set the inputs */\n  void\n  SetR_kPlusOne(const TInputImage * R_kPlusOne);\n  void\n  SetRk(const TInputImage * Rk);\n  void\n  SetPk(const TInputImage * Pk);\n\n  itkSetMacro(SquaredNormR_k, double);\n  itkSetMacro(SquaredNormR_kPlusOne, double);\n\n  /** Typedefs for sub filters */\n  using AddFilterType = itk::AddImageFilter<TInputImage>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<TInputImage, BetaImage, TInputImage>;\n\nprotected:\n  ConjugateGradientGetP_kPlusOneImageFilter();\n  ~ConjugateGradientGetP_kPlusOneImageFilter() override = default;\n\n  typename TInputImage::Pointer\n  GetR_kPlusOne();\n  typename TInputImage::Pointer\n  GetRk();\n  typename TInputImage::Pointer\n  GetPk();\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\nprivate:\n  double m_SquaredNormR_k;\n  double m_SquaredNormR_kPlusOne;\n  double m_Betak;\n\n  /** Pointers to sub filters */\n  typename AddFilterType::Pointer      m_AddFilter;\n  typename MultiplyFilterType::Pointer m_MultiplyFilter;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkConjugateGradientGetP_kPlusOneImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientGetP_kPlusOneImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientGetP_kPlusOneImageFilter_hxx\n#define rtkConjugateGradientGetP_kPlusOneImageFilter_hxx\n\n\n#include \"itkObjectFactory.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n\nnamespace rtk\n{\n\ntemplate <typename TInputType>\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::ConjugateGradientGetP_kPlusOneImageFilter()\n{\n  // Create the subfilters\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_AddFilter = AddFilterType::New();\n\n  // Create a permanent connection\n  m_AddFilter->SetInput1(m_MultiplyFilter->GetOutput());\n\n  m_SquaredNormR_k = 0;\n  m_SquaredNormR_kPlusOne = 0;\n  m_Betak = 0;\n\n  this->SetNumberOfRequiredInputs(3);\n\n  // Set memory management options\n  m_MultiplyFilter->ReleaseDataFlagOn();\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::SetR_kPlusOne(const TInputType * R_kPlusOne)\n{\n  this->SetNthInput(0, const_cast<TInputType *>(R_kPlusOne));\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::SetRk(const TInputType * Rk)\n{\n  this->SetNthInput(1, const_cast<TInputType *>(Rk));\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::SetPk(const TInputType * Pk)\n{\n  this->SetNthInput(2, const_cast<TInputType *>(Pk));\n}\n\ntemplate <typename TInputType>\ntypename TInputType::Pointer\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::GetR_kPlusOne()\n{\n  return static_cast<TInputType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename TInputType>\ntypename TInputType::Pointer\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::GetRk()\n{\n  return static_cast<TInputType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename TInputType>\ntypename TInputType::Pointer\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::GetPk()\n{\n  return static_cast<TInputType *>(this->itk::ProcessObject::GetInput(2));\n}\n\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::GenerateOutputInformation()\n{\n  // Compute m_Betak\n  float eps = 1e-8;\n  m_Betak = m_SquaredNormR_kPlusOne / (m_SquaredNormR_k + eps);\n\n  // Set inputs\n  m_MultiplyFilter->SetInput1(this->GetPk());\n  m_MultiplyFilter->SetConstant2(this->m_Betak);\n  m_AddFilter->SetInput2(this->GetR_kPlusOne());\n\n  // Have the last filter calculate its output information\n  m_AddFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_AddFilter->GetOutput());\n}\n\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetP_kPlusOneImageFilter<TInputType>::GenerateData()\n{\n  // Run the pipeline\n  m_AddFilter->Update();\n\n  // Pass the Add filter's output\n  this->GraftOutput(m_AddFilter->GetOutput());\n\n  // Release data in internal filters\n  m_MultiplyFilter->GetOutput()->ReleaseData();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientGetR_kPlusOneImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientGetR_kPlusOneImageFilter_h\n#define rtkConjugateGradientGetR_kPlusOneImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkVectorImage.h>\n\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class ConjugateGradientGetR_kPlusOneImageFilter\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <typename TInputImage>\nclass ITK_TEMPLATE_EXPORT ConjugateGradientGetR_kPlusOneImageFilter\n  : public itk::ImageToImageFilter<TInputImage, TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConjugateGradientGetR_kPlusOneImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ConjugateGradientGetR_kPlusOneImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using OutputImageRegionType = typename TInputImage::RegionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConjugateGradientGetR_kPlusOneImageFilter);\n\n  /** Functions to set the inputs */\n  void\n  SetRk(const TInputImage * Rk);\n  void\n  SetPk(const TInputImage * Pk);\n  void\n  SetAPk(const TInputImage * APk);\n\n  itkGetMacro(Alphak, double);\n  itkGetMacro(SquaredNormR_k, double);\n  itkGetMacro(SquaredNormR_kPlusOne, double);\n\nprotected:\n  ConjugateGradientGetR_kPlusOneImageFilter();\n  ~ConjugateGradientGetR_kPlusOneImageFilter() override = default;\n\n  typename TInputImage::Pointer\n  GetRk();\n  typename TInputImage::Pointer\n  GetPk();\n  typename TInputImage::Pointer\n  GetAPk();\n\n  void\n  GenerateData() override;\n\nprivate:\n  double m_Alphak{ 0. };\n  double m_SquaredNormR_k{ 0. };\n  double m_SquaredNormR_kPlusOne{ 0. };\n};\n\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkConjugateGradientGetR_kPlusOneImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientGetR_kPlusOneImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientGetR_kPlusOneImageFilter_hxx\n#define rtkConjugateGradientGetR_kPlusOneImageFilter_hxx\n\n\n#include \"itkObjectFactory.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n\nnamespace rtk\n{\n\ntemplate <typename TInputType>\nConjugateGradientGetR_kPlusOneImageFilter<TInputType>::ConjugateGradientGetR_kPlusOneImageFilter()\n{\n  this->SetNumberOfRequiredInputs(3);\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetR_kPlusOneImageFilter<TInputType>::SetRk(const TInputType * Rk)\n{\n  this->SetNthInput(0, const_cast<TInputType *>(Rk));\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetR_kPlusOneImageFilter<TInputType>::SetPk(const TInputType * Pk)\n{\n  this->SetNthInput(1, const_cast<TInputType *>(Pk));\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetR_kPlusOneImageFilter<TInputType>::SetAPk(const TInputType * APk)\n{\n  this->SetNthInput(2, const_cast<TInputType *>(APk));\n}\n\ntemplate <typename TInputType>\ntypename TInputType::Pointer\nConjugateGradientGetR_kPlusOneImageFilter<TInputType>::GetRk()\n{\n  return static_cast<TInputType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename TInputType>\ntypename TInputType::Pointer\nConjugateGradientGetR_kPlusOneImageFilter<TInputType>::GetPk()\n{\n  return static_cast<TInputType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename TInputType>\ntypename TInputType::Pointer\nConjugateGradientGetR_kPlusOneImageFilter<TInputType>::GetAPk()\n{\n  return static_cast<TInputType *>(this->itk::ProcessObject::GetInput(2));\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetR_kPlusOneImageFilter<TInputType>::GenerateData()\n{\n  this->AllocateOutputs();\n\n  // Prepare iterators\n  using RegionIterator = itk::ImageRegionIterator<TInputType>;\n\n  std::mutex accumulationLock;\n  m_SquaredNormR_k = 0;\n  double p_k_t_A_p_k = 0;\n  this->GetMultiThreader()->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  this->GetMultiThreader()->template ParallelizeImageRegion<TInputType::ImageDimension>(\n    this->GetOutput()->GetRequestedRegion(),\n    [this, &p_k_t_A_p_k, &accumulationLock](const typename TInputType::RegionType & outputRegionForThread) {\n      // Compute Norm(r_k)²\n      double         squaredNormR_kThread = 0.;\n      RegionIterator r_k_It(this->GetRk(), outputRegionForThread);\n      r_k_It.GoToBegin();\n      while (!r_k_It.IsAtEnd())\n      {\n        squaredNormR_kThread += r_k_It.Get() * r_k_It.Get();\n        ++r_k_It;\n      }\n\n      // Compute p_k_t_A_p_k\n      double         p_k_t_A_p_kThread = 0.;\n      RegionIterator p_k_It(this->GetPk(), outputRegionForThread);\n      p_k_It.GoToBegin();\n      RegionIterator A_p_k_It(this->GetAPk(), outputRegionForThread);\n      A_p_k_It.GoToBegin();\n      while (!p_k_It.IsAtEnd())\n      {\n        p_k_t_A_p_kThread += p_k_It.Get() * A_p_k_It.Get();\n        ++p_k_It;\n        ++A_p_k_It;\n      }\n      std::lock_guard<std::mutex> mutexHolder(accumulationLock);\n      this->m_SquaredNormR_k += squaredNormR_kThread;\n      p_k_t_A_p_k += p_k_t_A_p_kThread;\n    },\n    nullptr);\n\n  const double                                                         eps = 1e-8;\n  typename itk::PixelTraits<typename TInputType::PixelType>::ValueType alphak = m_SquaredNormR_k / (p_k_t_A_p_k + eps);\n\n  m_SquaredNormR_kPlusOne = 0;\n  this->GetMultiThreader()->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  this->GetMultiThreader()->template ParallelizeImageRegion<TInputType::ImageDimension>(\n    this->GetOutput()->GetRequestedRegion(),\n    [this, alphak, &accumulationLock](const typename TInputType::RegionType & outputRegionForThread) {\n      // Compute Rk+1 and write it on the output\n      double         squaredNormR_kPlusOneVectorThread = 0.;\n      RegionIterator outputIt(this->GetOutput(), outputRegionForThread);\n      outputIt.GoToBegin();\n      RegionIterator A_p_k_It(this->GetAPk(), outputRegionForThread);\n      A_p_k_It.GoToBegin();\n      RegionIterator r_k_It(this->GetRk(), outputRegionForThread);\n      r_k_It.GoToBegin();\n      while (!outputIt.IsAtEnd())\n      {\n        outputIt.Set(r_k_It.Get() - alphak * A_p_k_It.Get());\n        squaredNormR_kPlusOneVectorThread += outputIt.Get() * outputIt.Get();\n        ++r_k_It;\n        ++A_p_k_It;\n        ++outputIt;\n      }\n      std::lock_guard<std::mutex> mutexHolder(accumulationLock);\n      this->m_SquaredNormR_kPlusOne += squaredNormR_kPlusOneVectorThread;\n    },\n    nullptr);\n\n  m_Alphak = m_SquaredNormR_k / (p_k_t_A_p_k + eps);\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientGetX_kPlusOneImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientGetX_kPlusOneImageFilter_h\n#define rtkConjugateGradientGetX_kPlusOneImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkAddImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n\nnamespace rtk\n{\n/** \\class ConjugateGradientGetX_kPlusOneImageFilter\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <typename TInputImage>\nclass ITK_TEMPLATE_EXPORT ConjugateGradientGetX_kPlusOneImageFilter\n  : public itk::ImageToImageFilter<TInputImage, TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConjugateGradientGetX_kPlusOneImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ConjugateGradientGetX_kPlusOneImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using OutputImageRegionType = typename TInputImage::RegionType;\n  using AlphaImage = itk::Image<typename TInputImage::InternalPixelType, TInputImage::ImageDimension>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConjugateGradientGetX_kPlusOneImageFilter);\n\n  /** Functions to set the inputs */\n  void\n  SetXk(const TInputImage * Xk);\n  void\n  SetPk(const TInputImage * Pk);\n\n  itkGetMacro(Alphak, double);\n  itkSetMacro(Alphak, double);\n\n  /** Typedefs for sub filters */\n  using AddFilterType = itk::AddImageFilter<TInputImage>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<TInputImage, AlphaImage, TInputImage>;\n\nprotected:\n  ConjugateGradientGetX_kPlusOneImageFilter();\n  ~ConjugateGradientGetX_kPlusOneImageFilter() override = default;\n\n  typename TInputImage::Pointer\n  GetXk();\n  typename TInputImage::Pointer\n  GetPk();\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\nprivate:\n  double m_Alphak;\n\n  /** Pointers to sub filters */\n  typename AddFilterType::Pointer      m_AddFilter;\n  typename MultiplyFilterType::Pointer m_MultiplyFilter;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkConjugateGradientGetX_kPlusOneImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientGetX_kPlusOneImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientGetX_kPlusOneImageFilter_hxx\n#define rtkConjugateGradientGetX_kPlusOneImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TInputType>\nConjugateGradientGetX_kPlusOneImageFilter<TInputType>::ConjugateGradientGetX_kPlusOneImageFilter()\n{\n  // Create the subfilters\n  m_Alphak = 0;\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_AddFilter = AddFilterType::New();\n\n  // Create a permanent connection\n  m_AddFilter->SetInput1(m_MultiplyFilter->GetOutput());\n\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set memory management options\n  m_MultiplyFilter->ReleaseDataFlagOn();\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetX_kPlusOneImageFilter<TInputType>::SetXk(const TInputType * Xk)\n{\n  this->SetNthInput(0, const_cast<TInputType *>(Xk));\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetX_kPlusOneImageFilter<TInputType>::SetPk(const TInputType * Pk)\n{\n  this->SetNthInput(1, const_cast<TInputType *>(Pk));\n}\n\ntemplate <typename TInputType>\ntypename TInputType::Pointer\nConjugateGradientGetX_kPlusOneImageFilter<TInputType>::GetXk()\n{\n  return static_cast<TInputType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename TInputType>\ntypename TInputType::Pointer\nConjugateGradientGetX_kPlusOneImageFilter<TInputType>::GetPk()\n{\n  return static_cast<TInputType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetX_kPlusOneImageFilter<TInputType>::GenerateOutputInformation()\n{\n  // Set inputs\n  m_MultiplyFilter->SetInput1(this->GetPk());\n  m_MultiplyFilter->SetConstant2(this->m_Alphak);\n  m_AddFilter->SetInput2(this->GetXk());\n\n  // Have the last filter calculate its output information\n  m_AddFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_AddFilter->GetOutput());\n}\n\n\ntemplate <typename TInputType>\nvoid\nConjugateGradientGetX_kPlusOneImageFilter<TInputType>::GenerateData()\n{\n  // Run the pipeline\n  m_AddFilter->Update();\n\n  // Pass the Add filter's output\n  this->GraftOutput(m_AddFilter->GetOutput());\n\n  // Release data in internal filters\n  m_MultiplyFilter->GetOutput()->ReleaseData();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientImageFilter_h\n#define rtkConjugateGradientImageFilter_h\n\n#include <itkSubtractImageFilter.h>\n#include <itkStatisticsImageFilter.h>\n#include <itkTimeProbe.h>\n\n#include \"rtkSumOfSquaresImageFilter.h\"\n\n#include \"rtkConjugateGradientGetR_kPlusOneImageFilter.h\"\n#include \"rtkConjugateGradientGetX_kPlusOneImageFilter.h\"\n#include \"rtkConjugateGradientGetP_kPlusOneImageFilter.h\"\n#include \"rtkConjugateGradientOperator.h\"\n\nnamespace rtk\n{\n\n/** \\class ConjugateGradientImageFilter\n * \\brief Solves AX = B by conjugate gradient\n *\n * ConjugateGradientImageFilter implements the algorithm described\n * in https://en.wikipedia.org/wiki/Conjugate_gradient_method\n *\n * \\ingroup RTK\n */\n\ntemplate <typename OutputImageType>\nclass ITK_TEMPLATE_EXPORT ConjugateGradientImageFilter\n  : public itk::InPlaceImageFilter<OutputImageType, OutputImageType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConjugateGradientImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ConjugateGradientImageFilter;\n  using Superclass = itk::InPlaceImageFilter<OutputImageType, OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConjugateGradientOperatorType = ConjugateGradientOperator<OutputImageType>;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConjugateGradientImageFilter);\n\n  /** Get and Set macro*/\n  itkGetMacro(NumberOfIterations, int);\n  itkSetMacro(NumberOfIterations, int);\n\n  void\n  SetA(ConjugateGradientOperatorType * _arg);\n\n  /** The input image to be updated.*/\n  void\n  SetX(const OutputImageType * OutputImage);\n\n  /** The image called \"B\" in the CG algorithm.*/\n  void\n  SetB(const OutputImageType * OutputImage);\n\nprotected:\n  ConjugateGradientImageFilter();\n  ~ConjugateGradientImageFilter() override = default;\n\n  OutputImagePointer\n  GetX();\n  OutputImagePointer\n  GetB();\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Conjugate gradient requires the whole image */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n\n  ConjugateGradientOperatorType * m_A;\n\n  int m_NumberOfIterations;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkConjugateGradientImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientImageFilter_hxx\n#define rtkConjugateGradientImageFilter_hxx\n\n#include <itkMultiThreaderBase.h>\n#include <mutex>\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\n\ntemplate <typename OutputImageType>\nConjugateGradientImageFilter<OutputImageType>::ConjugateGradientImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n  this->SetInPlace(true);\n\n  m_NumberOfIterations = 1;\n\n  m_A = ConjugateGradientOperatorType::New();\n}\n\ntemplate <typename OutputImageType>\nvoid\nConjugateGradientImageFilter<OutputImageType>::SetX(const OutputImageType * OutputImage)\n{\n  this->SetNthInput(0, const_cast<OutputImageType *>(OutputImage));\n}\n\ntemplate <typename OutputImageType>\nvoid\nConjugateGradientImageFilter<OutputImageType>::SetB(const OutputImageType * OutputImage)\n{\n  this->SetNthInput(1, const_cast<OutputImageType *>(OutputImage));\n}\n\ntemplate <typename OutputImageType>\ntypename ConjugateGradientImageFilter<OutputImageType>::OutputImagePointer\nConjugateGradientImageFilter<OutputImageType>::GetX()\n{\n  return static_cast<OutputImageType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename OutputImageType>\ntypename ConjugateGradientImageFilter<OutputImageType>::OutputImagePointer\nConjugateGradientImageFilter<OutputImageType>::GetB()\n{\n  return static_cast<OutputImageType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename OutputImageType>\nvoid\nConjugateGradientImageFilter<OutputImageType>::SetA(ConjugateGradientOperatorType * _arg)\n{\n  this->m_A = _arg;\n  this->Modified();\n}\n\ntemplate <typename OutputImageType>\nvoid\nConjugateGradientImageFilter<OutputImageType>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the X of AX=B\n  typename Superclass::InputImagePointer inputPtr0 = const_cast<OutputImageType *>(this->GetInput(0));\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the B of AX=B\n  typename Superclass::InputImagePointer inputPtr1 = const_cast<OutputImageType *>(this->GetInput(1));\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n}\n\ntemplate <typename OutputImageType>\nvoid\nConjugateGradientImageFilter<OutputImageType>::GenerateOutputInformation()\n{\n  Superclass::GenerateOutputInformation();\n\n  // Initialization\n  m_A->SetX(this->GetX());\n\n  // Compute output information\n  this->m_A->UpdateOutputInformation();\n}\n\ntemplate <typename OutputImageType>\nvoid\nConjugateGradientImageFilter<OutputImageType>::GenerateData()\n{\n  typename OutputImageType::RegionType largest = this->GetOutput()->GetLargestPossibleRegion();\n  using DataType = typename itk::PixelTraits<typename OutputImageType::PixelType>::ValueType;\n\n  // Create and allocate images\n  auto Pk = OutputImageType::New();\n  auto Rk = OutputImageType::New();\n  Pk->SetRegions(largest);\n  Rk->SetRegions(largest);\n  this->GetOutput()->SetRegions(largest);\n  Pk->Allocate();\n  Rk->Allocate();\n  this->GetOutput()->Allocate();\n  Pk->CopyInformation(this->GetOutput());\n  Rk->CopyInformation(this->GetOutput());\n\n  // In rtkConjugateGradientConeBeamReconstructionFilter, B is not updated\n  // So at this point, it is only an empty shell. Let's update it\n  this->GetB()->Update();\n  m_A->Update();\n\n  // Declare intermediate variables\n  DataType numerator, denominator, alpha, beta;\n  DataType eps = itk::NumericTraits<DataType>::min();\n\n  // Instantiate the multithreader\n  auto       mt = itk::MultiThreaderBase::New();\n  std::mutex accumulationLock;\n\n  // Compute Xk+1\n  mt->template ParallelizeImageRegion<OutputImageType::ImageDimension>(\n    largest,\n    [this, Pk, Rk](const typename OutputImageType::RegionType & outputRegionForThread) {\n      itk::ImageRegionIterator<OutputImageType> itP(Pk, outputRegionForThread);\n      itk::ImageRegionIterator<OutputImageType> itR(Rk, outputRegionForThread);\n      itk::ImageRegionIterator<OutputImageType> itB(this->GetB(), outputRegionForThread);\n      itk::ImageRegionIterator<OutputImageType> itA_out(this->m_A->GetOutput(), outputRegionForThread);\n      itk::ImageRegionIterator<OutputImageType> itIn(this->GetX(), outputRegionForThread);\n      itk::ImageRegionIterator<OutputImageType> itX(this->GetOutput(), outputRegionForThread);\n      while (!itP.IsAtEnd())\n      {\n        itR.Set(itB.Get() - itA_out.Get());\n        itP.Set(itR.Get());\n        itX.Set(itIn.Get());\n        ++itP;\n        ++itR;\n        ++itA_out;\n        ++itB;\n        ++itIn;\n        ++itX;\n      }\n    },\n    nullptr);\n\n  itk::IterationReporter iterationReporter(this, 0, 1);\n  bool                   stopIterations = false;\n  for (int iter = 0; (iter < m_NumberOfIterations) && !stopIterations; iter++)\n  {\n    // Compute A * Pk\n    m_A->SetX(Pk);\n    m_A->Update();\n\n    // Compute alpha\n    numerator = 0;\n    denominator = 0;\n    mt->template ParallelizeImageRegion<OutputImageType::ImageDimension>(\n      largest,\n      [this, Pk, Rk, &numerator, &denominator, &accumulationLock](\n        const typename OutputImageType::RegionType & outputRegionForThread) {\n        itk::ImageRegionIterator<OutputImageType> itP(Pk, outputRegionForThread);\n        itk::ImageRegionIterator<OutputImageType> itR(Rk, outputRegionForThread);\n        itk::ImageRegionIterator<OutputImageType> itA_out(this->m_A->GetOutput(), outputRegionForThread);\n        DataType                                  currentThreadNumerator = 0.0;\n        DataType                                  currentThreadDenominator = 0.0;\n        while (!itP.IsAtEnd())\n        {\n          currentThreadNumerator += itR.Get() * itR.Get();\n          currentThreadDenominator += itP.Get() * itA_out.Get();\n          ++itR;\n          ++itA_out;\n          ++itP;\n        }\n\n        std::lock_guard<std::mutex> mutexHolder(accumulationLock);\n        numerator += currentThreadNumerator;\n        denominator += currentThreadDenominator;\n      },\n      nullptr);\n    alpha = numerator / (denominator + eps);\n\n    // Compute Xk+1\n    mt->template ParallelizeImageRegion<OutputImageType::ImageDimension>(\n      largest,\n      [this, alpha, Pk](const typename OutputImageType::RegionType & outputRegionForThread) {\n        itk::ImageRegionIterator<OutputImageType> itP(Pk, outputRegionForThread);\n        itk::ImageRegionIterator<OutputImageType> itX(this->GetOutput(), outputRegionForThread);\n        while (!itP.IsAtEnd())\n        {\n          itX.Set(itX.Get() + alpha * itP.Get());\n          ++itX;\n          ++itP;\n        }\n      },\n      nullptr);\n\n    // Compute Rk+1 and beta simultaneously\n    denominator = numerator;\n    numerator = 0;\n    mt->template ParallelizeImageRegion<OutputImageType::ImageDimension>(\n      largest,\n      [this, Rk, &numerator, &accumulationLock, alpha](\n        const typename OutputImageType::RegionType & outputRegionForThread) {\n        itk::ImageRegionIterator<OutputImageType> itR(Rk, outputRegionForThread);\n        itk::ImageRegionIterator<OutputImageType> itA_out(this->m_A->GetOutput(), outputRegionForThread);\n        DataType                                  currentThreadNumerator = 0.0;\n        while (!itR.IsAtEnd())\n        {\n          itR.Set(itR.Get() - alpha * itA_out.Get());\n          currentThreadNumerator += itR.Get() * itR.Get();\n          ++itR;\n          ++itA_out;\n        }\n\n        std::lock_guard<std::mutex> mutexHolder(accumulationLock);\n        numerator += currentThreadNumerator;\n      },\n      nullptr);\n    beta = numerator / (denominator + eps);\n\n    mt->template ParallelizeImageRegion<OutputImageType::ImageDimension>(\n      largest,\n      [Rk, Pk, beta](const typename OutputImageType::RegionType & outputRegionForThread) {\n        itk::ImageRegionIterator<OutputImageType> itR(Rk, outputRegionForThread);\n        itk::ImageRegionIterator<OutputImageType> itP(Pk, outputRegionForThread);\n        while (!itR.IsAtEnd())\n        {\n          itP.Set(itR.Get() + beta * itP.Get());\n          ++itR;\n          ++itP;\n        }\n      },\n      nullptr);\n\n    // Let the m_A filter know that Pk has been modified, and it should\n    // recompute its output at the beginning of next iteration\n    Pk->Modified();\n    iterationReporter.CompletedStep();\n  }\n  m_A->GetOutput()->ReleaseData();\n}\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientOperator.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkConjugateGradientOperator_h\n#define rtkConjugateGradientOperator_h\n\n#include \"itkImageToImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class ConjugateGradientOperator\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <typename OutputImageType>\nclass ITK_TEMPLATE_EXPORT ConjugateGradientOperator : public itk::ImageToImageFilter<OutputImageType, OutputImageType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConjugateGradientOperator);\n\n  /** Standard class type alias. */\n  using Self = ConjugateGradientOperator;\n  using Superclass = itk::ImageToImageFilter<OutputImageType, OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConjugateGradientOperator);\n\n  /** The image to be updated.*/\n  virtual void\n  SetX(const OutputImageType * OutputImage);\n\nprotected:\n  ConjugateGradientOperator();\n  ~ConjugateGradientOperator() override = default;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkConjugateGradientOperator.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkConjugateGradientOperator.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConjugateGradientOperator_hxx\n#define rtkConjugateGradientOperator_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename OutputImageType>\nConjugateGradientOperator<OutputImageType>::ConjugateGradientOperator() = default;\n\ntemplate <typename OutputImageType>\nvoid\nConjugateGradientOperator<OutputImageType>::SetX(const OutputImageType * OutputImage)\n{\n  this->SetNthInput(0, const_cast<OutputImageType *>(OutputImage));\n}\n\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkConstantImageSource.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConstantImageSource_h\n#define rtkConstantImageSource_h\n\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n\n#include <itkImageSource.h>\n#include <itkNumericTraits.h>\n#include <itkVariableLengthVector.h>\n#include <itkVectorImage.h>\n\nnamespace rtk\n{\n/** \\class ConstantImageSource\n * \\brief Generate an n-dimensional image with constant pixel values.\n *\n * ConstantImageSource generates an image with constant value. The filter is\n * useful to allow streaming of large images with a constant source, e.g., a\n * tomography reconstructed with a filtered backprojection algorithm.\n *\n * \\test rtkRaycastInterpolatorForwardProjectionTest.cxx,\n * rtkprojectgeometricphantomtest.cxx, rtkfdktest.cxx, rtksarttest.cxx,\n * rtkrampfiltertest.cxx, rtkamsterdamshroudtest.cxx,\n * rtkdrawgeometricphantomtest.cxx, rtkmotioncompensatedfdktest.cxx,\n * rtkfovtest.cxx, rtkforwardprojectiontest.cxx, rtkdisplaceddetectortest.cxx,\n * rtkshortscantest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageSource\n */\ntemplate <typename TOutputImage>\nclass ITK_TEMPLATE_EXPORT ConstantImageSource : public itk::ImageSource<TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConstantImageSource);\n\n  /** Standard class type alias. */\n  using Self = ConstantImageSource;\n  using Superclass = itk::ImageSource<TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Typedef for the output image type. */\n  using OutputImageType = TOutputImage;\n\n  /** Typedefs for the output image PixelType. */\n  using OutputImagePixelType = typename TOutputImage::PixelType;\n\n  /** Typedef to describe the output image region type. */\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConstantImageSource);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Basic types from the OutputImageType */\n  using SizeType = typename TOutputImage::SizeType;\n  using IndexType = typename TOutputImage::IndexType;\n  using SpacingType = typename TOutputImage::SpacingType;\n  using PointType = typename TOutputImage::PointType;\n  using SizeValueType = typename SizeType::SizeValueType;\n  typedef SizeValueType SizeValueArrayType[TOutputImage::ImageDimension];\n  using SpacingValueType = typename TOutputImage::SpacingValueType;\n  typedef SpacingValueType SpacingValueArrayType[TOutputImage::ImageDimension];\n  using PointValueType = typename TOutputImage::PointValueType;\n  typedef PointValueType PointValueArrayType[TOutputImage::ImageDimension];\n  using DirectionType = typename TOutputImage::DirectionType;\n\n  /** Set/Get size of the output image */\n  itkSetMacro(Size, SizeType);\n  itkGetMacro(Size, SizeType);\n  virtual void\n  SetSize(SizeValueArrayType sizeArray);\n  virtual const SizeValueType *\n  GetSize() const;\n\n  /** Set/Get spacing of the output image */\n  itkSetMacro(Spacing, SpacingType);\n  itkGetMacro(Spacing, SpacingType);\n\n  /** Set/Get origin of the output image */\n  itkSetMacro(Origin, PointType);\n  itkGetMacro(Origin, PointType);\n\n  /** Set/Get direction of the output image */\n  itkSetMacro(Direction, DirectionType);\n  itkGetMacro(Direction, DirectionType);\n\n  /** Set/Get index of the output image's largest possible region */\n  itkSetMacro(Index, IndexType);\n  itkGetMacro(Index, IndexType);\n\n  /** Set/Get the pixel value of output */\n  itkSetMacro(Constant, OutputImagePixelType);\n  itkGetConstMacro(Constant, OutputImagePixelType);\n\n  /** Set output image information from an existing image */\n  void\n  SetInformationFromImage(const itk::ImageBase<TOutputImage::ImageDimension> * image);\n\nprotected:\n  ConstantImageSource();\n  ~ConstantImageSource() override;\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  void\n  GenerateOutputInformation() override;\n\n  SizeType      m_Size;\n  SpacingType   m_Spacing;\n  PointType     m_Origin;\n  DirectionType m_Direction;\n  IndexType     m_Index;\n\n  OutputImagePixelType m_Constant;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkConstantImageSource.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkConstantImageSource.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConstantImageSource_hxx\n#define rtkConstantImageSource_hxx\n\n\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\ntemplate <class TOutputImage>\nConstantImageSource<TOutputImage>::ConstantImageSource()\n{\n  // Initial image is 64 wide in each direction.\n  for (unsigned int i = 0; i < TOutputImage::GetImageDimension(); i++)\n  {\n    m_Size[i] = 64;\n    m_Spacing[i] = 1.0;\n    m_Origin[i] = 0.0;\n    m_Index[i] = 0;\n\n    for (unsigned int j = 0; j < TOutputImage::GetImageDimension(); j++)\n      m_Direction[i][j] = (i == j) ? 1. : 0.;\n  }\n\n  m_Constant = itk::NumericTraits<OutputImagePixelType>::ZeroValue(m_Constant);\n}\n\ntemplate <class TOutputImage>\nConstantImageSource<TOutputImage>::~ConstantImageSource() = default;\n\ntemplate <class TOutputImage>\nvoid\nConstantImageSource<TOutputImage>::SetSize(SizeValueArrayType sizeArray)\n{\n  const unsigned int count = TOutputImage::ImageDimension;\n  unsigned int       i = 0;\n  for (i = 0; i < count; i++)\n  {\n    if (sizeArray[i] != this->m_Size[i])\n    {\n      break;\n    }\n  }\n  if (i < count)\n  {\n    this->Modified();\n    for (i = 0; i < count; i++)\n    {\n      this->m_Size[i] = sizeArray[i];\n    }\n  }\n}\n\ntemplate <class TOutputImage>\nconst typename ConstantImageSource<TOutputImage>::SizeValueType *\nConstantImageSource<TOutputImage>::GetSize() const\n{\n  return this->m_Size.GetSize();\n}\n\ntemplate <class TOutputImage>\nvoid\nConstantImageSource<TOutputImage>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n  os << indent << \"Constant: \" << static_cast<typename itk::NumericTraits<OutputImagePixelType>::PrintType>(m_Constant)\n     << std::endl;\n  unsigned int i = 0;\n  os << indent << \"Origin: [\";\n  for (i = 0; i < TOutputImage::ImageDimension - 1; i++)\n  {\n    os << m_Origin[i] << \", \";\n  }\n  os << m_Origin[i] << \"]\" << std::endl;\n\n  os << indent << \"Spacing: [\";\n  for (i = 0; i < TOutputImage::ImageDimension - 1; i++)\n  {\n    os << m_Spacing[i] << \", \";\n  }\n  os << m_Spacing[i] << \"]\" << std::endl;\n\n  os << indent << \"Size: [\";\n  for (i = 0; i < TOutputImage::ImageDimension - 1; i++)\n  {\n    os << m_Size[i] << \", \";\n  }\n  os << m_Size[i] << \"]\" << std::endl;\n}\n\n// template <class TOutputImage>\n// void\n// ConstantImageSource<TOutputImage>\n//::SetInformationFromImage(const typename TOutputImage::Superclass* image)\n//{\n//  this->SetSize( image->GetLargestPossibleRegion().GetSize() );\n//  this->SetIndex( image->GetLargestPossibleRegion().GetIndex() );\n//  this->SetSpacing( image->GetSpacing() );\n//  this->SetOrigin( image->GetOrigin() );\n//  this->SetDirection( image->GetDirection() );\n//}\n\ntemplate <class TOutputImage>\nvoid\nConstantImageSource<TOutputImage>::SetInformationFromImage(const itk::ImageBase<TOutputImage::ImageDimension> * image)\n{\n  this->SetSize(image->GetLargestPossibleRegion().GetSize());\n  this->SetIndex(image->GetLargestPossibleRegion().GetIndex());\n  this->SetSpacing(image->GetSpacing());\n  this->SetOrigin(image->GetOrigin());\n  this->SetDirection(image->GetDirection());\n}\n\n//----------------------------------------------------------------------------\ntemplate <class TOutputImage>\nvoid\nConstantImageSource<TOutputImage>::GenerateOutputInformation()\n{\n  TOutputImage * output = nullptr;\n  output = this->GetOutput(0);\n\n  typename TOutputImage::RegionType largestPossibleRegion;\n  largestPossibleRegion.SetSize(this->m_Size);\n  largestPossibleRegion.SetIndex(this->m_Index);\n  output->SetLargestPossibleRegion(largestPossibleRegion);\n\n  output->SetSpacing(m_Spacing);\n  output->SetOrigin(m_Origin);\n  output->SetDirection(m_Direction);\n}\n\n//----------------------------------------------------------------------------\ntemplate <class TOutputImage>\nvoid\nConstantImageSource<TOutputImage>::DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)\n{\n  itk::ImageRegionIterator<TOutputImage> it(this->GetOutput(), outputRegionForThread);\n\n  // Write the constant everywhere in the image\n  for (; !it.IsAtEnd(); ++it)\n    it.Set(m_Constant);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkConvexShape.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkConvexShape_h\n#define rtkConvexShape_h\n\n#include <itkMatrix.h>\n#include <itkPoint.h>\n#include <itkDataObject.h>\n#include <itkObjectFactory.h>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class ConvexShape\n * \\brief Base class for a 3D convex shape.\n *\n * A ConvexShape is used to draw and project (in the tomographic sense) a\n * geometric phantom using the functions IsInside and IsIntersectedByRay,\n * respectively.\n *\n * \\test rtkforbildtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n *\n */\nclass RTK_EXPORT ConvexShape : public itk::DataObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ConvexShape);\n\n  /** Standard class type alias. */\n  using Self = ConvexShape;\n  using Superclass = itk::DataObject;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  static constexpr unsigned int Dimension = 3;\n  using ScalarType = double;\n  using PointType = itk::Vector<ScalarType, Dimension>;\n  using VectorType = itk::Vector<ScalarType, Dimension>;\n  using RotationMatrixType = itk::Matrix<ScalarType, Dimension, Dimension>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ConvexShape);\n\n  /** Returns true if a point is inside the object. */\n  virtual bool\n  IsInside(const PointType & point) const;\n\n  /** Returns true if a ray intersects the object. If it does, the parameters\n  ** nearDist and farDist get the shape distance from the source in the ray direction.\n  ** Note that nearDist<farDist, and nearDist and farDist can be negative. */\n  virtual bool\n  IsIntersectedByRay(const PointType &  rayOrigin,\n                     const VectorType & rayDirection,\n                     double &           nearDist,\n                     double &           farDist) const;\n\n  /** Rescale object along each direction by a 3D vector. */\n  virtual void\n  Rescale(const VectorType & r);\n\n  /** Translate object by a given 3D vector. */\n  virtual void\n  Translate(const VectorType & t);\n\n  /** Rotate object according to a 3D rotation matrix. */\n  virtual void\n  Rotate(const RotationMatrixType & r);\n\n  /** Add clipping plane to the object. The plane is defined by the equation\n   * dir * (x,y,z)' + pos = 0. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n  void\n  SetClipPlanes(const std::vector<VectorType> & dir, const std::vector<ScalarType> & pos);\n\n  /** Volume density, i.e., value in the volume. */\n  itkSetMacro(Density, ScalarType);\n  itkGetConstMacro(Density, ScalarType);\n  itkGetMacro(Density, ScalarType);\n\n  /** Get reference to vector of plane parameters. */\n  itkGetConstReferenceMacro(PlaneDirections, std::vector<VectorType>);\n  itkGetConstReferenceMacro(PlanePositions, std::vector<ScalarType>);\n\nprotected:\n  ConvexShape();\n  bool\n  ApplyClipPlanes(const PointType &  rayOrigin,\n                  const VectorType & rayDirection,\n                  ScalarType &       nearDist,\n                  ScalarType &       farDist) const;\n  bool\n  ApplyClipPlanes(const PointType & point) const;\n  itk::LightObject::Pointer\n  InternalClone() const override;\n\nprivate:\n  ScalarType              m_Density{ 0. };\n  std::vector<VectorType> m_PlaneDirections;\n  std::vector<ScalarType> m_PlanePositions;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkCudaAverageOutOfROIImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaAverageOutOfROIImageFilter_h\n#define rtkCudaAverageOutOfROIImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkAverageOutOfROIImageFilter.h\"\n#  include \"itkCudaImage.h\"\n#  include \"itkCudaInPlaceImageFilter.h\"\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaAverageOutOfROIImageFilter\n * \\brief Implements the AverageOutOfROIImageFilter on GPU.\n *\n *\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaAverageOutOfROIImageFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<float, 4>,\n                                       itk::CudaImage<float, 4>,\n                                       AverageOutOfROIImageFilter<itk::CudaImage<float, 4>, itk::CudaImage<float, 3>>>\n\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaAverageOutOfROIImageFilter);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaAverageOutOfROIImageFilter;\n  using Superclass = rtk::AverageOutOfROIImageFilter<OutputImageType, InputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaAverageOutOfROIImageFilter);\n\nprotected:\n  CudaAverageOutOfROIImageFilter();\n  ~CudaAverageOutOfROIImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaAverageOutOfROIImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaAverageOutOfROIImageFilter_hcu\n#define rtkCudaAverageOutOfROIImageFilter_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_average_out_of_ROI(int size[4], float * input, float * output, float * roi);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaBackProjectionImageFilter_h\n#define rtkCudaBackProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkBackProjectionImageFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaInPlaceImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaBackProjectionImageFilter\n * \\brief Cuda version of the  backprojection.\n *\n * GPU-based implementation of the backprojection step of the\n * [Feldkamp, Davis, Kress, 1984] algorithm for filtered backprojection\n * reconstruction of cone-beam CT images with a circular source trajectory.\n *\n * \\test rtksarttest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Projector CudaImageToImageFilter\n */\n\ntemplate <class ImageType = itk::CudaImage<float, 3>>\nclass ITK_TEMPLATE_EXPORT CudaBackProjectionImageFilter\n  : public itk::CudaInPlaceImageFilter<ImageType, ImageType, BackProjectionImageFilter<ImageType, ImageType>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaBackProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using BackProjectionImageFilterType = BackProjectionImageFilter<ImageType, ImageType>;\n  using Self = CudaBackProjectionImageFilter;\n  using Superclass = itk::CudaInPlaceImageFilter<ImageType, ImageType, BackProjectionImageFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using OutputImageRegionType = typename ImageType::RegionType;\n  using ProjectionImageType = itk::CudaImage<float, 2>;\n  using ProjectionImagePointer = ProjectionImageType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaBackProjectionImageFilter);\n\nprotected:\n  CudaBackProjectionImageFilter();\n  virtual ~CudaBackProjectionImageFilter() {};\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // end namespace rtk\n\n#  ifndef ITK_MANUAL_INSTANTIATION\n#    include \"rtkCudaBackProjectionImageFilter.hxx\"\n#  endif\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaBackProjectionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaBackProjectionImageFilter_hcu\n#define rtkCudaBackProjectionImageFilter_hcu\n\n#include \"RTKExport.h\"\n\nvoid RTK_EXPORT\nCUDA_back_project(int          projSize[3],\n                  int          volSize[3],\n                  float *      matrices,\n                  float *      volIndexToProjPPs,\n                  float *      projPPToProjIndex,\n                  float *      dev_vol_in,\n                  float *      dev_vol_out,\n                  float *      dev_img,\n                  double       radiusCylindricalDetector,\n                  unsigned int vectorLength);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaBackProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaBackProjectionImageFilter_hxx\n#define rtkCudaBackProjectionImageFilter_hxx\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkCudaBackProjectionImageFilter.h\"\n#  include \"rtkCudaUtilities.hcu\"\n#  include \"rtkCudaBackProjectionImageFilter.hcu\"\n\n#  include <itkImageRegionConstIterator.h>\n#  include <itkImageRegionIteratorWithIndex.h>\n#  include <itkLinearInterpolateImageFunction.h>\n#  include <itkMacro.h>\n\nnamespace rtk\n{\n\ntemplate <class ImageType>\nCudaBackProjectionImageFilter<ImageType>::CudaBackProjectionImageFilter()\n{}\n\ntemplate <class ImageType>\nvoid\nCudaBackProjectionImageFilter<ImageType>::GPUGenerateData()\n{\n  const unsigned int Dimension = ImageType::ImageDimension;\n  const unsigned int nProj = this->GetInput(1)->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  const unsigned int iFirstProj = this->GetInput(1)->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n  if (SLAB_SIZE > 1024)\n    itkGenericExceptionMacro(\n      \"The CUDA voxel based back projection image filter can only handle slabs of at most 1024 projections\");\n\n  // Rotation center (assumed to be at 0 yet)\n  typename ImageType::PointType rotCenterPoint;\n  rotCenterPoint.Fill(0.0);\n  itk::ContinuousIndex<double, Dimension> rotCenterIndex =\n    this->GetInput(0)\n      ->template TransformPhysicalPointToContinuousIndex<typename ImageType::PointType::ValueType, double>(\n        rotCenterPoint);\n\n  // Include non-zero index in matrix\n  itk::Matrix<double, 4, 4> matrixIdxVol;\n  matrixIdxVol.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    matrixIdxVol[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n    rotCenterIndex[i] -= this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n  }\n\n  // Cuda convenient format for dimensions\n  int projectionSize[3];\n  projectionSize[0] = this->GetInput(1)->GetBufferedRegion().GetSize()[0];\n  projectionSize[1] = this->GetInput(1)->GetBufferedRegion().GetSize()[1];\n\n  int volumeSize[3];\n  volumeSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  volumeSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n  volumeSize[2] = this->GetOutput()->GetBufferedRegion().GetSize()[2];\n\n#  ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * stackGPUPointer = (float *)(this->GetInput(1)->GetCudaDataManager()->GetGPUBufferPointer());\n#  else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * stackGPUPointer = *(float **)(this->GetInput(1)->GetCudaDataManager()->GetGPUBufferPointer());\n#  endif\n\n  ptrdiff_t projSize = this->GetInput(1)->GetBufferedRegion().GetSize()[0] *\n                       this->GetInput(1)->GetBufferedRegion().GetSize()[1] *\n                       itk::NumericTraits<typename ImageType::PixelType>::GetLength();\n  stackGPUPointer += projSize * (iFirstProj - this->GetInput(1)->GetBufferedRegion().GetIndex()[2]);\n\n  // Allocate a large matrix to hold the matrix of all projections\n  // fMatrix is for flat detector, the other two are for cylindrical\n  float * fMatrix = new float[12 * nProj];\n  float * fvolIndexToProjPP = new float[12 * nProj];\n  float * fprojPPToProjIndex = new float[9];\n\n  // Correction for non-zero indices in the projections\n  itk::Matrix<double, 3, 3> matrixIdxProj;\n  matrixIdxProj.SetIdentity();\n  for (unsigned int i = 0; i < 2; i++)\n    // SR: 0.5 for 2D texture\n    matrixIdxProj[i][2] = -1 * (this->GetInput(1)->GetBufferedRegion().GetIndex()[i]) + 0.5;\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    // Projection physical point to projection index matrix\n    itk::Matrix<double, 3, 3> projPPToProjIndex = this->GetProjectionPhysicalPointToProjectionIndexMatrix(iProj);\n    projPPToProjIndex = matrixIdxProj.GetVnlMatrix() * projPPToProjIndex.GetVnlMatrix();\n    for (int j = 0; j < 9; j++)\n      fprojPPToProjIndex[j] = projPPToProjIndex[j / 3][j % 3];\n\n    // Volume index to projection physical point matrix\n    // normalized to have a correct backprojection weight\n    // (1 at the isocenter)\n    typename BackProjectionImageFilterType::ProjectionMatrixType volIndexToProjPP =\n      this->GetVolumeIndexToProjectionPhysicalPointMatrix(iProj);\n\n    // Correction for non-zero indices in the volume\n    volIndexToProjPP = volIndexToProjPP.GetVnlMatrix() * matrixIdxVol.GetVnlMatrix();\n\n    double perspFactor = volIndexToProjPP[Dimension - 1][Dimension];\n    for (unsigned int j = 0; j < Dimension; j++)\n      perspFactor += volIndexToProjPP[Dimension - 1][j] * rotCenterIndex[j];\n    volIndexToProjPP /= perspFactor;\n\n    typename BackProjectionImageFilterType::ProjectionMatrixType matrix =\n      typename BackProjectionImageFilterType::ProjectionMatrixType(projPPToProjIndex.GetVnlMatrix() *\n                                                                   volIndexToProjPP.GetVnlMatrix());\n\n    // Fill float arrays with matrices coefficients, to be passed to GPU\n    for (int j = 0; j < 12; j++)\n    {\n      fvolIndexToProjPP[j + (iProj - iFirstProj) * 12] = volIndexToProjPP[j / 4][j % 4];\n      fMatrix[j + (iProj - iFirstProj) * 12] = matrix[j / 4][j % 4];\n    }\n  }\n\n  const unsigned int vectorLength = itk::PixelTraits<typename ImageType::PixelType>::Dimension;\n\n  for (unsigned int i = 0; i < nProj; i += SLAB_SIZE)\n  {\n    // If nProj is not a multiple of SLAB_SIZE, the last slab will contain less than SLAB_SIZE projections\n    projectionSize[2] = std::min(nProj - i, (unsigned int)SLAB_SIZE);\n\n    // Run the back projection with a slab of SLAB_SIZE or less projections\n    CUDA_back_project(projectionSize,\n                      volumeSize,\n                      fMatrix + 12 * i,\n                      fvolIndexToProjPP + 12 * i,\n                      fprojPPToProjIndex,\n                      pin,\n                      pout,\n                      stackGPUPointer + projSize * i,\n                      this->m_Geometry->GetRadiusCylindricalDetector(),\n                      vectorLength);\n\n    // Re-use the output as input\n    pin = pout;\n  }\n\n  delete[] fMatrix;\n  delete[] fvolIndexToProjPP;\n  delete[] fprojPPToProjIndex;\n}\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaConjugateGradientImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaConjugateGradientImageFilter_h\n#define rtkCudaConjugateGradientImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkConjugateGradientImageFilter.h\"\n#  include <itkCudaImageToImageFilter.h>\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaConjugateGradientImageFilter\n * \\brief A 3D float conjugate gradient image filter on GPU.\n *\n *\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\n\ntemplate <class TImage>\nclass ITK_TEMPLATE_EXPORT CudaConjugateGradientImageFilter\n  : public itk::CudaImageToImageFilter<TImage, TImage, ConjugateGradientImageFilter<TImage>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaConjugateGradientImageFilter);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaConjugateGradientImageFilter<TImage>;\n  using Superclass = rtk::ConjugateGradientImageFilter<TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaConjugateGradientImageFilter);\n\nprotected:\n  CudaConjugateGradientImageFilter();\n  ~CudaConjugateGradientImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#  ifndef ITK_MANUAL_INSTANTIATION\n#    include \"rtkCudaConjugateGradientImageFilter.hxx\"\n#  endif\n\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaConjugateGradientImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaConjugateGradientImageFilter_hcu\n#define rtkCudaConjugateGradientImageFilter_hcu\n\n#include \"RTKExport.h\"\n\nvoid RTK_EXPORT\nCUDA_copy(size_t numberOfElements, float * in, float * out);\n\nvoid RTK_EXPORT\nCUDA_copy(size_t numberOfElements, double * in, double * out);\n\nvoid RTK_EXPORT\nCUDA_subtract(size_t numberOfElements, float * out, float * toBeSubtracted);\n\nvoid RTK_EXPORT\nCUDA_subtract(size_t numberOfElements, double * out, double * toBeSubtracted);\n\nvoid RTK_EXPORT\nCUDA_conjugate_gradient(size_t numberOfElements, float * Xk, float * Rk, float * Pk, float * APk);\n\nvoid RTK_EXPORT\nCUDA_conjugate_gradient(size_t numberOfElements, double * Xk, double * Rk, double * Pk, double * APk);\n#endif\n"
  },
  {
    "path": "include/rtkCudaConjugateGradientImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaConjugateGradientImageFilter_hxx\n#define rtkCudaConjugateGradientImageFilter_hxx\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkCudaConjugateGradientImageFilter.h\"\n#  include \"rtkCudaConjugateGradientImageFilter.hcu\"\n#  include \"rtkCudaConstantVolumeSource.h\"\n\n#  include <itkMacro.h>\n#  include <itkIterationReporter.h>\n\nnamespace rtk\n{\n\ntemplate <class TImage>\nCudaConjugateGradientImageFilter<TImage>::CudaConjugateGradientImageFilter()\n{}\n\ntemplate <class TImage>\nvoid\nCudaConjugateGradientImageFilter<TImage>::GPUGenerateData()\n{\n  using DataType = typename itk::PixelTraits<typename TImage::PixelType>::ValueType;\n  size_t numberOfElements = this->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels() *\n                            itk::PixelTraits<typename TImage::PixelType>::Dimension;\n\n  // Create and allocate images\n  auto P_k = TImage::New();\n  auto R_k = TImage::New();\n  P_k->SetRegions(this->GetOutput()->GetLargestPossibleRegion());\n  R_k->SetRegions(this->GetOutput()->GetLargestPossibleRegion());\n  P_k->Allocate();\n  R_k->Allocate();\n  P_k->CopyInformation(this->GetOutput());\n  R_k->CopyInformation(this->GetOutput());\n\n  // Copy the input to the output (X_0 = input)\n#  ifdef CudaCommon_VERSION_MAJOR\n  DataType * pin = (DataType *)(this->GetX()->GetCudaDataManager()->GetGPUBufferPointer());\n  DataType * pX = (DataType *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#  else\n  DataType * pin = *(DataType **)(this->GetX()->GetCudaDataManager()->GetGPUBufferPointer());\n  DataType * pX = *(DataType **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#  endif\n\n  // On GPU, initialize the output to the input\n  CUDA_copy(numberOfElements, pin, pX);\n\n  // Compute A * X0\n  this->m_A->SetX(this->GetX());\n  this->m_A->Update();\n\n  // Initialize AOut\n  typename TImage::Pointer AOut = this->m_A->GetOutput();\n  AOut->DisconnectPipeline();\n\n#  ifdef CudaCommon_VERSION_MAJOR\n  DataType * pR = (DataType *)(R_k->GetCudaDataManager()->GetGPUBufferPointer());\n  DataType * pB = (DataType *)(this->GetB()->GetCudaDataManager()->GetGPUBufferPointer());\n  DataType * pAOut = (DataType *)(AOut->GetCudaDataManager()->GetGPUBufferPointer());\n#  else\n  DataType * pR = *(DataType **)(R_k->GetCudaDataManager()->GetGPUBufferPointer());\n  DataType * pB = *(DataType **)(this->GetB()->GetCudaDataManager()->GetGPUBufferPointer());\n  DataType * pAOut = *(DataType **)(AOut->GetCudaDataManager()->GetGPUBufferPointer());\n#  endif\n\n  // Compute, on GPU, R_zero = P_zero = this->GetB() - this->m_A->GetOutput()\n  CUDA_copy(numberOfElements, pB, pR);\n  CUDA_subtract(numberOfElements, pR, pAOut);\n\n  // B is now useless, and the memory it takes on the GPU is critical.\n  // Transfer it back to the CPU memory\n  this->GetB()->GetCudaDataManager()->GetCPUBufferPointer();\n\n#  ifdef CudaCommon_VERSION_MAJOR\n  DataType * pP = (DataType *)(P_k->GetCudaDataManager()->GetGPUBufferPointer());\n#  else\n  DataType * pP = *(DataType **)(P_k->GetCudaDataManager()->GetGPUBufferPointer());\n#  endif\n\n  // P0 = R0\n  CUDA_copy(numberOfElements, pR, pP);\n\n  // Start iterations\n  itk::IterationReporter iterationReporter(this, 0, 1);\n  for (int iter = 0; iter < this->m_NumberOfIterations; iter++)\n  {\n    // Compute A * P_k\n    this->m_A->SetX(P_k);\n    this->m_A->Update();\n    AOut = this->m_A->GetOutput();\n    AOut->DisconnectPipeline();\n\n#  ifdef CudaCommon_VERSION_MAJOR\n    pX = (DataType *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n    pR = (DataType *)(R_k->GetCudaDataManager()->GetGPUBufferPointer());\n    pP = (DataType *)(P_k->GetCudaDataManager()->GetGPUBufferPointer());\n    pAOut = (DataType *)(AOut->GetCudaDataManager()->GetGPUBufferPointer());\n#  else\n    pX = *(DataType **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n    pR = *(DataType **)(R_k->GetCudaDataManager()->GetGPUBufferPointer());\n    pP = *(DataType **)(P_k->GetCudaDataManager()->GetGPUBufferPointer());\n    pAOut = *(DataType **)(AOut->GetCudaDataManager()->GetGPUBufferPointer());\n#  endif\n\n    // Compute, on GPU, alpha_k (only on GPU), X_k+1 (output), R_k+1, beta_k (only on GPU), P_k+1\n    // The inputs are replaced by their next iterate\n    CUDA_conjugate_gradient(numberOfElements, pX, pR, pP, pAOut);\n\n    P_k->Modified();\n    iterationReporter.CompletedStep();\n  }\n\n  P_k->ReleaseData();\n  R_k->ReleaseData();\n  AOut->ReleaseData();\n}\n} // namespace rtk\n\n#endif\n#endif\n"
  },
  {
    "path": "include/rtkCudaConstantVolumeSeriesSource.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaConstantVolumeSeriesSource_h\n#define rtkCudaConstantVolumeSeriesSource_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkConstantImageSource.h\"\n#  include <itkCudaImageToImageFilter.h>\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaConstantVolumeSeriesSource\n * \\brief A 4D constant image source on GPU.\n *\n *\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\n\nclass RTK_EXPORT CudaConstantVolumeSeriesSource\n  : public itk::CudaImageToImageFilter<itk::CudaImage<float, 4>,\n                                       itk::CudaImage<float, 4>,\n                                       ConstantImageSource<itk::CudaImage<float, 4>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaConstantVolumeSeriesSource);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaConstantVolumeSeriesSource;\n  using OutputImageType = itk::CudaImage<float, 3>;\n  using Superclass = rtk::ConstantImageSource<OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaConstantVolumeSeriesSource);\n\nprotected:\n  CudaConstantVolumeSeriesSource();\n  ~CudaConstantVolumeSeriesSource() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaConstantVolumeSeriesSource.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaConstantVolumeSeriesSource_hcu\n#define rtkCudaConstantVolumeSeriesSource_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_generate_constant_volume_series(int size[4], float * dev_out, float constantValue);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaConstantVolumeSource.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaConstantVolumeSource_h\n#define rtkCudaConstantVolumeSource_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkConstantImageSource.h\"\n#  include <itkCudaImageToImageFilter.h>\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaConstantVolumeSource\n * \\brief A 3D constant image source on GPU.\n *\n *\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\n\nclass RTK_EXPORT CudaConstantVolumeSource\n  : public itk::CudaImageToImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       ConstantImageSource<itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaConstantVolumeSource);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaConstantVolumeSource;\n  using OutputImageType = itk::CudaImage<float, 3>;\n  using Superclass = rtk::ConstantImageSource<OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaConstantVolumeSource);\n\nprotected:\n  CudaConstantVolumeSource();\n  ~CudaConstantVolumeSource() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaConstantVolumeSource.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaConstantVolumeSource_hcu\n#define rtkCudaConstantVolumeSource_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_generate_constant_volume(int size[3], float * dev_out, float constantValue);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaCropImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkCudaCropImageFilter_h\n#define rtkCudaCropImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include <itkCropImageFilter.h>\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaImageToImageFilter.h>\n\nnamespace rtk\n{\n/** \\class CudaCropImageFilter\n * \\brief Decrease the image size by cropping the image by an itk::Size at\n * both the upper and lower bounds of the largest possible region.\n *\n * CropImageFilter changes the image boundary of an image by removing\n * pixels outside the target region.  The target region is not specified in\n * advance, but calculated in BeforeThreadedGenerateData().\n *\n * This filter uses CropImageFilter to perform the cropping.\n *\n * \\author Marc Vila\n *\n * \\ingroup RTK CudaImageToImageFilter\n *\n */\nclass RTK_EXPORT CudaCropImageFilter\n  : public itk::CudaImageToImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       itk::CropImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaCropImageFilter);\n\n  /** Standard class type alias. */\n  using ImageType = itk::CudaImage<float, 3>;\n  using Self = CudaCropImageFilter;\n  using Superclass = itk::CropImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>>;\n  using GPUSuperclass = itk::CudaImageToImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, Superclass>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaCropImageFilter);\n\nprotected:\n  CudaCropImageFilter();\n  virtual ~CudaCropImageFilter() {};\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaCropImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaCropImageFilter_hcu\n#define rtkCudaCropImageFilter_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_crop(const long3 & cropIndex,\n          const uint3 & cropSize,\n          const uint3 & inputSize,\n          float *       deviceVolume,\n          float *       deviceCroppedVolume);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaCyclicDeformationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaCyclicDeformationImageFilter_h\n#define rtkCudaCyclicDeformationImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkCyclicDeformationImageFilter.h\"\n#  include <itkCudaImageToImageFilter.h>\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaCyclicDeformationImageFilter\n * \\brief GPU version of the temporal DVF interpolator\n *\n * This filter implements linear interpolation along time\n * in a DVF, assuming that the motion is periodic\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\n\nclass RTK_EXPORT CudaCyclicDeformationImageFilter\n  : public itk::CudaImageToImageFilter<itk::CudaImage<itk::CovariantVector<float, 3>, 4>,\n                                       itk::CudaImage<itk::CovariantVector<float, 3>, 3>,\n                                       CyclicDeformationImageFilter<itk::CudaImage<itk::CovariantVector<float, 3>, 4>,\n                                                                    itk::CudaImage<itk::CovariantVector<float, 3>, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaCyclicDeformationImageFilter);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaCyclicDeformationImageFilter;\n  using InputImageType = itk::CudaImage<itk::CovariantVector<float, 3>, 4>;\n  using OutputImageType = itk::CudaImage<itk::CovariantVector<float, 3>, 3>;\n  using Superclass = rtk::CyclicDeformationImageFilter<InputImageType, OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaCyclicDeformationImageFilter);\n\nprotected:\n  CudaCyclicDeformationImageFilter();\n  ~CudaCyclicDeformationImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaCyclicDeformationImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaCyclicDeformationImageFilter_hcu\n#define rtkCudaCyclicDeformationImageFilter_hcu\n\nvoid\nCUDA_linear_interpolate_along_fourth_dimension(unsigned int inputSize[4],\n                                               float *      input,\n                                               float *      output,\n                                               unsigned int frameInf,\n                                               unsigned int frameSup,\n                                               double       weightInf,\n                                               double       weightSup);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaDisplacedDetectorImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaDisplacedDetectorImageFilter_h\n#define rtkCudaDisplacedDetectorImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkDisplacedDetectorImageFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaInPlaceImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaDisplacedDetectorImageFilter\n * \\brief Cuda version of rtk::DisplacedDetectorImageFilter.\n *\n * Cuda version of rtk::DisplacedDetectorImageFilter.\n *\n * \\see rtk::DisplacedDetectorImageFilter\n *\n * \\test rtkdisplaceddetectortest.cxx, rtkdisplaceddetectorcompcudatest.cxx\n *\n * \\author peter\n *\n * \\ingroup RTK\n * \\version 0.1\n */\nclass RTK_EXPORT CudaDisplacedDetectorImageFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       rtk::DisplacedDetectorImageFilter<itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaDisplacedDetectorImageFilter);\n\n  /** Convenience type alias **/\n  using ImageType = itk::CudaImage<float, 3>;\n  using CPUWeightFilterType = rtk::DisplacedDetectorImageFilter<ImageType>;\n\n  /** Standard class type alias. */\n  using Self = CudaDisplacedDetectorImageFilter;\n  using Superclass = itk::CudaInPlaceImageFilter<ImageType, ImageType, CPUWeightFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaDisplacedDetectorImageFilter);\n\nprotected:\n  /** Standard constructor **/\n  CudaDisplacedDetectorImageFilter();\n  /** Destructor **/\n  virtual ~CudaDisplacedDetectorImageFilter();\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif // rtkCudaDisplacedDetectorImageFilter_h\n"
  },
  {
    "path": "include/rtkCudaDisplacedDetectorImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaDisplacedDetectorImageFilter_hcu\n#define rtkCudaDisplacedDetectorImageFilter_hcu\n\nvoid\nCUDA_displaced_weight(int     proj_idx_in[3],\n                      int     proj_dim_in[3],\n                      int     proj_dim_in_buf[2],\n                      int     proj_idx_out[3],\n                      int     proj_dim_out[3],\n                      int     proj_dim_out_buf[2],\n                      float * dev_proj_in,\n                      float * dev_proj_out,\n                      float * geometry,\n                      float   theta,\n                      bool    isPositiveCase,\n                      float   proj_orig,\n                      float   proj_row,\n                      float   proj_col);\n\n#endif // rtkCudaDisplacedDetectorImageFilter_hcu\n"
  },
  {
    "path": "include/rtkCudaFDKBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFDKBackProjectionImageFilter_h\n#define rtkCudaFDKBackProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkFDKBackProjectionImageFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaInPlaceImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaFDKBackProjectionImageFilter\n * \\brief Cuda version of the FDK backprojection.\n *\n * GPU-based implementation of the backprojection step of the\n * [Feldkamp, Davis, Kress, 1984] algorithm for filtered backprojection\n * reconstruction of cone-beam CT images with a circular source trajectory.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Projector CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaFDKBackProjectionImageFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       FDKBackProjectionImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaFDKBackProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using ImageType = itk::CudaImage<float, 3>;\n  using FDKBackProjectionImageFilterType = FDKBackProjectionImageFilter<ImageType, ImageType>;\n  using Self = CudaFDKBackProjectionImageFilter;\n  using Superclass = itk::CudaInPlaceImageFilter<ImageType, ImageType, FDKBackProjectionImageFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using OutputImageRegionType = ImageType::RegionType;\n  using ProjectionImageType = itk::CudaImage<float, 2>;\n  using ProjectionImagePointer = ProjectionImageType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaFDKBackProjectionImageFilter);\n\nprotected:\n  CudaFDKBackProjectionImageFilter();\n  virtual ~CudaFDKBackProjectionImageFilter() {};\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaFDKBackProjectionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFDKBackProjectionImageFilter_hcu\n#define rtkCudaFDKBackProjectionImageFilter_hcu\n\nvoid\nCUDA_reconstruct_conebeam(int     img_dim[3],\n                          int     vol_dim[3],\n                          float * matrices,\n                          float * dev_vol_in,\n                          float * dev_vol_out,\n                          float * dev_img);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaFDKConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFDKConeBeamReconstructionFilter_h\n#define rtkCudaFDKConeBeamReconstructionFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkFDKConeBeamReconstructionFilter.h\"\n#  include \"rtkCudaFDKWeightProjectionFilter.h\"\n#  include \"rtkCudaFFTRampImageFilter.h\"\n#  include \"rtkCudaFDKBackProjectionImageFilter.h\"\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaFDKConeBeamReconstructionFilter\n * \\brief Implements [Feldkamp, Davis, Kress, 1984] algorithm using Cuda\n *\n * Replaces ramp filter and backprojection in FDKConeBeamReconstructionFilter\n * with CudaFFTRampImageFilter and CudaFDKBackProjectionImageFilter.\n * Also take care to create the reconstructed volume on the GPU at the beginning and\n * transfers it at the end.\n *\n * \\test rtkfdktest.cxx, rtkrampfiltertest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ReconstructionAlgorithm CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaFDKConeBeamReconstructionFilter\n  : public itk::CudaInPlaceImageFilter<\n      itk::CudaImage<float, 3>,\n      itk::CudaImage<float, 3>,\n      FDKConeBeamReconstructionFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaFDKConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = CudaFDKConeBeamReconstructionFilter;\n  using Superclass = FDKConeBeamReconstructionFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Typedefs of subfilters which have been implemented with CUDA */\n  using WeightFilterType = rtk::CudaFDKWeightProjectionFilter;\n  using RampFilterType = rtk::CudaFFTRampImageFilter;\n  using BackProjectionFilterType = rtk::CudaFDKBackProjectionImageFilter;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaFDKConeBeamReconstructionFilter);\n\nprotected:\n  CudaFDKConeBeamReconstructionFilter();\n  ~CudaFDKConeBeamReconstructionFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaFDKWeightProjectionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFDKWeightProjectionFilter_h\n#define rtkCudaFDKWeightProjectionFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkFDKWeightProjectionFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaInPlaceImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaFDKWeightProjectionFilter\n * \\brief Cuda version of rtk::FDKWeightProjectionFilter.\n *\n * Cuda version of rtk::FDKWeightProjectionFilter.\n *\n * \\see rtk::FDKWeightProjectionFilter\n *\n * \\test rtkfdktest.cxx, rtkrampfiltertest.cxx, rtkdisplaceddetectortest.cxx,\n * rtkshortscantest.cxx, rtkfdkprojweightcompcudatest.cxx\n *\n * \\author peter\n *\n * \\ingroup RTK\n * \\version 0.1\n */\nclass RTK_EXPORT CudaFDKWeightProjectionFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       rtk::FDKWeightProjectionFilter<itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaFDKWeightProjectionFilter);\n\n  /** Convenience type alias **/\n  using ImageType = itk::CudaImage<float, 3>;\n  using CPUWeightFilterType = rtk::FDKWeightProjectionFilter<ImageType>;\n\n  /** Standard class type alias. */\n  using Self = CudaFDKWeightProjectionFilter;\n  using Superclass = itk::CudaInPlaceImageFilter<ImageType, ImageType, CPUWeightFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaFDKWeightProjectionFilter);\n\nprotected:\n  /** Standard constructor **/\n  CudaFDKWeightProjectionFilter();\n  /** Destructor **/\n  virtual ~CudaFDKWeightProjectionFilter();\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif // rtkCudaFDKWeightProjectionFilter_h\n"
  },
  {
    "path": "include/rtkCudaFDKWeightProjectionFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFDKWeightProjectionFilter_hcu\n#define rtkCudaFDKWeightProjectionFilter_hcu\n\nvoid\nCUDA_weight_projection(int     proj_idx[2],\n                       int     proj_dim[3],\n                       int     proj_dim_buf_in[2],\n                       int     proj_dim_buf_out[2],\n                       float * dev_proj_in,\n                       float * dev_proj_out,\n                       float * geometry,\n                       float   proj_orig[2],\n                       float   proj_row[2],\n                       float   proj_col[2]);\n\n#endif // rtkCudaFDKWeightProjectionFilter_hcu\n"
  },
  {
    "path": "include/rtkCudaFFTProjectionsConvolutionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFFTProjectionsConvolutionImageFilter_h\n#define rtkCudaFFTProjectionsConvolutionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include <itkCudaImage.h>\n#  include <itkCudaImageToImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaFFTProjectionsConvolutionImageFilter\n * \\brief Implements 1D or 2D FFT convolution.\n *\n * This filter implements a convolution using FFT of the input image. The\n * convolution kernel must be defined in the parent class, passed via the\n * template argument. The template argument must be a child of\n * rtk::FFTProjectionsConvolutionImageFilter.\n *\n * \\see rtk::FFTProjectionsConvolutionImageFilter\n *\n * \\test rtkrampfiltertest.cxx, rtkrampfiltertest2.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\ntemplate <class TParentImageFilter>\nclass ITK_TEMPLATE_EXPORT CudaFFTProjectionsConvolutionImageFilter\n  : public itk::CudaImageToImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, TParentImageFilter>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaFFTProjectionsConvolutionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = CudaFFTProjectionsConvolutionImageFilter;\n  using Superclass = TParentImageFilter;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using RegionType = typename TParentImageFilter::RegionType;\n  using FFTInputImagePointer = typename TParentImageFilter::FFTInputImagePointer;\n  using CudaImageType = itk::CudaImage<float, 3>;\n  using CudaFFTOutputImageType = itk::CudaImage<std::complex<float>, 3>;\n  using CudaFFTOutputImagePointer = CudaFFTOutputImageType::Pointer;\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaFFTProjectionsConvolutionImageFilter);\n\nprotected:\n  CudaFFTProjectionsConvolutionImageFilter();\n  ~CudaFFTProjectionsConvolutionImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n  virtual FFTInputImagePointer\n  PadInputImageRegion(const RegionType & inputRegion);\n\nprivate:\n  CudaFFTOutputImagePointer m_KernelFFTCUDA;\n}; // end of class\n\n} // end namespace rtk\n\n#  ifndef ITK_MANUAL_INSTANTIATION\n#    include \"rtkCudaFFTProjectionsConvolutionImageFilter.hxx\"\n#  endif\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaFFTProjectionsConvolutionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFFTProjectionsConvolutionImageFilter_hcu\n#define rtkCudaFFTProjectionsConvolutionImageFilter_hcu\n\n#include <vector_types.h>\n#include <vector>\n#include \"RTKExport.h\"\n\nvoid RTK_EXPORT\nCUDA_fft_convolution(const int3 & inputDimension,\n                     const int2 & kernelDimension,\n                     float *      deviceProjection,\n                     float2 *     deviceKernelFFT);\n\nvoid RTK_EXPORT\nCUDA_padding(const int3 &               paddingIndex,\n             const uint3 &              paddingSize,\n             const uint3 &              inputSize,\n             float *                    deviceVolume,\n             float *                    devicePaddedVolume,\n             const std::vector<float> & mirrorWeights);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaFFTProjectionsConvolutionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFFTProjectionsConvolutionImageFilter_hxx\n#define rtkCudaFFTProjectionsConvolutionImageFilter_hxx\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkCudaFFTProjectionsConvolutionImageFilter.h\"\n#  include \"rtkCudaFFTProjectionsConvolutionImageFilter.hcu\"\n\n#  include \"rtkCudaCropImageFilter.h\"\n#  include \"rtkCudaCropImageFilter.hcu\"\n\n#  include <itkMacro.h>\n\nnamespace rtk\n{\n\ntemplate <class TParentImageFilter>\nCudaFFTProjectionsConvolutionImageFilter<TParentImageFilter>::CudaFFTProjectionsConvolutionImageFilter()\n{\n  // We use FFTW for the kernel so we need to do the same thing as in the parent\n#  if defined(USE_FFTWF)\n  this->SetGreatestPrimeFactor(13);\n#  endif\n}\n\ntemplate <class TParentImageFilter>\ntypename CudaFFTProjectionsConvolutionImageFilter<TParentImageFilter>::FFTInputImagePointer\nCudaFFTProjectionsConvolutionImageFilter<TParentImageFilter>::PadInputImageRegion(const RegionType & inputRegion)\n{\n  CudaImageType::RegionType inBuffRegion = this->GetInput()->GetBufferedRegion();\n  if (inBuffRegion != this->GetInput()->GetRequestedRegion())\n  {\n    itkExceptionMacro(\n      << \"CudaFFTProjectionsConvolutionImageFilter assumes that input requested and buffered regions are equal.\");\n  }\n\n  TParentImageFilter::UpdateTruncationMirrorWeights();\n  RegionType paddedRegion = TParentImageFilter::GetPaddedImageRegion(inputRegion);\n\n  // Create padded image (spacing and origin do not matter)\n  auto paddedImage = itk::CudaImage<float, 3>::New();\n  paddedImage->SetRegions(paddedRegion);\n  paddedImage->Allocate();\n\n  uint3 sz, sz_i;\n  int3  idx;\n  idx.x = inBuffRegion.GetIndex()[0] - paddedRegion.GetIndex()[0];\n  idx.y = inBuffRegion.GetIndex()[1] - paddedRegion.GetIndex()[1];\n  idx.z = inBuffRegion.GetIndex()[2] - paddedRegion.GetIndex()[2];\n  sz.x = paddedRegion.GetSize()[0];\n  sz.y = paddedRegion.GetSize()[1];\n  sz.z = paddedRegion.GetSize()[2];\n  sz_i.x = inBuffRegion.GetSize()[0];\n  sz_i.y = inBuffRegion.GetSize()[1];\n  sz_i.z = inBuffRegion.GetSize()[2];\n\n#  ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(paddedImage->GetCudaDataManager()->GetGPUBufferPointer());\n#  else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(paddedImage->GetCudaDataManager()->GetGPUBufferPointer());\n#  endif\n\n  CUDA_padding(idx, sz, sz_i, pin, pout, TParentImageFilter::m_TruncationMirrorWeights);\n\n  return paddedImage.GetPointer();\n}\n\ntemplate <class TParentImageFilter>\nvoid\nCudaFFTProjectionsConvolutionImageFilter<TParentImageFilter>::GPUGenerateData()\n{\n  // Pad image region\n  FFTInputImagePointer paddedImage = PadInputImageRegion(this->GetInput()->GetRequestedRegion());\n\n  int3 inputDimension;\n  inputDimension.x = paddedImage->GetBufferedRegion().GetSize()[0];\n  inputDimension.y = paddedImage->GetBufferedRegion().GetSize()[1];\n  inputDimension.z = paddedImage->GetBufferedRegion().GetSize()[2];\n  if (inputDimension.y == 1 && inputDimension.z > 1) // Troubles cuda 3.2 and 4.0\n    std::swap(inputDimension.y, inputDimension.z);\n\n  // Get FFT ramp kernel. Must be itk::Image because GetFFTProjectionsConvolutionKernel is not\n  // compatible with itk::CudaImage + ITK 3.20.\n  typename Superclass::FFTOutputImageType::SizeType s = paddedImage->GetLargestPossibleRegion().GetSize();\n  this->UpdateFFTProjectionsConvolutionKernel(s);\n  if (this->m_KernelFFTCUDA.GetPointer() == nullptr ||\n      this->m_KernelFFTCUDA->GetTimeStamp() < this->m_KernelFFT->GetTimeStamp())\n  {\n\n    // Create the itk::CudaImage holding the kernel\n    typename Superclass::FFTOutputImageType::RegionType kreg = this->m_KernelFFT->GetLargestPossibleRegion();\n\n    this->m_KernelFFTCUDA = CudaFFTOutputImageType::New();\n    this->m_KernelFFTCUDA->SetRegions(kreg);\n    this->m_KernelFFTCUDA->Allocate();\n\n    // CUFFT scales by the number of element, correct for it in kernel.\n    // Also transfer the kernel from the itk::Image to the itk::CudaImage.\n    itk::ImageRegionIterator<typename TParentImageFilter::FFTOutputImageType> itKI(this->m_KernelFFT, kreg);\n    itk::ImageRegionIterator<CudaFFTOutputImageType>                          itKO(this->m_KernelFFTCUDA, kreg);\n    typename TParentImageFilter::FFTPrecisionType                             invNPixels;\n    invNPixels = 1 / double(paddedImage->GetBufferedRegion().GetNumberOfPixels());\n    while (!itKO.IsAtEnd())\n    {\n      itKO.Set(itKI.Get() * invNPixels);\n      ++itKI;\n      ++itKO;\n    }\n  }\n\n  CudaImageType * cuPadImgP = dynamic_cast<CudaImageType *>(paddedImage.GetPointer());\n\n  int2 kernelDimension;\n  kernelDimension.x = this->m_KernelFFT->GetBufferedRegion().GetSize()[0];\n  kernelDimension.y = this->m_KernelFFT->GetBufferedRegion().GetSize()[1];\n  CUDA_fft_convolution(inputDimension,\n                       kernelDimension,\n#  ifdef CudaCommon_VERSION_MAJOR\n                       (float *)(cuPadImgP->GetCudaDataManager()->GetGPUBufferPointer()),\n                       (float2 *)(this->m_KernelFFTCUDA->GetCudaDataManager()->GetGPUBufferPointer()));\n#  else\n                       *(float **)(cuPadImgP->GetCudaDataManager()->GetGPUBufferPointer()),\n                       *(float2 **)(this->m_KernelFFTCUDA->GetCudaDataManager()->GetGPUBufferPointer()));\n#  endif\n\n  /* Impossible to get a pixel-wise progress reporting with CUDA\n   * so this filter only reports 0 and 100% completion. */\n  itk::ProgressReporter progress(this, 0, 1);\n  progress.CompletedPixel();\n\n  // CUDA Cropping and Graft Output\n  auto                                           cf = CudaCropImageFilter::New();\n  typename Superclass::OutputImageType::SizeType upCropSize, lowCropSize;\n  for (unsigned int i = 0; i < CudaImageType::ImageDimension; i++)\n  {\n    lowCropSize[i] =\n      this->GetOutput()->GetRequestedRegion().GetIndex()[i] - paddedImage->GetLargestPossibleRegion().GetIndex()[i];\n    upCropSize[i] = paddedImage->GetLargestPossibleRegion().GetSize()[i] -\n                    this->GetOutput()->GetRequestedRegion().GetSize()[i] - lowCropSize[i];\n  }\n  cf->SetUpperBoundaryCropSize(upCropSize);\n  cf->SetLowerBoundaryCropSize(lowCropSize);\n  cf->SetInput(cuPadImgP);\n  cf->Update();\n\n  // We only want to graft the data. To do so, we copy the rest before grafting.\n  cf->GetOutput()->CopyInformation(this->GetOutput());\n  cf->GetOutput()->SetBufferedRegion(this->GetOutput()->GetBufferedRegion());\n  cf->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  this->GraftOutput(cf->GetOutput());\n}\n\n} // namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaFFTRampImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFFTRampImageFilter_h\n#define rtkCudaFFTRampImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkCudaFFTProjectionsConvolutionImageFilter.h\"\n#  include \"rtkFFTRampImageFilter.h\"\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaFFTRampImageFilter\n * \\brief Implements the ramp image filter of the FDK algorithm on GPU.\n *\n * Uses CUFFT for the projection fft and ifft.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaFFTRampImageFilter\n  : public CudaFFTProjectionsConvolutionImageFilter<\n      FFTRampImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaFFTRampImageFilter);\n\n  /** Standard class type alias. */\n  using Self = CudaFFTRampImageFilter;\n  using Superclass = FFTRampImageFilter<CudaImageType, CudaImageType, float>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaFFTRampImageFilter);\n\nprotected:\n  CudaFFTRampImageFilter() {}\n  ~CudaFFTRampImageFilter() {}\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaFirstOrderKernels.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaFirstOrderKernels_hcu\n#define rtkCudaFirstOrderKernels_hcu\n\n__global__ void\ndivergence_kernel(float * grad_x, float * grad_y, float * grad_z, float * out, int3 c_Size, float3 c_Spacing);\n\n__global__ void\ngradient_kernel(float * in, float * grad_x, float * grad_y, float * grad_z, int3 c_Size, float3 c_Spacing);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaForwardProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaForwardProjectionImageFilter_h\n#define rtkCudaForwardProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkForwardProjectionImageFilter.h\"\n#  include \"itkCudaInPlaceImageFilter.h\"\n#  include \"itkCudaUtil.h\"\n#  include \"RTKExport.h\"\n\n/** \\class CudaForwardProjectionImageFilter\n * \\brief Trilinear interpolation forward projection implemented in CUDA\n *\n * CudaForwardProjectionImageFilter is similar to\n * JosephForwardProjectionImageFilter, except it uses a\n * fixed step between sampling points instead of placing these\n * sampling points only on the main direction slices.\n *\n * The code was developed based on the file tt_project_ray_gpu_kernels.cu of\n * NiftyRec (https://sourceforge.net/projects/niftyrec/) which is distributed under a BSD\n * license. See COPYRIGHT.TXT.\n *\n * \\author Marc Vila, updated by Simon Rit and Cyril Mory\n *\n * \\ingroup RTK Projector CudaImageToImageFilter\n */\n\nnamespace rtk\n{\n\ntemplate <class TInputImage = itk::CudaImage<float, 3>, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT CudaForwardProjectionImageFilter\n  : public itk::\n      CudaInPlaceImageFilter<TInputImage, TOutputImage, ForwardProjectionImageFilter<TInputImage, TOutputImage>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaForwardProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = CudaForwardProjectionImageFilter;\n  using Superclass = ForwardProjectionImageFilter<TInputImage, TOutputImage>;\n  using GPUSuperclass = itk::CudaInPlaceImageFilter<TInputImage, TOutputImage, Superclass>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using VectorType = itk::Vector<float, 3>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaForwardProjectionImageFilter);\n\n  /** Set step size along ray (in mm). Default is 1 mm. */\n  itkGetConstMacro(StepSize, double);\n  itkSetMacro(StepSize, double);\n\nprotected:\n  CudaForwardProjectionImageFilter();\n  ~CudaForwardProjectionImageFilter() {};\n\n  virtual void\n  GPUGenerateData();\n\nprivate:\n  double m_StepSize;\n}; // end of class\n\n} // end namespace rtk\n\n#  ifndef ITK_MANUAL_INSTANTIATION\n#    include \"rtkCudaForwardProjectionImageFilter.hxx\"\n#  endif\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaForwardProjectionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaForwardProjectionImageFilter_hcu\n#define rtkCudaForwardProjectionImageFilter_hcu\n\n#include \"RTKExport.h\"\n\nvoid RTK_EXPORT\nCUDA_forward_project(int                projSize[3],\n                     int                volSize[3],\n                     float *            translatedProjectionIndexTransformMatrices,\n                     float *            translatedVolumeTransformMatrices,\n                     float *            dev_proj_in,\n                     float *            dev_proj_out,\n                     float *            dev_vol,\n                     float              t_step,\n                     float *            source_positions,\n                     float              radiusCylindricalDetector,\n                     float              box_min[3],\n                     float              box_max[3],\n                     float              spacing[3],\n                     const unsigned int vectorLength);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaForwardProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaForwardProjectionImageFilter_hxx\n#define rtkCudaForwardProjectionImageFilter_hxx\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkCudaForwardProjectionImageFilter.h\"\n#  include \"rtkCudaUtilities.hcu\"\n#  include \"rtkCudaForwardProjectionImageFilter.hcu\"\n\n#  include <itkImageRegionConstIterator.h>\n#  include <itkImageRegionIteratorWithIndex.h>\n#  include <itkLinearInterpolateImageFunction.h>\n#  include <itkMacro.h>\n#  include \"rtkMacro.h\"\n#  include \"itkCudaUtil.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nCudaForwardProjectionImageFilter<TInputImage, TOutputImage>::CudaForwardProjectionImageFilter()\n  : m_StepSize(1)\n{}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nCudaForwardProjectionImageFilter<TInputImage, TOutputImage>::GPUGenerateData()\n{\n  if (this->GetGeometry()->GetSourceToDetectorDistances().size() &&\n      this->GetGeometry()->GetSourceToDetectorDistances()[0] == 0)\n  {\n    itkGenericExceptionMacro(<< \"Parallel geometry is not handled by CUDA forward projector.\");\n  }\n\n  const typename Superclass::GeometryType * geometry = this->GetGeometry();\n  const unsigned int                        Dimension = TInputImage::ImageDimension;\n  const unsigned int iFirstProj = this->GetInput(0)->GetRequestedRegion().GetIndex(Dimension - 1);\n  const unsigned int nProj = this->GetInput(0)->GetRequestedRegion().GetSize(Dimension - 1);\n  const unsigned int nPixelsPerProj = this->GetOutput()->GetBufferedRegion().GetSize(0) *\n                                      this->GetOutput()->GetBufferedRegion().GetSize(1) *\n                                      itk::NumericTraits<typename TInputImage::PixelType>::GetLength();\n\n  itk::Vector<double, 4> source_position;\n\n  // Setting BoxMin and BoxMax\n  // SR: we are using cuda textures where the pixel definition is not center but corner.\n  // Therefore, we set the box limits from index to index+size instead of, for ITK,\n  // index-0.5 to index+size-0.5.\n  float boxMin[3];\n  float boxMax[3];\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    boxMin[i] = this->GetInput(1)->GetBufferedRegion().GetIndex()[i] + 0.5;\n    boxMax[i] = boxMin[i] + this->GetInput(1)->GetBufferedRegion().GetSize()[i] - 1.0;\n  }\n\n  // Getting Spacing\n  float spacing[3];\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    spacing[i] = this->GetInput(1)->GetSpacing()[i];\n  }\n\n  // Cuda convenient format for dimensions\n  int projectionSize[3];\n  projectionSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  projectionSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n\n  int volumeSize[3];\n  volumeSize[0] = this->GetInput(1)->GetBufferedRegion().GetSize()[0];\n  volumeSize[1] = this->GetInput(1)->GetBufferedRegion().GetSize()[1];\n  volumeSize[2] = this->GetInput(1)->GetBufferedRegion().GetSize()[2];\n\n#  ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput(0)->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pvol = (float *)(this->GetInput(1)->GetCudaDataManager()->GetGPUBufferPointer());\n#  else\n  float * pin = *(float **)(this->GetInput(0)->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pvol = *(float **)(this->GetInput(1)->GetCudaDataManager()->GetGPUBufferPointer());\n#  endif\n\n  // Account for system rotations\n  typename Superclass::GeometryType::ThreeDHomogeneousMatrixType volPPToIndex;\n  volPPToIndex = GetPhysicalPointToIndexMatrix(this->GetInput(1));\n\n  // Compute matrix to translate the pixel indices on the volume and the detector\n  // if the Requested region has non-zero index\n  typename Superclass::GeometryType::ThreeDHomogeneousMatrixType projIndexTranslation, volIndexTranslation;\n  projIndexTranslation.SetIdentity();\n  volIndexTranslation.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    projIndexTranslation[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex(i);\n    volIndexTranslation[i][3] = -this->GetInput(1)->GetBufferedRegion().GetIndex(i);\n\n    // Adding 0.5 offset to change from the centered pixel convention (ITK)\n    // to the corner pixel convention (CUDA).\n    volPPToIndex[i][3] += 0.5;\n  }\n\n  // Compute matrices to transform projection index to volume index, one per projection\n  float * translatedProjectionIndexTransformMatrices = new float[12 * nProj];\n  float * translatedVolumeTransformMatrices = new float[12 * nProj];\n  float * source_positions = new float[4 * nProj];\n\n  float radiusCylindricalDetector = geometry->GetRadiusCylindricalDetector();\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    typename Superclass::GeometryType::ThreeDHomogeneousMatrixType translatedProjectionIndexTransformMatrix;\n    typename Superclass::GeometryType::ThreeDHomogeneousMatrixType translatedVolumeTransformMatrix;\n    translatedVolumeTransformMatrix.Fill(0);\n\n    // The matrices required depend on the type of detector\n    if (radiusCylindricalDetector == 0)\n    {\n      translatedProjectionIndexTransformMatrix =\n        volIndexTranslation.GetVnlMatrix() * volPPToIndex.GetVnlMatrix() *\n        geometry->GetProjectionCoordinatesToFixedSystemMatrix(iProj).GetVnlMatrix() *\n        rtk::GetIndexToPhysicalPointMatrix(this->GetInput()).GetVnlMatrix() * projIndexTranslation.GetVnlMatrix();\n      for (int j = 0; j < 3; j++) // Ignore the 4th row\n        for (int k = 0; k < 4; k++)\n          translatedProjectionIndexTransformMatrices[(j + 3 * (iProj - iFirstProj)) * 4 + k] =\n            (float)translatedProjectionIndexTransformMatrix[j][k];\n    }\n    else\n    {\n      translatedProjectionIndexTransformMatrix =\n        geometry->GetProjectionCoordinatesToDetectorSystemMatrix(iProj).GetVnlMatrix() *\n        rtk::GetIndexToPhysicalPointMatrix(this->GetInput()).GetVnlMatrix() * projIndexTranslation.GetVnlMatrix();\n      for (int j = 0; j < 3; j++) // Ignore the 4th row\n        for (int k = 0; k < 4; k++)\n          translatedProjectionIndexTransformMatrices[(j + 3 * (iProj - iFirstProj)) * 4 + k] =\n            (float)translatedProjectionIndexTransformMatrix[j][k];\n\n      translatedVolumeTransformMatrix = volIndexTranslation.GetVnlMatrix() * volPPToIndex.GetVnlMatrix() *\n                                        geometry->GetRotationMatrices()[iProj].GetInverse();\n      for (int j = 0; j < 3; j++) // Ignore the 4th row\n        for (int k = 0; k < 4; k++)\n          translatedVolumeTransformMatrices[(j + 3 * (iProj - iFirstProj)) * 4 + k] =\n            (float)translatedVolumeTransformMatrix[j][k];\n    }\n\n    // Compute source position in volume indices\n    source_position = volPPToIndex * geometry->GetSourcePosition(iProj);\n\n    // Copy it into a single large array\n    for (unsigned int d = 0; d < 3; d++)\n      source_positions[(iProj - iFirstProj) * 3 + d] = source_position[d]; // Ignore the 4th component\n  }\n\n  int                projectionOffset = 0;\n  const unsigned int vectorLength = itk::PixelTraits<typename TInputImage::PixelType>::Dimension;\n\n  for (unsigned int i = 0; i < nProj; i += SLAB_SIZE)\n  {\n    // If nProj is not a multiple of SLAB_SIZE, the last slab will contain less than SLAB_SIZE projections\n    projectionSize[2] = std::min(nProj - i, (unsigned int)SLAB_SIZE);\n    projectionOffset = iFirstProj + i - this->GetOutput()->GetBufferedRegion().GetIndex(2);\n\n    // Run the forward projection with a slab of SLAB_SIZE or less projections\n    CUDA_forward_project(projectionSize,\n                         volumeSize,\n                         (float *)&(translatedProjectionIndexTransformMatrices[12 * i]),\n                         (float *)&(translatedVolumeTransformMatrices[12 * i]),\n                         pin + nPixelsPerProj * projectionOffset,\n                         pout + nPixelsPerProj * projectionOffset,\n                         pvol,\n                         m_StepSize,\n                         (float *)&(source_positions[3 * i]),\n                         radiusCylindricalDetector,\n                         boxMin,\n                         boxMax,\n                         spacing,\n                         vectorLength);\n  }\n\n  delete[] translatedProjectionIndexTransformMatrices;\n  delete[] translatedVolumeTransformMatrices;\n  delete[] source_positions;\n}\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaForwardWarpImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaForwardWarpImageFilter_h\n#define rtkCudaForwardWarpImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"RTKExport.h\"\n#  include \"rtkForwardWarpImageFilter.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaImageToImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaForwardWarpImageFilter\n * \\brief Cuda version of the ForwardWarpImageFilter\n *\n * Deform an image using a Displacement Vector Field, by performing\n * trilinear splat. Adjoint of the regular warp filter. GPU-based implementation\n *\n * \\test rtkwarptest\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaForwardWarpImageFilter\n  : public itk::CudaImageToImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       rtk::ForwardWarpImageFilter<itk::CudaImage<float, 3>,\n                                                                   itk::CudaImage<float, 3>,\n                                                                   itk::CudaImage<itk::CovariantVector<float, 3>, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaForwardWarpImageFilter);\n\n  /** Standard class type alias. */\n  using ImageType = itk::CudaImage<float, 3>;\n  using DisplacementVectorType = itk::CovariantVector<float, 3>;\n  using DVFType = itk::CudaImage<DisplacementVectorType, 3>;\n  using ForwardWarpImageFilterType = ForwardWarpImageFilter<ImageType, ImageType, DVFType>;\n  using Self = CudaForwardWarpImageFilter;\n  using Superclass = itk::CudaImageToImageFilter<ImageType, ImageType, ForwardWarpImageFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using OutputImageRegionType = ImageType::RegionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaForwardWarpImageFilter);\n\nprotected:\n  CudaForwardWarpImageFilter();\n  virtual ~CudaForwardWarpImageFilter() {};\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaForwardWarpImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaForwardWarpImageFilter_hcu\n#define rtkCudaForwardWarpImageFilter_hcu\n\nvoid\nCUDA_ForwardWarp(int     input_vol_dim[3],\n                 int     input_dvf_dim[3],\n                 int     output_vol_dim[3],\n                 float   IndexInputToPPInputMatrix[12],\n                 float   IndexInputToIndexDVFMatrix[12],\n                 float   PPOutputToIndexOutputMatrix[12],\n                 float * dev_input_vol,\n                 float * dev_input_xdvf,\n                 float * dev_input_ydvf,\n                 float * dev_input_zdvf,\n                 float * dev_output_vol,\n                 bool    isLinear);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaInterpolateImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaInterpolateImageFilter_h\n#define rtkCudaInterpolateImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkInterpolatorWithKnownWeightsImageFilter.h\"\n#  include \"itkCudaImage.h\"\n#  include \"itkCudaInPlaceImageFilter.h\"\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaInterpolateImageFilter\n * \\brief Implements the InterpolateWithKnownWeightsImageFilter on GPU.\n *\n *\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaInterpolateImageFilter\n  : public itk::CudaInPlaceImageFilter<\n      itk::CudaImage<float, 3>,\n      itk::CudaImage<float, 3>,\n      InterpolatorWithKnownWeightsImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 4>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaInterpolateImageFilter);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaInterpolateImageFilter;\n  using Superclass = rtk::InterpolatorWithKnownWeightsImageFilter<OutputImageType, InputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaInterpolateImageFilter);\n\nprotected:\n  CudaInterpolateImageFilter();\n  ~CudaInterpolateImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaInterpolateImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaInterpolateImageFilter_hcu\n#define rtkCudaInterpolateImageFilter_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_interpolation(const int4 & inputSize, float * input, float * output, int projectionNumber, float ** weights);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaIntersectBox.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaIntersectBox_hcu\n#define rtkCudaIntersectBox_hcu\n\n#include \"RTKExport.h\"\n#include \"rtkCudaUtilities.hcu\"\n\nstruct Ray\n{\n  float3 o; // origin\n  float3 d; // direction\n};\n\n// Intersection function of a ray with a box, followed \"slabs\" method\n// https://education.siggraph.org/static/HyperGraph/raytrace/rtinter3.htm\n// The function has to be explicitely inlined, otherwise \"multiple definition\" errors\n// will pop during linking. See https://choorucode.com/2011/03/15/cuda-device-function-in-header-file/\n// for more information\n__forceinline__ __device__ int\nintersectBox(Ray r, float * tnear, float * tfar, float3 boxMin, float3 boxMax)\n{\n  // Compute intersection of ray with all six bbox planes\n  float3 invR = make_float3(1.f / r.d.x, 1.f / r.d.y, 1.f / r.d.z);\n  float3 T1;\n  T1 = invR * (boxMin - r.o);\n  float3 T2;\n  T2 = invR * (boxMax - r.o);\n\n  // Re-order intersections to find smallest and largest on each axis\n  float3 tmin;\n  tmin = fminf(T2, T1);\n  float3 tmax;\n  tmax = fmaxf(T2, T1);\n\n  // Find the largest tmin and the smallest tmax\n  float largest_tmin = fmaxf(fmaxf(tmin.x, tmin.y), fmaxf(tmin.x, tmin.z));\n  float smallest_tmax = fminf(fminf(tmax.x, tmax.y), fminf(tmax.x, tmax.z));\n\n  *tnear = largest_tmin;\n  *tfar = smallest_tmax;\n\n  return smallest_tmax > largest_tmin;\n}\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaIterativeFDKConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaIterativeFDKConeBeamReconstructionFilter_h\n#define rtkCudaIterativeFDKConeBeamReconstructionFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkIterativeFDKConeBeamReconstructionFilter.h\"\n#  include \"rtkCudaFDKConeBeamReconstructionFilter.h\"\n#  include \"rtkCudaDisplacedDetectorImageFilter.h\"\n#  include \"rtkCudaParkerShortScanImageFilter.h\"\n#  include \"rtkCudaConstantVolumeSource.h\"\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaIterativeFDKConeBeamReconstructionFilter\n * \\brief Implements the iterative FDK algorithm using Cuda\n *\n * Replaces:\n * - FDKConeBeamReconstructionFilter with CudaFDKConeBeamReconstructionFilter\n *\n * Also take care to create the reconstructed volume on the GPU at the beginning and\n * transfers it at the end.\n *\n * \\test rtkfdktest.cxx, rtkrampfiltertest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ReconstructionAlgorithm CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaIterativeFDKConeBeamReconstructionFilter\n  : public itk::CudaImageToImageFilter<\n      itk::CudaImage<float, 3>,\n      itk::CudaImage<float, 3>,\n      IterativeFDKConeBeamReconstructionFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaIterativeFDKConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = CudaIterativeFDKConeBeamReconstructionFilter;\n  using Superclass =\n    IterativeFDKConeBeamReconstructionFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Typedefs of subfilters which have been implemented with CUDA */\n  using DisplacedDetectorFilterType = rtk::CudaDisplacedDetectorImageFilter;\n  using ParkerFilterType = rtk::CudaParkerShortScanImageFilter;\n  using FDKFilterType = rtk::CudaFDKConeBeamReconstructionFilter;\n  using ConstantImageSourceType = rtk::CudaConstantVolumeSource;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaIterativeFDKConeBeamReconstructionFilter);\n\nprotected:\n  CudaIterativeFDKConeBeamReconstructionFilter();\n  ~CudaIterativeFDKConeBeamReconstructionFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaLagCorrectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaLagCorrectionImageFilter_h\n#define rtkCudaLagCorrectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkLagCorrectionImageFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaInPlaceImageFilter.h>\n\n#  include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaLagCorrectionImageFilter\n * \\brief Cuda version of LagCorrectionImageFilter.\n *\n * Cuda version of LagCorrectionImageFilter.\n *\n * \\see LagCorrectionImageFilter\n *\n * \\author Sebastien Brousmiche\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT CudaLagCorrectionImageFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<unsigned short, 3>,\n                                       itk::CudaImage<unsigned short, 3>,\n                                       LagCorrectionImageFilter<itk::CudaImage<unsigned short, 3>, 4>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaLagCorrectionImageFilter);\n\n  /** Convenience type alias **/\n  using ImageType = itk::CudaImage<unsigned short, 3>;\n  using CPULagFilterType = LagCorrectionImageFilter<ImageType, 4>;\n\n  /** Standard class type alias. */\n  using Self = CudaLagCorrectionImageFilter;\n  using Superclass = itk::CudaInPlaceImageFilter<ImageType, ImageType, CPULagFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaLagCorrectionImageFilter);\n\nprotected:\n  /** Standard constructor **/\n  CudaLagCorrectionImageFilter();\n  /** Destructor **/\n  virtual ~CudaLagCorrectionImageFilter();\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif // rtkCudaLagCorrectionImageFilter_h\n"
  },
  {
    "path": "include/rtkCudaLagCorrectionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaLagCorrectionImageFilter_hcu\n#define rtkCudaLagCorrectionImageFilter_hcu\n\nvoid\nCUDA_lag_correction(int              proj_idx_in[3],\n                    int              proj_dim_in[3],\n                    int              proj_dim_in_buf[2],\n                    int              proj_idx_out[3],\n                    int              proj_dim_out[3],\n                    int              proj_dim_out_buf[2],\n                    unsigned short * dev_proj_in,\n                    unsigned short * dev_proj_out,\n                    float *          h_state,\n                    size_t           state_size,\n                    float *          coefficients);\n\n#endif // rtkCudaLagCorrectionImageFilter_hcu\n"
  },
  {
    "path": "include/rtkCudaLaplacianImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaLaplacianImageFilter_h\n#define rtkCudaLaplacianImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkLaplacianImageFilter.h\"\n#  include <itkCudaInPlaceImageFilter.h>\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaLaplacianImageFilter\n * \\brief Implements the 3D float LaplacianImageFilter on GPU\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\n\nclass RTK_EXPORT CudaLaplacianImageFilter\n  : public itk::CudaImageToImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       LaplacianImageFilter<itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaLaplacianImageFilter);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaLaplacianImageFilter;\n  using OutputImageType = itk::CudaImage<float, 3>;\n  using Superclass = rtk::LaplacianImageFilter<OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaLaplacianImageFilter);\n\nprotected:\n  CudaLaplacianImageFilter();\n  ~CudaLaplacianImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaLaplacianImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaLaplacianImageFilter_hcu\n#define rtkCudaLaplacianImageFilter_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_laplacian(int size[3], float spacing[3], float * dev_in, float * dev_out);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaLastDimensionTVDenoisingImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaLastDimensionTVDenoisingImageFilter_h\n#define rtkCudaLastDimensionTVDenoisingImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkTotalVariationDenoisingBPDQImageFilter.h\"\n#  include <itkCudaInPlaceImageFilter.h>\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaLastDimensionTVDenoisingImageFilter\n * \\brief Implements the TotalVariationDenoisingBPDQImageFilter on GPU\n * for a specific case : denoising only along the last dimension\n *\n *\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\n\nclass RTK_EXPORT CudaLastDimensionTVDenoisingImageFilter\n  : public itk::CudaInPlaceImageFilter<\n      itk::CudaImage<float, 4>,\n      itk::CudaImage<float, 4>,\n      TotalVariationDenoisingBPDQImageFilter<itk::CudaImage<float, 4>,\n                                             itk::CudaImage<itk::CovariantVector<float, 1>, 4>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaLastDimensionTVDenoisingImageFilter);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaLastDimensionTVDenoisingImageFilter;\n  using OutputImageType = itk::CudaImage<float, 4>;\n  using GradientType = itk::CudaImage<itk::CovariantVector<float, 1>, 4>;\n  using Superclass = rtk::TotalVariationDenoisingBPDQImageFilter<OutputImageType, GradientType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaLastDimensionTVDenoisingImageFilter);\n\nprotected:\n  CudaLastDimensionTVDenoisingImageFilter();\n  ~CudaLastDimensionTVDenoisingImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaLastDimensionTVDenoisingImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaLastDimensionTVDenoisingImageFilter_hcu\n#define rtkCudaLastDimensionTVDenoisingImageFilter_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_total_variation_last_dimension(int     size[4],\n                                    float * dev_in,\n                                    float * dev_out,\n                                    float   gamma,\n                                    float   beta,\n                                    int     NumberOfIterations);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaParkerShortScanImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaParkerShortScanImageFilter_h\n#define rtkCudaParkerShortScanImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkParkerShortScanImageFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaInPlaceImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaParkerShortScanImageFilter\n * \\brief Cuda version of rtk::ParkerShortScanImageFilter.\n *\n * Cuda version of rtk::ParkerShortScanImageFilter.\n *\n * \\see rtk::ParkerShortScanImageFilter\n *\n * \\test rtkshortscantest.cxx, rtkshortscancompcudatest.cxx\n *\n * \\author peter\n *\n * \\ingroup RTK\n * \\version 0.1\n */\nclass RTK_EXPORT CudaParkerShortScanImageFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       rtk::ParkerShortScanImageFilter<itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaParkerShortScanImageFilter);\n\n  /** Convenience type alias **/\n  using ImageType = itk::CudaImage<float, 3>;\n  using CPUWeightFilterType = rtk::ParkerShortScanImageFilter<ImageType>;\n\n  /** Standard class type alias. */\n  using Self = CudaParkerShortScanImageFilter;\n  using Superclass = itk::CudaInPlaceImageFilter<ImageType, ImageType, CPUWeightFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaParkerShortScanImageFilter);\n\nprotected:\n  /** Standard constructor **/\n  CudaParkerShortScanImageFilter();\n  /** Destructor **/\n  virtual ~CudaParkerShortScanImageFilter();\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif // rtkCudaParkerShortScanImageFilter_h\n"
  },
  {
    "path": "include/rtkCudaParkerShortScanImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaParkerShortScanImageFilter_hcu\n#define rtkCudaParkerShortScanImageFilter_hcu\n\nvoid\nCUDA_parker_weight(int     proj_idx[2],\n                   int     proj_dim[3],\n                   int     proj_dim_buf_in[2],\n                   int     proj_dim_buf_out[2],\n                   float * dev_proj_in,\n                   float * dev_proj_out,\n                   float * geometry,\n                   float   delta,\n                   float   firstAngle,\n                   float   proj_orig,\n                   float   proj_row,\n                   float   proj_col);\n\n#endif // rtkCudaParkerShortScanImageFilter_hcu\n"
  },
  {
    "path": "include/rtkCudaPolynomialGainCorrectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaPolynomialGainCorrectionImageFilter_h\n#define rtkCudaPolynomialGainCorrectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkPolynomialGainCorrectionImageFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaImageToImageFilter.h>\n\n#  include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class PolynomialGainCorrectionImageFilter\n * \\brief Cuda version of PolynomialGainCorrectionImageFilter.\n *\n * Cuda version of PolynomialGainCorrectionImageFilter.\n *\n * \\see PolynomialGainCorrectionImageFilter\n *\n * \\author Sebastien Brousmiche\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT CudaPolynomialGainCorrectionImageFilter\n  : public itk::CudaImageToImageFilter<\n      itk::CudaImage<unsigned short, 3>,\n      itk::CudaImage<float, 3>,\n      PolynomialGainCorrectionImageFilter<itk::CudaImage<unsigned short, 3>, itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaPolynomialGainCorrectionImageFilter);\n\n  /** Convenience type alias **/\n  using ImageType = itk::CudaImage<float, 3>;\n  using CPUPolyGainFilterType =\n    PolynomialGainCorrectionImageFilter<itk::CudaImage<unsigned short, 3>, itk::CudaImage<float, 3>>;\n\n  /** Standard class type alias. */\n  using Self = CudaPolynomialGainCorrectionImageFilter;\n  using Superclass = itk::CudaImageToImageFilter<ImageType, ImageType, CPUPolyGainFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaPolynomialGainCorrectionImageFilter);\n\nprotected:\n  /** Standard constructor **/\n  CudaPolynomialGainCorrectionImageFilter();\n  /** Destructor **/\n  virtual ~CudaPolynomialGainCorrectionImageFilter();\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif // rtkCudaPolynomialGainCorrectionImageFilter_h\n"
  },
  {
    "path": "include/rtkCudaPolynomialGainCorrectionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaPolynomialGainCorrectionImageFilter_hcu\n#define rtkCudaPolynomialGainCorrectionImageFilter_hcu\n\nvoid\nCUDA_gain_correction(int              proj_idx_in[3],\n                     int              proj_dim_in[3],\n                     int              proj_dim_in_buf[2],\n                     int              proj_idx_out[3],\n                     int              proj_dim_out[3],\n                     int              proj_dim_out_buf[2],\n                     unsigned short * dev_proj_in,\n                     float *          dev_proj_out,\n                     unsigned short * dev_dark_in,\n                     float *          dev_gain_in,\n                     float *          h_powerlut,\n                     size_t           lut_size,\n                     float *          coefficients);\n\n#endif // rtkCudaPolynomialGainCorrectionImageFilter_hcu\n"
  },
  {
    "path": "include/rtkCudaRayCastBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaRayCastBackProjectionImageFilter_h\n#define rtkCudaRayCastBackProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkBackProjectionImageFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaInPlaceImageFilter.h>\n#  include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaRayCastBackProjectionImageFilter\n * \\brief Cuda version of the  backprojection.\n *\n * GPU-based implementation of the backprojection step of the\n * [Feldkamp, Davis, Kress, 1984] algorithm for filtered backprojection\n * reconstruction of cone-beam CT images with a circular source trajectory.\n *\n * \\test rtksarttest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Projector CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaRayCastBackProjectionImageFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       BackProjectionImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaRayCastBackProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using ImageType = itk::CudaImage<float, 3>;\n  using BackProjectionImageFilterType = BackProjectionImageFilter<ImageType, ImageType>;\n  using Self = CudaRayCastBackProjectionImageFilter;\n  using Superclass = itk::CudaInPlaceImageFilter<ImageType, ImageType, BackProjectionImageFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using OutputImageRegionType = ImageType::RegionType;\n  using ProjectionImageType = itk::CudaImage<float, 2>;\n  using ProjectionImagePointer = ProjectionImageType::Pointer;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryPointer = GeometryType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaRayCastBackProjectionImageFilter);\n\n  /** Set step size along ray (in mm). Default is 1 mm. */\n  itkGetConstMacro(StepSize, double);\n  itkSetMacro(StepSize, double);\n\n  /** Set whether the back projection should be divided by the sum of splat weights */\n  itkGetMacro(Normalize, bool);\n  itkSetMacro(Normalize, bool);\n\nprotected:\n  CudaRayCastBackProjectionImageFilter();\n  virtual ~CudaRayCastBackProjectionImageFilter() {};\n\n  virtual void\n  GPUGenerateData();\n\nprivate:\n  double m_StepSize;\n  bool   m_Normalize;\n};\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaRayCastBackProjectionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaRayCastBackProjectionImageFilter_hcu\n#define rtkCudaRayCastBackProjectionImageFilter_hcu\n\nvoid\nCUDA_ray_cast_back_project(int      projSize[3],\n                           int      volSize[3],\n                           float *  translatedProjectionIndexTransformMatrices,\n                           float *  translatedVolumeTransformMatrices,\n                           float *  dev_vol_in,\n                           float *  dev_vol_out,\n                           float *  dev_proj,\n                           float    t_step,\n                           double * source_positions,\n                           float    radiusCylindricalDetector,\n                           float    box_min[3],\n                           float    box_max[3],\n                           float    spacing[3],\n                           bool     normalize);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaScatterGlareCorrectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaScatterGlareCorrectionImageFilter_h\n#define rtkCudaScatterGlareCorrectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n\n#  include \"rtkScatterGlareCorrectionImageFilter.h\"\n#  include \"rtkCudaFFTProjectionsConvolutionImageFilter.h\"\nnamespace rtk\n{\n\n/** \\class CudaScatterGlareCorrectionImageFilter\n * \\brief Implements the scatter glare correction\n *\n * Uses CUFFT for the projection fft and ifft.\n *\n * \\test rtkscatterglarefiltertest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\nclass CudaScatterGlareCorrectionImageFilter\n  : public CudaFFTProjectionsConvolutionImageFilter<\n      ScatterGlareCorrectionImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaScatterGlareCorrectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = CudaScatterGlareCorrectionImageFilter;\n  using Superclass = ScatterGlareCorrectionImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaScatterGlareCorrectionImageFilter);\n\nprotected:\n  CudaScatterGlareCorrectionImageFilter() {}\n  ~CudaScatterGlareCorrectionImageFilter() {}\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaSplatImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaSplatImageFilter_h\n#define rtkCudaSplatImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkSplatWithKnownWeightsImageFilter.h\"\n#  include \"itkCudaImage.h\"\n#  include \"itkCudaInPlaceImageFilter.h\"\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaSplatImageFilter\n * \\brief Implements the SplatWithKnownWeightsImageFilter on GPU.\n *\n *\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaSplatImageFilter\n  : public itk::CudaInPlaceImageFilter<\n      itk::CudaImage<float, 4>,\n      itk::CudaImage<float, 4>,\n      SplatWithKnownWeightsImageFilter<itk::CudaImage<float, 4>, itk::CudaImage<float, 3>>>\n\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaSplatImageFilter);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaSplatImageFilter;\n  using Superclass = rtk::SplatWithKnownWeightsImageFilter<OutputImageType, InputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaSplatImageFilter);\n\nprotected:\n  CudaSplatImageFilter();\n  ~CudaSplatImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaSplatImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaSplatImageFilter_hcu\n#define rtkCudaSplatImageFilter_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_splat(const int4 & outputSize, float * input, float * output, int projectionNumber, float ** weights);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaTotalVariationDenoisingBPDQImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaTotalVariationDenoisingBPDQImageFilter_h\n#define rtkCudaTotalVariationDenoisingBPDQImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkTotalVariationDenoisingBPDQImageFilter.h\"\n#  include <itkCudaImageToImageFilter.h>\n#  include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class CudaTotalVariationDenoisingBPDQImageFilter\n * \\brief Implements the TotalVariationDenoisingBPDQImageFilter on GPU.\n *\n *\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\n\nclass RTK_EXPORT CudaTotalVariationDenoisingBPDQImageFilter\n  : public itk::CudaImageToImageFilter<\n      itk::CudaImage<float, 3>,\n      itk::CudaImage<float, 3>,\n      TotalVariationDenoisingBPDQImageFilter<itk::CudaImage<float, 3>,\n                                             itk::CudaImage<itk::CovariantVector<float, 3>, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaTotalVariationDenoisingBPDQImageFilter);\n\n  /** Standard class type alias. */\n  using Self = rtk::CudaTotalVariationDenoisingBPDQImageFilter;\n  using OutputImageType = itk::CudaImage<float, 3>;\n  using GradientType = itk::CudaImage<itk::CovariantVector<float, 3>, 3>;\n  using Superclass = rtk::TotalVariationDenoisingBPDQImageFilter<OutputImageType, GradientType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(CudaTotalVariationDenoisingBPDQImageFilter);\n\nprotected:\n  CudaTotalVariationDenoisingBPDQImageFilter();\n  ~CudaTotalVariationDenoisingBPDQImageFilter() {}\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaTotalVariationDenoisingBPDQImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaTotalVariationDenoisingBPDQImageFilter_hcu\n#define rtkCudaTotalVariationDenoisingBPDQImageFilter_hcu\n\n#include <vector_types.h>\n\nvoid\nCUDA_total_variation(int     size[3],\n                     float   spacing[3],\n                     float * dev_in,\n                     float * dev_out,\n                     float   gamma,\n                     float   beta,\n                     int     NumberOfIterations);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaUtilities.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaUtilities_hcu\n#define rtkCudaUtilities_hcu\n\n#include <cuda_runtime_api.h>\n#include <string>\n#include <vector>\n#define ITK_STATIC\n#include <itkMacro.h>\n#undef ITK_STATIC\n#include <cuda.h>\n\n#define CUDA_CHECK_ERROR                                                                   \\\n  {                                                                                        \\\n    cudaError_t err = cudaGetLastError();                                                  \\\n    if (cudaSuccess != err)                                                                \\\n      itkGenericExceptionMacro(<< \"CUDA ERROR: \" << cudaGetErrorString(err) << std::endl); \\\n  }\n\n#define CUFFT_CHECK_ERROR(result)                                          \\\n  {                                                                        \\\n    if (result)                                                            \\\n      itkGenericExceptionMacro(<< \"CUFFT ERROR #\" << result << std::endl); \\\n  }\n\nstd::vector<int>\nGetListOfCudaDevices();\nstd::pair<int, int>\nGetCudaComputeCapability(int device);\nsize_t\nGetFreeGPUGlobalMemory(int device);\n\ninline __host__ __device__ float3\nmatrix_multiply(float3 a, float * matrix)\n{\n  return make_float3(matrix[0] * a.x + matrix[1] * a.y + matrix[2] * a.z + matrix[3],\n                     matrix[4] * a.x + matrix[5] * a.y + matrix[6] * a.z + matrix[7],\n                     matrix[8] * a.x + matrix[9] * a.y + matrix[10] * a.z + matrix[11]);\n}\ninline __host__ __device__ float3\noperator-(float3 a, float3 b)\n{\n  return make_float3(a.x - b.x, a.y - b.y, a.z - b.z);\n}\ninline __host__ __device__ float3\nfminf(float3 a, float3 b)\n{\n  return make_float3(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z));\n}\ninline __host__ __device__ float3\nfmaxf(float3 a, float3 b)\n{\n  return make_float3(fmaxf(a.x, b.x), fmaxf(a.y, b.y), fmaxf(a.z, b.z));\n}\ninline __host__ __device__ float\ndot(float3 a, float3 b)\n{\n  return a.x * b.x + a.y * b.y + a.z * b.z;\n}\ninline __host__ __device__ float3\noperator/(float3 a, float3 b)\n{\n  return make_float3(a.x / b.x, a.y / b.y, a.z / b.z);\n}\ninline __host__ __device__ float3\noperator/(float3 a, float b)\n{\n  return make_float3(a.x / b, a.y / b, a.z / b);\n}\ninline __host__ __device__ float3\noperator*(float3 a, float3 b)\n{\n  return make_float3(a.x * b.x, a.y * b.y, a.z * b.z);\n}\ninline __host__ __device__ float3\noperator*(float b, float3 a)\n{\n  return make_float3(b * a.x, b * a.y, b * a.z);\n}\ninline __host__ __device__ float3\noperator+(float3 a, float3 b)\n{\n  return make_float3(a.x + b.x, a.y + b.y, a.z + b.z);\n}\ninline __host__ __device__ float3\noperator+(float3 a, float b)\n{\n  return make_float3(a.x + b, a.y + b, a.z + b);\n}\ninline __host__ __device__ void\noperator+=(float3 & a, float3 b)\n{\n  a.x += b.x;\n  a.y += b.y;\n  a.z += b.z;\n}\ninline __host__ __device__ int\niDivUp(int a, int b)\n{\n  return (a % b != 0) ? (a / b + 1) : (a / b);\n}\ninline __host__ __device__ float\ndot_vector(float3 u, float3 v)\n{\n  return u.x * v.x + u.y * v.y + u.z * v.z;\n}\n\n__host__ void\nprepareScalarTextureObject(int                          size[3],\n                           float *                      dev_ptr,\n                           cudaArray *&                 threeDArray,\n                           cudaTextureObject_t &        tex,\n                           const bool                   isProjections,\n                           const bool                   isLinear = true,\n                           const cudaTextureAddressMode texAddressMode = cudaAddressModeBorder);\n\n__host__ void\nprepareVectorTextureObject(int                                size[3],\n                           const float *                      dev_ptr,\n                           std::vector<cudaArray *> &         componentArrays,\n                           const unsigned int                 nComponents,\n                           std::vector<cudaTextureObject_t> & tex,\n                           const bool                         isProjections,\n                           const cudaTextureAddressMode       texAddressMode = cudaAddressModeBorder);\n\n__host__ void\nprepareGeometryTextureObject(int                   size,\n                             const float *         geometry,\n                             float *&              dev_geom,\n                             cudaTextureObject_t & tex_geom,\n                             const unsigned int    nParam);\n\ninline __device__ void\nmatrix_matrix_multiply(float * A, float * B, float * C, unsigned int rowsA, unsigned int colsB, unsigned int colsArowsB)\n{\n  unsigned int indexInA, indexInB, indexInC;\n  for (unsigned int rowA = 0; rowA < rowsA; rowA++)\n  {\n    for (unsigned int colB = 0; colB < colsB; colB++)\n    {\n      indexInC = rowA * colsB + colB;\n      C[indexInC] = 0.0f;\n      for (unsigned int colArowB = 0; colArowB < colsArowsB; colArowB++)\n      {\n        indexInA = rowA * colsArowsB + colArowB;\n        indexInB = colArowB * colsB + colB;\n        C[indexInC] += A[indexInA] * B[indexInB];\n      }\n    }\n  }\n}\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaWarpBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWarpBackProjectionImageFilter_h\n#define rtkCudaWarpBackProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkBackProjectionImageFilter.h\"\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkCudaInPlaceImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaWarpBackProjectionImageFilter\n * \\brief Voxel-based backprojection into warped volume implemented in CUDA\n *\n * GPU-based implementation of the voxel-based backprojection, assuming\n * a deformation of the volume.\n *\n * \\test rtksarttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK Projector CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaWarpBackProjectionImageFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       BackProjectionImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaWarpBackProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using ImageType = itk::CudaImage<float, 3>;\n  using DVFType = itk::CudaImage<itk::CovariantVector<float, 3>, 3>;\n  using BackProjectionImageFilterType = BackProjectionImageFilter<ImageType, ImageType>;\n  using Self = CudaWarpBackProjectionImageFilter;\n  using Superclass = itk::CudaInPlaceImageFilter<ImageType, ImageType, BackProjectionImageFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using OutputImageRegionType = ImageType::RegionType;\n  using ProjectionImageType = itk::CudaImage<float, 2>;\n  using ProjectionImagePointer = ProjectionImageType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaWarpBackProjectionImageFilter);\n\n  /** Input projection stack */\n  void\n  SetInputProjectionStack(const InputImageType * ProjectionStack);\n  InputImageType::Pointer\n  GetInputProjectionStack();\n\n  /** Input displacement vector field */\n  void\n  SetInputVolume(const InputImageType * Volume);\n  InputImageType::Pointer\n  GetInputVolume();\n\n  /** Input displacement vector field */\n  void\n  SetDisplacementField(const DVFType * MVF);\n  DVFType::Pointer\n  GetDisplacementField();\n\nprotected:\n  CudaWarpBackProjectionImageFilter();\n  ~CudaWarpBackProjectionImageFilter() {};\n\n  virtual void\n  GenerateInputRequestedRegion();\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaWarpBackProjectionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWarpBackProjectionImageFilter_hcu\n#define rtkCudaWarpBackProjectionImageFilter_hcu\n\nvoid\nCUDA_warp_back_project(int     projSize[3],\n                       int     volSize[3],\n                       int     dvf_size[3],\n                       float * matrices,\n                       float * volIndexToProjPPs,\n                       float * projPPToProjIndex,\n                       float * dev_vol_in,\n                       float * dev_vol_out,\n                       float * dev_proj,\n                       float * dev_input_dvf,\n                       float   IndexInputToIndexDVFMatrix[12],\n                       float   PPInputToIndexInputMatrix[12],\n                       float   IndexInputToPPInputMatrix[12],\n                       double  radiusCylindricalDetector);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaWarpForwardProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWarpForwardProjectionImageFilter_h\n#define rtkCudaWarpForwardProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkForwardProjectionImageFilter.h\"\n#  include \"itkCudaInPlaceImageFilter.h\"\n#  include \"itkCudaUtil.h\"\n#  include \"RTKExport.h\"\n\n/** \\class CudaWarpForwardProjectionImageFilter\n * \\brief Trilinear interpolation forward projection in warped volume implemented in CUDA\n *\n * CudaWarpForwardProjectionImageFilter is similar to\n * CudaForwardProjectionImageFilter, but assumes the object has\n * undergone a known deformation, and compensates for it during the\n * forward projection. It amounts to bending the trajectories of the rays.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK Projector CudaImageToImageFilter\n */\n\nnamespace rtk\n{\n\nclass RTK_EXPORT CudaWarpForwardProjectionImageFilter\n  : public itk::CudaInPlaceImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       ForwardProjectionImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaWarpForwardProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using InputImageType = itk::CudaImage<float, 3>;\n  using DisplacementVectorType = itk::CovariantVector<float, 3>;\n  using Self = CudaWarpForwardProjectionImageFilter;\n  using Superclass = ForwardProjectionImageFilter<InputImageType, InputImageType>;\n  using GPUSuperclass = itk::CudaInPlaceImageFilter<InputImageType, InputImageType, Superclass>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using DVFType = itk::CudaImage<DisplacementVectorType, 3>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaWarpForwardProjectionImageFilter);\n\n  /** Input projection stack */\n  void\n  SetInputProjectionStack(const InputImageType * ProjectionStack);\n  InputImageType::Pointer\n  GetInputProjectionStack();\n\n  /** Input displacement vector field */\n  void\n  SetInputVolume(const InputImageType * Volume);\n  InputImageType::Pointer\n  GetInputVolume();\n\n  /** Input displacement vector field */\n  void\n  SetDisplacementField(const DVFType * DVF);\n  DVFType::Pointer\n  GetDisplacementField();\n\n  /** Set step size along ray (in mm). Default is 1 mm. */\n  itkGetConstMacro(StepSize, double);\n  itkSetMacro(StepSize, double);\n\nprotected:\n  CudaWarpForwardProjectionImageFilter();\n  ~CudaWarpForwardProjectionImageFilter() {};\n\n  virtual void\n  GenerateInputRequestedRegion();\n\n  virtual void\n  GPUGenerateData();\n\nprivate:\n  double m_StepSize;\n}; // end of class\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaWarpForwardProjectionImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWarpForwardProjectionImageFilter_hcu\n#define rtkCudaWarpForwardProjectionImageFilter_hcu\n\nvoid\nCUDA_warp_forward_project(int     projSize[3],\n                          int     volSize[3],\n                          int     dvfSize[3],\n                          float * matrices,\n                          float * dev_proj_in,\n                          float * dev_proj_out,\n                          float * dev_vol,\n                          float   t_step,\n                          float * source_positions,\n                          float   box_min[3],\n                          float   box_max[3],\n                          float   spacing[3],\n                          float * dev_input_dvf,\n                          float   IndexInputToIndexDVFMatrix[12],\n                          float   PPInputToIndexInputMatrix[12],\n                          float   IndexInputToPPInputMatrix[12]);\n#endif\n"
  },
  {
    "path": "include/rtkCudaWarpImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWarpImageFilter_h\n#define rtkCudaWarpImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"RTKExport.h\"\n\n#  include <itkCudaImage.h>\n#  include <itkWarpImageFilter.h>\n#  include <itkCudaImageToImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class CudaWarpImageFilter\n * \\brief Cuda version of the WarpImageFilter\n *\n * Deform an image using a Displacement Vector Field. GPU-based implementation\n *\n * \\test rtkwarptest\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK CudaImageToImageFilter\n */\nclass RTK_EXPORT CudaWarpImageFilter\n  : public itk::CudaImageToImageFilter<itk::CudaImage<float, 3>,\n                                       itk::CudaImage<float, 3>,\n                                       itk::WarpImageFilter<itk::CudaImage<float, 3>,\n                                                            itk::CudaImage<float, 3>,\n                                                            itk::CudaImage<itk::CovariantVector<float, 3>, 3>>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaWarpImageFilter);\n\n  /** Standard class type alias. */\n  using ImageType = itk::CudaImage<float, 3>;\n  using DisplacementVectorType = itk::CovariantVector<float, 3>;\n  using DVFType = itk::CudaImage<DisplacementVectorType, 3>;\n  using WarpImageFilterType = itk::WarpImageFilter<ImageType, ImageType, DVFType>;\n  using Self = CudaWarpImageFilter;\n  using Superclass = itk::CudaImageToImageFilter<ImageType, ImageType, WarpImageFilterType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using OutputImageRegionType = ImageType::RegionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaWarpImageFilter);\n\nprotected:\n  CudaWarpImageFilter();\n  virtual ~CudaWarpImageFilter() {};\n\n  virtual void\n  GPUGenerateData();\n};\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaWarpImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWarpImageFilter_hcu\n#define rtkCudaWarpImageFilter_hcu\n\nvoid\nCUDA_warp(int     input_vol_dim[3],\n          int     input_dvf_dim[3],\n          int     output_vol_dim[3],\n          float   IndexOutputToPPOutputMatrix[12],\n          float   IndexOutputToIndexDVFMatrix[12],\n          float   PPInputToIndexInputMatrix[12],\n          float * dev_input_vol,\n          float * dev_output_vol,\n          float * dev_DVF,\n          bool    isLinear);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaWeidingerForwardModelImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWeidingerForwardModelImageFilter_h\n#define rtkCudaWeidingerForwardModelImageFilter_h\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkWeidingerForwardModelImageFilter.h\"\n#  include \"itkCudaImageToImageFilter.h\"\n#  include \"itkCudaUtil.h\"\n#  include \"RTKExport.h\"\n\n/** \\class CudaWeidingerForwardModelImageFilter\n * \\brief CUDA implementation of the Weidinger forward model filter\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\nnamespace rtk\n{\ntemplate <class TMaterialProjections,\n          class TPhotonCounts,\n          class TSpectrum,\n          class TProjections =\n            itk::CudaImage<typename TMaterialProjections::PixelType::ValueType, TMaterialProjections::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT CudaWeidingerForwardModelImageFilter\n  : public itk::CudaImageToImageFilter<\n      TMaterialProjections,\n      TMaterialProjections,\n      WeidingerForwardModelImageFilter<TMaterialProjections, TPhotonCounts, TSpectrum, TProjections>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CudaWeidingerForwardModelImageFilter);\n\n  /** Standard class type alias. */\n  using Self = CudaWeidingerForwardModelImageFilter;\n  using Superclass = WeidingerForwardModelImageFilter<TMaterialProjections, TPhotonCounts, TSpectrum, TProjections>;\n  using GPUSuperclass = itk::CudaImageToImageFilter<TMaterialProjections, TMaterialProjections, Superclass>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CudaWeidingerForwardModelImageFilter);\n\nprotected:\n  CudaWeidingerForwardModelImageFilter();\n  ~CudaWeidingerForwardModelImageFilter() {};\n\n  virtual void\n  GPUGenerateData();\n\n}; // end of class\n\n} // end namespace rtk\n\n#  ifndef ITK_MANUAL_INSTANTIATION\n#    include \"rtkCudaWeidingerForwardModelImageFilter.hxx\"\n#  endif\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaWeidingerForwardModelImageFilter.hcu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWeidingerForwardModelImageFilter_hcu\n#define rtkCudaWeidingerForwardModelImageFilter_hcu\n\n#include \"RTKExport.h\"\n\nvoid RTK_EXPORT\nCUDA_WeidingerForwardModel(int          projectionSize[3],\n                           float *      materialAttenuations,\n                           float *      binnedDetectorResponse,\n                           float *      pMatProj,\n                           float *      pPhoCount,\n                           float *      pSpectrum,\n                           float *      pProjOnes,\n                           float *      pOut1,\n                           float *      pOut2,\n                           unsigned int nBins,\n                           unsigned int nEnergies,\n                           unsigned int nMaterials,\n                           unsigned int nProjSpectrum,\n                           int          nIdxProj);\n\n#endif\n"
  },
  {
    "path": "include/rtkCudaWeidingerForwardModelImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCudaWeidingerForwardModelImageFilter_hxx\n#define rtkCudaWeidingerForwardModelImageFilter_hxx\n\n#include \"rtkConfiguration.h\"\n// Conditional definition of the class to pass ITKHeaderTest\n#ifdef RTK_USE_CUDA\n\n#  include \"rtkCudaWeidingerForwardModelImageFilter.h\"\n#  include \"rtkCudaUtilities.hcu\"\n#  include \"rtkCudaWeidingerForwardModelImageFilter.hcu\"\n\n#  include <itkMacro.h>\n#  include \"rtkMacro.h\"\n#  include \"itkCudaUtil.h\"\n\nnamespace rtk\n{\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nCudaWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  CudaWeidingerForwardModelImageFilter()\n{}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nCudaWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GPUGenerateData()\n{\n  this->AllocateOutputs();\n\n  const unsigned int Dimension = TDecomposedProjections::ImageDimension;\n  unsigned int       nEnergies = this->m_MaterialAttenuations.rows();\n\n  // Get the size of the input projections in a Cuda-convenient format\n  int projectionSize[Dimension];\n  for (unsigned int d = 0; d < Dimension; d++)\n    projectionSize[d] = this->GetInputDecomposedProjections()->GetBufferedRegion().GetSize()[d];\n\n  // Pointers to inputs and outputs\n#  ifdef CudaCommon_VERSION_MAJOR\n  float * pMatProj = (float *)(this->GetInputDecomposedProjections()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pPhoCount = (float *)(this->GetInputMeasuredProjections()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pSpectrum = (float *)(this->GetInputIncidentSpectrum()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pProjOnes = (float *)(this->GetInputProjectionsOfOnes()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pOut1 = (float *)(this->GetOutput1()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pOut2 = (float *)(this->GetOutput2()->GetCudaDataManager()->GetGPUBufferPointer());\n#  else\n  float * pMatProj = *(float **)(this->GetInputDecomposedProjections()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pPhoCount = *(float **)(this->GetInputMeasuredProjections()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pSpectrum = *(float **)(this->GetInputIncidentSpectrum()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pProjOnes = *(float **)(this->GetInputProjectionsOfOnes()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pOut1 = *(float **)(this->GetOutput1()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pOut2 = *(float **)(this->GetOutput2()->GetCudaDataManager()->GetGPUBufferPointer());\n#  endif\n\n  // Run the forward projection with a slab of SLAB_SIZE or less projections\n  CUDA_WeidingerForwardModel(projectionSize,\n                             this->m_MaterialAttenuations.data_block(),\n                             this->m_BinnedDetectorResponse.data_block(),\n                             pMatProj,\n                             pPhoCount,\n                             pSpectrum,\n                             pProjOnes,\n                             pOut1,\n                             pOut2,\n                             CudaWeidingerForwardModelImageFilter<TDecomposedProjections,\n                                                                  TMeasuredProjections,\n                                                                  TIncidentSpectrum,\n                                                                  TProjections>::nBins,\n                             nEnergies,\n                             CudaWeidingerForwardModelImageFilter<TDecomposedProjections,\n                                                                  TMeasuredProjections,\n                                                                  TIncidentSpectrum,\n                                                                  TProjections>::nMaterials,\n                             this->m_NumberOfProjectionsInIncidentSpectrum,\n                             this->GetInputMeasuredProjections()->GetBufferedRegion().GetIndex(Dimension - 1));\n}\n\n} // end namespace rtk\n\n#endif // end conditional definition of the class\n\n#endif\n"
  },
  {
    "path": "include/rtkCyclicDeformationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCyclicDeformationImageFilter_h\n#define rtkCyclicDeformationImageFilter_h\n\n#include <itkImageToImageFilter.h>\n\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class CyclicDeformationImageFilter\n * \\brief Return 3D deformation vector field according to input 4D vector field,\n * phase signal and frame number.\n *\n * The 4D deformation vector field (DVF) describes the deformation along one cycle.\n * The phase signal is passed via a file name pointing to a text file with one\n * value per line. It must be in the inteval [0,1), 0 meaning frame 0 of the 4D\n * DVF, 0.5 the middle frame (if the number of frames of the 4D DVF is odd), etc.\n * The frame number is the value of the signal for which we wish to obtain the\n * resulting 3D DVF. Linear interpolation is used to compute that DVF.\n * This cyclic deformation model has been described in [Rit et al, TMI, 2009] and\n * [Rit et al, Med Phys, 2009].\n *\n * \\test rtkmotioncompensatedfdktest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT CyclicDeformationImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(CyclicDeformationImageFilter);\n\n  /** Standard class type alias. */\n  using Self = CyclicDeformationImageFilter;\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using Superclass = itk::ImageToImageFilter<InputImageType, OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(CyclicDeformationImageFilter);\n\n  /** Get / Set the signal file name relating each frame to a phase position.\n      The signal file is a text file containing one line per frame. */\n  itkGetMacro(SignalFilename, std::string);\n  virtual void\n  SetSignalFilename(const std::string _arg);\n  virtual void\n  SetSignalVector(std::vector<double> _arg);\n\n  /** Get / Set the frame number. The number is used to lookup in the signal file\n   * which phase value should be used to interpolate. */\n  itkGetMacro(Frame, unsigned int);\n  itkSetMacro(Frame, unsigned int);\n\nprotected:\n  CyclicDeformationImageFilter() = default;\n  ~CyclicDeformationImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  BeforeThreadedGenerateData() override;\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  // Linear interpolation position and weights\n  unsigned int m_FrameInf;\n  unsigned int m_FrameSup;\n  double       m_WeightInf;\n  double       m_WeightSup;\n\nprivate:\n  unsigned int m_Frame{ 0 };\n\n  std::string         m_SignalFilename;\n  std::vector<double> m_Signal;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkCyclicDeformationImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkCyclicDeformationImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkCyclicDeformationImageFilter_hxx\n#define rtkCyclicDeformationImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n#include <fstream>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nCyclicDeformationImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  typename OutputImageType::PointType   origin;\n  typename OutputImageType::SpacingType spacing;\n  OutputImageRegionType                 region;\n  for (unsigned int i = 0; i < OutputImageType::ImageDimension; i++)\n  {\n    origin[i] = this->GetInput()->GetOrigin()[i];\n    spacing[i] = this->GetInput()->GetSpacing()[i];\n    region.SetIndex(i, this->GetInput()->GetLargestPossibleRegion().GetIndex(i));\n    region.SetSize(i, this->GetInput()->GetLargestPossibleRegion().GetSize(i));\n  }\n  this->GetOutput()->SetOrigin(origin);\n  this->GetOutput()->SetSpacing(spacing);\n  this->GetOutput()->SetLargestPossibleRegion(region);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nCyclicDeformationImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  typename InputImageType::Pointer inputPtr = const_cast<InputImageType *>(this->GetInput());\n  if (!inputPtr)\n    return;\n  inputPtr->SetRequestedRegion(inputPtr->GetLargestPossibleRegion());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nCyclicDeformationImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  unsigned int nframe = this->GetInput()->GetLargestPossibleRegion().GetSize(OutputImageType::ImageDimension);\n  if (this->GetFrame() > m_Signal.size())\n    itkGenericExceptionMacro(<< \"Frame number #\" << this->GetFrame() << \" is larger than phase signal which has size \"\n                             << m_SignalFilename);\n\n  double sigValue = m_Signal[this->GetFrame()];\n  if (sigValue < 0. || sigValue >= 1.)\n    itkGenericExceptionMacro(<< \"Signal value #\" << this->GetFrame() << \" is \" << sigValue << \" which is not in [0,1)\");\n\n  sigValue *= nframe;\n  m_FrameInf = itk::Math::Floor<unsigned int, double>(sigValue);\n  m_FrameSup = itk::Math::Floor<unsigned int, double>(sigValue + 1.);\n  m_WeightInf = m_FrameSup - sigValue;\n  m_WeightSup = sigValue - m_FrameInf;\n  m_FrameInf = m_FrameInf % nframe;\n  m_FrameSup = m_FrameSup % nframe;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nCyclicDeformationImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Prepare inferior input iterator\n  typename InputImageType::RegionType inputRegionForThreadInf;\n  inputRegionForThreadInf = this->GetInput()->GetLargestPossibleRegion();\n  for (unsigned int i = 0; i < OutputImageType::ImageDimension; i++)\n  {\n    inputRegionForThreadInf.SetIndex(i, outputRegionForThread.GetIndex(i));\n    inputRegionForThreadInf.SetSize(i, outputRegionForThread.GetSize(i));\n  }\n  inputRegionForThreadInf.SetSize(OutputImageType::ImageDimension, 1);\n  inputRegionForThreadInf.SetIndex(OutputImageType::ImageDimension, m_FrameInf);\n  typename itk::ImageRegionConstIterator<InputImageType> itInf(this->GetInput(), inputRegionForThreadInf);\n\n  // Prepare superior input iterator\n  typename InputImageType::RegionType inputRegionForThreadSup = inputRegionForThreadInf;\n  inputRegionForThreadSup.SetIndex(OutputImageType::ImageDimension, m_FrameSup);\n  typename itk::ImageRegionConstIterator<InputImageType> itSup(this->GetInput(), inputRegionForThreadSup);\n\n  // Output iterator\n  itk::ImageRegionIterator<OutputImageType> itOut(this->GetOutput(), outputRegionForThread);\n  while (!itOut.IsAtEnd())\n  {\n    itOut.Set(itInf.Get() * m_WeightInf + itSup.Get() * m_WeightSup);\n    ++itOut;\n    ++itInf;\n    ++itSup;\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nCyclicDeformationImageFilter<TInputImage, TOutputImage>::SetSignalFilename(const std::string _arg)\n{\n  itkDebugMacro(\"setting SignalFilename to \" << _arg);\n  if (this->m_SignalFilename != _arg)\n  {\n    this->m_SignalFilename = _arg;\n    this->Modified();\n\n    std::ifstream is(_arg.c_str());\n    if (!is.is_open())\n    {\n      itkGenericExceptionMacro(<< \"Could not open signal file \" << m_SignalFilename);\n    }\n\n    double value = NAN;\n    while (!is.eof())\n    {\n      is >> value;\n      m_Signal.push_back(value);\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nCyclicDeformationImageFilter<TInputImage, TOutputImage>::SetSignalVector(std::vector<double> _arg)\n{\n  if (m_Signal != _arg)\n  {\n    m_Signal = _arg;\n    this->Modified();\n  }\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDCMImagXImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDCMImagXImageIO_h\n#define rtkDCMImagXImageIO_h\n\n#include <itkGDCMImageIO.h>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class DCMImagXImageIO\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT DCMImagXImageIO : public itk::GDCMImageIO\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DCMImagXImageIO);\n\n  /** Standard class type alias. */\n  using Self = DCMImagXImageIO;\n  using Superclass = itk::GDCMImageIO;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DCMImagXImageIO);\n\n  void\n  ReadImageInformation() override;\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n  bool\n  CanWriteFile(const char * filename) override;\n\nprotected:\n  DCMImagXImageIO() = default;\n  ~DCMImagXImageIO() override = default;\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDCMImagXImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDCMImagXImageIOFactory_h\n#define rtkDCMImagXImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkDCMImagXImageIO.h\"\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class DCMImagXImageIOFactory\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT DCMImagXImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DCMImagXImageIOFactory);\n\n  /** Standard class type alias. */\n  using Self = DCMImagXImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"ImagX ImageIO Factory, allows the loading of ImagX images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DCMImagXImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\nprotected:\n  DCMImagXImageIOFactory();\n  ~DCMImagXImageIOFactory() override = default;\n  using myProductType = DCMImagXImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDPExtractShroudSignalImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDPExtractShroudSignalImageFilter_h\n#define rtkDPExtractShroudSignalImageFilter_h\n\n#include <itkImageToImageFilter.h>\n\nnamespace rtk\n{\n/** \\class DPExtractShroudSignalImageFilter\n * \\brief Extract the signal corresponding to the breathing motion\n * (1D) from a shroud image (2D).\n *\n * \\test rtkamsterdamshroudtest.cxx\n *\n * \\author Vivien Delmon\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputPixel, class TOutputPixel>\nclass ITK_TEMPLATE_EXPORT DPExtractShroudSignalImageFilter\n  : public itk::ImageToImageFilter<itk::Image<TInputPixel, 2>, itk::Image<TOutputPixel, 1>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DPExtractShroudSignalImageFilter);\n\n  /** Standard class type alias. */\n  using TInputImage = itk::Image<TInputPixel, 2>;\n  using TOutputImage = itk::Image<TOutputPixel, 1>;\n  using Self = DPExtractShroudSignalImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n  static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension;\n  static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(DPExtractShroudSignalImageFilter);\n\n  /** Set/Get exploration amplitude. */\n  itkGetMacro(Amplitude, double);\n  itkSetMacro(Amplitude, double);\n\nprotected:\n  DPExtractShroudSignalImageFilter();\n  ~DPExtractShroudSignalImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateData() override;\n\nprivate:\n  double m_Amplitude{ 0. };\n\n}; // end of class\n\n} // end of namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDPExtractShroudSignalImageFilter.hxx\"\n#endif\n\n#endif // ! rtkDPExtractShroudSignalImageFilter_h\n"
  },
  {
    "path": "include/rtkDPExtractShroudSignalImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDPExtractShroudSignalImageFilter_hxx\n#define rtkDPExtractShroudSignalImageFilter_hxx\n\n\n#include <itkArray.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputPixel, class TOutputPixel>\nDPExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::DPExtractShroudSignalImageFilter() = default;\n\ntemplate <class TInputPixel, class TOutputPixel>\nvoid\nDPExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput());\n  if (!inputPtr)\n  {\n    return;\n  }\n  inputPtr->SetRequestedRegion(inputPtr->GetLargestPossibleRegion());\n}\n\ntemplate <class TInputPixel, class TOutputPixel>\nvoid\nDPExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::GenerateOutputInformation()\n{\n  // get pointers to the input and output\n  typename Superclass::InputImageConstPointer inputPtr = this->GetInput();\n  typename Superclass::OutputImagePointer     outputPtr = this->GetOutput();\n\n  if (!outputPtr || !inputPtr)\n  {\n    return;\n  }\n  typename TOutputImage::RegionType            outRegion;\n  typename TOutputImage::RegionType::SizeType  outSize;\n  typename TOutputImage::RegionType::IndexType outIdx;\n  outSize[0] = this->GetInput()->GetLargestPossibleRegion().GetSize()[1];\n  outIdx[0] = this->GetInput()->GetLargestPossibleRegion().GetIndex()[1];\n  outRegion.SetSize(outSize);\n  outRegion.SetIndex(outIdx);\n\n  const typename TInputImage::SpacingType & inputSpacing = inputPtr->GetSpacing();\n  typename TOutputImage::SpacingType        outputSpacing;\n  outputSpacing[0] = inputSpacing[1];\n  outputPtr->SetSpacing(outputSpacing);\n\n  typename TOutputImage::DirectionType outputDirection;\n  outputDirection[0][0] = 1;\n  outputPtr->SetDirection(outputDirection);\n\n  const typename TInputImage::PointType & inputOrigin = inputPtr->GetOrigin();\n  typename TOutputImage::PointType        outputOrigin;\n  outputOrigin[0] = inputOrigin[1];\n  outputPtr->SetOrigin(outputOrigin);\n\n  outputPtr->SetLargestPossibleRegion(outRegion);\n}\n\ntemplate <class TInputPixel, class TOutputPixel>\nvoid\nDPExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::GenerateData()\n{\n  this->AllocateOutputs();\n\n  typename TInputImage::ConstPointer          input = this->GetInput();\n  typename TInputImage::RegionType::IndexType inputIdx = input->GetLargestPossibleRegion().GetIndex();\n  typename TInputImage::RegionType::SizeType  inputSize = input->GetLargestPossibleRegion().GetSize();\n\n  auto from = itk::Image<int, InputImageDimension>::New();\n  from->CopyInformation(input);\n  from->SetRegions(input->GetLargestPossibleRegion());\n  from->Allocate();\n  int amplitudeInVoxel = m_Amplitude / input->GetSpacing()[0];\n\n  auto * prev = new itk::Array<double>(inputSize[0]);\n  auto * curr = new itk::Array<double>(inputSize[0]);\n\n  typename TInputImage::RegionType::IndexType idx = inputIdx;\n  for (unsigned i = 0; i < inputSize[0]; ++i)\n  {\n    (*prev)[i] = (*input)[idx];\n    idx[0]++;\n  }\n\n  for (unsigned i = 1; i < inputSize[1]; ++i)\n  {\n    (*curr).Fill(0.0);\n    idx[0] = inputIdx[0];\n    for (unsigned j = 0; j < inputSize[0]; ++j)\n    {\n      for (int r = -amplitudeInVoxel; r <= amplitudeInVoxel; ++r)\n      {\n        typename TInputImage::RegionType::IndexType idx_to = idx;\n        idx_to[0] += r;\n        idx_to[1]++;\n        if (input->GetLargestPossibleRegion().IsInside(idx_to) && (*input)[idx_to] + (*prev)[j] > (*curr)[j + r])\n        {\n          (*curr)[j + r] = (*input)[idx_to] + (*prev)[j];\n          (*from)[idx_to] = -r;\n        }\n      }\n      idx[0]++;\n    }\n    idx[1]++;\n    std::swap(prev, curr);\n  }\n\n  unsigned max = 0;\n  for (unsigned j = 1; j < inputSize[0]; ++j)\n    if ((*prev)[j] > (*prev)[max])\n      max = j;\n\n  idx[0] = inputIdx[0] + max;\n\n  typename Superclass::OutputImagePointer output = this->GetOutput();\n  output->Allocate();\n  typename TOutputImage::RegionType::IndexType outputIdx;\n  TOutputPixel                                 value = 0;\n  outputIdx[0] = idx[1];\n  (*output)[outputIdx] = value;\n  while (idx[1] != inputIdx[1])\n  {\n    outputIdx[0]--;\n    value -= (*from)[idx] * input->GetSpacing()[0];\n    (*output)[outputIdx] = value;\n    idx[0] += (*from)[idx];\n    idx[1]--;\n  }\n  delete prev;\n  delete curr;\n}\n\n} // end of namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkDaubechiesWaveletsConvolutionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDaubechiesWaveletsConvolutionImageFilter_h\n#define rtkDaubechiesWaveletsConvolutionImageFilter_h\n\n// Includes\n#include <itkImageToImageFilter.h>\n#include <itkConvolutionImageFilter.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/**\n * \\class DaubechiesWaveletsConvolutionImageFilter\n * \\brief Creates a Daubechies wavelets kernel image with the requested\n * attributes (order, type, pass along each dimension)\n *\n * This filter is inspired from Dan Mueller's GIFT package\n * https://www.insight-journal.org/browse/publication/103\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT DaubechiesWaveletsConvolutionImageFilter : public itk::ImageToImageFilter<TImage, TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DaubechiesWaveletsConvolutionImageFilter);\n\n  enum Pass\n  {\n    Low = 0x0, // Indicates to return the low-pass filter coefficients\n    High = 0x1 // Indicates to return the high-pass filter coefficients\n  };\n\n  enum Type\n  {\n    Deconstruct = 0x0, // Indicates to deconstruct the image into levels/bands\n    Reconstruct = 0x1  // Indicates to reconstruct the image from levels/bands\n  };\n\n\n  /** Standard class type alias. */\n  using Self = DaubechiesWaveletsConvolutionImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImage, TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Typedef for the output image type. */\n  using OutputImageType = TImage;\n\n  /** Typedef for the output image PixelType. */\n  using OutputImagePixelType = typename TImage::PixelType;\n\n  /** Typedef to describe the output image region type. */\n  using OutputImageRegionType = typename TImage::RegionType;\n\n  /** Typedef for the \"pass\" vector (high pass or low pass along each dimension). */\n  using PassVector = typename itk::Vector<typename Self::Pass, TImage::ImageDimension>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DaubechiesWaveletsConvolutionImageFilter);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Typedef for the internal convolution filter */\n  using ConvolutionFilterType = typename itk::ConvolutionImageFilter<TImage>;\n\n  /** Sets the filter to return coefficients for low pass, deconstruct. */\n  void\n  SetDeconstruction();\n\n  /** Sets the filter to return coefficients for low pass, reconstruct. */\n  void\n  SetReconstruction();\n\n  /** Prints some debugging information. */\n  void\n  PrintSelf(std::ostream & os, itk::Indent i) const override;\n\n  /** Set and Get macro for the wavelet order */\n  itkSetMacro(Order, unsigned int);\n  itkGetConstMacro(Order, unsigned int);\n\n  /** Set and Get macro for the pass vector */\n  itkSetMacro(Pass, PassVector);\n  itkGetMacro(Pass, PassVector);\n\nprotected:\n  DaubechiesWaveletsConvolutionImageFilter();\n  ~DaubechiesWaveletsConvolutionImageFilter() override;\n\n  using CoefficientVector = std::vector<typename TImage::PixelType>;\n\n  /** Calculates CoefficientsVector coefficients. */\n  CoefficientVector\n  GenerateCoefficients();\n\n  /** Does the real work */\n  void\n  GenerateData() override;\n\n  /** Defines the size, spacing, ... of the output kernel image */\n  void\n  GenerateOutputInformation() override;\n\nprivate:\n  /** Returns the wavelet coefficients for each type*/\n  CoefficientVector\n  GenerateCoefficientsLowpassDeconstruct();\n  CoefficientVector\n  GenerateCoefficientsHighpassDeconstruct();\n  CoefficientVector\n  GenerateCoefficientsLowpassReconstruct();\n  CoefficientVector\n  GenerateCoefficientsHighpassReconstruct();\n\n  /** Specifies the wavelet type name */\n  unsigned int m_Order{ 3 };\n\n  /** Specifies the filter pass along each dimension */\n  PassVector m_Pass{ PassVector(typename PassVector::ComponentType(0)) };\n\n  /** Specifies the filter type */\n  Type m_Type;\n};\n\n} // namespace rtk\n\n// Include CXX\n#ifndef rtk_MANUAL_INSTANTIATION\n#  include \"rtkDaubechiesWaveletsConvolutionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDaubechiesWaveletsConvolutionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDaubechiesWaveletsConvolutionImageFilter_hxx\n#define rtkDaubechiesWaveletsConvolutionImageFilter_hxx\n\n// Includes\n\n#include <vector>\n#include <algorithm>\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\n\ntemplate <typename TImage>\nDaubechiesWaveletsConvolutionImageFilter<TImage>::DaubechiesWaveletsConvolutionImageFilter()\n{\n  this->SetDeconstruction();\n}\n\ntemplate <typename TImage>\nDaubechiesWaveletsConvolutionImageFilter<TImage>::~DaubechiesWaveletsConvolutionImageFilter() = default;\n\ntemplate <typename TImage>\nvoid\nDaubechiesWaveletsConvolutionImageFilter<TImage>::SetDeconstruction()\n{\n  m_Type = Self::Deconstruct;\n}\n\ntemplate <typename TImage>\nvoid\nDaubechiesWaveletsConvolutionImageFilter<TImage>::SetReconstruction()\n{\n  m_Type = Self::Reconstruct;\n}\n\ntemplate <typename TImage>\nvoid\nDaubechiesWaveletsConvolutionImageFilter<TImage>::PrintSelf(std::ostream & os, itk::Indent i) const\n{\n  os << i << \"DaubechiesWaveletsConvolutionImageFilter { this=\" << this << \" }\" << std::endl;\n\n  os << i << \"m_Order=\" << this->GetOrder() << std::endl;\n  os << i << \"m_Pass=\" << std::endl;\n  for (unsigned int dim = 0; dim < TImage::ImageDimension; dim++)\n  {\n    os << i << i << this->m_Pass[dim] << std::endl;\n  }\n  os << i << \"m_Type=\" << this->m_Type << std::endl;\n\n  Superclass::PrintSelf(os, i.GetNextIndent());\n}\n\ntemplate <typename TImage>\ntypename DaubechiesWaveletsConvolutionImageFilter<TImage>::CoefficientVector\nDaubechiesWaveletsConvolutionImageFilter<TImage>::GenerateCoefficientsLowpassDeconstruct()\n{\n  CoefficientVector coeff;\n  switch (this->GetOrder())\n  {\n    case 1:\n      coeff.push_back(1.0 / itk::Math::sqrt2);\n      coeff.push_back(1.0 / itk::Math::sqrt2);\n      break;\n    case 2:\n      coeff.push_back(-0.1830127 / itk::Math::sqrt2);\n      coeff.push_back(0.3169873 / itk::Math::sqrt2);\n      coeff.push_back(1.1830127 / itk::Math::sqrt2);\n      coeff.push_back(0.6830127 / itk::Math::sqrt2);\n      break;\n    case 3:\n      coeff.push_back(0.0498175 / itk::Math::sqrt2);\n      coeff.push_back(-0.12083221 / itk::Math::sqrt2);\n      coeff.push_back(-0.19093442 / itk::Math::sqrt2);\n      coeff.push_back(0.650365 / itk::Math::sqrt2);\n      coeff.push_back(1.14111692 / itk::Math::sqrt2);\n      coeff.push_back(0.47046721 / itk::Math::sqrt2);\n      break;\n    case 4:\n      coeff.push_back(-0.01498699 / itk::Math::sqrt2);\n      coeff.push_back(0.0465036 / itk::Math::sqrt2);\n      coeff.push_back(0.0436163 / itk::Math::sqrt2);\n      coeff.push_back(-0.26450717 / itk::Math::sqrt2);\n      coeff.push_back(-0.03957503 / itk::Math::sqrt2);\n      coeff.push_back(0.8922014 / itk::Math::sqrt2);\n      coeff.push_back(1.01094572 / itk::Math::sqrt2);\n      coeff.push_back(0.32580343 / itk::Math::sqrt2);\n      break;\n    case 5:\n      coeff.push_back(0.00471742793 / itk::Math::sqrt2);\n      coeff.push_back(-0.01779187 / itk::Math::sqrt2);\n      coeff.push_back(-0.00882680 / itk::Math::sqrt2);\n      coeff.push_back(0.10970265 / itk::Math::sqrt2);\n      coeff.push_back(-0.04560113 / itk::Math::sqrt2);\n      coeff.push_back(-0.34265671 / itk::Math::sqrt2);\n      coeff.push_back(0.19576696 / itk::Math::sqrt2);\n      coeff.push_back(1.02432694 / itk::Math::sqrt2);\n      coeff.push_back(0.85394354 / itk::Math::sqrt2);\n      coeff.push_back(0.22641898 / itk::Math::sqrt2);\n      break;\n    case 6:\n      coeff.push_back(-0.00152353381 / itk::Math::sqrt2);\n      coeff.push_back(0.00675606236 / itk::Math::sqrt2);\n      coeff.push_back(0.000783251152 / itk::Math::sqrt2);\n      coeff.push_back(-0.04466375 / itk::Math::sqrt2);\n      coeff.push_back(0.03892321 / itk::Math::sqrt2);\n      coeff.push_back(0.13788809 / itk::Math::sqrt2);\n      coeff.push_back(-0.18351806 / itk::Math::sqrt2);\n      coeff.push_back(-0.31998660 / itk::Math::sqrt2);\n      coeff.push_back(0.44583132 / itk::Math::sqrt2);\n      coeff.push_back(1.06226376 / itk::Math::sqrt2);\n      coeff.push_back(0.69950381 / itk::Math::sqrt2);\n      coeff.push_back(0.15774243 / itk::Math::sqrt2);\n      break;\n    case 7:\n      coeff.push_back(0.000500226853 / itk::Math::sqrt2);\n      coeff.push_back(-0.00254790472 / itk::Math::sqrt2);\n      coeff.push_back(0.000607514995 / itk::Math::sqrt2);\n      coeff.push_back(0.01774979 / itk::Math::sqrt2);\n      coeff.push_back(-0.02343994 / itk::Math::sqrt2);\n      coeff.push_back(-0.05378245 / itk::Math::sqrt2);\n      coeff.push_back(0.11400345 / itk::Math::sqrt2);\n      coeff.push_back(0.1008467 / itk::Math::sqrt2);\n      coeff.push_back(-0.31683501 / itk::Math::sqrt2);\n      coeff.push_back(-0.20351382 / itk::Math::sqrt2);\n      coeff.push_back(0.66437248 / itk::Math::sqrt2);\n      coeff.push_back(1.03114849 / itk::Math::sqrt2);\n      coeff.push_back(0.56079128 / itk::Math::sqrt2);\n      coeff.push_back(0.11009943 / itk::Math::sqrt2);\n      break;\n    default:\n      itkGenericExceptionMacro(<< \"In rtkDaubechiesWaveletsConvolutionImageFilter.hxx: Order should be <= 7.\");\n  } // end case(Order)\n  return coeff;\n}\n\ntemplate <typename TImage>\ntypename DaubechiesWaveletsConvolutionImageFilter<TImage>::CoefficientVector\nDaubechiesWaveletsConvolutionImageFilter<TImage>::GenerateCoefficientsHighpassDeconstruct()\n{\n  CoefficientVector coeff = this->GenerateCoefficientsLowpassDeconstruct();\n  std::reverse(coeff.begin(), coeff.end());\n  unsigned int it = 0;\n\n  double factor = -1;\n  for (it = 0; it < coeff.size(); it++)\n  {\n    coeff[it] *= factor;\n    factor *= -1;\n  }\n  return coeff;\n}\n\ntemplate <typename TImage>\ntypename DaubechiesWaveletsConvolutionImageFilter<TImage>::CoefficientVector\nDaubechiesWaveletsConvolutionImageFilter<TImage>::GenerateCoefficientsLowpassReconstruct()\n{\n  CoefficientVector coeff = this->GenerateCoefficientsLowpassDeconstruct();\n  std::reverse(coeff.begin(), coeff.end());\n  return coeff;\n}\n\ntemplate <typename TImage>\ntypename DaubechiesWaveletsConvolutionImageFilter<TImage>::CoefficientVector\nDaubechiesWaveletsConvolutionImageFilter<TImage>::GenerateCoefficientsHighpassReconstruct()\n{\n  CoefficientVector coeff = this->GenerateCoefficientsHighpassDeconstruct();\n  std::reverse(coeff.begin(), coeff.end());\n  return coeff;\n}\n\ntemplate <typename TImage>\nvoid\nDaubechiesWaveletsConvolutionImageFilter<TImage>::GenerateOutputInformation()\n{\n  unsigned int                                         dim = TImage::ImageDimension;\n  std::vector<typename TImage::Pointer>                kernelImages;\n  std::vector<typename ConvolutionFilterType::Pointer> convolutionFilters;\n\n  // Create and connect as many Convolution filters as the number of dimensions\n  for (unsigned int d = 0; d < dim; d++)\n  {\n    // Create the 1-D kernel image\n    typename TImage::SizeType kernelSize;\n    kernelSize.Fill(1);\n    kernelSize[d] = 2 * m_Order;\n\n    typename TImage::IndexType kernelIndex;\n    kernelIndex.Fill(0);\n\n    typename TImage::RegionType kernelRegion;\n    kernelRegion.SetSize(kernelSize);\n    kernelRegion.SetIndex(kernelIndex);\n\n    kernelImages.push_back(TImage::New());\n    kernelImages[d]->SetRegions(kernelRegion);\n\n    // Create the convolution filters\n    convolutionFilters.push_back(ConvolutionFilterType::New());\n    convolutionFilters[d]->SetKernelImage(kernelImages[d]);\n    convolutionFilters[d]->SetOutputRegionModeToValid();\n\n    if (d == 0)\n      convolutionFilters[d]->SetInput(this->GetInput());\n    else\n      convolutionFilters[d]->SetInput(convolutionFilters[d - 1]->GetOutput());\n  }\n\n  // Generate output information\n  convolutionFilters[dim - 1]->UpdateOutputInformation();\n\n  // Copy it to the output\n  this->GetOutput()->CopyInformation(convolutionFilters[dim - 1]->GetOutput());\n}\n\ntemplate <typename TImage>\nvoid\nDaubechiesWaveletsConvolutionImageFilter<TImage>::GenerateData()\n{\n  int dim = TImage::ImageDimension;\n\n  // Create a vector holding the coefficients along each direction\n  auto * coeffs = new CoefficientVector[dim];\n  for (int d = 0; d < dim; d++)\n  {\n    if (m_Type == Self::Deconstruct)\n    {\n      switch (m_Pass[d])\n      {\n        case Self::Low:\n          coeffs[d] = GenerateCoefficientsLowpassDeconstruct();\n          break;\n        case Self::High:\n          coeffs[d] = GenerateCoefficientsHighpassDeconstruct();\n          break;\n        default:\n          itkGenericExceptionMacro(\"In rtkDaubechiesWaveletsConvolutionImageFilter : unknown pass\");\n      }\n    }\n    if (m_Type == Self::Reconstruct)\n    {\n      switch (m_Pass[d])\n      {\n        case Self::Low:\n          coeffs[d] = GenerateCoefficientsLowpassReconstruct();\n          break;\n        case Self::High:\n          coeffs[d] = GenerateCoefficientsHighpassReconstruct();\n          break;\n        default:\n          itkGenericExceptionMacro(\"In rtkDaubechiesWaveletsConvolutionImageFilter : unknown pass\");\n      }\n    }\n  }\n\n  std::vector<typename TImage::Pointer>                kernelImages;\n  std::vector<typename ConvolutionFilterType::Pointer> convolutionFilters;\n\n  // Convolve the input \"Dimension\" times, each time with a 1-D kernel\n  for (int d = 0; d < dim; d++)\n  {\n    // Create the 1-D kernel image\n    typename TImage::SizeType kernelSize;\n    kernelSize.Fill(1);\n    kernelSize[d] = 2 * m_Order;\n\n    typename TImage::IndexType kernelIndex;\n    kernelIndex.Fill(0);\n\n    typename TImage::RegionType kernelRegion;\n    kernelRegion.SetSize(kernelSize);\n    kernelRegion.SetIndex(kernelIndex);\n\n    kernelImages.push_back(TImage::New());\n    kernelImages[d]->SetRegions(kernelRegion);\n    kernelImages[d]->Allocate();\n    itk::ImageRegionIterator<TImage> kernelIt(kernelImages[d], kernelImages[d]->GetLargestPossibleRegion());\n\n    int pos = 0;\n    while (!kernelIt.IsAtEnd())\n    {\n      kernelIt.Set(coeffs[d][pos]);\n      pos++;\n      ++kernelIt;\n    }\n\n    // Create the convolution filters\n    convolutionFilters.push_back(ConvolutionFilterType::New());\n    convolutionFilters[d]->SetKernelImage(kernelImages[d]);\n    convolutionFilters[d]->SetOutputRegionModeToValid();\n\n    if (d == 0)\n      convolutionFilters[d]->SetInput(this->GetInput());\n    else\n      convolutionFilters[d]->SetInput(convolutionFilters[d - 1]->GetOutput());\n  }\n\n  // Generate output information\n  convolutionFilters[dim - 1]->Update();\n\n  this->GraftOutput(convolutionFilters[dim - 1]->GetOutput());\n\n  // Clean up\n  delete[] coeffs;\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDaubechiesWaveletsDenoiseSequenceImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDaubechiesWaveletsDenoiseSequenceImageFilter_h\n#define rtkDaubechiesWaveletsDenoiseSequenceImageFilter_h\n\n#include \"rtkConstantImageSource.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkPasteImageFilter.h>\n#include <itkCastImageFilter.h>\n#include \"rtkDeconstructSoftThresholdReconstructImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class DaubechiesWaveletsDenoiseSequenceImageFilter\n * \\brief Applies 3D Daubechies wavelets denoising to a 3D + time sequence of images\n *\n * Most of the work in this filter is performed by the underlying\n * rtkDeconstructSoftThresholdReconstructImageFilter\n *\n * \\dot\n * digraph DaubechiesWaveletsDenoiseSequenceImageFilter {\n *\n * Input0 [ label=\"Input 0 (Sequence of images)\"];\n * Input0 [shape=Mdiamond];\n * Output [label=\"Output (Sequence of images)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * Extract [label=\"itk::ExtractImageFilter (for images)\" URL=\"\\ref itk::ExtractImageFilter\"];\n * WaveletsDenoising [ label=\"rtk::DeconstructSoftThresholdReconstructImageFilter\"\n *                     URL=\"\\ref rtk::DeconstructSoftThresholdReconstructImageFilter\"];\n * Cast [ label=\"itk::CastImageFilter\" URL=\"\\ref itk::CastImageFilter\"];\n * Paste [ label=\"itk::PasteImageFilter\" URL=\"\\ref itk::PasteImageFilter\"];\n * ConstantSource [ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * BeforePaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterPaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * Input0 -> Extract;\n * Extract -> WaveletsDenoising;\n * WaveletsDenoising -> Cast;\n * Cast -> BeforePaste [arrowhead=none];\n * BeforePaste -> Paste;\n * Paste -> AfterPaste [arrowhead=none];\n * AfterPaste -> BeforePaste [style=dashed];\n * AfterPaste -> Output [style=dashed];\n * }\n * \\enddot\n *\n * \\test rtkfourdroostertest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TImageSequence>\nclass ITK_TEMPLATE_EXPORT DaubechiesWaveletsDenoiseSequenceImageFilter\n  : public itk::ImageToImageFilter<TImageSequence, TImageSequence>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DaubechiesWaveletsDenoiseSequenceImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DaubechiesWaveletsDenoiseSequenceImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImageSequence, TImageSequence>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DaubechiesWaveletsDenoiseSequenceImageFilter);\n\n  /** Set the number of levels of the deconstruction and reconstruction */\n  itkGetMacro(NumberOfLevels, unsigned int);\n  itkSetMacro(NumberOfLevels, unsigned int);\n\n  /** Sets the order of the Daubechies wavelet used to deconstruct/reconstruct the image pyramid */\n  itkGetMacro(Order, unsigned int);\n  itkSetMacro(Order, unsigned int);\n\n  /** Sets the threshold used in soft thresholding */\n  itkGetMacro(Threshold, float);\n  itkSetMacro(Threshold, float);\n\n  /** Typedefs of internal filters */\n  using TImage = itk::Image<typename TImageSequence::PixelType, TImageSequence::ImageDimension - 1>;\n  using WaveletsDenoisingFilterType = rtk::DeconstructSoftThresholdReconstructImageFilter<TImage>;\n  using ExtractFilterType = itk::ExtractImageFilter<TImageSequence, TImage>;\n  using PasteFilterType = itk::PasteImageFilter<TImageSequence, TImageSequence>;\n  using CastFilterType = itk::CastImageFilter<TImage, TImageSequence>;\n  using ConstantImageSourceType = rtk::ConstantImageSource<TImageSequence>;\n\nprotected:\n  DaubechiesWaveletsDenoiseSequenceImageFilter();\n  ~DaubechiesWaveletsDenoiseSequenceImageFilter() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename WaveletsDenoisingFilterType::Pointer m_WaveletsDenoisingFilter;\n  typename ExtractFilterType::Pointer           m_ExtractFilter;\n  typename PasteFilterType::Pointer             m_PasteFilter;\n  typename CastFilterType::Pointer              m_CastFilter;\n  typename ConstantImageSourceType::Pointer     m_ConstantSource;\n\n  /** Extraction regions for both extract filters */\n  typename TImageSequence::RegionType m_ExtractAndPasteRegion;\n\n  /** Information for the wavelets denoising filter */\n  unsigned int m_Order{ 5 };\n  float        m_Threshold{ 1 };\n  unsigned int m_NumberOfLevels{ 3 };\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDaubechiesWaveletsDenoiseSequenceImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDaubechiesWaveletsDenoiseSequenceImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDaubechiesWaveletsDenoiseSequenceImageFilter_hxx\n#define rtkDaubechiesWaveletsDenoiseSequenceImageFilter_hxx\n\n#include <itkImageFileWriter.h>\n\nnamespace rtk\n{\n\ntemplate <typename TImageSequence>\nDaubechiesWaveletsDenoiseSequenceImageFilter<TImageSequence>::DaubechiesWaveletsDenoiseSequenceImageFilter()\n{\n  // Create the filters\n  m_WaveletsDenoisingFilter = WaveletsDenoisingFilterType::New();\n  m_ExtractFilter = ExtractFilterType::New();\n  m_PasteFilter = PasteFilterType::New();\n  m_CastFilter = CastFilterType::New();\n  m_ConstantSource = ConstantImageSourceType::New();\n\n  // Set permanent connections\n  m_WaveletsDenoisingFilter->SetInput(m_ExtractFilter->GetOutput());\n  m_CastFilter->SetInput(m_WaveletsDenoisingFilter->GetOutput());\n  m_PasteFilter->SetSourceImage(m_CastFilter->GetOutput());\n\n  // Set permanent parameters\n  m_ExtractFilter->SetDirectionCollapseToIdentity();\n\n  // Set memory management parameters\n  m_CastFilter->SetInPlace(false);\n}\n\ntemplate <typename TImageSequence>\nvoid\nDaubechiesWaveletsDenoiseSequenceImageFilter<TImageSequence>::GenerateOutputInformation()\n{\n  int Dimension = TImageSequence::ImageDimension;\n\n  // Set runtime connections\n  m_ExtractFilter->SetInput(this->GetInput());\n\n  // Initialize the source\n  m_ConstantSource->SetInformationFromImage(this->GetInput());\n  m_ConstantSource->Update();\n  m_PasteFilter->SetDestinationImage(m_ConstantSource->GetOutput());\n\n  // Set runtime parameters\n  m_WaveletsDenoisingFilter->SetOrder(m_Order);\n  m_WaveletsDenoisingFilter->SetThreshold(m_Threshold);\n  m_WaveletsDenoisingFilter->SetNumberOfLevels(m_NumberOfLevels);\n\n  // Set extraction regions and indices\n  m_ExtractAndPasteRegion = this->GetInput()->GetLargestPossibleRegion();\n  m_ExtractAndPasteRegion.SetSize(Dimension - 1, 0);\n  m_ExtractAndPasteRegion.SetIndex(Dimension - 1, 0);\n\n  m_ExtractFilter->SetExtractionRegion(m_ExtractAndPasteRegion);\n  m_ExtractFilter->UpdateOutputInformation();\n  m_CastFilter->UpdateOutputInformation();\n\n  m_PasteFilter->SetSourceRegion(m_CastFilter->GetOutput()->GetLargestPossibleRegion());\n  m_PasteFilter->SetDestinationIndex(m_ExtractAndPasteRegion.GetIndex());\n\n  // Have the last filter calculate its output information\n  m_PasteFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_PasteFilter->GetOutput());\n}\n\n\ntemplate <typename TImageSequence>\nvoid\nDaubechiesWaveletsDenoiseSequenceImageFilter<TImageSequence>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get pointers to the input and output\n  typename TImageSequence::Pointer inputPtr = const_cast<TImageSequence *>(this->GetInput());\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename TImageSequence>\nvoid\nDaubechiesWaveletsDenoiseSequenceImageFilter<TImageSequence>::GenerateData()\n{\n  int Dimension = TImageSequence::ImageDimension;\n\n  // Declare an image pointer to disconnect the output of paste\n  typename TImageSequence::Pointer pimg;\n\n  for (unsigned int frame = 0; frame < this->GetInput(0)->GetLargestPossibleRegion().GetSize(Dimension - 1); frame++)\n  {\n    if (frame > 0) // After the first frame, use the output of paste as input\n    {\n      pimg = m_PasteFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      m_PasteFilter->SetDestinationImage(pimg);\n    }\n\n    m_ExtractAndPasteRegion.SetIndex(Dimension - 1, frame);\n\n    m_ExtractFilter->SetExtractionRegion(m_ExtractAndPasteRegion);\n    m_ExtractFilter->UpdateLargestPossibleRegion();\n\n    m_WaveletsDenoisingFilter->Update();\n\n    m_CastFilter->Update();\n\n    m_PasteFilter->SetSourceRegion(m_CastFilter->GetOutput()->GetLargestPossibleRegion());\n    m_PasteFilter->SetDestinationIndex(m_ExtractAndPasteRegion.GetIndex());\n\n    m_PasteFilter->UpdateLargestPossibleRegion();\n  }\n  this->GraftOutput(m_PasteFilter->GetOutput());\n\n  m_ExtractFilter->GetOutput()->ReleaseData();\n  m_WaveletsDenoisingFilter->GetOutput()->ReleaseData();\n  m_CastFilter->GetOutput()->ReleaseData();\n}\n\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkDbf.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDbf_h\n#define rtkDbf_h\n\n#include \"RTKExport.h\"\n#include \"itkWin32Header.h\"\n#include <string>\n#include <fstream>\n#include <vector>\n#include <map>\n#include <cstdlib>\n\nnamespace rtk\n{\n\n/** \\class DbfField\n *\n * Class for the description of a dbase field.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT DbfField\n{\npublic:\n  /** Constructor */\n  DbfField(std::string name, char type, unsigned char length, short recOffset);\n\n  /** Basic field properties stored in the header of the dbf file */\n  std::string\n  GetName()\n  {\n    return m_Name;\n  }\n  char\n  GetType() const\n  {\n    return m_Type;\n  }\n  short\n  GetLength() const\n  {\n    return m_Length;\n  }\n\n  /** Memory offset from beginning of the record */\n  short\n  GetRecOffset() const\n  {\n    return m_RecOffset;\n  }\n\nprivate:\n  std::string m_Name;\n  char        m_Type;\n  short       m_Length;\n  short       m_RecOffset;\n};\n\n/** \\class DbfFile\n *\n * Light dbase file (.dbf) file reader. It assumes little-endianness\n * (least significant byte first). The format describet on this page:\n * https://www.dbf2002.com/dbf-file-format.html\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT DbfFile\n{\npublic:\n  /** Constructor initializes the structure and goes to first record */\n  DbfFile(std::string fileName);\n  ~DbfFile();\n\n  /** Return open status of file stream */\n  bool\n  is_open()\n  {\n    return m_Stream.is_open();\n  }\n\n  /** Number of records contained in the tabe */\n  size_t\n  GetNumberOfRecords()\n  {\n    return m_Fields.size();\n  }\n\n  /** Read in memory the next record. Return true if successful and false\n    oftherwise. */\n  bool\n  ReadNextRecord();\n\n  /** Access to field value of field named fldName */\n  std::string\n  GetFieldAsString(std::string fldName);\n\n  double\n  GetFieldAsDouble(std::string fldName)\n  {\n    return std::stod(GetFieldAsString(fldName).c_str());\n  }\n\nprivate:\n  /** File stream. AFter constructor, positionned to next record to read. */\n  std::ifstream m_Stream;\n\n  /** Global properties of a dbf file */\n  unsigned int   m_NumRecords;\n  unsigned short m_RecordSize;\n  unsigned short m_HeaderSize;\n\n  /** Set of fields described in the header */\n  std::vector<DbfField> m_Fields;\n\n  /** Map between field names and field index */\n  std::map<std::string, unsigned int> m_MapFieldNameIndex;\n\n  /** Current record in memory */\n  char * m_Record;\n};\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDePierroRegularizationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDePierroRegularizationImageFilter_h\n#define rtkDePierroRegularizationImageFilter_h\n\n#include <itkMultiplyImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkDivideImageFilter.h>\n#include <itkImageKernelOperator.h>\n#include <itkNeighborhoodOperatorImageFilter.h>\n#include <itkConstantBoundaryCondition.h>\n#include \"rtkConstantImageSource.h\"\n\nnamespace rtk\n{\n\n/** \\class DePierroRegularizationImageFilter\n * \\brief Implements a regularization for MLEM/OSEM reconstruction.\n *\n * Perform the quadratic penalization described in [De Pierro, IEEE TMI, 1995] for\n * MLEM/OSEM reconstruction.\n *\n * This filter takes the k and k+1 updates of the classic MLEM/OSEM algorithm as\n * inputs and return the regularization factor.\n *\n * \\dot\n * digraph DePierroRegularizationImageFilter {\n *\n *  Input0 [ label=\"Input 0 (Update k of MLEM)\"];\n *  Input0 [shape=Mdiamond];\n *  Input1 [label=\"Input 1 (Update k+1 of MLEM)\"];\n *  Input1 [shape=Mdiamond];\n *  Input2 [label=\"Input 2 (Backprojection of one)\"];\n *  Input2 [shape=Mdiamond];\n *  Output [label=\"Output (Regularization factor)\"];\n *  Output [shape=Mdiamond];\n *  KernelImage [ label=\"KernelImage\"];\n *  KernelImage [shape=Mdiamond];\n *\n *  node [shape=box];\n *  ImageKernelOperator [ label=\"itk::ImageKernelOperator\" URL=\"\\ref itk::ImageKernelOperator\"];\n *  NOIF[ label=\"itk::NeighborhoodOperatorImageFilter\" URL=\"\\ref itk::NeighborhoodOperatorImageFilter\"];\n *  Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n *  Multiply1 [ label=\"itk::MultiplyImageFilter (by constant)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n *  Multiply2 [ label=\"itk::MultiplyImageFilter (by constant)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n *  CustomBinary [ label=\"itk::BinaryGeneratorImageFilter ((A + sqrt(A*A + B))/2)\" URL=\"\\ref\n * itk::BinaryGeneratorImageFilter\"]; Input2 -> Subtract; KernelImage -> ImageKernelOperator; ImageKernelOperator ->\n * NOIF; Input0 -> NOIF; NOIF -> Multiply1; Multiply1 -> Subtract; Subtract -> CustomBinary; Input1 -> Multiply2;\n *  Multiply2 -> CustomBinary;\n *  CustomBinary -> Output;\n *  }\n * \\enddot\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT DePierroRegularizationImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DePierroRegularizationImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DePierroRegularizationImageFilter;\n  using Superclass = itk::ImageToImageFilter<TOutputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using InputImagePointerType = typename TInputImage::Pointer;\n  using OutputImageType = TOutputImage;\n  using InputPixelType = typename TInputImage::PixelType;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using MultiplyImageFilterType = itk::MultiplyImageFilter<InputImageType, InputImageType>;\n  using MultpiplyImageFilterPointerType = typename MultiplyImageFilterType::Pointer;\n  using ConstantVolumeSourceType = rtk::ConstantImageSource<InputImageType>;\n  using ConstantVolumeSourcePointerType = typename ConstantVolumeSourceType::Pointer;\n  using SubtractImageFilterType = itk::SubtractImageFilter<InputImageType, InputImageType>;\n  using SubtractImageFilterPointerType = typename SubtractImageFilterType::Pointer;\n  using ImageKernelOperatorType = itk::ImageKernelOperator<InputPixelType, InputImageDimension>;\n  using NOIFType = itk::NeighborhoodOperatorImageFilter<InputImageType, InputImageType>;\n  using NOIFPointerType = typename NOIFType::Pointer;\n  using CustomBinaryFilterType = itk::BinaryGeneratorImageFilter<InputImageType, InputImageType, OutputImageType>;\n  using CustomBinaryFilterPointerType = typename CustomBinaryFilterType::Pointer;\n\n  /** Typedef for the boundary condition */\n  using BoundaryCondition = itk::ConstantBoundaryCondition<InputImageType>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DePierroRegularizationImageFilter);\n\n  /** Get / Set the hyper parameter for the regularization */\n  itkGetMacro(Beta, double);\n  itkSetMacro(Beta, double);\n\nprotected:\n  DePierroRegularizationImageFilter();\n  ~DePierroRegularizationImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  MultpiplyImageFilterPointerType m_MultiplyConstant1ImageFilter;\n  MultpiplyImageFilterPointerType m_MultiplyConstant2ImageFilter;\n  ConstantVolumeSourcePointerType m_KernelImage;\n  ConstantVolumeSourcePointerType m_DefaultNormalizationVolume;\n  SubtractImageFilterPointerType  m_SubtractImageFilter;\n  BoundaryCondition               m_BoundsCondition;\n  ImageKernelOperatorType         m_KernelOperator;\n  NOIFPointerType                 m_ConvolutionFilter;\n  CustomBinaryFilterPointerType   m_CustomBinaryFilter;\n\nprivate:\n  double m_Beta{ 0.01 };\n\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDePierroRegularizationImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDePierroRegularizationImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDePierroRegularizationImageFilter_hxx\n#define rtkDePierroRegularizationImageFilter_hxx\n\n\nnamespace rtk\n{\ntemplate <class TInputImage, class TOutputImage>\nDePierroRegularizationImageFilter<TInputImage, TOutputImage>::DePierroRegularizationImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Create each filter of the composite filter\n  m_MultiplyConstant1ImageFilter = MultiplyImageFilterType::New();\n  m_MultiplyConstant2ImageFilter = MultiplyImageFilterType::New();\n  m_KernelImage = ConstantVolumeSourceType::New();\n  m_DefaultNormalizationVolume = ConstantVolumeSourceType::New();\n  m_SubtractImageFilter = SubtractImageFilterType::New();\n  m_ConvolutionFilter = NOIFType::New();\n  m_CustomBinaryFilter = CustomBinaryFilterType::New();\n\n  // Set Lambda function\n  auto customLambda = [](const typename InputImageType::PixelType & input1,\n                         const typename InputImageType::PixelType & input2) -> typename OutputImageType::PixelType {\n    return static_cast<typename OutputImageType::PixelType>((input1 + std::sqrt(input1 * input1 + input2)) / 2);\n  };\n  m_CustomBinaryFilter->SetFunctor(customLambda);\n\n  // Permanent internal connections\n  m_SubtractImageFilter->SetInput2(m_MultiplyConstant1ImageFilter->GetOutput());\n  m_CustomBinaryFilter->SetInput1(m_SubtractImageFilter->GetOutput());\n  m_CustomBinaryFilter->SetInput2(m_MultiplyConstant2ImageFilter->GetOutput());\n\n  // Set the kernel image\n  typename ConstantVolumeSourceType::PointType   origin;\n  typename ConstantVolumeSourceType::SizeType    size;\n  typename ConstantVolumeSourceType::SpacingType spacing;\n  origin.Fill(-1);\n  size.Fill(3);\n  spacing.Fill(1);\n  m_KernelImage->SetOrigin(origin);\n  m_KernelImage->SetSpacing(spacing);\n  m_KernelImage->SetSize(size);\n  m_KernelImage->SetConstant(1.);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDePierroRegularizationImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the k uptade of classic MLEM/OSEM algorithm\n  typename TInputImage::Pointer inputPtr0 = const_cast<TInputImage *>(this->GetInput(0));\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 0 is the k+1 uptade of classic MLEM/OSEM algorithm\n  typename TInputImage::Pointer inputPtr1 = const_cast<TInputImage *>(this->GetInput(1));\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n\n  // Input 3 is the normalization volume (optional)\n  typename TInputImage::Pointer inputPtr3 = const_cast<TInputImage *>(this->GetInput(2));\n  if (inputPtr3)\n    inputPtr3->SetRequestedRegion(inputPtr0->GetRequestedRegion());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDePierroRegularizationImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  m_MultiplyConstant1ImageFilter->SetInput1(this->GetInput(0));\n  m_MultiplyConstant2ImageFilter->SetInput1(this->GetInput(1));\n  if (this->GetInput(2) != nullptr)\n  {\n    m_SubtractImageFilter->SetInput1(this->GetInput(2));\n  }\n  else\n  {\n    m_DefaultNormalizationVolume->SetInformationFromImage(const_cast<TInputImage *>(this->GetInput(0)));\n    m_DefaultNormalizationVolume->SetConstant(1);\n    m_SubtractImageFilter->SetInput1(m_DefaultNormalizationVolume->GetOutput());\n  }\n  m_MultiplyConstant1ImageFilter->SetConstant2(m_Beta);\n  m_MultiplyConstant2ImageFilter->SetConstant2(4 * 2 * m_Beta * (pow(3, InputImageDimension) - 1));\n\n  m_CustomBinaryFilter->UpdateOutputInformation();\n  this->GetOutput()->SetOrigin(m_CustomBinaryFilter->GetOutput()->GetOrigin());\n  this->GetOutput()->SetSpacing(m_CustomBinaryFilter->GetOutput()->GetSpacing());\n  this->GetOutput()->SetDirection(m_CustomBinaryFilter->GetOutput()->GetDirection());\n  this->GetOutput()->SetLargestPossibleRegion(m_CustomBinaryFilter->GetOutput()->GetLargestPossibleRegion());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDePierroRegularizationImageFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  m_KernelImage->Update();\n  typename TInputImage::IndexType pixelIndex;\n  pixelIndex.Fill(1);\n  m_KernelImage->GetOutput()->SetPixel(pixelIndex, pow(3, InputImageDimension) - 1);\n  m_KernelOperator.SetImageKernel(m_KernelImage->GetOutput());\n  // The radius of the kernel must be the radius of the patch, NOT the size of the patch\n  itk::Size<InputImageDimension> radius;\n  radius.Fill(1);\n  m_KernelOperator.CreateToRadius(radius);\n  m_ConvolutionFilter->OverrideBoundaryCondition(&m_BoundsCondition);\n  m_ConvolutionFilter->SetOperator(m_KernelOperator);\n  m_ConvolutionFilter->SetInput(this->GetInput(0));\n  m_MultiplyConstant1ImageFilter->SetInput1(m_ConvolutionFilter->GetOutput());\n\n  m_CustomBinaryFilter->Update();\n  this->GraftOutput(m_CustomBinaryFilter->GetOutput());\n}\n\n} // end namespace rtk\n\n#endif // rtkDePierroRegularizationImageFilter_hxx\n"
  },
  {
    "path": "include/rtkDeconstructImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDeconstructImageFilter_h\n#define rtkDeconstructImageFilter_h\n\n// Includes\n#include <itkImageToImageFilter.h>\n#include <itkMacro.h>\n#include <itkMirrorPadImageFilter.h>\n\n#include \"rtkDaubechiesWaveletsConvolutionImageFilter.h\"\n#include \"rtkDownsampleImageFilter.h\"\n\nnamespace rtk\n{\n\n/**\n * \\class DeconstructImageFilter\n * \\brief An image filter that deconstructs an image using\n * Daubechies wavelets.\n *\n * This filter is inspired from Dan Mueller's GIFT package\n * https://www.insight-journal.org/browse/publication/103\n *\n *\n * \\dot\n * digraph DeconstructImageFilter {\n *\n * Input [ label=\"Input (here, 2D)\"];\n * Input [shape=Mdiamond];\n * Output0 [label=\"Output 0\"];\n * Output0 [shape=Mdiamond];\n * Output1 [label=\"Output 1\"];\n * Output1 [shape=Mdiamond];\n * Output2 [label=\"Output 2\"];\n * Output2 [shape=Mdiamond];\n * Output3 [label=\"Output 3\"];\n * Output3 [shape=Mdiamond];\n * Output4 [label=\"Output 4\"];\n * Output4 [shape=Mdiamond];\n * Output5 [label=\"Output 5\"];\n * Output5 [shape=Mdiamond];\n * Output6 [label=\"Output 6\"];\n * Output6 [shape=Mdiamond];\n *\n * node [shape=box];\n * Pad0 [ label=\"itk::MirrorPadImageFilter\" URL=\"\\ref itk::MirrorPadImageFilter\"];\n * Pad1 [ label=\"itk::MirrorPadImageFilter\" URL=\"\\ref itk::MirrorPadImageFilter\"];\n * Conv0 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Lowpass, Lowpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv1 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Lowpass, Highpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv2 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Highpass, Lowpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv3 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Highpass, Highpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv4 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Lowpass, Lowpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv5 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Lowpass, Highpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv6 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Highpass, Lowpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv7 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Highpass, Highpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Down0 [ label=\"rtk::DownsampleImageFilter (by 2)\" URL=\"\\ref rtk::DownsampleImageFilter\"];\n * Down1 [ label=\"rtk::DownsampleImageFilter (by 2)\" URL=\"\\ref rtk::DownsampleImageFilter\"];\n * Down2 [ label=\"rtk::DownsampleImageFilter (by 2)\" URL=\"\\ref rtk::DownsampleImageFilter\"];\n * Down3 [ label=\"rtk::DownsampleImageFilter (by 2)\" URL=\"\\ref rtk::DownsampleImageFilter\"];\n * Down4 [ label=\"rtk::DownsampleImageFilter (by 2)\" URL=\"\\ref rtk::DownsampleImageFilter\"];\n * Down5 [ label=\"rtk::DownsampleImageFilter (by 2)\" URL=\"\\ref rtk::DownsampleImageFilter\"];\n * Down6 [ label=\"rtk::DownsampleImageFilter (by 2)\" URL=\"\\ref rtk::DownsampleImageFilter\"];\n * Down7 [ label=\"rtk::DownsampleImageFilter (by 2)\" URL=\"\\ref rtk::DownsampleImageFilter\"];\n * AfterPad0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterPad1 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Input -> Pad1;\n * Pad1 -> AfterPad1 [arrowhead=none];\n * AfterPad1 -> Conv4;\n * AfterPad1 -> Conv5;\n * AfterPad1 -> Conv6;\n * AfterPad1 -> Conv7;\n * Conv4 -> Down4;\n * Conv5 -> Down5;\n * Conv6 -> Down6;\n * Conv7 -> Down7;\n * Down4 -> Pad0;\n * Pad0 -> AfterPad0 [arrowhead=none];\n * AfterPad0 -> Conv0;\n * AfterPad0 -> Conv1;\n * AfterPad0 -> Conv2;\n * AfterPad0 -> Conv3;\n * Conv0 -> Down0;\n * Conv1 -> Down1;\n * Conv2 -> Down2;\n * Conv3 -> Down3;\n * Down0 -> Output0;\n * Down1 -> Output1;\n * Down2 -> Output2;\n * Down3 -> Output3;\n * Down5 -> Output4;\n * Down6 -> Output5;\n * Down7 -> Output6;\n * }\n * \\enddot\n *\n * \\test rtkwaveletstest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <class TImage>\nclass ITK_TEMPLATE_EXPORT DeconstructImageFilter : public itk::ImageToImageFilter<TImage, TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DeconstructImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DeconstructImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImage, TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DeconstructImageFilter);\n\n  /** ImageDimension enumeration. */\n  static constexpr unsigned int ImageDimension = TImage::ImageDimension;\n\n  /** Inherit types from Superclass. */\n  using InputImageType = typename Superclass::InputImageType;\n  using OutputImageType = typename Superclass::OutputImageType;\n  using InputImagePointer = typename Superclass::InputImagePointer;\n  using OutputImagePointer = typename Superclass::OutputImagePointer;\n  using InputImageConstPointer = typename Superclass::InputImageConstPointer;\n  using PixelType = typename TImage::PixelType;\n  using InternalPixelType = typename TImage::InternalPixelType;\n\n  /** Typedefs for pipeline's subfilters */\n  using PadFilterType = itk::MirrorPadImageFilter<InputImageType, InputImageType>;\n  using ConvolutionFilterType = rtk::DaubechiesWaveletsConvolutionImageFilter<InputImageType>;\n  using DownsampleImageFilterType = rtk::DownsampleImageFilter<InputImageType>;\n\n  /** Set the number of input levels. */\n  virtual void\n  SetNumberOfLevels(unsigned int levels)\n  {\n    this->m_NumberOfLevels = levels;\n    this->ModifyInputOutputStorage();\n  }\n\n  /** Get the number of input levels (per image). */\n  virtual unsigned int\n  GetNumberOfLevels()\n  {\n    return this->m_NumberOfLevels;\n  }\n\n  /** DeconstructImageFilter produces images which are of different size\n   *  than the input image. As such, we reimplement GenerateOutputInformation()\n   *  in order to inform the pipeline execution model.\n   */\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Get/Set the order of the wavelet filters */\n  itkGetMacro(Order, unsigned int);\n  itkSetMacro(Order, unsigned int);\n\n  /** Get the size of each convolution filter's output\n   * This is required because the downsampling implies\n   * a loss of information on the size (both 2n+1 and 2n\n   * are downsampled to n), and the upsampling filters\n   * used in the reconstruction process need this\n   * information.\n   */\n  typename InputImageType::SizeType *\n  GetSizes()\n  {\n    return m_Sizes.data();\n  }\n\n  /** Get the index of each convolution filter's output\n   * This is required because the downsampling implies\n   * a loss of information on the index (both 2n+1 and 2n\n   * are downsampled to n), and the upsampling filters\n   * used in the reconstruction process need this\n   * information.\n   */\n  typename InputImageType::IndexType *\n  GetIndices()\n  {\n    return m_Indices.data();\n  }\n\nprotected:\n  DeconstructImageFilter();\n  ~DeconstructImageFilter() override = default;\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  /** Modifies the storage for Input and Output images.\n   * Should be called after changes to levels, bands,\n   * deconstruct, reconstruct, etc... */\n  void\n  ModifyInputOutputStorage();\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Calculates the number of ProcessObject output images */\n  virtual unsigned int\n  CalculateNumberOfOutputs();\n\n  /** Creates and sets the kernel sources to generate all kernels. */\n  void\n  GeneratePassVectors();\n\nprivate:\n  unsigned int m_NumberOfLevels{ 5 }; // Holds the number of deconstruction levels\n  unsigned int m_Order{ 3 };          // Holds the order of the wavelet filters\n  bool         m_PipelineConstructed{\n    false\n  }; // Filters instantiated by GenerateOutputInformation() should be instantiated only once\n\n  typename std::vector<typename InputImageType::SizeType>  m_Sizes;      // Holds the size of sub-images at each level\n  typename std::vector<typename InputImageType::IndexType> m_Indices;    // Holds the size of sub-images at each level\n  typename std::vector<typename PadFilterType::Pointer>    m_PadFilters; // Holds a vector of padding filters\n  typename std::vector<typename ConvolutionFilterType::Pointer>\n    m_ConvolutionFilters; // Holds a vector of convolution filters\n  typename std::vector<typename DownsampleImageFilterType::Pointer>\n    m_DownsampleFilters; // Holds a vector of downsample filters\n  // Holds a vector of PassVectors. A PassVector has Dimension components, each one storing either \"High\" or \"Low\"\n  typename std::vector<typename ConvolutionFilterType::PassVector> m_PassVectors;\n};\n\n} // namespace rtk\n\n// Include CXX\n#ifndef rtk_MANUAL_INSTANTIATION\n#  include \"rtkDeconstructImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDeconstructImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDeconstructImageFilter_hxx\n#define rtkDeconstructImageFilter_hxx\n\n\nnamespace rtk\n{\n\n/////////////////////////////////////////////////////////\n// Default Constructor\ntemplate <class TImage>\nDeconstructImageFilter<TImage>::DeconstructImageFilter() = default;\n\n/////////////////////////////////////////////////////////\n// PrintSelf()\ntemplate <class TImage>\nvoid\nDeconstructImageFilter<TImage>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n}\n\n/////////////////////////////////////////////////////////\n// ModifyInputOutputStorage()\ntemplate <class TImage>\nvoid\nDeconstructImageFilter<TImage>::ModifyInputOutputStorage()\n{\n  this->Modified();\n\n  // Set required number of outputs\n  int requiredNumberOfOutputs = this->CalculateNumberOfOutputs();\n  this->SetNumberOfRequiredOutputs(requiredNumberOfOutputs);\n\n  // Make actual outputs and required outputs match\n  int actualNumberOfOutputs = this->GetNumberOfOutputs();\n\n  if (actualNumberOfOutputs < requiredNumberOfOutputs)\n  {\n    // Add extra outputs\n    for (int idx = actualNumberOfOutputs; idx < requiredNumberOfOutputs; idx++)\n    {\n      typename itk::DataObject::Pointer output = this->MakeOutput(idx);\n      this->SetNthOutput(idx, output.GetPointer());\n    }\n  }\n  else if (actualNumberOfOutputs > requiredNumberOfOutputs)\n  {\n    // Remove extra outputs\n    for (int idx = (actualNumberOfOutputs - 1); idx >= requiredNumberOfOutputs; idx--)\n    {\n      if (idx < 0)\n      {\n        break;\n      }\n      this->RemoveOutput(idx);\n    }\n  }\n}\n\ntemplate <class TImage>\nunsigned int\nDeconstructImageFilter<TImage>::CalculateNumberOfOutputs()\n{\n  int          dimension = TImage::ImageDimension;\n  unsigned int n = itk::Math::Round<double>(std::pow(2.0, dimension));\n  return (m_NumberOfLevels * (n - 1) + 1);\n}\n\ntemplate <class TImage>\nvoid\nDeconstructImageFilter<TImage>::GeneratePassVectors()\n{\n  int          dimension = TImage::ImageDimension;\n  unsigned int n = itk::Math::Round<double>(std::pow(2.0, dimension));\n\n  // Create a vector of PassVector\n  m_PassVectors.clear();\n  for (unsigned int vectIndex = 0; vectIndex < n; vectIndex++)\n  {\n    typename ConvolutionFilterType::PassVector temp;\n    m_PassVectors.push_back(temp);\n  }\n\n  // Fill it with the right values\n  unsigned int powerOfTwo = 1;\n  for (int dim = 0; dim < dimension; dim++)\n  {\n    for (unsigned int vectIndex = 0; vectIndex < n; vectIndex++)\n    {\n      // vectIndex / powerOfTwo is a division between unsigned ints, and will return the quotient\n      // of their euclidian division\n      if ((vectIndex / powerOfTwo) % 2)\n        m_PassVectors[vectIndex][dim] = ConvolutionFilterType::High;\n      else\n        m_PassVectors[vectIndex][dim] = ConvolutionFilterType::Low;\n    }\n    powerOfTwo *= 2;\n  }\n}\n\ntemplate <class TImage>\nvoid\nDeconstructImageFilter<TImage>::GenerateInputRequestedRegion()\n{\n  InputImagePointer inputPtr = const_cast<TImage *>(this->GetInput());\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <class TImage>\nvoid\nDeconstructImageFilter<TImage>::GenerateOutputInformation()\n{\n  // n is the number of bands per level, including the ones\n  // that will be deconstructed and won't appear in the outputs\n  int          dimension = TImage::ImageDimension;\n  unsigned int n = itk::Math::Round<double>(std::pow(2.0, dimension));\n\n  if (!m_PipelineConstructed)\n  {\n\n    // Before the cascade pipeline\n    // Create and set the padding filters\n    for (unsigned int l = 0; l < m_NumberOfLevels; l++)\n    {\n      m_PadFilters.push_back(PadFilterType::New());\n      typename TImage::SizeType padSize;\n      padSize.Fill(2 * m_Order - 1);\n      m_PadFilters[l]->SetPadBound(padSize);\n    }\n\n    // Create and set the kernel sources\n    this->GeneratePassVectors();\n\n    // Create all FFTProjectionsConvolution and Downsampling filters\n    for (unsigned int i = 0; i < n * m_NumberOfLevels; i++)\n    {\n      m_ConvolutionFilters.push_back(ConvolutionFilterType::New());\n      m_DownsampleFilters.push_back(DownsampleImageFilterType::New());\n    }\n\n    // Cascade pipeline\n    // Set all the filters and connect them together\n    auto * downsamplingFactors = new unsigned int[dimension];\n    for (int d = 0; d < dimension; d++)\n      downsamplingFactors[d] = 2;\n\n    for (unsigned int l = 0; l < m_NumberOfLevels; l++)\n    {\n      for (unsigned int band = 0; band < n; band++)\n      {\n        m_ConvolutionFilters[band + l * n]->SetInput(m_PadFilters[l]->GetOutput());\n        m_ConvolutionFilters[band + l * n]->SetPass(m_PassVectors[band]);\n        m_ConvolutionFilters[band + l * n]->SetDeconstruction();\n        m_ConvolutionFilters[band + l * n]->SetOrder(this->GetOrder());\n        m_ConvolutionFilters[band + l * n]->ReleaseDataFlagOn();\n\n        m_DownsampleFilters[band + l * n]->SetInput(m_ConvolutionFilters[band + l * n]->GetOutput());\n        m_DownsampleFilters[band + l * n]->SetFactors(downsamplingFactors);\n\n        if ((band > 0) || (l == 0))\n        {\n          m_DownsampleFilters[band + l * n]->ReleaseDataFlagOn();\n        }\n      }\n      if (l < m_NumberOfLevels - 1)\n      {\n        m_PadFilters[l]->SetInput(m_DownsampleFilters[n * (l + 1)]->GetOutput());\n      }\n    }\n    m_PadFilters[m_NumberOfLevels - 1]->SetInput(this->GetInput());\n\n    // Clean up\n    delete[] downsamplingFactors;\n  }\n\n  // Have the last filters calculate their output information\n  // and copy it as the output information of the composite filter\n  // Since not all downsample filters are connected to an output,\n  // some are skipped\n  unsigned int outputBand = 0;\n  for (unsigned int i = 0; i < n * m_NumberOfLevels; i++)\n  {\n    if ((i % n) || (i == 0))\n    {\n      m_DownsampleFilters[i]->UpdateOutputInformation();\n      this->GetOutput(outputBand)->CopyInformation(m_DownsampleFilters[i]->GetOutput());\n      outputBand++;\n    }\n  }\n\n  if (!m_PipelineConstructed)\n  {\n    m_Sizes.clear();\n    m_Indices.clear();\n    for (unsigned int i = 0; i < n * m_NumberOfLevels; i++)\n    {\n      m_Sizes.push_back(m_ConvolutionFilters[i]->GetOutput()->GetLargestPossibleRegion().GetSize());\n      m_Indices.push_back(m_ConvolutionFilters[i]->GetOutput()->GetLargestPossibleRegion().GetIndex());\n    }\n  }\n\n  m_PipelineConstructed = true;\n}\n\ntemplate <class TImage>\nvoid\nDeconstructImageFilter<TImage>::GenerateData()\n{\n  //  std::cout << \"Starting deconstruction\" << std::endl;\n\n  int          dimension = TImage::ImageDimension;\n  unsigned int n = itk::Math::Round<double>(std::pow(2.0, dimension));\n\n  // Have the last filters calculate their output image\n  // and graft it to the output of the composite filter\n  // Since not all downsample filters are connected to an output,\n  // some are skipped\n  unsigned int outputBand = 0;\n  for (unsigned int i = 0; i < n * m_NumberOfLevels; i++)\n  {\n    if ((i % n) || (i == 0))\n    {\n      m_DownsampleFilters[i]->Update();\n      this->GraftNthOutput(outputBand, m_DownsampleFilters[i]->GetOutput());\n      outputBand++;\n    }\n  }\n  //  std::cout << \"Done deconstruction\" << std::endl;\n}\n\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDeconstructSoftThresholdReconstructImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDeconstructSoftThresholdReconstructImageFilter_h\n#define rtkDeconstructSoftThresholdReconstructImageFilter_h\n\n// ITK includes\n#include \"itkMacro.h\"\n#include \"itkProgressReporter.h\"\n\n// rtk includes\n#include \"rtkDeconstructImageFilter.h\"\n#include \"rtkReconstructImageFilter.h\"\n#include \"rtkSoftThresholdImageFilter.h\"\n\nnamespace rtk\n{\n\n/**\n * \\class DeconstructSoftThresholdReconstructImageFilter\n * \\brief Deconstructs an image, soft thresholds its wavelets coefficients,\n * then reconstructs\n *\n * This filter is inspired from Dan Mueller's GIFT package\n * https://www.insight-journal.org/browse/publication/103\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <class TImage>\nclass ITK_TEMPLATE_EXPORT DeconstructSoftThresholdReconstructImageFilter\n  : public itk::ImageToImageFilter<TImage, TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DeconstructSoftThresholdReconstructImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DeconstructSoftThresholdReconstructImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImage, TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DeconstructSoftThresholdReconstructImageFilter);\n\n  /** ImageDimension enumeration. */\n  static constexpr unsigned int ImageDimension = TImage::ImageDimension;\n\n  /** Inherit types from Superclass. */\n  using InputImageType = typename Superclass::InputImageType;\n  using OutputImageType = typename Superclass::OutputImageType;\n  using InputImagePointer = typename Superclass::InputImagePointer;\n  using OutputImagePointer = typename Superclass::OutputImagePointer;\n  using InputImageConstPointer = typename Superclass::InputImageConstPointer;\n  using PixelType = typename TImage::PixelType;\n  using InternalPixelType = typename TImage::InternalPixelType;\n\n  /** Define the types of subfilters */\n  using DeconstructFilterType = rtk::DeconstructImageFilter<InputImageType>;\n  using ReconstructFilterType = rtk::ReconstructImageFilter<InputImageType>;\n  using SoftThresholdFilterType = rtk::SoftThresholdImageFilter<InputImageType, InputImageType>;\n\n  /** Set the number of levels of the deconstruction and reconstruction */\n  void\n  SetNumberOfLevels(unsigned int levels);\n\n  /** Sets the order of the Daubechies wavelet used to deconstruct/reconstruct the image pyramid */\n  itkGetMacro(Order, unsigned int);\n  itkSetMacro(Order, unsigned int);\n\n  /** Sets the threshold used in soft thresholding */\n  itkGetMacro(Threshold, float);\n  itkSetMacro(Threshold, float);\n\nprotected:\n  DeconstructSoftThresholdReconstructImageFilter();\n  ~DeconstructSoftThresholdReconstructImageFilter() override = default;\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  /** Generate the output data. */\n  void\n  GenerateData() override;\n\n  /** Compute the information on output's size and index */\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\nprivate:\n  unsigned int m_Order;\n  float        m_Threshold;\n  bool         m_PipelineConstructed;\n\n  typename DeconstructFilterType::Pointer m_DeconstructionFilter;\n  typename ReconstructFilterType::Pointer m_ReconstructionFilter;\n  std::vector<typename SoftThresholdFilterType::Pointer>\n    m_SoftTresholdFilters; // Holds an array of soft threshold filters\n};\n\n} // namespace rtk\n\n// Include CXX\n#ifndef rtk_MANUAL_INSTANTIATION\n#  include \"rtkDeconstructSoftThresholdReconstructImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDeconstructSoftThresholdReconstructImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDeconstructSoftThresholdReconstructImageFilter_hxx\n#define rtkDeconstructSoftThresholdReconstructImageFilter_hxx\n\n// rtk Includes\n\nnamespace rtk\n{\n\n/////////////////////////////////////////////////////////\n// Constructor()\ntemplate <class TImage>\nDeconstructSoftThresholdReconstructImageFilter<TImage>::DeconstructSoftThresholdReconstructImageFilter()\n{\n  m_DeconstructionFilter = DeconstructFilterType::New();\n  m_ReconstructionFilter = ReconstructFilterType::New();\n  m_Order = 3;\n  m_Threshold = 0;\n  m_PipelineConstructed = false;\n}\n\n\n/////////////////////////////////////////////////////////\n// PrintSelf()\ntemplate <class TImage>\nvoid\nDeconstructSoftThresholdReconstructImageFilter<TImage>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n}\n\n/////////////////////////////////////////////////////////\n// Pass the number of decomposition levels to the wavelet\n// filters\ntemplate <class TImage>\nvoid\nDeconstructSoftThresholdReconstructImageFilter<TImage>::SetNumberOfLevels(unsigned int levels)\n{\n  m_DeconstructionFilter->SetNumberOfLevels(levels);\n  m_ReconstructionFilter->SetNumberOfLevels(levels);\n}\n\n/////////////////////////////////////////////////////////\n// GenerateInputRequestedRegion()\ntemplate <class TImage>\nvoid\nDeconstructSoftThresholdReconstructImageFilter<TImage>::GenerateInputRequestedRegion()\n{\n  InputImagePointer inputPtr = const_cast<TImage *>(this->GetInput());\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\n/////////////////////////////////////////////////////////\n// GenerateOutputInformation()\ntemplate <class TImage>\nvoid\nDeconstructSoftThresholdReconstructImageFilter<TImage>::GenerateOutputInformation()\n{\n\n  if (!m_PipelineConstructed)\n  {\n    // Connect the inputs\n    m_DeconstructionFilter->SetInput(this->GetInput());\n    m_DeconstructionFilter->ReleaseDataFlagOn();\n\n    // Set runtime parameters\n    m_DeconstructionFilter->SetOrder(this->GetOrder());\n    m_ReconstructionFilter->SetOrder(this->GetOrder());\n    m_DeconstructionFilter->UpdateOutputInformation();\n    m_ReconstructionFilter->SetSizes(m_DeconstructionFilter->GetSizes());\n    m_ReconstructionFilter->SetIndices(m_DeconstructionFilter->GetIndices());\n\n    // Create and setup an array of soft threshold filters\n    for (unsigned int index = 0; index < m_DeconstructionFilter->GetNumberOfOutputs(); index++)\n    {\n      // Soft thresholding\n      m_SoftTresholdFilters.push_back(SoftThresholdFilterType::New());\n      m_SoftTresholdFilters[index]->SetInput(m_DeconstructionFilter->GetOutput(index));\n      m_SoftTresholdFilters[index]->SetThreshold(m_Threshold);\n      m_SoftTresholdFilters[index]->ReleaseDataFlagOn();\n\n      // Set input for reconstruction\n      m_ReconstructionFilter->SetInput(index, m_SoftTresholdFilters[index]->GetOutput());\n    }\n\n    // The low pass coefficients are not thresholded\n    m_SoftTresholdFilters[0]->SetThreshold(0);\n  }\n\n  m_PipelineConstructed = true;\n\n  // Have the last filter calculate its output information\n  // and copy it as the output information of the composite filter\n  m_ReconstructionFilter->UpdateOutputInformation();\n  this->GetOutput()->CopyInformation(m_ReconstructionFilter->GetOutput());\n}\n\n/////////////////////////////////////////////////////////\n// GenerateData()\ntemplate <class TImage>\nvoid\nDeconstructSoftThresholdReconstructImageFilter<TImage>::GenerateData()\n{\n  // Perform reconstruction\n  m_ReconstructionFilter->Update();\n  this->GraftOutput(m_ReconstructionFilter->GetOutput());\n}\n\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDenoisingBPDQImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDenoisingBPDQImageFilter_h\n#define rtkDenoisingBPDQImageFilter_h\n\n#include \"rtkForwardDifferenceGradientImageFilter.h\"\n#include \"rtkBackwardDifferenceDivergenceImageFilter.h\"\n\n#include <itkCastImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n#include <itkInPlaceImageFilter.h>\n\nnamespace rtk\n{\n/** \\class DenoisingBPDQImageFilter\n * \\brief Base class for Basis Pursuit DeQuantization denoising filters\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK IntensityImageFilters\n */\n\ntemplate <typename TOutputImage, typename TGradientImage>\nclass ITK_TEMPLATE_EXPORT DenoisingBPDQImageFilter : public itk::InPlaceImageFilter<TOutputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DenoisingBPDQImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DenoisingBPDQImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TOutputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DenoisingBPDQImageFilter);\n\n  /** Sub filter type definitions */\n  typedef ForwardDifferenceGradientImageFilter<TOutputImage,\n                                               typename TOutputImage::ValueType,\n                                               typename TOutputImage::ValueType,\n                                               TGradientImage>\n    GradientFilterType;\n  using MultiplyFilterType = itk::MultiplyImageFilter<TOutputImage>;\n  using SubtractImageFilterType = itk::SubtractImageFilter<TOutputImage>;\n  using SubtractGradientFilterType = itk::SubtractImageFilter<TGradientImage>;\n  using ThresholdFilterType = itk::InPlaceImageFilter<TGradientImage>;\n  using DivergenceFilterType = BackwardDifferenceDivergenceImageFilter<TGradientImage, TOutputImage>;\n\n  itkGetMacro(NumberOfIterations, int);\n  itkSetMacro(NumberOfIterations, int);\n\n  itkSetMacro(Gamma, double);\n  itkGetMacro(Gamma, double);\n\nprotected:\n  DenoisingBPDQImageFilter();\n  ~DenoisingBPDQImageFilter() override = default;\n\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  virtual ThresholdFilterType *\n  GetThresholdFilter()\n  {\n    return nullptr;\n  }\n\n  /** Sub filter pointers */\n  typename GradientFilterType::Pointer         m_GradientFilter;\n  typename MultiplyFilterType::Pointer         m_MultiplyFilter;\n  typename SubtractImageFilterType::Pointer    m_SubtractFilter;\n  typename SubtractGradientFilterType::Pointer m_SubtractGradientFilter;\n  typename DivergenceFilterType::Pointer       m_DivergenceFilter;\n\n  double m_Gamma;\n  double m_Beta;\n  double m_MinSpacing;\n  int    m_NumberOfIterations;\n  bool   m_DimensionsProcessed[TOutputImage::ImageDimension];\n\nprivate:\n  virtual void\n  SetPipelineForFirstIteration();\n  virtual void\n  SetPipelineAfterFirstIteration();\n};\n\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDenoisingBPDQImageFilter.hxx\"\n#endif\n\n#endif //__rtkDenoisingBPDQImageFilter__\n"
  },
  {
    "path": "include/rtkDenoisingBPDQImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDenoisingBPDQImageFilter_hxx\n#define rtkDenoisingBPDQImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage, typename TGradientImage>\nDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::DenoisingBPDQImageFilter()\n{\n  m_Gamma = 1.0;\n  m_NumberOfIterations = 1;\n  m_MinSpacing = 0;\n\n  // This is an InPlace filter only for the subclasses to have the possibility to run in place\n  this->SetInPlace(false);\n\n  // Create the sub filters\n  m_GradientFilter = GradientFilterType::New();\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_SubtractFilter = SubtractImageFilterType::New();\n  m_SubtractGradientFilter = SubtractGradientFilterType::New();\n  m_DivergenceFilter = DivergenceFilterType::New();\n\n  // Set whether the sub filters should release their data during pipeline execution\n  m_DivergenceFilter->ReleaseDataFlagOn();\n  m_SubtractFilter\n    ->ReleaseDataFlagOn(); // It is the pipeline's output, but it is explicitely computed during the last iteration\n  m_GradientFilter->ReleaseDataFlagOn();\n  m_MultiplyFilter->ReleaseDataFlagOn();\n  m_SubtractGradientFilter->ReleaseDataFlagOn();\n\n  // Set some filters to be InPlace\n\n  // DenoisingBPDQ reaches its memory consumption peak\n  // when m_SubtractGradientFilter allocates its output (a covariant vector image)\n  // and uses its two inputs (two covariant vector images)\n  // Setting it in place reduces the memory requirement from 3 covariant vector images to 2\n  m_SubtractGradientFilter->SetInPlace(true);\n}\n\ntemplate <typename TOutputImage, typename TGradientImage>\nvoid\nDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::GenerateOutputInformation()\n{\n  // Set the pipeline for the first iteration\n  SetPipelineForFirstIteration();\n\n  // Compute the parameters used in Basis Pursuit Dequantization\n  // and set the filters to use them\n  double numberOfDimensionsProcessed = 0;\n  m_MinSpacing = this->GetInput()->GetSpacing()[0];\n  for (unsigned int dim = 0; dim < TOutputImage::ImageDimension; dim++)\n  {\n    if (m_DimensionsProcessed[dim])\n    {\n      numberOfDimensionsProcessed += 1.0;\n      if (this->GetInput()->GetSpacing()[dim] < m_MinSpacing)\n        m_MinSpacing = this->GetInput()->GetSpacing()[dim];\n    }\n  }\n\n  // Set the gradient and divergence filter to take spacing into account\n  m_GradientFilter->SetUseImageSpacingOn();\n  m_DivergenceFilter->SetUseImageSpacingOn();\n\n  // Beta must be smaller than 1 / (2 ^ NumberOfDimensionsProcessed) for the algorithm to converge\n  m_Beta = 1 / pow(2, numberOfDimensionsProcessed) * 0.9 * m_MinSpacing;\n\n  m_MultiplyFilter->SetConstant2(m_Beta);\n  m_GradientFilter->SetDimensionsProcessed(m_DimensionsProcessed);\n  m_DivergenceFilter->SetDimensionsProcessed(m_DimensionsProcessed);\n\n  // Have the last filter calculate its output information,\n  // which should update that of the whole pipeline\n  this->GetThresholdFilter()->UpdateOutputInformation();\n  this->GetOutput()->CopyInformation(m_MultiplyFilter->GetOutput());\n}\n\ntemplate <typename TOutputImage, typename TGradientImage>\nvoid\nDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::SetPipelineForFirstIteration()\n{\n  m_MultiplyFilter->SetInput1(this->GetInput());\n  m_GradientFilter->SetInput(m_MultiplyFilter->GetOutput());\n  this->GetThresholdFilter()->SetInput(m_GradientFilter->GetOutput());\n}\n\ntemplate <typename TOutputImage, typename TGradientImage>\nvoid\nDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::SetPipelineAfterFirstIteration()\n{\n  m_SubtractFilter->SetInput1(this->GetInput());\n  m_SubtractFilter->SetInput2(m_DivergenceFilter->GetOutput());\n\n  m_MultiplyFilter->SetInput1(m_SubtractFilter->GetOutput());\n\n  m_GradientFilter->SetInput(m_MultiplyFilter->GetOutput());\n\n  m_SubtractGradientFilter->SetInput2(m_GradientFilter->GetOutput());\n\n  this->GetThresholdFilter()->SetInput(m_SubtractGradientFilter->GetOutput());\n\n  m_MultiplyFilter->SetConstant2(m_Beta * m_MinSpacing);\n}\n\ntemplate <typename TOutputImage, typename TGradientImage>\nvoid\nDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::GenerateData()\n{\n  typename TGradientImage::Pointer pimg;\n\n  // The first iteration only updates intermediate variables, not the output\n  // The output is updated m_NumberOfIterations-1 times, therefore an additional\n  // iteration must be performed so that even m_NumberOfIterations=1 has an effect\n  for (int iter = 0; iter < m_NumberOfIterations; iter++)\n  {\n    if (iter == 1)\n      SetPipelineAfterFirstIteration();\n\n    this->GetThresholdFilter()->Update();\n\n    pimg = this->GetThresholdFilter()->GetOutput();\n    pimg->DisconnectPipeline();\n    m_DivergenceFilter->SetInput(pimg);\n    m_SubtractGradientFilter->SetInput1(pimg);\n  }\n  m_DivergenceFilter->Update();\n  pimg->ReleaseData();\n\n  m_SubtractFilter->Update();\n  this->GraftOutput(m_SubtractFilter->GetOutput());\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDigisensGeometryReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDigisensGeometryReader_h\n#define rtkDigisensGeometryReader_h\n\n#include \"RTKExport.h\"\n#include <itkLightProcessObject.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class DigisensGeometryReader\n *\n * Creates a 3D circular geometry from an xml file created by the calibration\n * software developed by the Digisens company.\n *\n * \\test rtkdigisenstest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT DigisensGeometryReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DigisensGeometryReader);\n\n  /** Standard type alias */\n  using Self = DigisensGeometryReader;\n  using Superclass = itk::LightProcessObject;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DigisensGeometryReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Get the pointer to the generated geometry object. */\n  itkGetMacro(Geometry, GeometryType::Pointer);\n\n  /** Set the path to the file XML calibration file */\n  itkGetMacro(XMLFileName, std::string);\n  itkSetMacro(XMLFileName, std::string);\n\nprotected:\n  DigisensGeometryReader();\n\n\nprivate:\n  void\n  GenerateData() override;\n\n  GeometryType::Pointer m_Geometry;\n  std::string           m_XMLFileName;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkDigisensGeometryXMLFileReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDigisensGeometryXMLFileReader_h\n#define rtkDigisensGeometryXMLFileReader_h\n\n#include \"RTKExport.h\"\n#include <itkXMLFile.h>\n#include <itkMetaDataDictionary.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class DigisensGeometryXMLFileReader\n *\n * Reads the XML-format file written by Digisens geometric\n * calibration tool.\n *\n * \\author Simon Rit\n *\n * \\test rtkdigisenstest.cxx\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT DigisensGeometryXMLFileReader : public itk::XMLReader<itk::MetaDataDictionary>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DigisensGeometryXMLFileReader);\n\n  /** Standard type alias */\n  using Self = DigisensGeometryXMLFileReader;\n  using Superclass = itk::XMLReader<itk::MetaDataDictionary>;\n  using Pointer = itk::SmartPointer<Self>;\n  using CurrentSectionType = enum { NONE, ROTATION, XRAY, CAMERA, RADIOS, GRID, PROCESSING };\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DigisensGeometryXMLFileReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Determine if a file can be read */\n  int\n  CanReadFile(const char * name) override;\n\nprotected:\n  DigisensGeometryXMLFileReader();\n  ~DigisensGeometryXMLFileReader() override = default;\n\n  void\n  StartElement(const char * name, const char ** atts) override;\n\n  void\n  EndElement(const char * name) override;\n\n  void\n  CharacterDataHandler(const char * inData, int inLength) override;\n\nprivate:\n  itk::MetaDataDictionary m_Dictionary;\n  std::string             m_CurCharacterData;\n  int                     m_NumberOfFiles;\n  CurrentSectionType      m_CurrentSection;\n  int                     m_TreeLevel;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkDisplacedDetectorForOffsetFieldOfViewImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDisplacedDetectorForOffsetFieldOfViewImageFilter_h\n#define rtkDisplacedDetectorForOffsetFieldOfViewImageFilter_h\n\n#include \"rtkDisplacedDetectorImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class DisplacedDetectorForOffsetFieldOfViewImageFilter\n * \\brief Weigting for displaced detectors with offset field-of-view\n *\n * The class does something similar to rtk::DisplacedDetectorImageFilter but\n * handles in addition the case of a field-of-view that is not centered on the\n * center of rotation.\n *\n * \\test rtkdisplaceddetectorcompoffsettest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT DisplacedDetectorForOffsetFieldOfViewImageFilter\n  : public rtk::DisplacedDetectorImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DisplacedDetectorForOffsetFieldOfViewImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DisplacedDetectorForOffsetFieldOfViewImageFilter;\n  using Superclass = rtk::DisplacedDetectorImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n  using WeightImageType = itk::Image<typename TOutputImage::PixelType, 1>;\n\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using GeometryPointer = GeometryType::Pointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(DisplacedDetectorForOffsetFieldOfViewImageFilter);\n\nprotected:\n  DisplacedDetectorForOffsetFieldOfViewImageFilter() = default;\n  ~DisplacedDetectorForOffsetFieldOfViewImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  /**\n   * Center coordinates and size of the FOV cylinder.\n   */\n  double m_FOVRadius{ -1. };\n  double m_FOVCenterX{ 0. };\n  double m_FOVCenterZ{ 0. };\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDisplacedDetectorForOffsetFieldOfViewImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDisplacedDetectorForOffsetFieldOfViewImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDisplacedDetectorForOffsetFieldOfViewImageFilter_hxx\n#define rtkDisplacedDetectorForOffsetFieldOfViewImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n#include \"rtkFieldOfViewImageFilter.h\"\n\nnamespace rtk\n{\n\n/**\n * When the detector is displaced, one needs to zero pad the input data on the\n * nearest side to the center.\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDisplacedDetectorForOffsetFieldOfViewImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  // get pointers to the input and output\n  typename Superclass::Superclass::InputImagePointer  inputPtr = const_cast<TInputImage *>(this->GetInput());\n  typename Superclass::Superclass::OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!outputPtr || !inputPtr)\n  {\n    return;\n  }\n\n  // Copy the meta data for this data type\n  outputPtr->SetSpacing(inputPtr->GetSpacing());\n  outputPtr->SetOrigin(inputPtr->GetOrigin());\n  outputPtr->SetDirection(inputPtr->GetDirection());\n  outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel());\n\n  typename TOutputImage::RegionType outputLargestPossibleRegion = inputPtr->GetLargestPossibleRegion();\n\n  if (this->GetDisable())\n  {\n    outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);\n    return;\n  }\n  else if (this->GetGeometry()->GetRadiusCylindricalDetector() != 0)\n  {\n    itkGenericExceptionMacro(<< \"Displaced detector cannot handle cylindrical detector. \"\n                             << \"Consider disabling it by setting m_Disable=true \"\n                             << \"or using the nodisplaced flag of the application you are running\");\n  }\n\n  using FOVFilterType = typename rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType>;\n  auto fieldofview = FOVFilterType::New();\n  fieldofview->SetProjectionsStack(inputPtr.GetPointer());\n  fieldofview->SetGeometry(this->GetGeometry());\n  bool   hasOverlap = fieldofview->ComputeFOVRadius(FOVFilterType::RADIUSBOTH, m_FOVCenterX, m_FOVCenterZ, m_FOVRadius);\n  double xi = NAN, zi = NAN, ri = NAN;\n  fieldofview->ComputeFOVRadius(FOVFilterType::RADIUSINF, xi, zi, ri);\n  double xs = NAN, zs = NAN, rs = NAN;\n  fieldofview->ComputeFOVRadius(FOVFilterType::RADIUSSUP, xs, zs, rs);\n\n  // 4 cases depending on the position of the two corners\n  // Case 1: Impossible to account for too large displacements\n  if (!hasOverlap)\n  {\n    itkGenericExceptionMacro(<< \"Cannot account for too large detector displacements, a part of\"\n                             << \" space must be covered by all projections.\");\n  }\n  // Case 2: Not displaced if less than 10% relative difference between radii\n  else if (200. * itk::Math::abs(ri - rs) / (ri + rs) < 10.)\n  {\n  }\n  else if (rs > ri)\n  {\n    this->SetInPlace(false);\n    itk::Index<3>::IndexValueType index =\n      outputLargestPossibleRegion.GetIndex()[0] - outputLargestPossibleRegion.GetSize()[0];\n    outputLargestPossibleRegion.SetIndex(0, index);\n    outputLargestPossibleRegion.SetSize(0, outputLargestPossibleRegion.GetSize()[0] * 2);\n  }\n  else\n  {\n    this->SetInPlace(false);\n    outputLargestPossibleRegion.SetSize(0, outputLargestPossibleRegion.GetSize()[0] * 2);\n  }\n\n  outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDisplacedDetectorForOffsetFieldOfViewImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Compute overlap between input and output\n  itk::ImageRegionIterator<OutputImageType> itOut(this->GetOutput(), outputRegionForThread);\n  OutputImageRegionType                     overlapRegion = outputRegionForThread;\n  if (!overlapRegion.Crop(this->GetInput()->GetLargestPossibleRegion()))\n  {\n    // No overlap, set output region to 0\n    while (!itOut.IsAtEnd())\n    {\n      itOut.Set(0.);\n      ++itOut;\n    }\n    return;\n  }\n  itk::ImageRegionConstIterator<InputImageType> itIn(this->GetInput(), overlapRegion);\n\n  // Not displaced, nothing to do\n  if (this->GetInput()->GetLargestPossibleRegion().GetSize()[0] ==\n        this->GetOutput()->GetLargestPossibleRegion().GetSize()[0] ||\n      this->GetDisable())\n  {\n    // If not in place, copy is required\n    if (this->GetInput() != this->GetOutput())\n    {\n      while (!itIn.IsAtEnd())\n      {\n        itOut.Set(itIn.Get());\n        ++itIn;\n        ++itOut;\n      }\n    }\n    return;\n  }\n\n  // Weight image parameters\n  typename WeightImageType::RegionType  region;\n  typename WeightImageType::SpacingType spacing;\n  typename WeightImageType::PointType   origin;\n  region.SetSize(0, overlapRegion.GetSize(0));\n  region.SetIndex(0, overlapRegion.GetIndex(0));\n  spacing[0] = this->GetInput()->GetSpacing()[0];\n  origin[0] = this->GetInput()->GetOrigin()[0];\n\n  // Create one line of weights\n  auto weights = WeightImageType::New();\n  weights->SetSpacing(spacing);\n  weights->SetOrigin(origin);\n  weights->SetRegions(region);\n  weights->Allocate();\n  typename itk::ImageRegionIteratorWithIndex<WeightImageType> itWeights(weights, weights->GetLargestPossibleRegion());\n  for (unsigned int k = 0; k < overlapRegion.GetSize(2); k++, itWeights.GoToBegin())\n  {\n    typename GeometryType::HomogeneousVectorType sourcePosition;\n    sourcePosition = this->GetGeometry()->GetSourcePosition(itIn.GetIndex()[2]);\n    double oppInvNormSource = -1. / (sourcePosition[0] * sourcePosition[0] + sourcePosition[2] * sourcePosition[2]);\n    const double sourceToCenterFOVX = m_FOVCenterX - sourcePosition[0];\n    const double sourceToCenterFOVZ = m_FOVCenterZ - sourcePosition[2];\n    double       invNormSourceCenterFOV =\n      1. / sqrt(sourceToCenterFOVX * sourceToCenterFOVX + sourceToCenterFOVZ * sourceToCenterFOVZ);\n    double centerFOVAngle =\n      atan2(sourceToCenterFOVZ * invNormSourceCenterFOV, sourceToCenterFOVX * invNormSourceCenterFOV) -\n      atan2(sourcePosition[2] * oppInvNormSource, sourcePosition[0] * oppInvNormSource);\n    if (centerFOVAngle > itk::Math::pi)\n      centerFOVAngle -= 2 * itk::Math::pi;\n    if (centerFOVAngle < -itk::Math::pi)\n      centerFOVAngle += 2 * itk::Math::pi;\n    double theta2 =\n      asin(m_FOVRadius / sqrt(pow(m_FOVCenterX - sourcePosition[0], 2.) + pow(m_FOVCenterZ - sourcePosition[2], 2.)));\n    double theta1 = -1. * theta2;\n    theta1 += centerFOVAngle;\n    theta2 += centerFOVAngle;\n\n    // Prepare weights for current slice (depends on ProjectionOffsetsX)\n    const double sx = this->GetGeometry()->GetSourceOffsetsX()[itIn.GetIndex()[2]];\n    double       sid = this->GetGeometry()->GetSourceToIsocenterDistances()[itIn.GetIndex()[2]];\n    sid = sqrt(sid * sid + sx * sx); // To untilted situation\n    const double liml1 = tan(theta1) * sid;\n    const double liml2 = tan(theta2) * sid;\n    double       invsid = 0.;\n    double       piOverDen = 0.;\n    if (sid != 0.)\n    {\n      invsid = 1. / sid;\n      piOverDen = itk::Math::pi_over_2 *\n                  sqrt(sourceToCenterFOVX * sourceToCenterFOVX + sourceToCenterFOVZ * sourceToCenterFOVZ) / m_FOVRadius;\n    }\n    typename WeightImageType::PointType point;\n    weights->TransformIndexToPhysicalPoint(itWeights.GetIndex(), point);\n\n    if (this->GetInput()->GetLargestPossibleRegion().GetIndex()[0] !=\n        this->GetOutput()->GetLargestPossibleRegion().GetIndex()[0])\n    {\n      while (!itWeights.IsAtEnd())\n      {\n        const double l = this->GetGeometry()->ToUntiltedCoordinateAtIsocenter(itIn.GetIndex()[2], point[0]);\n        if (l <= liml1)\n          itWeights.Set(0.);\n        else if (l >= liml2)\n          itWeights.Set(2.);\n        else\n          itWeights.Set(sin(sin(atan(l * invsid) - centerFOVAngle) * piOverDen) + 1.);\n        ++itWeights;\n        point[0] += spacing[0];\n      }\n    }\n    else\n    {\n      while (!itWeights.IsAtEnd())\n      {\n        const double l = this->GetGeometry()->ToUntiltedCoordinateAtIsocenter(itIn.GetIndex()[2], point[0]);\n        if (l <= liml1)\n          itWeights.Set(2.0);\n        else if (l >= liml2)\n          itWeights.Set(0.0);\n        else\n          itWeights.Set(1. - sin(sin(atan(l * invsid) - centerFOVAngle) * piOverDen));\n        ++itWeights;\n        point[0] += spacing[0];\n      }\n    }\n\n    // Multiply each line of the current slice\n    for (unsigned int j = 0; j < overlapRegion.GetSize(1); j++)\n    {\n      // Set outside of overlap to 0 values\n      while (itOut.GetIndex()[0] != itIn.GetIndex()[0])\n      {\n        itOut.Set(0);\n        ++itOut;\n      }\n\n      itWeights.GoToBegin();\n      while (!itWeights.IsAtEnd())\n      {\n        itOut.Set(itIn.Get() * itWeights.Get());\n        ++itWeights;\n        ++itIn;\n        ++itOut;\n      }\n    }\n  }\n\n  // Make sure that last values are set to 0\n  while (!itOut.IsAtEnd())\n  {\n    itOut.Set(0);\n    ++itOut;\n  }\n}\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkDisplacedDetectorImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDisplacedDetectorImageFilter_h\n#define rtkDisplacedDetectorImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class DisplacedDetectorImageFilter\n * \\brief Weigting for displaced detectors\n *\n * Weighting of image projections to handle off-centered panels\n * in tomography reconstruction. Based on [Wang, Med Phys, 2002].\n *\n * Note that the filter does nothing if the panel shift is less than 10%\n * of its size. Otherwise, it does the weighting described in the publication\n * and zero pads the data on the nearest side to the center.\n * Therefore, the InPlace capability depends on the displacement.\n * It can only be inplace if there is no displacement, it can not otherwise.\n * The GenerateOutputInformation method takes care of properly setting this up.\n *\n * By default, it computes the minimum and maximum offsets from the complete geometry object.\n * When an independent projection has to be processed, these values have to be set by the user from\n * a priori knowledge of the detector displacements.\n *\n * The weighting accounts for variations in SourceToDetectorDistances,\n * SourceOffsetsX and ProjectionOffsetsX. It currently assumes constant\n * SourceToIsocenterDistances and 0. InPlaneAngles. The other parameters are\n * not relevant in the computation because the weighting is reproduced at\n * every gantry angle on each line of the projection images.\n *\n * \\test rtkdisplaceddetectortest.cxx, rtkdisplaceddetectorcompcudatest.cxx,\n * rtkdisplaceddetectorcompoffsettest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT DisplacedDetectorImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DisplacedDetectorImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DisplacedDetectorImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  static constexpr unsigned int NDimension = TInputImage::ImageDimension;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n  using WeightImageType = itk::Image<double, 1>;\n\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using GeometryConstPointer = GeometryType::ConstPointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(DisplacedDetectorImageFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetConstObjectMacro(Geometry, GeometryType);\n  itkSetConstObjectMacro(Geometry, GeometryType);\n\n  /** Get / Set whether the projections should be padded\n   * (yes for FDK, no for iterative) */\n  itkGetMacro(PadOnTruncatedSide, bool);\n  itkSetMacro(PadOnTruncatedSide, bool);\n\n  /**\n   * Get / Set the minimum and maximum offsets of the detector along the\n   * weighting direction desribed in ToUntiltedCoordinate.\n   */\n  void\n  SetOffsets(double minOffset, double maxOffset);\n  itkGetMacro(MinimumOffset, double);\n  itkGetMacro(MaximumOffset, double);\n\n  /** Get / Set the Disable parameter\n   */\n  itkGetMacro(Disable, bool);\n  itkSetMacro(Disable, bool);\n\nprotected:\n  DisplacedDetectorImageFilter() = default;\n\n  ~DisplacedDetectorImageFilter() override = default;\n\n  /** Retrieve computed inferior and superior corners */\n  itkGetMacro(InferiorCorner, double);\n  itkGetMacro(SuperiorCorner, double);\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  // Iterative filters do not need padding\n  bool m_PadOnTruncatedSide{ true };\n\nprivate:\n  /** RTK geometry object */\n  GeometryConstPointer m_Geometry;\n\n  /**\n   * Minimum and maximum offsets of the detector along the weighting direction, i.e. x.\n   * If a priori known, these values can be given as input. Otherwise, they are computed from the\n   * complete geometry.\n   */\n  double m_MinimumOffset{ 0. };\n  double m_MaximumOffset{ 0. };\n\n  /**\n   * Flag used to know if the user has entered the min/max values of the detector offset.\n   */\n  bool m_OffsetsSet{ false };\n\n  /** Superior and inferior position of the detector along the weighting\n   *  direction, i.e., the virtual detector described in ToUntiltedCoordinate.\n   */\n  double m_InferiorCorner{ 0. };\n  double m_SuperiorCorner{ 0. };\n\n  /** When using a geometry that the displaced detector cannot manage,\n   * it has to be disabled\n   */\n  bool m_Disable{ false };\n\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDisplacedDetectorImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDisplacedDetectorImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDisplacedDetectorImageFilter_hxx\n#define rtkDisplacedDetectorImageFilter_hxx\n\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDisplacedDetectorImageFilter<TInputImage, TOutputImage>::SetOffsets(double minOffset, double maxOffset)\n{\n  m_OffsetsSet = true;\n  itkDebugMacro(\"setting MinimumOffset to \" << minOffset);\n  if (this->m_MinimumOffset != minOffset)\n  {\n    this->m_MinimumOffset = minOffset;\n    this->Modified();\n  }\n  itkDebugMacro(\"setting MaximumOffset to \" << maxOffset);\n  if (this->m_MaximumOffset != maxOffset)\n  {\n    this->m_MaximumOffset = maxOffset;\n    this->Modified();\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDisplacedDetectorImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\n/**\n * Account for the padding computed in GenerateOutputInformation to propagate the\n * requested region.\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDisplacedDetectorImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer  inputPtr = const_cast<TInputImage *>(this->GetInput());\n  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n    return;\n\n  typename TInputImage::RegionType inputRequestedRegion = outputPtr->GetRequestedRegion();\n  inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion());\n\n  inputPtr->SetRequestedRegion(inputRequestedRegion);\n}\n\n/**\n * When the detector is displaced, one needs to zero pad the input data on the\n * nearest side to the center.\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDisplacedDetectorImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  // get pointers to the input and output\n  typename Superclass::InputImagePointer  inputPtr = const_cast<TInputImage *>(this->GetInput());\n  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!outputPtr || !inputPtr)\n  {\n    return;\n  }\n\n  // Copy the meta data for this data type\n  outputPtr->SetSpacing(inputPtr->GetSpacing());\n  outputPtr->SetOrigin(inputPtr->GetOrigin());\n  outputPtr->SetDirection(inputPtr->GetDirection());\n  outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel());\n\n  typename TOutputImage::RegionType outputLargestPossibleRegion = inputPtr->GetLargestPossibleRegion();\n\n  if (m_Disable)\n  {\n    outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);\n    return;\n  }\n  else if (this->GetGeometry()->GetRadiusCylindricalDetector() != 0)\n  {\n    itkGenericExceptionMacro(<< \"Displaced detector cannot handle cylindrical detector. \"\n                             << \"Consider disabling it by setting m_Disable=true \"\n                             << \"or using the nodisplaced flag of the application you are running\");\n  }\n\n  // Compute the X coordinates of the corners of the image\n  typename Superclass::InputImageType::PointType corner;\n  inputPtr->TransformIndexToPhysicalPoint(inputPtr->GetLargestPossibleRegion().GetIndex(), corner);\n  m_InferiorCorner = corner[0];\n  m_SuperiorCorner = m_InferiorCorner;\n  if (inputPtr->GetSpacing()[0] < 0.)\n    m_InferiorCorner += inputPtr->GetSpacing()[0] * (outputLargestPossibleRegion.GetSize(0) - 1);\n  else\n    m_SuperiorCorner += inputPtr->GetSpacing()[0] * (outputLargestPossibleRegion.GetSize(0) - 1);\n\n  if (!m_OffsetsSet)\n  {\n    // Account for projections offsets\n    double minSupUntiltCorner = itk::NumericTraits<double>::max();\n    double maxInfUntiltCorner = itk::NumericTraits<double>::NonpositiveMin();\n    for (unsigned int i = 0; i < m_Geometry->GetProjectionOffsetsX().size(); i++)\n    {\n      maxInfUntiltCorner =\n        std::max(maxInfUntiltCorner, m_Geometry->ToUntiltedCoordinateAtIsocenter(i, m_InferiorCorner));\n      minSupUntiltCorner =\n        std::min(minSupUntiltCorner, m_Geometry->ToUntiltedCoordinateAtIsocenter(i, m_SuperiorCorner));\n    }\n    m_InferiorCorner = maxInfUntiltCorner;\n    m_SuperiorCorner = minSupUntiltCorner;\n  }\n  else\n  {\n    m_InferiorCorner += m_MaximumOffset;\n    m_SuperiorCorner += m_MinimumOffset;\n  }\n\n  // 4 cases depending on the position of the two corners\n  // Case 1: Impossible to account for too large displacements\n  if (m_InferiorCorner > 0. || m_SuperiorCorner < 0.)\n  {\n    itkGenericExceptionMacro(<< \"Cannot account for detector displacement larger than 50% of panel size.\"\n                             << \" Corner inf=\" << m_InferiorCorner << \" and corner sup=\" << m_SuperiorCorner);\n  }\n  // Case 2: Not displaced, or explicit request not to pad: default outputLargestPossibleRegion is fine\n  else if ((itk::Math::abs(m_InferiorCorner + m_SuperiorCorner) <\n            0.1 * itk::Math::abs(m_SuperiorCorner - m_InferiorCorner)) ||\n           !m_PadOnTruncatedSide)\n  {\n  }\n  else if (m_SuperiorCorner + m_InferiorCorner > 0.)\n  {\n    this->SetInPlace(false);\n    typename itk::Index<NDimension>::IndexValueType index =\n      outputLargestPossibleRegion.GetIndex()[0] - outputLargestPossibleRegion.GetSize()[0];\n    outputLargestPossibleRegion.SetIndex(0, index);\n    outputLargestPossibleRegion.SetSize(0, outputLargestPossibleRegion.GetSize()[0] * 2);\n  }\n  else\n  {\n    this->SetInPlace(false);\n    outputLargestPossibleRegion.SetSize(0, outputLargestPossibleRegion.GetSize()[0] * 2);\n  }\n\n  outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDisplacedDetectorImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Declare the pixel and initialize it to the right length (for vector images)\n  typename TOutputImage::PixelType pix;\n  itk::NumericTraits<typename TOutputImage::PixelType>::SetLength(pix,\n                                                                  this->GetInput()->GetNumberOfComponentsPerPixel());\n\n  // Compute overlap between input and output\n  itk::ImageRegionIterator<OutputImageType> itOut(this->GetOutput(), outputRegionForThread);\n  OutputImageRegionType                     overlapRegion = outputRegionForThread;\n  if (!overlapRegion.Crop(this->GetInput()->GetLargestPossibleRegion()))\n  {\n    // No overlap, set output region to 0\n    while (!itOut.IsAtEnd())\n    {\n      itOut.Set({});\n      ++itOut;\n    }\n    return;\n  }\n  itk::ImageRegionConstIterator<InputImageType> itIn(this->GetInput(), overlapRegion);\n\n  // Not displaced, nothing to do\n  if ((itk::Math::abs(m_InferiorCorner + m_SuperiorCorner) <\n       0.1 * itk::Math::abs(m_SuperiorCorner - m_InferiorCorner)) ||\n      m_Disable)\n  {\n    // If not in place, copy is required\n    if (this->GetInput() != this->GetOutput())\n    {\n      while (!itIn.IsAtEnd())\n      {\n        itOut.Set(itIn.Get());\n        ++itIn;\n        ++itOut;\n      }\n    }\n    return;\n  }\n\n  // Weight image parameters\n  typename WeightImageType::RegionType  region;\n  typename WeightImageType::SpacingType spacing;\n  typename WeightImageType::PointType   origin;\n  region.SetSize(0, overlapRegion.GetSize(0));\n  region.SetIndex(0, overlapRegion.GetIndex(0));\n  spacing[0] = this->GetInput()->GetSpacing()[0];\n  origin[0] = this->GetInput()->GetOrigin()[0];\n\n  // Create one line of weights\n  auto weights = WeightImageType::New();\n  weights->SetSpacing(spacing);\n  weights->SetOrigin(origin);\n  weights->SetRegions(region);\n  weights->Allocate();\n  typename itk::ImageRegionIteratorWithIndex<WeightImageType> itWeights(weights, weights->GetLargestPossibleRegion());\n\n  double       theta = std::min(-1 * m_InferiorCorner, m_SuperiorCorner);\n  unsigned int nLinesPerProjection = overlapRegion.GetNumberOfPixels();\n  nLinesPerProjection /= overlapRegion.GetSize(0);\n  nLinesPerProjection /= overlapRegion.GetSize(NDimension - 1);\n  for (unsigned int k = 0; k < overlapRegion.GetSize(NDimension - 1); k++)\n  {\n    // Prepare weights for current slice (depends on ProjectionOffsetsX)\n    const double sx = m_Geometry->GetSourceOffsetsX()[itIn.GetIndex()[NDimension - 1]];\n    double       sid = m_Geometry->GetSourceToIsocenterDistances()[itIn.GetIndex()[NDimension - 1]];\n    sid = sqrt(sid * sid + sx * sx); // To untilted situation\n    double invsid = 0.;\n    double invden = 0.;\n    if (sid != 0.)\n    {\n      invsid = 1. / sid;\n      invden = 1. / (2. * std::atan(theta * invsid));\n    }\n    typename WeightImageType::PointType point;\n    weights->TransformIndexToPhysicalPoint(itWeights.GetIndex(), point);\n\n    if (m_SuperiorCorner + m_InferiorCorner > 0.)\n    {\n      itWeights.GoToBegin();\n      while (!itWeights.IsAtEnd())\n      {\n        const double l = m_Geometry->ToUntiltedCoordinateAtIsocenter(itIn.GetIndex()[NDimension - 1], point[0]);\n        if (l <= -1 * theta)\n          itWeights.Set(0.0);\n        else if (l >= theta)\n          itWeights.Set(2.0);\n        else\n          itWeights.Set(sin(itk::Math::pi * atan(l * invsid) * invden) + 1);\n        ++itWeights;\n        point[0] += spacing[0];\n      }\n    }\n    else\n    {\n      while (!itWeights.IsAtEnd())\n      {\n        const double l = m_Geometry->ToUntiltedCoordinateAtIsocenter(itIn.GetIndex()[NDimension - 1], point[0]);\n        if (l <= -1 * theta)\n          itWeights.Set(2.0);\n        else if (l >= theta)\n          itWeights.Set(0.0);\n        else\n          itWeights.Set(1 - sin(itk::Math::pi * atan(l * invsid) * invden));\n        ++itWeights;\n        point[0] += spacing[0];\n      }\n    }\n\n    // Multiply each line of the current 2D or 3D slice\n    for (unsigned int j = 0; j < nLinesPerProjection; j++)\n    {\n      // Set outside of overlap to 0 values\n      while (itOut.GetIndex()[0] != itIn.GetIndex()[0])\n      {\n        pix = itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue(pix);\n        itOut.Set(pix);\n        ++itOut;\n      }\n\n      itWeights.GoToBegin();\n      while (!itWeights.IsAtEnd())\n      {\n        itOut.Set(itIn.Get() * itWeights.Get());\n        ++itWeights;\n        ++itIn;\n        ++itOut;\n      }\n    }\n  }\n\n  // Make sure that last values are set to 0\n  while (!itOut.IsAtEnd())\n  {\n    pix = itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue(pix);\n    itOut.Set(pix);\n    ++itOut;\n  }\n}\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkDivergenceOfGradientConjugateGradientOperator.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDivergenceOfGradientConjugateGradientOperator_h\n#define rtkDivergenceOfGradientConjugateGradientOperator_h\n\n#include \"rtkConjugateGradientOperator.h\"\n\n#include \"rtkForwardDifferenceGradientImageFilter.h\"\n#include \"rtkBackwardDifferenceDivergenceImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class DivergenceOfGradientConjugateGradientOperator\n * \\brief Computes the divergence of the gradient of an image. To be used\n * with the ConjugateGradientImageFilter\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK IntensityImageFilters\n */\ntemplate <class TInputImage>\nclass ITK_TEMPLATE_EXPORT DivergenceOfGradientConjugateGradientOperator : public ConjugateGradientOperator<TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DivergenceOfGradientConjugateGradientOperator);\n\n  /** Extract dimension from input and output image. */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n\n  /** Convenient type alias for simplifying declarations. */\n  using InputImageType = TInputImage;\n\n  /** Standard class type alias. */\n  using Self = DivergenceOfGradientConjugateGradientOperator;\n  using Superclass = itk::ImageToImageFilter<InputImageType, InputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DivergenceOfGradientConjugateGradientOperator);\n\n  /** Image type alias support. */\n  using InputPixelType = typename InputImageType::PixelType;\n  using InputImageRegionType = typename InputImageType::RegionType;\n  using InputSizeType = typename InputImageType::SizeType;\n\n  /** Sub filter type definitions */\n  using GradientFilterType = ForwardDifferenceGradientImageFilter<TInputImage>;\n  using GradientImageType = typename GradientFilterType::OutputImageType;\n  using DivergenceFilterType = BackwardDifferenceDivergenceImageFilter<GradientImageType>;\n\n  void\n  SetDimensionsProcessed(bool * arg);\n\nprotected:\n  DivergenceOfGradientConjugateGradientOperator();\n  ~DivergenceOfGradientConjugateGradientOperator() override = default;\n\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  /** Sub filter pointers */\n  typename GradientFilterType::Pointer   m_GradientFilter;\n  typename DivergenceFilterType::Pointer m_DivergenceFilter;\n\n  bool m_DimensionsProcessed[TInputImage::ImageDimension];\n};\n\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDivergenceOfGradientConjugateGradientOperator.hxx\"\n#endif\n\n#endif //__rtkDivergenceOfGradientConjugateGradientOperator__\n"
  },
  {
    "path": "include/rtkDivergenceOfGradientConjugateGradientOperator.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDivergenceOfGradientConjugateGradientOperator_hxx\n#define rtkDivergenceOfGradientConjugateGradientOperator_hxx\n\n#include \"itkConstShapedNeighborhoodIterator.h\"\n#include \"itkNeighborhoodInnerProduct.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n#include \"itkNeighborhoodAlgorithm.h\"\n#include \"itkPeriodicBoundaryCondition.h\"\n#include \"itkOffset.h\"\n#include \"itkProgressReporter.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage>\nDivergenceOfGradientConjugateGradientOperator<TInputImage>::DivergenceOfGradientConjugateGradientOperator()\n{\n  // Default behaviour is to process all dimensions\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    m_DimensionsProcessed[dim] = true;\n  }\n\n  // Create the sub filters\n  m_GradientFilter = GradientFilterType::New();\n  m_DivergenceFilter = DivergenceFilterType::New();\n\n  // Set their initial connections\n  // These connections change after the first iteration\n  m_DivergenceFilter->SetInput(m_GradientFilter->GetOutput());\n\n  // Set whether the sub filters should release their data during pipeline execution\n  m_GradientFilter->ReleaseDataFlagOn();\n}\n\ntemplate <class TInputImage>\nvoid\nDivergenceOfGradientConjugateGradientOperator<TInputImage>::SetDimensionsProcessed(bool * arg)\n{\n  bool Modified = false;\n  for (int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    if (m_DimensionsProcessed[dim] != arg[dim])\n    {\n      m_DimensionsProcessed[dim] = arg[dim];\n      Modified = true;\n    }\n  }\n  if (Modified)\n    this->Modified();\n}\n\ntemplate <class TInputImage>\nvoid\nDivergenceOfGradientConjugateGradientOperator<TInputImage>::GenerateOutputInformation()\n{\n  // get pointers to the input and output\n  typename Superclass::OutputImagePointer     outputPtr = this->GetOutput();\n  typename Superclass::InputImageConstPointer inputPtr = this->GetInput();\n\n  // Set the inputs\n  m_GradientFilter->SetInput(inputPtr);\n\n  m_GradientFilter->SetDimensionsProcessed(m_DimensionsProcessed);\n  m_DivergenceFilter->SetDimensionsProcessed(m_DimensionsProcessed);\n\n  // Have the last filter calculate its output information,\n  m_DivergenceFilter->UpdateOutputInformation();\n  outputPtr->CopyInformation(m_DivergenceFilter->GetOutput());\n}\n\n\ntemplate <class TInputImage>\nvoid\nDivergenceOfGradientConjugateGradientOperator<TInputImage>::GenerateData()\n{\n  m_DivergenceFilter->Update();\n  this->GraftOutput(m_DivergenceFilter->GetOutput());\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDownsampleImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDownsampleImageFilter_h\n#define rtkDownsampleImageFilter_h\n\n#include \"itkImageToImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class DownsampleImageFilter\n * \\brief Downsamples an image by a factor in each dimension.\n *\n * This filter is inspired from Dan Mueller's GIFT package\n * https://www.insight-journal.org/browse/publication/103\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT DownsampleImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DownsampleImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DownsampleImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DownsampleImageFilter);\n\n  /** Typedef to images */\n  using OutputImageType = TOutputImage;\n  using InputImageType = TInputImage;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using InputImageConstPointer = typename InputImageType::ConstPointer;\n\n  /** Typedef to describe the output image region type. */\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n\n  /** ImageDimension enumeration. */\n  static constexpr unsigned int ImageDimension = TInputImage::ImageDimension;\n\n  /** Set the downsample factors. Values are clamped to\n   * a minimum value of 1.*/\n  void\n  SetFactors(const unsigned int factors[]);\n\n  /** Sets the downsample factor for the given dimension.\n   * All other dimensions are set to 1 */\n  void\n  SetFactor(unsigned int dimension, unsigned int factor);\n\n  /** DownsampleImageFilter produces an image which is a different\n   * resolution and with a different pixel spacing than its input\n   * image.  As such, DownsampleImageFilter needs to provide an\n   * implementation for GenerateOutputInformation() in order to inform\n   * the pipeline execution model.  The original documentation of this\n   * method is below.\n   * \\sa ProcessObject::GenerateOutputInformaton() */\n  void\n  GenerateOutputInformation() override;\n\n  /** DownsampleImageFilter needs a larger input requested region than the output\n   * requested region.  As such, DownsampleImageFilter needs to provide an\n   * implementation for GenerateInputRequestedRegion() in order to inform the\n   * pipeline execution model.\n   * \\sa ProcessObject::GenerateInputRequestedRegion() */\n  void\n  GenerateInputRequestedRegion() override;\n\nprotected:\n  DownsampleImageFilter();\n  ~DownsampleImageFilter() override = default;\n\n  /** DownsampleImageFilter can be implemented as a multithreaded filter.\n   * Therefore, this implementation provides a ThreadedGenerateData() routine\n   * which is called for each processing thread. The output image data is\n   * allocated automatically by the superclass prior to calling\n   * ThreadedGenerateData().  ThreadedGenerateData can only write to the\n   * portion of the output image specified by the parameter\n   * \"outputRegionForThread\"\n   *\n   * \\sa ImageToImageFilter::ThreadedGenerateData(),\n   *     ImageToImageFilter::GenerateData() */\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  unsigned int m_Factors[ImageDimension];\n  int          m_Offsets[ImageDimension];\n};\n\n\n} // end namespace rtk\n\n#ifndef rtk_MANUAL_INSTANTIATION\n#  include \"rtkDownsampleImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDownsampleImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDownsampleImageFilter_hxx\n#define rtkDownsampleImageFilter_hxx\n\n\n#include \"itkImageRegionIterator.h\"\n#include \"itkObjectFactory.h\"\n\nnamespace rtk\n{\n\n/**\n *   Constructor\n */\ntemplate <class TInputImage, class TOutputImage>\nDownsampleImageFilter<TInputImage, TOutputImage>::DownsampleImageFilter()\n{\n  this->SetNumberOfRequiredInputs(1);\n}\n\n/**\n *\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDownsampleImageFilter<TInputImage, TOutputImage>::SetFactors(const unsigned int factors[])\n{\n  unsigned int j = 0;\n\n  this->Modified();\n  for (j = 0; j < ImageDimension; j++)\n  {\n    m_Factors[j] = factors[j];\n    if (m_Factors[j] < 1)\n    {\n      m_Factors[j] = 1;\n    }\n  }\n}\n\n/**\n *\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDownsampleImageFilter<TInputImage, TOutputImage>::SetFactor(unsigned int dimension, unsigned int factor)\n{\n  unsigned int j = 0;\n\n  this->Modified();\n  for (j = 0; j < ImageDimension; j++)\n  {\n    if (j == dimension)\n    {\n      m_Factors[j] = factor;\n    }\n    else\n    {\n      m_Factors[j] = 1;\n    }\n  }\n}\n\n\n/**\n *\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDownsampleImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  itkDebugMacro(<< \"Actually executing\");\n\n  // Get the input and output pointers\n  InputImageConstPointer inputPtr = this->GetInput();\n  OutputImagePointer     outputPtr = this->GetOutput();\n\n  // Define/declare an iterator that will walk the output region for this\n  // thread.\n  using OutputIterator = itk::ImageRegionIterator<TOutputImage>;\n\n  // Define a few indices that will be used to translate from an input pixel\n  // to an output pixel\n  typename TInputImage::IndexType  inputStartIndex = inputPtr->GetLargestPossibleRegion().GetIndex();\n  typename TOutputImage::IndexType outputStartIndex = outputPtr->GetLargestPossibleRegion().GetIndex();\n\n  typename TOutputImage::OffsetType firstPixelOfOutputRegionForThreadOffset;\n  typename TInputImage::OffsetType  firstPixelOfInputRegionForThreadOffset;\n  typename TOutputImage::OffsetType firstPixelOfOutputLineOffset;\n  typename TInputImage::OffsetType  firstPixelOfInputLineOffset;\n  typename TOutputImage::OffsetType offset;\n\n  // Unless the downsampling factor is 1, we always skip the first pixel\n  // Create an offset array to enforce this behavior\n  for (unsigned int i = 0; i < TInputImage::ImageDimension; i++)\n  {\n    if (m_Factors[i] == 1)\n    {\n      offset[i] = 0;\n    }\n    else\n    {\n      offset[i] = 1;\n    }\n  }\n\n  // Find the first input pixel that is copied to the output (the one with lowest indices\n  // in all dimensions)\n  firstPixelOfOutputRegionForThreadOffset = outputRegionForThread.GetIndex() - outputStartIndex;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    firstPixelOfInputRegionForThreadOffset[dim] =\n      firstPixelOfOutputRegionForThreadOffset[dim] * m_Factors[dim] + offset[dim];\n  }\n\n  // Walk the slice obtained by setting the first coordinate to zero.\n  // Each pixel is the beginning of a line (a 1D vector traversing\n  // the output region along the first dimension). For each pixel,\n  // create an iterator and perform the copy from the input\n  OutputImageRegionType slice = outputRegionForThread;\n  slice.SetSize(0, 1);\n  OutputIterator sliceIt(outputPtr, slice);\n\n  while (!sliceIt.IsAtEnd())\n  {\n    // Determine the offset of the current pixel in the slice\n    firstPixelOfOutputLineOffset = sliceIt.GetIndex() - outputStartIndex;\n\n    // Calculate the offset of the corresponding input pixel\n    for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n    {\n      firstPixelOfInputLineOffset[dim] = firstPixelOfOutputLineOffset[dim] * m_Factors[dim] + offset[dim];\n    }\n\n    // Create the iterators\n    typename TOutputImage::RegionType outputLine = outputRegionForThread;\n    typename TOutputImage::SizeType   outputLineSize;\n    outputLineSize.Fill(1);\n    outputLineSize[0] = outputRegionForThread.GetSize(0);\n    outputLine.SetSize(outputLineSize);\n    outputLine.SetIndex(sliceIt.GetIndex());\n\n    typename TInputImage::RegionType inputLine = inputPtr->GetLargestPossibleRegion();\n    typename TInputImage::SizeType   inputLineSize;\n    inputLineSize.Fill(1);\n\n    // Short example of how to calculate the inputLineSize :\n    // If we downsample by a factor 3 the vector [x a x x b x x],\n    // (starting in \"a\" because we have already taken into account the\n    // offset, using firstPixelOfInputLineOffset) we obtain [a b],\n    // so all we need is a vector of length 4 = (2 - 1) * 3 + 1\n    inputLineSize[0] = (outputLineSize[0] - 1) * m_Factors[0] + 1;\n    inputLine.SetSize(inputLineSize);\n    inputLine.SetIndex(inputStartIndex + firstPixelOfInputLineOffset);\n\n    OutputIterator                             outIt(outputPtr, outputLine);\n    itk::ImageRegionConstIterator<TInputImage> inIt(inputPtr, inputLine);\n\n    // Walk the line and copy the pixels\n    while (!outIt.IsAtEnd())\n    {\n      outIt.Set(inIt.Get());\n      for (unsigned int i = 0; i < m_Factors[0]; i++)\n        ++inIt;\n      ++outIt;\n    }\n\n    // Move to next pixel in the slice\n    ++sliceIt;\n  }\n}\n\n\n/**\n *\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDownsampleImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get pointers to the input and output\n  InputImagePointer  inputPtr = const_cast<TInputImage *>(this->GetInput());\n  OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n  {\n    return;\n  }\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\n/**\n *\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDownsampleImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateOutputInformation();\n\n  // Get pointers to the input and output\n  InputImageConstPointer inputPtr = this->GetInput();\n  OutputImagePointer     outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n  {\n    return;\n  }\n\n  // We need to compute the output spacing, the output image size, and the\n  // output image start index\n  unsigned int                              i = 0;\n  const typename TInputImage::SpacingType & inputSpacing = inputPtr->GetSpacing();\n  const typename TInputImage::SizeType &    inputSize = inputPtr->GetLargestPossibleRegion().GetSize();\n  const typename TInputImage::IndexType &   inputStartIndex = inputPtr->GetLargestPossibleRegion().GetIndex();\n\n  typename TOutputImage::SpacingType outputSpacing;\n  typename TOutputImage::SizeType    outputSize;\n  typename TOutputImage::IndexType   outputStartIndex;\n\n  for (i = 0; i < TOutputImage::ImageDimension; i++)\n  {\n    outputSpacing[i] = inputSpacing[i] * (float)m_Factors[i];\n    outputSize[i] = (unsigned long)floor((float)inputSize[i] / (float)m_Factors[i]);\n    if (outputSize[i] < 1)\n    {\n      outputSize[i] = 1;\n    }\n\n    outputStartIndex[i] = (long)floor((float)inputStartIndex[i] / (float)m_Factors[i]);\n  }\n\n  outputPtr->SetSpacing(outputSpacing);\n\n  typename TOutputImage::RegionType outputLargestPossibleRegion;\n  outputLargestPossibleRegion.SetSize(outputSize);\n  outputLargestPossibleRegion.SetIndex(outputStartIndex);\n\n  outputPtr->SetRegions(outputLargestPossibleRegion);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawBoxImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawBoxImageFilter_h\n#define rtkDrawBoxImageFilter_h\n\n#include \"rtkDrawConvexImageFilter.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkBoxShape.h\"\n\nnamespace rtk\n{\n\n/** \\class DrawBoxImageFilter\n * \\brief Draws a 3D image user defined BoxShape.\n *\n * \\test rtkdrawgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT DrawBoxImageFilter : public DrawConvexImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DrawBoxImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DrawBoxImageFilter;\n  using Superclass = DrawConvexImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using PointType = BoxShape::PointType;\n  using VectorType = BoxShape::VectorType;\n  using ScalarType = BoxShape::ScalarType;\n  using RotationMatrixType = BoxShape::RotationMatrixType;\n  using ImageBaseType = BoxShape::ImageBaseType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DrawBoxImageFilter);\n\n  /** Get / Set the constant density of the volume */\n  itkGetMacro(Density, ScalarType);\n  itkSetMacro(Density, ScalarType);\n\n  /** Get reference to vector of plane parameters. */\n  itkGetConstReferenceMacro(PlaneDirections, std::vector<VectorType>);\n  itkGetConstReferenceMacro(PlanePositions, std::vector<ScalarType>);\n\n  /** See ConvexShape for the definition of clip planes. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n\n  /** Set the box from an image. See rtk::BoxShape::SetBoxFromImage. */\n  void\n  SetBoxFromImage(const ImageBaseType * img, bool bWithExternalHalfPixelBorder = true);\n\n  /** Get/Set the box parameters. See rtk::BoxShape. */\n  itkGetMacro(BoxMin, VectorType);\n  itkSetMacro(BoxMin, VectorType);\n  itkGetMacro(BoxMax, VectorType);\n  itkSetMacro(BoxMax, VectorType);\n  itkGetMacro(Direction, RotationMatrixType);\n  itkSetMacro(Direction, RotationMatrixType);\n\nprotected:\n  DrawBoxImageFilter();\n  ~DrawBoxImageFilter() = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\nprivate:\n  ScalarType              m_Density{ 1. };\n  std::vector<VectorType> m_PlaneDirections;\n  std::vector<ScalarType> m_PlanePositions;\n\n  VectorType         m_BoxMin{ 0. };\n  VectorType         m_BoxMax{ 0. };\n  RotationMatrixType m_Direction;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDrawBoxImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawBoxImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawBoxImageFilter_hxx\n#define rtkDrawBoxImageFilter_hxx\n\n#include <iostream>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nDrawBoxImageFilter<TInputImage, TOutputImage>::DrawBoxImageFilter()\n{\n  m_Direction.SetIdentity();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawBoxImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->GetConvexObject() == nullptr)\n    this->SetConvexObject(BoxShape::New().GetPointer());\n\n  Superclass::BeforeThreadedGenerateData();\n\n  BoxShape * qo = dynamic_cast<BoxShape *>(this->GetConvexObject());\n  if (qo == nullptr)\n  {\n    itkExceptionMacro(\"This is not a BoxShape!\");\n  }\n\n  qo->SetDensity(this->GetDensity());\n  qo->SetClipPlanes(this->GetPlaneDirections(), this->GetPlanePositions());\n  qo->SetBoxMin(this->GetBoxMin());\n  qo->SetBoxMax(this->GetBoxMax());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawBoxImageFilter<TInputImage, TOutputImage>::AddClipPlane(const VectorType & dir, const ScalarType & pos)\n{\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawBoxImageFilter<TInputImage, TOutputImage>::SetBoxFromImage(const ImageBaseType * _arg,\n                                                               bool                  bWithExternalHalfPixelBorder)\n{\n  if (this->GetConvexObject() == nullptr)\n    this->SetConvexObject(BoxShape::New().GetPointer());\n  BoxShape * qo = dynamic_cast<BoxShape *>(this->GetConvexObject());\n  if (qo == nullptr)\n  {\n    itkExceptionMacro(\"This is not a BoxShape!\");\n  }\n  qo->SetBoxFromImage(_arg, bWithExternalHalfPixelBorder);\n  SetBoxMin(qo->GetBoxMin());\n  SetBoxMax(qo->GetBoxMin());\n  SetDirection(qo->GetDirection());\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawConeImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawConeImageFilter_h\n#define rtkDrawConeImageFilter_h\n\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class DrawConeImageFilter\n * \\brief Draws a cone in a 3D image.\n *\n * \\test rtkdrawgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT DrawConeImageFilter : public DrawEllipsoidImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DrawConeImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DrawConeImageFilter;\n  using Superclass = DrawEllipsoidImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using ScalarType = ConvexShape::ScalarType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DrawConeImageFilter);\n\nprotected:\n  DrawConeImageFilter() = default;\n  ~DrawConeImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDrawConeImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawConeImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawConeImageFilter_hxx\n#define rtkDrawConeImageFilter_hxx\n\n#include \"rtkQuadricShape.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawConeImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  Superclass::BeforeThreadedGenerateData();\n  dynamic_cast<QuadricShape *>(this->GetModifiableConvexShape())->SetJ(0.);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawConvexImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawConvexImageFilter_h\n#define rtkDrawConvexImageFilter_h\n\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkConvexShape.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class DrawConvexImageFilter\n * \\brief Draws a rtk::ConvexShape in a 3D image.\n *\n * \\test rtkforbildtest.cxx\n *\n * \\author Mathieu Dupont, Simon Rit\n *\n * \\ingroup RTK\n *\n */\n\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT DrawConvexImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DrawConvexImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DrawConvexImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using ConvexShapePointer = ConvexShape::Pointer;\n  using ScalarType = ConvexShape::ScalarType;\n  using PointType = ConvexShape::PointType;\n  using VectorType = ConvexShape::VectorType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DrawConvexImageFilter);\n\n  /** Get / Set the object pointer to the ConvexShape. */\n  itkGetModifiableObjectMacro(ConvexShape, ConvexShape);\n  itkSetObjectMacro(ConvexShape, ConvexShape);\n\nprotected:\n  DrawConvexImageFilter();\n  ~DrawConvexImageFilter() override = default;\n\n  /** ConvexShape must be created in the BeforeThreadedGenerateData in the\n   * daugter classes. */\n  void\n  BeforeThreadedGenerateData() override;\n\n  /** Apply changes to the input image requested region. */\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  ConvexShapePointer m_ConvexShape;\n};\n\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDrawConvexImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawConvexImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawConvexImageFilter_hxx\n#define rtkDrawConvexImageFilter_hxx\n\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nDrawConvexImageFilter<TInputImage, TOutputImage>::DrawConvexImageFilter() = default;\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawConvexImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->m_ConvexShape.IsNull())\n    itkExceptionMacro(<< \"ConvexShape has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawConvexImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  typename TOutputImage::PointType point;\n  const TInputImage *              input = this->GetInput();\n\n  typename itk::ImageRegionConstIterator<TInputImage> itIn(input, outputRegionForThread);\n  typename itk::ImageRegionIterator<TOutputImage>     itOut(this->GetOutput(), outputRegionForThread);\n\n  while (!itOut.IsAtEnd())\n  {\n    this->GetInput()->TransformIndexToPhysicalPoint(itOut.GetIndex(), point);\n    PointType p(&(point[0]));\n    if (m_ConvexShape->IsInside(p))\n      itOut.Set(itIn.Get() + m_ConvexShape->GetDensity());\n    else\n      itOut.Set(itIn.Get());\n    ++itIn;\n    ++itOut;\n  }\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawCubeImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawCubeImageFilter_h\n#define rtkDrawCubeImageFilter_h\n\n#include \"rtkDrawBoxImageFilter.h\"\n\n#include <vector>\n\n// Kept for backward compatibility\n#define DrawCubeImageFilter DrawBoxImageFilter\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawCylinderImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawCylinderImageFilter_h\n#define rtkDrawCylinderImageFilter_h\n\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class DrawCylinderImageFilter\n * \\brief Draws a cylinder in a 3D image.\n *\n * A cylinder is actually defined by a QuadricShape using first\n * QuadricShape::SetEllipsoid and then with the cylinder direction defined by\n * one 0 component in the axis vector.\n *\n * \\test rtkdrawgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT DrawCylinderImageFilter : public DrawEllipsoidImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DrawCylinderImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DrawCylinderImageFilter;\n  using Superclass = DrawEllipsoidImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using ScalarType = ConvexShape::ScalarType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DrawCylinderImageFilter);\n\nprotected:\n  DrawCylinderImageFilter() = default;\n  ~DrawCylinderImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDrawCylinderImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawCylinderImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawCylinderImageFilter_hxx\n#define rtkDrawCylinderImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawCylinderImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->GetAxis()[0] * this->GetAxis()[1] * this->GetAxis()[2] != itk::NumericTraits<ScalarType>::ZeroValue())\n  {\n    itkExceptionMacro(<< \"Axis \" << this->GetAxis() << \" does not contain any 0 value as a cylinder should.\");\n  }\n  Superclass::BeforeThreadedGenerateData();\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawEllipsoidImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawEllipsoidImageFilter_h\n#define rtkDrawEllipsoidImageFilter_h\n\n#include \"rtkDrawConvexImageFilter.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class DrawEllipsoidImageFilter\n * \\brief Draws an ellipsoid in a 3D image\n *\n * \\test rtkdrawgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT DrawEllipsoidImageFilter : public DrawConvexImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DrawEllipsoidImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DrawEllipsoidImageFilter;\n  using Superclass = DrawConvexImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using PointType = ConvexShape::PointType;\n  using VectorType = ConvexShape::VectorType;\n  using ScalarType = ConvexShape::ScalarType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DrawEllipsoidImageFilter);\n\n  /** Get / Set the constant density of the volume */\n  itkGetMacro(Density, ScalarType);\n  itkSetMacro(Density, ScalarType);\n\n  /** Get reference to vector of plane parameters. */\n  itkGetConstReferenceMacro(PlaneDirections, std::vector<VectorType>);\n  itkGetConstReferenceMacro(PlanePositions, std::vector<ScalarType>);\n\n  /** See ConvexShape for the definition of clip planes. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n\n  /** Get/Set the center of the ellipsoid. */\n  itkGetMacro(Center, PointType);\n  itkSetMacro(Center, PointType);\n\n  /** Get/Set the semi-principal axes of the ellipsoid. */\n  itkGetMacro(Axis, VectorType);\n  itkSetMacro(Axis, VectorType);\n\n  /** Get/Set the rotation angle around the y axis. */\n  itkGetMacro(Angle, ScalarType);\n  itkSetMacro(Angle, ScalarType);\n\nprotected:\n  DrawEllipsoidImageFilter();\n  ~DrawEllipsoidImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\nprivate:\n  ScalarType              m_Density{ 1. };\n  std::vector<VectorType> m_PlaneDirections;\n  std::vector<ScalarType> m_PlanePositions;\n\n  PointType  m_Center;\n  VectorType m_Axis;\n  ScalarType m_Angle{ 0. };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDrawEllipsoidImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawEllipsoidImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawEllipsoidImageFilter_hxx\n#define rtkDrawEllipsoidImageFilter_hxx\n\n#include <iostream>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n#include \"rtkQuadricShape.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nDrawEllipsoidImageFilter<TInputImage, TOutputImage>::DrawEllipsoidImageFilter()\n{\n  m_Center.Fill(0.);\n  m_Axis.Fill(90.);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawEllipsoidImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->GetConvexShape() == nullptr)\n    this->SetConvexShape(QuadricShape::New().GetPointer());\n  Superclass::BeforeThreadedGenerateData();\n  auto * qo = dynamic_cast<QuadricShape *>(this->GetModifiableConvexShape());\n  if (qo == nullptr)\n  {\n    itkExceptionMacro(\"This is not a QuadricShape!\");\n  }\n  qo->SetEllipsoid(m_Center, m_Axis, m_Angle);\n  qo->SetDensity(m_Density);\n  qo->SetClipPlanes(this->GetPlaneDirections(), this->GetPlanePositions());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawEllipsoidImageFilter<TInputImage, TOutputImage>::AddClipPlane(const VectorType & dir, const ScalarType & pos)\n{\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawGeometricPhantomImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawGeometricPhantomImageFilter_h\n#define rtkDrawGeometricPhantomImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include <itkAddImageFilter.h>\n#include \"rtkGeometricPhantom.h\"\n\nnamespace rtk\n{\n\n/** \\class DrawGeometricPhantomImageFilter\n * \\brief Draws a GeometricPhantom in a 3D image\n *\n * \\test rtkprojectgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT DrawGeometricPhantomImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DrawGeometricPhantomImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DrawGeometricPhantomImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using GeometricPhantomConstPointer = GeometricPhantom::ConstPointer;\n  using StringType = std::string;\n  using VectorType = ConvexShape::VectorType;\n  using RotationMatrixType = ConvexShape::RotationMatrixType;\n  using ScalarType = ConvexShape::ScalarType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DrawGeometricPhantomImageFilter);\n\n  /** Get / Set the object pointer to the geometry. */\n  itkGetConstObjectMacro(GeometricPhantom, GeometricPhantom);\n  itkSetConstObjectMacro(GeometricPhantom, GeometricPhantom);\n\n  /** Get/Set the phantom file path. */\n  itkSetMacro(ConfigFile, StringType);\n  itkGetMacro(ConfigFile, StringType);\n\n  /** Multiplicative scaling factor along each 3D component. */\n  itkSetMacro(PhantomScale, VectorType);\n  itkGetMacro(PhantomScale, VectorType);\n\n  /** Set isotropic scaling factor. */\n  virtual void\n  SetPhantomScale(const ScalarType _arg)\n  {\n    SetPhantomScale(VectorType(_arg));\n  }\n\n  /** Get / Set the spatial offset of the phantom relative to its center. The\n   * default value is (0, 0, 0). */\n  itkSetMacro(OriginOffset, VectorType);\n  itkGetMacro(OriginOffset, VectorType);\n\n  /** Get / Set a rotation matrix for the phantom. Default is identity. */\n  itkSetMacro(RotationMatrix, RotationMatrixType);\n  itkGetMacro(RotationMatrix, RotationMatrixType);\n\n  /** Add clipping plane to the object. The plane is defined by the equation\n   * dir * (x,y,z)' + pos = 0. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n  void\n  SetClipPlanes(const std::vector<VectorType> & dir, const std::vector<ScalarType> & pos);\n\nprotected:\n  DrawGeometricPhantomImageFilter();\n  ~DrawGeometricPhantomImageFilter() override = default;\n\n  void\n  GenerateData() override;\n\nprivate:\n  GeometricPhantomConstPointer m_GeometricPhantom;\n  StringType                   m_ConfigFile;\n  VectorType                   m_PhantomScale{ 1. };\n  VectorType                   m_OriginOffset{ 0. };\n  RotationMatrixType           m_RotationMatrix;\n  std::vector<VectorType>      m_PlaneDirections;\n  std::vector<ScalarType>      m_PlanePositions;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDrawGeometricPhantomImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawGeometricPhantomImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawGeometricPhantomImageFilter_hxx\n#define rtkDrawGeometricPhantomImageFilter_hxx\n\n#include \"rtkForbildPhantomFileReader.h\"\n#include \"rtkDrawConvexImageFilter.h\"\n\n#include <iostream>\n#include <fstream>\n#include <sstream>\n#include <cstdio>\n#include <cstdlib>\n\nnamespace rtk\n{\ntemplate <class TInputImage, class TOutputImage>\nDrawGeometricPhantomImageFilter<TInputImage, TOutputImage>::DrawGeometricPhantomImageFilter()\n{\n  m_RotationMatrix.SetIdentity();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawGeometricPhantomImageFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  // Reading figure config file\n  if (!m_ConfigFile.empty())\n  {\n    auto reader = rtk::ForbildPhantomFileReader::New();\n    reader->SetFilename(m_ConfigFile);\n    reader->GenerateOutputInformation();\n    this->m_GeometricPhantom = reader->GetGeometricPhantom();\n  }\n\n  // Check that it's not empty\n  const GeometricPhantom::ConvexShapeVector & cov = m_GeometricPhantom->GetConvexShapes();\n  if (cov.empty())\n    itkExceptionMacro(<< \"Empty phantom\");\n\n  // Create one add filter per convex object\n  std::vector<typename itk::ImageSource<TOutputImage>::Pointer> drawers;\n  for (const auto & convexShape : cov)\n  {\n    ConvexShape::Pointer co = convexShape->Clone();\n    co->Rotate(m_RotationMatrix);\n    co->Translate(m_OriginOffset);\n    co->Rescale(m_PhantomScale);\n    for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n      co->AddClipPlane(m_PlaneDirections[i], m_PlanePositions[i]);\n\n    if (!drawers.empty())\n    {\n      using RCOIType = DrawConvexImageFilter<TOutputImage, TOutputImage>;\n      auto rcoi = RCOIType::New();\n      rcoi->SetInput(drawers.back()->GetOutput());\n      rcoi->SetConvexShape(co);\n      drawers.push_back(rcoi.GetPointer());\n    }\n    else\n    {\n      using RCOIType = DrawConvexImageFilter<TInputImage, TOutputImage>;\n      auto rcoi = RCOIType::New();\n      rcoi->SetInput(this->GetInput());\n      rcoi->SetConvexShape(co);\n      drawers.push_back(rcoi.GetPointer());\n    }\n  }\n\n  drawers.back()->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  drawers.back()->Update();\n  this->GraftOutput(drawers.back()->GetOutput());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawGeometricPhantomImageFilter<TInputImage, TOutputImage>::AddClipPlane(const VectorType & dir, const ScalarType & pos)\n{\n  for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n  {\n    if (dir == m_PlaneDirections[i] && pos == m_PlanePositions[i])\n      return;\n  }\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawGeometricPhantomImageFilter<TInputImage, TOutputImage>::SetClipPlanes(const std::vector<VectorType> & dir,\n                                                                          const std::vector<ScalarType> & pos)\n{\n  m_PlaneDirections = dir;\n  m_PlanePositions = pos;\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawQuadricImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawQuadricImageFilter_h\n#define rtkDrawQuadricImageFilter_h\n\n#include \"rtkDrawConvexImageFilter.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class DrawQuadricImageFilter\n * \\brief Draws a QuadricShape in a 3D image\n *\n * \\test rtkdrawgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT DrawQuadricImageFilter : public DrawConvexImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DrawQuadricImageFilter);\n\n  /** Standard class type alias. */\n  using Self = DrawQuadricImageFilter;\n  using Superclass = DrawConvexImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using VectorType = ConvexShape::VectorType;\n  using ScalarType = ConvexShape::ScalarType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DrawQuadricImageFilter);\n\n  /** Get / Set the constant density of the QuadricShape */\n  itkGetMacro(Density, ScalarType);\n  itkSetMacro(Density, ScalarType);\n\n  /** Get reference to vector of plane parameters. */\n  itkGetConstReferenceMacro(PlaneDirections, std::vector<VectorType>);\n  itkGetConstReferenceMacro(PlanePositions, std::vector<ScalarType>);\n\n  /** See ConvexShape for the definition of clip planes. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n\n  itkGetMacro(A, ScalarType);\n  itkSetMacro(A, ScalarType);\n  itkGetMacro(B, ScalarType);\n  itkSetMacro(B, ScalarType);\n  itkGetMacro(C, ScalarType);\n  itkSetMacro(C, ScalarType);\n  itkGetMacro(D, ScalarType);\n  itkSetMacro(D, ScalarType);\n  itkGetMacro(E, ScalarType);\n  itkSetMacro(E, ScalarType);\n  itkGetMacro(F, ScalarType);\n  itkSetMacro(F, ScalarType);\n  itkGetMacro(G, ScalarType);\n  itkSetMacro(G, ScalarType);\n  itkGetMacro(H, ScalarType);\n  itkSetMacro(H, ScalarType);\n  itkGetMacro(I, ScalarType);\n  itkSetMacro(I, ScalarType);\n  itkGetMacro(J, ScalarType);\n  itkSetMacro(J, ScalarType);\n\nprotected:\n  DrawQuadricImageFilter();\n  ~DrawQuadricImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\nprivate:\n  ScalarType              m_Density{ 1. };\n  std::vector<VectorType> m_PlaneDirections;\n  std::vector<ScalarType> m_PlanePositions;\n\n  ScalarType m_A{ 0. };\n  ScalarType m_B{ 0. };\n  ScalarType m_C{ 0. };\n  ScalarType m_D{ 0. };\n  ScalarType m_E{ 0. };\n  ScalarType m_F{ 0. };\n  ScalarType m_G{ 0. };\n  ScalarType m_H{ 0. };\n  ScalarType m_I{ 0. };\n  ScalarType m_J{ 0. };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDrawQuadricImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawQuadricImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawQuadricImageFilter_hxx\n#define rtkDrawQuadricImageFilter_hxx\n\n#include <iostream>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n#include \"rtkQuadricShape.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nDrawQuadricImageFilter<TInputImage, TOutputImage>::DrawQuadricImageFilter()\n{}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawQuadricImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->GetConvexShape() == nullptr)\n    this->SetConvexShape(QuadricShape::New().GetPointer());\n\n  Superclass::BeforeThreadedGenerateData();\n\n  auto * qo = dynamic_cast<QuadricShape *>(this->GetModifiableConvexShape());\n  if (qo == nullptr)\n  {\n    itkExceptionMacro(\"This is not a QuadricShape!\");\n  }\n\n  qo->SetDensity(this->GetDensity());\n  qo->SetClipPlanes(this->GetPlaneDirections(), this->GetPlanePositions());\n  qo->SetA(this->GetA());\n  qo->SetB(this->GetB());\n  qo->SetC(this->GetC());\n  qo->SetD(this->GetD());\n  qo->SetE(this->GetE());\n  qo->SetF(this->GetF());\n  qo->SetG(this->GetG());\n  qo->SetH(this->GetH());\n  qo->SetI(this->GetI());\n  qo->SetJ(this->GetJ());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawQuadricImageFilter<TInputImage, TOutputImage>::AddClipPlane(const VectorType & dir, const ScalarType & pos)\n{\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawSheppLoganFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawSheppLoganFilter_h\n#define rtkDrawSheppLoganFilter_h\n\n#include \"rtkDrawGeometricPhantomImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class DrawSheppLoganFilter\n * \\brief Draws a SheppLoganPhantom in a 3D image with a default scale of 128.\n *\n * \\test rtkRaycastInterpolatorForwardProjectionTest.cxx,\n * rtkprojectgeometricphantomtest.cxx, rtkfdktest.cxx, rtkrampfiltertest.cxx,\n * rtkforwardprojectiontest.cxx, rtkdisplaceddetectortest.cxx,\n * rtkshortscantest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT DrawSheppLoganFilter : public DrawGeometricPhantomImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DrawSheppLoganFilter);\n\n  /** Standard class type alias. */\n  using Self = DrawSheppLoganFilter;\n  using Superclass = DrawGeometricPhantomImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(DrawSheppLoganFilter);\n\nprotected:\n  DrawSheppLoganFilter();\n  ~DrawSheppLoganFilter() override = default;\n\n  void\n  GenerateData() override;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkDrawSheppLoganFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkDrawSheppLoganFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDrawSheppLoganFilter_hxx\n#define rtkDrawSheppLoganFilter_hxx\n\n#include \"rtkSheppLoganPhantom.h\"\n\nnamespace rtk\n{\ntemplate <class TInputImage, class TOutputImage>\nDrawSheppLoganFilter<TInputImage, TOutputImage>::DrawSheppLoganFilter()\n{\n  this->SetPhantomScale(ConvexShape::VectorType(128));\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nDrawSheppLoganFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  this->SetGeometricPhantom(SheppLoganPhantom::New().GetPointer());\n  this->SetConfigFile(\"\");\n  Superclass::GenerateData();\n}\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkDualEnergyNegativeLogLikelihood.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkDualEnergyNegativeLogLikelihood_h\n#define rtkDualEnergyNegativeLogLikelihood_h\n\n#include \"rtkProjectionsDecompositionNegativeLogLikelihood.h\"\n#include \"rtkMacro.h\"\n\n#include <itkVectorImage.h>\n#include <itkVariableLengthVector.h>\n#include <itkVariableSizeMatrix.h>\n\nnamespace rtk\n{\n/** \\class rtkDualEnergyNegativeLogLikelihood\n * \\brief Cost function for dual energy decomposition into material, and associated forward model\n *\n * This class requires the method \"Initialize()\" to be run once, before it\n * is passed to the simplex minimizer\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\n// We have to define the cost function first\nclass DualEnergyNegativeLogLikelihood : public rtk::ProjectionsDecompositionNegativeLogLikelihood\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(DualEnergyNegativeLogLikelihood);\n\n  using Self = DualEnergyNegativeLogLikelihood;\n  using Superclass = rtk::ProjectionsDecompositionNegativeLogLikelihood;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  itkNewMacro(Self);\n  itkOverrideGetNameOfClassMacro(DualEnergyNegativeLogLikelihood);\n\n  using ParametersType = Superclass::ParametersType;\n  using DerivativeType = Superclass::DerivativeType;\n  using MeasureType = Superclass::MeasureType;\n\n  using DetectorResponseType = Superclass::DetectorResponseType;\n  using MaterialAttenuationsType = Superclass::MaterialAttenuationsType;\n  using MeasuredDataType = Superclass::MeasuredDataType;\n  using IncidentSpectrumType = Superclass::IncidentSpectrumType;\n\n  // Constructor\n  DualEnergyNegativeLogLikelihood() { m_NumberOfSpectralBins = 2; }\n\n  // Destructor\n  ~DualEnergyNegativeLogLikelihood() override = default;\n\n  void\n  Initialize() override\n  {\n    // This method computes the combined m_IncidentSpectrumAndDetectorResponseProduct\n    // from m_DetectorResponse and m_IncidentSpectrum\n    m_Thresholds.SetSize(2);\n    m_Thresholds[0] = 1;\n    m_Thresholds[1] = m_NumberOfEnergies;\n\n    // In dual energy CT, one possible design is to illuminate the object with\n    // either a low energy or a high energy spectrum, alternating between the two. In that case\n    // m_DetectorResponse has only one row (there is a single detector) and m_IncidentSpectrum\n    // has two rows (one for high energy, the other for low)\n    m_IncidentSpectrumAndDetectorResponseProduct.set_size(2, m_DetectorResponse.cols());\n    for (unsigned int i = 0; i < 2; i++)\n      for (unsigned int j = 0; j < m_DetectorResponse.cols(); j++)\n        m_IncidentSpectrumAndDetectorResponseProduct[i][j] = m_DetectorResponse[0][j] * m_IncidentSpectrum[i][j];\n  }\n\n  // Not used with a simplex optimizer, but may be useful later\n  // for gradient based methods\n  void\n  GetDerivative(const ParametersType & itkNotUsed(lineIntegrals),\n                DerivativeType &       itkNotUsed(derivatives)) const override\n  {\n    itkExceptionMacro(<< \"Not implemented\");\n  }\n\n  // Main method\n  MeasureType\n  GetValue(const ParametersType & parameters) const override\n  {\n    // Forward model: compute the expected total energy measured by the detector for each spectrum\n    vnl_vector<double> forward = ForwardModel(parameters);\n    vnl_vector<double> variances = GetVariances(parameters);\n\n    long double measure = 0;\n    // From equation (5) of \"Cramer-Rao lower bound of basis image noise in multiple-energy x-ray imaging\",\n    // PMB 2009, Roessl et al.\n\n    // Compute the negative log likelihood from the expectedEnergies\n    for (unsigned int i = 0; i < this->m_NumberOfMaterials; i++)\n      measure += std::log((long double)variances[i]) +\n                 (forward[i] - this->m_MeasuredData[i]) * (forward[i] - this->m_MeasuredData[i]) / variances[i];\n    measure *= 0.5;\n\n    return measure;\n  }\n\n  vnl_vector<double>\n  GetVariances(const ParametersType & lineIntegrals) const override\n  {\n    vnl_vector<double> attenuationFactors;\n    attenuationFactors.set_size(m_NumberOfEnergies);\n    GetAttenuationFactors(lineIntegrals, attenuationFactors);\n\n    // Apply detector response, getting the lambdas\n    vnl_vector<double> intermediate;\n    intermediate.set_size(m_NumberOfEnergies);\n    for (unsigned int i = 0; i < m_NumberOfEnergies; i++)\n      intermediate[i] = i + 1;\n    intermediate = element_product(attenuationFactors, intermediate);\n    return (m_IncidentSpectrumAndDetectorResponseProduct * intermediate);\n  }\n\nprotected:\n  itk::VariableSizeMatrix<float> m_Fischer;\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkEdfImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkEdfImageIO_h\n#define rtkEdfImageIO_h\n\n#include <itkImageIOBase.h>\n#include <fstream>\n#include <cstring>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class EdfImageIO\n * \\brief Class for reading Edf image file format. Edf is the format of\n * X-ray projection images at the ESRF.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT EdfImageIO : public itk::ImageIOBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(EdfImageIO);\n\n  /** Standard class type alias. */\n  using Self = EdfImageIO;\n  using Superclass = itk::ImageIOBase;\n  using Pointer = itk::SmartPointer<Self>;\n\n  EdfImageIO()\n    : Superclass()\n  {}\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(EdfImageIO);\n\n  /*-------- This part of the interface deals with reading data. ------ */\n  void\n  ReadImageInformation() override;\n\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n\n  void\n  Read(void * buffer) override;\n\n  /*-------- This part of the interfaces deals with writing data. ----- */\n  virtual void\n  WriteImageInformation(bool keepOfStream);\n\n  void\n  WriteImageInformation() override\n  {\n    WriteImageInformation(false);\n  }\n\n  bool\n  CanWriteFile(const char * filename) override;\n\n  void\n  Write(const void * buffer) override;\n\nprotected:\n  std::string m_BinaryFileName;\n  int         m_BinaryFileSkip;\n\n  static char *\n  edf_findInHeader(char * header, const char * key);\n\n  /* List of EDF supported datatypes\n   */\n  enum DataType\n  {\n    U_CHAR_DATATYPE = 0,\n    CHAR_DATATYPE, //  8 bits = 1 B\n    U_SHORT_DATATYPE,\n    SHORT_DATATYPE, // 16 bits = 2 B\n    U_INT_DATATYPE,\n    INT_DATATYPE, // 32 bits = 4 B\n    U_L_INT_DATATYPE,\n    L_INT_DATATYPE, // 32 bits = 4 B\n    FLOAT_DATATYPE,\n    DOUBLE_DATATYPE, // 4 B, 8 B\n    UNKNOWN_DATATYPE = -1\n  };\n\n  /* Note - compatibility:\n    Unsigned8 = 1,Signed8,  Unsigned16, Signed16,\n    Unsigned32,   Signed32, Unsigned64, Signed64,\n    FloatIEEE32,  DoubleIEEE64\n  */\n\n  /***************************************************************************\n   * Tables\n   ***************************************************************************/\n\n  // table key-value structure\n  struct table\n  {\n    const char * key;\n    int          value;\n  };\n\n  struct table3\n  {\n    const char * key;\n    int          value;\n    short        sajzof;\n  };\n\n  /* Returns index of the table tbl whose key matches the beginning of the\n   * search string search_str.\n   * It returns index into the table or -1 if there is no match.\n   */\n  static int\n  lookup_table_nth(const struct table * tbl, const char * search_str)\n  {\n    int k = -1;\n\n    while (tbl[++k].key)\n      if (tbl[k].key && !strncmp(search_str, tbl[k].key, strlen(tbl[k].key)))\n        return k;\n    return -1; // not found\n  }\n\n  static int\n  lookup_table3_nth(const struct table3 * tbl, const char * search_str)\n  {\n    int k = -1;\n\n    while (tbl[++k].key)\n      if (tbl[k].key && !strncmp(search_str, tbl[k].key, strlen(tbl[k].key)))\n        return k;\n    return -1; // not found\n  }\n\n  ///* Orientation of axes of the raster, as the binary matrix is saved in\n  // * the file. (Determines the scanning direction, or the \"fastest\" index\n  // * of the matrix in the data file.)\n  // */\n  // enum EdfRasterAxes {\n  // RASTER_AXES_XrightYdown, // matricial format: rows, columns\n  // RASTER_AXES_XrightYup    // cartesian coordinate system\n  //    // other 6 combinations not available (not needed until now)\n  //};\n\n  // static const struct table rasteraxes_table[] =\n  //{\n  //    { \"XrightYdown\", RASTER_AXES_XrightYdown },\n  //    { \"XrightYup\",   RASTER_AXES_XrightYup },\n  //    { NULL, -1 }\n  //};\n\n}; // end class EdfImageIO\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkEdfImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkEdfImageIOFactory_h\n#define rtkEdfImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkEdfImageIO.h\"\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class EdfImageIOFactory\n * \\brief ITK factory for Edf file I/O.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT EdfImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(EdfImageIOFactory);\n\n  /** Standard class type alias. */\n  using Self = EdfImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"Edf ImageIO Factory, allows the loading of Edf images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(EdfImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\nprotected:\n  EdfImageIOFactory();\n  ~EdfImageIOFactory() override = default;\n\n  using myProductType = EdfImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkEdfRawToAttenuationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkEdfRawToAttenuationImageFilter_h\n#define rtkEdfRawToAttenuationImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkImageSeriesReader.h>\n\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class EdfRawToAttenuationImageFilter\n * \\brief Convert raw ESRF data to attenuation images\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITKIOImageBase_HIDDEN EdfRawToAttenuationImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(EdfRawToAttenuationImageFilter);\n\n  /** Standard class type alias. */\n  using Self = EdfRawToAttenuationImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n\n  using FileNamesContainer = std::vector<std::string>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(EdfRawToAttenuationImageFilter);\n\n  /** Set the vector of strings that contains the file names. Files\n   * are processed in sequential order. */\n  void\n  SetFileNames(const FileNamesContainer & name)\n  {\n    if (m_FileNames != name)\n    {\n      m_FileNames = name;\n      this->Modified();\n    }\n  }\n\n  const FileNamesContainer &\n  GetFileNames() const\n  {\n    return m_FileNames;\n  }\n\nprotected:\n  EdfRawToAttenuationImageFilter();\n  ~EdfRawToAttenuationImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  using EdfImageSeries = itk::ImageSeriesReader<InputImageType>;\n  typename EdfImageSeries::Pointer m_DarkProjectionsReader;\n  typename EdfImageSeries::Pointer m_ReferenceProjectionsReader;\n\n  /** A list of filenames from which the input was read. */\n  FileNamesContainer m_FileNames;\n\n  /** The list of indices of the input for each reference image. */\n  std::vector<typename InputImageType::IndexValueType> m_ReferenceIndices;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkEdfRawToAttenuationImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkEdfRawToAttenuationImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkEdfRawToAttenuationImageFilter_hxx\n#define rtkEdfRawToAttenuationImageFilter_hxx\n\n\n#include <itkImageFileWriter.h>\n#include <itksys/SystemTools.hxx>\n#include <itkRegularExpressionSeriesFileNames.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nEdfRawToAttenuationImageFilter<TInputImage, TOutputImage>::EdfRawToAttenuationImageFilter()\n  : m_DarkProjectionsReader(EdfImageSeries::New())\n  , m_ReferenceProjectionsReader(EdfImageSeries::New())\n{}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nEdfRawToAttenuationImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (m_FileNames.size() != this->GetInput()->GetLargestPossibleRegion().GetSize()[2])\n  {\n    itkGenericExceptionMacro(<< \"Error, file names do not correspond to input\");\n  }\n\n  std::string              path = itksys::SystemTools::GetFilenamePath(m_FileNames[0]);\n  std::vector<std::string> pathComponents;\n  itksys::SystemTools::SplitPath(m_FileNames[0].c_str(), pathComponents);\n  std::string fileName = pathComponents.back();\n\n  // Reference images (flood field)\n  auto refNames = itk::RegularExpressionSeriesFileNames::New();\n  refNames->SetDirectory(path.c_str());\n  refNames->SetNumericSort(false);\n  refNames->SetRegularExpression(\"refHST[0-9]*.edf$\");\n  refNames->SetSubMatch(0);\n\n  m_ReferenceProjectionsReader->SetFileNames(refNames->GetFileNames());\n  m_ReferenceProjectionsReader->Update();\n\n  m_ReferenceIndices.clear();\n  for (const std::string & name : refNames->GetFileNames())\n  {\n    const std::string::size_type nameSize = name.size();\n    const std::string            indexStr(name, nameSize - 8, 4);\n    m_ReferenceIndices.push_back(std::stoi(indexStr.c_str()));\n  }\n\n  // Dark images\n  FileNamesContainer darkFilenames;\n  darkFilenames.push_back(path + std::string(\"/dark.edf\"));\n  //  darkFilenames.push_back( path + std::string(\"/darkend0000.edf\") );\n  m_DarkProjectionsReader->SetFileNames(darkFilenames);\n  m_DarkProjectionsReader->Update();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nEdfRawToAttenuationImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Dark image iterator\n  OutputImageRegionType darkRegion = outputRegionForThread;\n\n  darkRegion.SetSize(2, 1);\n  darkRegion.SetIndex(2, 0);\n  itk::ImageRegionConstIterator<InputImageType> itDark(m_DarkProjectionsReader->GetOutput(), darkRegion);\n\n  // Ref and projection regions\n  OutputImageRegionType refRegion1 = outputRegionForThread;\n  OutputImageRegionType refRegion2 = outputRegionForThread;\n  OutputImageRegionType outputRegionSlice = outputRegionForThread;\n  refRegion1.SetSize(2, 1);\n  refRegion2.SetSize(2, 1);\n  outputRegionSlice.SetSize(2, 1);\n\n  for (int k = outputRegionForThread.GetIndex(2);\n       k < outputRegionForThread.GetIndex(2) + (int)outputRegionForThread.GetSize(2);\n       k++)\n  {\n    outputRegionSlice.SetIndex(2, k);\n\n    // Create iterators\n    itk::ImageRegionConstIterator<InputImageType> itIn(this->GetInput(), outputRegionSlice);\n    itk::ImageRegionIterator<OutputImageType>     itOut(this->GetOutput(), outputRegionSlice);\n\n    // Find index of reference images\n    for (unsigned int i = 0; i < m_ReferenceIndices.size(); i++)\n    {\n      itDark.GoToBegin();\n      if (k == m_ReferenceIndices[i])\n      {\n        refRegion1.SetIndex(2, i);\n        itk::ImageRegionConstIterator<InputImageType> itRef(m_ReferenceProjectionsReader->GetOutput(), refRegion1);\n        while (!itDark.IsAtEnd())\n        {\n          // The reference has been exactly acquired at the same position\n          itOut.Set(-log(((double)itIn.Get() - (double)itDark.Get()) / ((double)itRef.Get() - (double)itDark.Get())));\n          ++itIn;\n          ++itOut;\n          ++itDark;\n          ++itRef;\n        }\n      }\n      else if (i > 0 && k > m_ReferenceIndices[i - 1] && k < m_ReferenceIndices[i])\n      {\n        // The reference must be interpolated\n        refRegion1.SetIndex(2, i - 1);\n        refRegion2.SetIndex(2, i);\n        itk::ImageRegionConstIterator<InputImageType> itRef1(m_ReferenceProjectionsReader->GetOutput(), refRegion1);\n        itk::ImageRegionConstIterator<InputImageType> itRef2(m_ReferenceProjectionsReader->GetOutput(), refRegion2);\n\n        double w1 = 1. / (m_ReferenceIndices[i] - m_ReferenceIndices[i - 1]);\n        double w2 = w1 * (k - m_ReferenceIndices[i - 1]);\n\n        w1 *= (m_ReferenceIndices[i] - k);\n        while (!itDark.IsAtEnd())\n        {\n          double ref = w1 * itRef1.Get() + w2 * itRef2.Get();\n          itOut.Set(-log(((double)itIn.Get() - (double)itDark.Get()) / (ref - (double)itDark.Get())));\n          ++itIn;\n          ++itOut;\n          ++itDark;\n          ++itRef1;\n          ++itRef2;\n        }\n      }\n    }\n  }\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkElektaSynergyGeometryReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkElektaSynergyGeometryReader_h\n#define rtkElektaSynergyGeometryReader_h\n\n#include \"RTKExport.h\"\n#include <itkLightProcessObject.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class ElektaSynergyGeometryReader\n *\n * Creates a 3D circular geometry from the Elekta database input.\n *\n * \\test rtkelektatest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT ElektaSynergyGeometryReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ElektaSynergyGeometryReader);\n\n  /** Standard type alias */\n  using Self = ElektaSynergyGeometryReader;\n  using Superclass = itk::LightProcessObject;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ElektaSynergyGeometryReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Get the pointer to the generated geometry object. */\n  itkGetMacro(Geometry, GeometryType::Pointer);\n\n  /** Set the dicom unique ID of the acquisition, usually contained in the\n   * name of the directory containing the projection images. The name is\n   * of the form img_DicomUID. */\n  itkGetMacro(DicomUID, std::string);\n  itkSetMacro(DicomUID, std::string);\n\n  /** Set the path to the file IMAGE.DBF */\n  itkGetMacro(ImageDbfFileName, std::string);\n  itkSetMacro(ImageDbfFileName, std::string);\n\n  /** Set the path to the file FRAME.DBF */\n  itkGetMacro(FrameDbfFileName, std::string);\n  itkSetMacro(FrameDbfFileName, std::string);\n\nprotected:\n  ElektaSynergyGeometryReader();\n\n\nprivate:\n  std::string\n  GetImageIDFromDicomUID();\n  void\n  GetProjInfoFromDB(const std::string &  imageID,\n                    std::vector<float> & projAngle,\n                    std::vector<float> & projFlexX,\n                    std::vector<float> & projFlexY);\n\n  void\n  GenerateData() override;\n\n  GeometryType::Pointer m_Geometry;\n  std::string           m_DicomUID;\n  std::string           m_ImageDbfFileName;\n  std::string           m_FrameDbfFileName;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkElektaSynergyLookupTableImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkElektaSynergyLookupTableImageFilter_h\n#define rtkElektaSynergyLookupTableImageFilter_h\n\n#include \"rtkLookupTableImageFilter.h\"\n#include <itkNumericTraits.h>\n\nnamespace rtk\n{\n\n/** \\class ElektaSynergyLookupTableImageFilter\n * \\brief Lookup table for Elekta Synergy data.\n *\n * The lookup table converts the raw values measured by the panel after a first\n * raw lookup table to the logarithm of the value divided by the maximum\n * numerical value. This could be improved with a calibration of the air value.\n *\n * \\test rtkelektatest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TOutputImage>\nclass ITK_TEMPLATE_EXPORT ElektaSynergyLookupTableImageFilter\n  : public LookupTableImageFilter<itk::Image<unsigned short, TOutputImage::ImageDimension>, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ElektaSynergyLookupTableImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ElektaSynergyLookupTableImageFilter;\n  using Superclass = LookupTableImageFilter<itk::Image<unsigned short, TOutputImage::ImageDimension>, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using InputImagePixelType = unsigned short;\n  using OutputImagePixelType = typename TOutputImage::PixelType;\n  using LookupTableType = typename Superclass::FunctorType::LookupTableType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(ElektaSynergyLookupTableImageFilter);\n\nprotected:\n  ElektaSynergyLookupTableImageFilter();\n  ~ElektaSynergyLookupTableImageFilter() override = default;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkElektaSynergyLookupTableImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkElektaSynergyLookupTableImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkElektaSynergyLookupTableImageFilter_hxx\n#define rtkElektaSynergyLookupTableImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <class TOutputImage>\nElektaSynergyLookupTableImageFilter<TOutputImage>::ElektaSynergyLookupTableImageFilter()\n{\n  // Create the lut\n  auto                               lut = LookupTableType::New();\n  typename LookupTableType::SizeType size;\n  size[0] = itk::NumericTraits<InputImagePixelType>::max() - itk::NumericTraits<InputImagePixelType>::min() + 1;\n  lut->SetRegions(size);\n  lut->Allocate();\n\n  // Iterate and set lut\n  OutputImagePixelType logRef;\n  logRef = log(OutputImagePixelType(size[0]));\n  itk::ImageRegionIteratorWithIndex<LookupTableType> it(lut, lut->GetBufferedRegion());\n  it.GoToBegin();\n\n  // First value takes value of pixel #1\n  it.Set(logRef - log(OutputImagePixelType(size[0] - 1)));\n  ++it;\n\n  // Conventional lookup table for the rest\n  while (!it.IsAtEnd())\n  {\n    it.Set(logRef - log(OutputImagePixelType(size[0] - it.GetIndex()[0])));\n    ++it;\n  }\n\n  // Last value takes value of pixel #1\n  --it;\n  it.Set(logRef - log(OutputImagePixelType(size[0] - 1)));\n\n  // Set the lut to member and functor\n  this->SetLookupTable(lut);\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkElektaSynergyRawLookupTableImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkElektaSynergyRawLookupTableImageFilter_h\n#define rtkElektaSynergyRawLookupTableImageFilter_h\n\n#include \"rtkLookupTableImageFilter.h\"\n#include <itkNumericTraits.h>\n\nnamespace rtk\n{\n\n/** \\class ElektaSynergyRawLookupTableImageFilter\n * \\brief First part of ElektaSynergyLookupTableImageFilter.\n *\n * The lookup table has been split in two to allow application of the scatter\n * correction algorithm in between. The first part only set values to have max\n * value in air.\n *\n * \\test rtkelektatest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage = itk::Image<unsigned short, 2>, class TOutputImage = itk::Image<unsigned short, 2>>\nclass ITK_TEMPLATE_EXPORT ElektaSynergyRawLookupTableImageFilter\n  : public LookupTableImageFilter<TInputImage, TOutputImage>\n{\n\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ElektaSynergyRawLookupTableImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ElektaSynergyRawLookupTableImageFilter;\n  using Superclass = LookupTableImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using InputImagePixelType = typename TInputImage::PixelType;\n  using OutputImagePixelType = typename TOutputImage::PixelType;\n  using LookupTableType = typename Superclass::FunctorType::LookupTableType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(ElektaSynergyRawLookupTableImageFilter);\n\n  // Begin concept checking\n  itkConceptMacro(SameTypeCheck, (itk::Concept::SameType<InputImagePixelType, unsigned short>));\n\nprotected:\n  ElektaSynergyRawLookupTableImageFilter();\n  ~ElektaSynergyRawLookupTableImageFilter() override = default;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkElektaSynergyRawLookupTableImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkElektaSynergyRawLookupTableImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkElektaSynergyRawLookupTableImageFilter_hxx\n#define rtkElektaSynergyRawLookupTableImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nElektaSynergyRawLookupTableImageFilter<TInputImage, TOutputImage>::ElektaSynergyRawLookupTableImageFilter()\n{\n  // Create the lut\n  auto                               lut = LookupTableType::New();\n  typename LookupTableType::SizeType size;\n  size[0] = itk::NumericTraits<InputImagePixelType>::max() - itk::NumericTraits<InputImagePixelType>::min() + 1;\n  lut->SetRegions(size);\n  lut->Allocate();\n\n  // Iterate and set lut\n  itk::ImageRegionIteratorWithIndex<LookupTableType> it(lut, lut->GetBufferedRegion());\n  it.GoToBegin();\n\n  // First value takes value of pixel #1\n  it.Set(OutputImagePixelType(size[0] - 1));\n  ++it;\n\n  // Conventional lookup table for the rest\n  while (!it.IsAtEnd())\n  {\n    it.Set(OutputImagePixelType(size[0] - it.GetIndex()[0]));\n    ++it;\n  }\n\n  // Last value takes value of pixel #1\n  --it;\n  it.Set(OutputImagePixelType(size[0] - 1));\n\n  // Set the lut to member and functor\n  this->SetLookupTable(lut);\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkElektaXVI5GeometryXMLFileReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkElektaXVI5GeometryXMLFileReader_h\n#define rtkElektaXVI5GeometryXMLFileReader_h\n\n#ifdef _MSC_VER\n#  pragma warning(disable : 4786)\n#endif\n\n#include \"RTKExport.h\"\n#include <itkXMLFile.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class ElektaXVI5GeometryXMLFileReader\n *\n * Reads an XML-format file of XVI version = 5.0.2  (_Frame.xml in each projection directory). From XVI_v5 on, thre is\n * no need of accessing .DBF files (FRAME.DBF / IMAGE.DBF). This class is basically inspired by\n * ThreeDCircularProjectionGeometryXMLFileReader. Writer is not implemented. SAD = 1000 mm, SID = 1536 mm are hard-coded\n * since _Frame.xml doesn't include these values. Regarding PanelOffset, XVI5 specifies position of the center (UCentre,\n * VCentre) instead of offset. Therefore, negation is required to get classical m_ProjectionOffsetX and\n * m_ProjectionOffsetY values.\n *\n * \\author Yang K Park (theday79@gmail.com)\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT ElektaXVI5GeometryXMLFileReader : public itk::XMLReader<ThreeDCircularProjectionGeometry>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ElektaXVI5GeometryXMLFileReader);\n\n  /** Standard type alias */\n  using Self = ElektaXVI5GeometryXMLFileReader;\n  using Superclass = itk::XMLReader<ThreeDCircularProjectionGeometry>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using GeometryPointer = GeometryType::Pointer;\n\n  /** Latest version */\n  static const unsigned int CurrentVersion = 2;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ElektaXVI5GeometryXMLFileReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Determine if a file can be read */\n  int\n  CanReadFile(const char * name) override;\n\n  /** Get smart pointer to projection geometry. */\n  itkGetMacro(Geometry, GeometryPointer);\n\nprotected:\n  ElektaXVI5GeometryXMLFileReader();\n  ~ElektaXVI5GeometryXMLFileReader() override = default;\n\n  /** Callback function -- called from XML parser with start-of-element\n   * information.\n   */\n  void\n  StartElement(const char * name, const char ** atts) override;\n\n  void\n  StartElement(const char * name);\n\n  void\n  EndElement(const char * name) override;\n\n  void\n  CharacterDataHandler(const char * inData, int inLength) override;\n\nprivate:\n  GeometryPointer m_Geometry{ GeometryType::New() };\n\n  std::string m_CurCharacterData;\n\n  /** Projection parameters */\n  double m_InPlaneAngle{ 0. };\n  double m_OutOfPlaneAngle{ 0. };\n  double m_GantryAngle{ 0. };\n  double m_SourceToIsocenterDistance{ 1000. };\n  double m_SourceOffsetX{ 0. };\n  double m_SourceOffsetY{ 0. };\n  double m_SourceToDetectorDistance{ 1536. };\n  double m_ProjectionOffsetX{ 0. };\n  double m_ProjectionOffsetY{ 0. };\n\n  /** Projection matrix */\n  ThreeDCircularProjectionGeometry::MatrixType m_Matrix;\n};\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkExtractPhaseImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkExtractPhaseImageFilter_h\n#define rtkExtractPhaseImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n\nnamespace rtk\n{\n/** \\class ExtractPhaseImageFilter\n *\n * \\brief Extracts the phase of a 1D signal\n *\n * The filter extracts the phase of a 1D periodic signal, which is useful in\n * gated CT. There are several ways of defining the phase of a signal and the\n * filter offers two of them:\n * - the phase of the complex analytic signal as defined in\n * rtk::HilbertImageFilter,\n * - linear between chosen extrema, either minima or maxima.\n * There are several parameters to the extraction that should be at least\n * adjusted for every system and possibly for some patients.\n *\n * \\test rtkamsterdamshroudtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TImage>\nclass ITK_TEMPLATE_EXPORT ExtractPhaseImageFilter : public itk::InPlaceImageFilter<TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ExtractPhaseImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ExtractPhaseImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using KernelSizeType = typename TImage::SizeType::SizeValueType;\n  using PositionsListType = std::vector<int>;\n  typedef enum\n  {\n    LOCAL_PHASE = 0,\n    LINEAR_BETWEEN_MINIMA,\n    LINEAR_BETWEEN_MAXIMA\n  } ModelType;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(ExtractPhaseImageFilter);\n\n  /** The input signal may be smoothed before taking the phase of the Hilbert\n   * transform. This parameter sets the number of samples for this smoothing. */\n  itkSetMacro(MovingAverageSize, KernelSizeType);\n  itkGetMacro(MovingAverageSize, KernelSizeType);\n\n  /** Low frequencies of the signal are removed before taking the phase of the\n   * Hilbert transform using an unsharp mask, i.e., the difference of the\n   * signal and its moving average. This parameter sets the number of samples\n   * used for the moving average, default is 55. */\n  itkSetMacro(UnsharpMaskSize, KernelSizeType);\n  itkGetMacro(UnsharpMaskSize, KernelSizeType);\n\n  /** During the update, extrema are extracted and can be retrieved after an\n   * update of the output. */\n  itkGetMacro(MinimaPositions, PositionsListType);\n  itkGetMacro(MaximaPositions, PositionsListType);\n\n  /** After smoothing and unsharping, you can chose the model for the phase\n   * extraction which describes the position in the respiratory cycle by a\n   * number between 0 and 1:\n   * - LOCAL_PHASE: local phase, i.e., phase of the Hilbert transform of the signal,\n   * - LINEAR_BETWEEN_MINIMA (LINEAR_BETWEEN_MAXIMA): phase phase is linear\n   * between two consecutive minima (maxima), with the minima (maxima) at 0.\n   * Default is LINEAR_BETWEEN_MINIMA. */\n  itkSetMacro(Model, ModelType);\n  itkGetMacro(Model, ModelType);\n\nprotected:\n  ExtractPhaseImageFilter();\n  ~ExtractPhaseImageFilter() override = default;\n\n  void\n  GenerateData() override;\n\nprivate:\n  void\n  ComputeLinearPhaseBetweenPositions(const PositionsListType & positions);\n\n  KernelSizeType    m_MovingAverageSize;\n  KernelSizeType    m_UnsharpMaskSize;\n  PositionsListType m_MinimaPositions;\n  PositionsListType m_MaximaPositions;\n  ModelType         m_Model;\n}; // end of class\n\n} // end of namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkExtractPhaseImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkExtractPhaseImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkExtractPhaseImageFilter_hxx\n#define rtkExtractPhaseImageFilter_hxx\n\n\n#include \"rtkHilbertImageFilter.h\"\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkComplexToPhaseImageFilter.h>\n#include <itkConvolutionImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkConvolutionImageFilter.h>\n#include <itkNumericTraits.h>\nnamespace rtk\n{\n\ntemplate <class TImage>\nExtractPhaseImageFilter<TImage>::ExtractPhaseImageFilter()\n  : m_MovingAverageSize(1)\n  , m_UnsharpMaskSize(55)\n  , m_Model(LINEAR_BETWEEN_MINIMA)\n{}\n\ntemplate <class TImage>\nvoid\nExtractPhaseImageFilter<TImage>::GenerateData()\n{\n  // Moving average\n  typename TImage::SizeType kernelSz;\n  kernelSz[0] = m_MovingAverageSize;\n\n  auto kernel = TImage::New();\n  kernel->SetRegions(kernelSz);\n  kernel->Allocate();\n  kernel->FillBuffer(1. / m_MovingAverageSize);\n\n  using ConvolutionType = itk::ConvolutionImageFilter<TImage, TImage>;\n  auto conv = ConvolutionType::New();\n  conv->SetInput(this->GetInput());\n  conv->SetKernelImage(kernel);\n\n  // Unsharp mask\n  kernelSz[0] = m_UnsharpMaskSize;\n  auto kernel2 = TImage::New();\n  kernel2->SetRegions(kernelSz);\n  kernel2->Allocate();\n  kernel2->FillBuffer(1. / m_UnsharpMaskSize);\n\n  auto conv2 = ConvolutionType::New();\n  conv2->SetInput(conv->GetOutput());\n  conv2->SetKernelImage(kernel2);\n\n  // Define real image type for FFT\n  using RealOutputPixelType = typename itk::NumericTraits<typename TImage::PixelType>::RealType;\n  using RealOutputImageType = itk::Image<RealOutputPixelType, 1>;\n\n  auto sub = itk::SubtractImageFilter<TImage, TImage, RealOutputImageType>::New();\n  sub->SetInput1(conv->GetOutput());\n  sub->SetInput2(conv2->GetOutput());\n  sub->InPlaceOff();\n  sub->Update();\n\n  // Define FFT output type (complex)\n  using ComplexSignalType = itk::Image<std::complex<RealOutputPixelType>, 1>;\n\n  // Hilbert transform\n  auto hilbert = rtk::HilbertImageFilter<RealOutputImageType, ComplexSignalType>::New();\n  hilbert->SetInput(sub->GetOutput());\n\n  // Take the linear phase of this signal\n  auto phase = itk::ComplexToPhaseImageFilter<ComplexSignalType, TImage>::New();\n  phase->SetInput(hilbert->GetOutput());\n  phase->Update();\n\n  // Find extrema at 0 and pi\n  m_MinimaPositions.clear();\n  m_MaximaPositions.clear();\n  using IteratorType = typename itk::ImageRegionIteratorWithIndex<TImage>;\n  IteratorType               it(phase->GetOutput(), phase->GetOutput()->GetLargestPossibleRegion());\n  typename TImage::PixelType curr, prev = it.Get();\n  ++it;\n  int prevType = 0; // 1 if maximum, 2 if minimum\n  while (!it.IsAtEnd())\n  {\n    curr = it.Get();\n    if (curr * prev <= 0.)\n    {\n      if (prevType != 1 && curr >= 0. && curr - prev <= itk::Math::pi)\n      {\n        m_MaximaPositions.push_back(it.GetIndex()[0]);\n        prevType = 1;\n      }\n      else if (prevType != 2 && curr < 0. && prev - curr > itk::Math::pi)\n      {\n        m_MinimaPositions.push_back(it.GetIndex()[0]);\n        prevType = 2;\n      }\n    }\n    ++it;\n    prev = curr;\n  }\n\n  if (m_MinimaPositions.empty() || m_MaximaPositions.empty())\n    itkExceptionMacro(<< \"Problem detecting extremas\");\n\n  const typename TImage::PixelType * sig = this->GetInput()->GetBufferPointer();\n  int                                nsig = this->GetInput()->GetLargestPossibleRegion().GetSize()[0];\n\n  // Find minimum between two maxima\n  int currMinPos = 0;\n  if (m_MinimaPositions[currMinPos] < m_MaximaPositions.front())\n  {\n    // Before first maximum\n    for (int i = 0; i < m_MaximaPositions.front(); i++)\n      if (sig[i] < sig[m_MinimaPositions[currMinPos]])\n        m_MinimaPositions[currMinPos] = i;\n    currMinPos++;\n  }\n  for (unsigned int j = 1; j < m_MaximaPositions.size(); j++, currMinPos++)\n  {\n    // Between maxima\n    for (int i = m_MaximaPositions[j - 1]; i < m_MaximaPositions[j]; i++)\n      if (sig[i] < sig[m_MinimaPositions[currMinPos]])\n        m_MinimaPositions[currMinPos] = i;\n  }\n  if (m_MinimaPositions.back() > m_MaximaPositions.back())\n  {\n    // After last maximum\n    for (int i = m_MaximaPositions.back(); i < nsig; i++)\n      if (sig[i] < sig[m_MinimaPositions[currMinPos]])\n        m_MinimaPositions[currMinPos] = i;\n  }\n\n  // Find maximum between two minima\n  int currMaxPos = 0;\n  if (m_MaximaPositions[currMaxPos] < m_MinimaPositions.front())\n  {\n    // Before first minimum\n    for (int i = 0; i < m_MinimaPositions.front(); i++)\n      if (sig[i] > sig[m_MaximaPositions[currMaxPos]])\n        m_MaximaPositions[currMaxPos] = i;\n    currMaxPos++;\n  }\n  for (unsigned int j = 1; j < m_MinimaPositions.size(); j++, currMaxPos++)\n  {\n    // Between minima\n    for (int i = m_MinimaPositions[j - 1]; i < m_MinimaPositions[j]; i++)\n      if (sig[i] > sig[m_MaximaPositions[currMaxPos]])\n        m_MaximaPositions[currMaxPos] = i;\n  }\n  if (m_MaximaPositions.back() > m_MinimaPositions.back())\n  {\n    // After last minimum\n    for (int i = m_MinimaPositions.back(); i < nsig; i++)\n      if (sig[i] > sig[m_MaximaPositions[currMaxPos]])\n        m_MaximaPositions[currMaxPos] = i;\n  }\n\n  switch (m_Model)\n  {\n    case (LOCAL_PHASE):\n      it.GoToBegin();\n      while (!it.IsAtEnd())\n      {\n        curr = it.Get() / (2. * itk::Math::pi);\n        curr -= itk::Math::Floor<typename TImage::PixelType>(curr);\n        it.Set(curr);\n        ++it;\n      }\n      this->GetOutput()->Graft(phase->GetOutput());\n      break;\n    case (LINEAR_BETWEEN_MINIMA):\n      ComputeLinearPhaseBetweenPositions(m_MinimaPositions);\n      break;\n    case (LINEAR_BETWEEN_MAXIMA):\n      ComputeLinearPhaseBetweenPositions(m_MaximaPositions);\n      break;\n  }\n}\n\ntemplate <class TImage>\nvoid\nExtractPhaseImageFilter<TImage>::ComputeLinearPhaseBetweenPositions(const PositionsListType & positions)\n{\n  if (positions.size() < 2)\n    itkExceptionMacro(<< \"Cannot compute linear phase with only one position\");\n\n  this->AllocateOutputs();\n\n  using IteratorType = typename itk::ImageRegionIteratorWithIndex<TImage>;\n  IteratorType               it(this->GetOutput(), this->GetOutput()->GetLargestPossibleRegion());\n  typename TImage::PixelType phase = 0.;\n\n  // Before the first position\n  double slope = 1. / (positions[1] - positions[0]);\n  for (int i = 0; i < positions[0]; i++, ++it)\n  {\n    phase = slope * (i - positions[0]);\n    phase -= itk::Math::Floor<typename TImage::PixelType>(phase);\n    it.Set(phase);\n  }\n\n  // Between positions\n  for (unsigned int j = 1; j < positions.size(); j++)\n  {\n    slope = 1. / (positions[j] - positions[j - 1]);\n    for (int i = positions[j - 1]; i < positions[j]; i++, ++it)\n    {\n      phase = slope * (i - positions[j - 1]);\n      it.Set(phase);\n    }\n  }\n\n  // After the last position\n  slope = 1. / (positions.back() - positions[positions.size() - 2]);\n  for (unsigned int i = positions.back(); i < this->GetOutput()->GetLargestPossibleRegion().GetSize(0); i++, ++it)\n  {\n    phase = slope * (i - positions[positions.size() - 2]);\n    phase -= itk::Math::Floor<typename TImage::PixelType>(phase);\n    it.Set(phase);\n  }\n}\n\n} // end of namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkFDKBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKBackProjectionImageFilter_h\n#define rtkFDKBackProjectionImageFilter_h\n\n#include \"rtkBackProjectionImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class FDKBackProjectionImageFilter\n * \\brief CPU version of the backprojection of the FDK algorithm.\n *\n * CPU implementation of the backprojection step of the\n * [Feldkamp, Davis, Kress, 1984] algorithm for filtered backprojection\n * reconstruction of cone-beam CT images with a circular source trajectory.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Projector\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT FDKBackProjectionImageFilter : public BackProjectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FDKBackProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = FDKBackProjectionImageFilter;\n  using Superclass = BackProjectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using ProjectionMatrixType = typename Superclass::ProjectionMatrixType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using ProjectionImageType = typename Superclass::ProjectionImageType;\n  using ProjectionImagePointer = typename ProjectionImageType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(FDKBackProjectionImageFilter);\n\nprotected:\n  FDKBackProjectionImageFilter() = default;\n  ~FDKBackProjectionImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  /** Optimized version when the rotation is parallel to X, i.e. matrix[1][0]\n    and matrix[2][0] are zeros. */\n  void\n  OptimizedBackprojectionX(const OutputImageRegionType & region,\n                           const ProjectionMatrixType &  matrix,\n                           const ProjectionImagePointer  projection) override;\n\n  /** Optimized version when the rotation is parallel to Y, i.e. matrix[1][1]\n    and matrix[2][1] are zeros. */\n  void\n  OptimizedBackprojectionY(const OutputImageRegionType & region,\n                           const ProjectionMatrixType &  matrix,\n                           const ProjectionImagePointer  projection) override;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFDKBackProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFDKBackProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKBackProjectionImageFilter_hxx\n#define rtkFDKBackProjectionImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkLinearInterpolateImageFunction.h>\n\n#define BILINEAR_BACKPROJECTION\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFDKBackProjectionImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  // Check if detector is cylindrical\n  if (this->m_Geometry->GetRadiusCylindricalDetector() != 0)\n  {\n    itkGenericExceptionMacro(<< \"Voxel-based FDK back projector can currently not handle cylindrical detectors\");\n  }\n\n  // Run superclass' GenerateOutputInformation\n  Superclass::GenerateOutputInformation();\n}\n\n/**\n * GenerateData performs the accumulation\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFDKBackProjectionImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  const unsigned int Dimension = TInputImage::ImageDimension;\n  const unsigned int nProj = this->GetInput(1)->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  const unsigned int iFirstProj = this->GetInput(1)->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n\n  // Create interpolator, could be any interpolation\n  auto interpolator = itk::LinearInterpolateImageFunction<ProjectionImageType, double>::New();\n\n  // Iterators on volume input and output\n  itk::ImageRegionConstIterator<TInputImage>      itIn(this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIteratorWithIndex<TOutputImage> itOut(this->GetOutput(), outputRegionForThread);\n\n  // Initialize output region with input region in case the filter is not in\n  // place\n  if (this->GetInput() != this->GetOutput())\n  {\n    itIn.GoToBegin();\n    while (!itIn.IsAtEnd())\n    {\n      itOut.Set(itIn.Get());\n      ++itIn;\n      ++itOut;\n    }\n  }\n\n  // Rotation center (assumed to be at 0 yet)\n  typename TInputImage::PointType rotCenterPoint;\n  rotCenterPoint.Fill(0.0);\n  const itk::ContinuousIndex<double, Dimension> rotCenterIndex =\n    this->GetInput(0)\n      ->template TransformPhysicalPointToContinuousIndex<typename TInputImage::PointType::ValueType, double>(\n        rotCenterPoint);\n\n  // Continuous index at which we interpolate\n  itk::ContinuousIndex<double, Dimension - 1> pointProj;\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    // Extract the current slice\n    ProjectionImagePointer projection;\n    projection = this->template GetProjection<ProjectionImageType>(iProj);\n    interpolator->SetInputImage(projection);\n\n    // Index to index matrix normalized to have a correct backprojection weight\n    // (1 at the isocenter)\n    ProjectionMatrixType matrix = this->GetIndexToIndexProjectionMatrix(iProj);\n    double               perspFactor = matrix[Dimension - 1][Dimension];\n    for (unsigned int j = 0; j < Dimension; j++)\n      perspFactor += matrix[Dimension - 1][j] * rotCenterIndex[j];\n    matrix /= perspFactor;\n\n    // Optimized version\n    if (itk::Math::abs(matrix[1][0]) < 1e-10 && itk::Math::abs(matrix[2][0]) < 1e-10)\n    {\n      OptimizedBackprojectionX(outputRegionForThread, matrix, projection);\n      continue;\n    }\n    if (itk::Math::abs(matrix[1][1]) < 1e-10 && itk::Math::abs(matrix[2][1]) < 1e-10)\n    {\n      OptimizedBackprojectionY(outputRegionForThread, matrix, projection);\n      continue;\n    }\n\n    // Go over each voxel\n    itOut.GoToBegin();\n    while (!itOut.IsAtEnd())\n    {\n      // Compute projection index\n      for (unsigned int i = 0; i < Dimension - 1; i++)\n      {\n        pointProj[i] = matrix[i][Dimension];\n        for (unsigned int j = 0; j < Dimension; j++)\n          pointProj[i] += matrix[i][j] * itOut.GetIndex()[j];\n      }\n\n      // Apply perspective\n      double perspFactor_local = matrix[Dimension - 1][Dimension];\n      for (unsigned int j = 0; j < Dimension; j++)\n        perspFactor_local += matrix[Dimension - 1][j] * itOut.GetIndex()[j];\n      perspFactor_local = 1 / perspFactor_local;\n      for (unsigned int i = 0; i < Dimension - 1; i++)\n        pointProj[i] = pointProj[i] * perspFactor_local;\n\n      // Interpolate if in projection\n      if (interpolator->IsInsideBuffer(pointProj))\n      {\n        itOut.Set(itOut.Get() +\n                  perspFactor_local * perspFactor_local * interpolator->EvaluateAtContinuousIndex(pointProj));\n      }\n\n      ++itOut;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFDKBackProjectionImageFilter<TInputImage, TOutputImage>::OptimizedBackprojectionX(\n  const OutputImageRegionType & region,\n  const ProjectionMatrixType &  matrix,\n  const ProjectionImagePointer  projection)\n{\n  typename ProjectionImageType::SizeType  pSize = projection->GetBufferedRegion().GetSize();\n  typename ProjectionImageType::IndexType pIndex = projection->GetBufferedRegion().GetIndex();\n  typename TOutputImage::SizeType         vBufferSize = this->GetOutput()->GetBufferedRegion().GetSize();\n  typename TOutputImage::IndexType        vBufferIndex = this->GetOutput()->GetBufferedRegion().GetIndex();\n  typename TInputImage::PixelType *       pProj = nullptr;\n  typename TOutputImage::PixelType *      pVol = nullptr, *pVolZeroPointer = nullptr;\n\n  // Pointers in memory to index (0,0,0) which do not necessarily exist\n  pVolZeroPointer = this->GetOutput()->GetBufferPointer();\n  pVolZeroPointer -= vBufferIndex[0] + vBufferSize[0] * (vBufferIndex[1] + vBufferSize[1] * vBufferIndex[2]);\n\n  // Continuous index at which we interpolate\n  double u = NAN, v = NAN, w = NAN;\n  int    ui = 0, vi = 0;\n  double du = NAN;\n\n  for (int k = region.GetIndex(2); k < region.GetIndex(2) + (int)region.GetSize(2); k++)\n  {\n    for (int j = region.GetIndex(1); j < region.GetIndex(1) + (int)region.GetSize(1); j++)\n    {\n      int i = region.GetIndex(0);\n      u = matrix[0][0] * i + matrix[0][1] * j + matrix[0][2] * k + matrix[0][3];\n      v = matrix[1][1] * j + matrix[1][2] * k + matrix[1][3];\n      w = matrix[2][1] * j + matrix[2][2] * k + matrix[2][3];\n\n      // Apply perspective\n      w = 1 / w;\n      u = u * w - pIndex[0];\n      v = v * w - pIndex[1];\n      du = w * matrix[0][0];\n      w *= w;\n\n#ifdef BILINEAR_BACKPROJECTION\n      double u1 = NAN, u2 = NAN, v1 = NAN, v2 = NAN;\n      vi = itk::Math::floor(v);\n      if (vi >= 0 && vi < (int)pSize[1] - 1)\n      {\n        v1 = v - vi;\n        v2 = 1.0 - v1;\n#else\n      vi = itk::Math::Round<double>(v) - pIndex[1];\n      if (vi >= 0 && vi < (int)pSize[1])\n      {\n#endif\n\n        pProj = projection->GetBufferPointer() + vi * pSize[0];\n        pVol = pVolZeroPointer + i + vBufferSize[0] * (j + k * vBufferSize[1]);\n\n        // Innermost loop\n        for (; i < (region.GetIndex(0) + (int)region.GetSize(0)); i++, u += du, pVol++)\n        {\n#ifdef BILINEAR_BACKPROJECTION\n          ui = itk::Math::floor(u);\n          if (ui >= 0 && ui < (int)pSize[0] - 1)\n          {\n            u1 = u - ui;\n            u2 = 1.0 - u1;\n            *pVol += w * (v2 * (u2 * *(pProj + ui) + u1 * *(pProj + ui + 1)) +\n                          v1 * (u2 * *(pProj + ui + pSize[0]) + u1 * *(pProj + ui + pSize[0] + 1)));\n          }\n#else\n          ui = itk::Math::Round<double>(u);\n          if (ui >= 0 && ui < (int)pSize[0])\n          {\n            *pVol += w * *(pProj + ui);\n          }\n#endif\n        } // i\n      }\n    } // j\n  } // k\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFDKBackProjectionImageFilter<TInputImage, TOutputImage>::OptimizedBackprojectionY(\n  const OutputImageRegionType & region,\n  const ProjectionMatrixType &  matrix,\n  const ProjectionImagePointer  projection)\n{\n  typename ProjectionImageType::SizeType  pSize = projection->GetBufferedRegion().GetSize();\n  typename ProjectionImageType::IndexType pIndex = projection->GetBufferedRegion().GetIndex();\n  typename TOutputImage::SizeType         vBufferSize = this->GetOutput()->GetBufferedRegion().GetSize();\n  typename TOutputImage::IndexType        vBufferIndex = this->GetOutput()->GetBufferedRegion().GetIndex();\n  typename TInputImage::PixelType *       pProj = nullptr;\n  typename TOutputImage::PixelType *      pVol = nullptr, *pVolZeroPointer = nullptr;\n\n  // Pointers in memory to index (0,0,0) which do not necessarily exist\n  pVolZeroPointer = this->GetOutput()->GetBufferPointer();\n  pVolZeroPointer -= vBufferIndex[0] + vBufferSize[0] * (vBufferIndex[1] + vBufferSize[1] * vBufferIndex[2]);\n\n  // Continuous index at which we interpolate\n  double u = NAN, v = NAN, w = NAN;\n  int    ui = 0, vi = 0;\n  double du = NAN;\n\n  for (int k = region.GetIndex(2); k < region.GetIndex(2) + (int)region.GetSize(2); k++)\n  {\n    for (int i = region.GetIndex(0); i < region.GetIndex(0) + (int)region.GetSize(0); i++)\n    {\n      int j = region.GetIndex(1);\n      u = matrix[0][0] * i + matrix[0][1] * j + matrix[0][2] * k + matrix[0][3];\n      v = matrix[1][0] * i + matrix[1][2] * k + matrix[1][3];\n      w = matrix[2][0] * i + matrix[2][2] * k + matrix[2][3];\n\n      // Apply perspective\n      w = 1 / w;\n      u = u * w - pIndex[0];\n      v = v * w - pIndex[1];\n      du = w * matrix[0][1];\n      w *= w;\n\n#ifdef BILINEAR_BACKPROJECTION\n      vi = itk::Math::floor(v);\n      if (vi >= 0 && vi < (int)pSize[1] - 1)\n      {\n#else\n      vi = itk::Math::Round<double>(v);\n      if (vi >= 0 && vi < (int)pSize[1])\n      {\n#endif\n        pVol = pVolZeroPointer + i + vBufferSize[0] * (j + k * vBufferSize[1]);\n        for (; j < (region.GetIndex(1) + (int)region.GetSize(1)); j++, pVol += vBufferSize[0], u += du)\n        {\n#ifdef BILINEAR_BACKPROJECTION\n          ui = itk::Math::floor(u);\n          if (ui >= 0 && ui < (int)pSize[0] - 1)\n          {\n            double u1 = NAN, u2 = NAN, v1 = NAN, v2 = NAN;\n            pProj = projection->GetBufferPointer() + vi * pSize[0] + ui;\n            v1 = v - vi;\n            v2 = 1.0 - v1;\n            u1 = u - ui;\n            u2 = 1.0 - u1;\n            *pVol += w * (v2 * (u2 * *(pProj) + u1 * *(pProj + 1)) +\n                          v1 * (u2 * *(pProj + pSize[0]) + u1 * *(pProj + pSize[0] + 1)));\n          }\n#else\n          ui = itk::Math::Round<double>(u);\n          if (ui >= 0 && ui < (int)pSize[0])\n          {\n            pProj = projection->GetBufferPointer() + vi * pSize[0];\n            *pVol += w * *(pProj + ui);\n          }\n#endif\n        } // j\n      }\n    } // i\n  } // k\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkFDKConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKConeBeamReconstructionFilter_h\n#define rtkFDKConeBeamReconstructionFilter_h\n\n#include \"rtkFDKWeightProjectionFilter.h\"\n#include \"rtkFFTRampImageFilter.h\"\n#include \"rtkFDKBackProjectionImageFilter.h\"\n#include \"rtkConfiguration.h\"\n\n#include <itkExtractImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class FDKConeBeamReconstructionFilter\n * \\brief Implements Feldkamp, David and Kress cone-beam reconstruction\n *\n * FDKConeBeamReconstructionFilter is a mini-pipeline filter which combines\n * the different steps of the FDK cone-beam reconstruction filter:\n * - rtk::FDKWeightProjectionFilter for 2D weighting of the projections,\n * - rtk::FFTRampImageFilter for ramp filtering,\n * - rtk::FDKBackProjectionImageFilter for backprojection.\n * The input stack of projections is processed piece by piece (the size is\n * controlled with ProjectionSubsetSize) via the use of itk::ExtractImageFilter\n * to extract sub-stacks.\n *\n * \\dot\n * digraph FDKConeBeamReconstructionFilter {\n * node [shape=box];\n * 1 [ label=\"rtk::FDKWeightProjectionFilter\" URL=\"\\ref rtk::FDKWeightProjectionFilter\"];\n * 2 [ label=\"rtk::FFTRampImageFilter\" URL=\"\\ref rtk::FFTRampImageFilter\"];\n * 3 [ label=\"rtk::FDKBackProjectionImageFilter\" URL=\"\\ref rtk::FDKBackProjectionImageFilter\"];\n * 1 -> 2;\n * 2 -> 3;\n * }\n * \\enddot\n *\n * \\test rtkfdktest.cxx, rtkrampfiltertest.cxx, rtkmotioncompensatedfdktest.cxx,\n * rtkdisplaceddetectortest.cxx, rtkshortscantest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage, class TFFTPrecision = double>\nclass ITK_TEMPLATE_EXPORT FDKConeBeamReconstructionFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FDKConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = FDKConeBeamReconstructionFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using ExtractFilterType = itk::ExtractImageFilter<InputImageType, OutputImageType>;\n  using WeightFilterType = rtk::FDKWeightProjectionFilter<InputImageType, OutputImageType>;\n  using RampFilterType = rtk::FFTRampImageFilter<OutputImageType, OutputImageType, TFFTPrecision>;\n  using BackProjectionFilterType = rtk::FDKBackProjectionImageFilter<OutputImageType, OutputImageType>;\n  using BackProjectionFilterPointer = typename BackProjectionFilterType::Pointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FDKConeBeamReconstructionFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Get pointer to the weighting filter used by the feldkamp reconstruction */\n  typename WeightFilterType::Pointer\n  GetWeightFilter()\n  {\n    return m_WeightFilter;\n  }\n\n  /** Get pointer to the ramp filter used by the feldkamp reconstruction */\n  typename RampFilterType::Pointer\n  GetRampFilter()\n  {\n    return m_RampFilter;\n  }\n\n  /** Get / Set the number of cone-beam projection images processed\n      simultaneously. Default is 4. */\n  itkGetMacro(ProjectionSubsetSize, unsigned int);\n  itkSetMacro(ProjectionSubsetSize, unsigned int);\n\n  /** Get / Set and init the backprojection filter. The set function takes care\n   * of initializing the mini-pipeline and the ramp filter must therefore be\n   * created before calling this set function. */\n  itkGetMacro(BackProjectionFilter, BackProjectionFilterPointer);\n  virtual void\n  SetBackProjectionFilter(BackProjectionFilterType * _arg);\n\nprotected:\n  FDKConeBeamReconstructionFilter();\n  ~FDKConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Pointers to each subfilter of this composite filter */\n  typename ExtractFilterType::Pointer m_ExtractFilter;\n  typename WeightFilterType::Pointer  m_WeightFilter;\n  typename RampFilterType::Pointer    m_RampFilter;\n  BackProjectionFilterPointer         m_BackProjectionFilter;\n\nprivate:\n  /** Number of projections processed at a time. */\n  unsigned int m_ProjectionSubsetSize{ 16 };\n\n  /** Geometry propagated to subfilters of the mini-pipeline. */\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFDKConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFDKConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKConeBeamReconstructionFilter_hxx\n#define rtkFDKConeBeamReconstructionFilter_hxx\n\n\n#include <itkProgressAccumulator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::FDKConeBeamReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Create each filter of the composite filter\n  m_ExtractFilter = ExtractFilterType::New();\n  m_WeightFilter = WeightFilterType::New();\n  m_RampFilter = RampFilterType::New();\n  this->SetBackProjectionFilter(BackProjectionFilterType::New());\n\n  // Permanent internal connections\n  m_WeightFilter->SetInput(m_ExtractFilter->GetOutput());\n  m_RampFilter->SetInput(m_WeightFilter->GetOutput());\n\n  // Default parameters\n  m_ExtractFilter->SetDirectionCollapseToSubmatrix();\n  m_WeightFilter->InPlaceOn();\n\n  // Default to one projection per subset when FFTW is not available\n#if !defined(USE_FFTWD)\n  if (typeid(TFFTPrecision).name() == typeid(double).name())\n    m_ProjectionSubsetSize = 2;\n#endif\n#if !defined(USE_FFTWF)\n  if (typeid(TFFTPrecision).name() == typeid(float).name())\n    m_ProjectionSubsetSize = 2;\n#endif\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput());\n  if (!inputPtr)\n    return;\n\n  // SR: is this useful?\n  m_BackProjectionFilter->SetInput(0, this->GetInput(0));\n  m_BackProjectionFilter->SetInPlace(this->GetInPlace());\n  m_ExtractFilter->SetInput(this->GetInput(1));\n  m_BackProjectionFilter->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  m_BackProjectionFilter->GetOutput()->PropagateRequestedRegion();\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateOutputInformation()\n{\n  const unsigned int Dimension = this->InputImageDimension;\n\n  m_WeightFilter->SetGeometry(m_Geometry);\n  m_BackProjectionFilter->SetGeometry(m_Geometry);\n\n  // We only set the first sub-stack at that point, the rest will be\n  // requested in the GenerateData function\n  typename ExtractFilterType::InputImageRegionType projRegion;\n  projRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  unsigned int firstStackSize = std::min(m_ProjectionSubsetSize, (unsigned int)projRegion.GetSize(Dimension - 1));\n  projRegion.SetSize(Dimension - 1, firstStackSize);\n  m_ExtractFilter->SetExtractionRegion(projRegion);\n\n  // Run composite filter update\n  m_BackProjectionFilter->SetInput(0, this->GetInput(0));\n  m_BackProjectionFilter->SetInPlace(this->GetInPlace());\n  m_ExtractFilter->SetInput(this->GetInput(1));\n  m_BackProjectionFilter->UpdateOutputInformation();\n\n  // Update output information\n  this->GetOutput()->SetOrigin(m_BackProjectionFilter->GetOutput()->GetOrigin());\n  this->GetOutput()->SetSpacing(m_BackProjectionFilter->GetOutput()->GetSpacing());\n  this->GetOutput()->SetDirection(m_BackProjectionFilter->GetOutput()->GetDirection());\n  this->GetOutput()->SetLargestPossibleRegion(m_BackProjectionFilter->GetOutput()->GetLargestPossibleRegion());\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateData()\n{\n  const unsigned int Dimension = this->InputImageDimension;\n\n  // The backprojection works on a small stack of projections, not the full stack\n  typename ExtractFilterType::InputImageRegionType subsetRegion;\n  subsetRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  unsigned int nProj = subsetRegion.GetSize(Dimension - 1);\n\n  // The progress accumulator tracks the progress of the pipeline\n  // Each filter is equally weighted across all iterations of the stack\n  auto progress = itk::ProgressAccumulator::New();\n  progress->SetMiniPipelineFilter(this);\n  auto frac = (1.0f / 3) / itk::Math::ceil(double(nProj) / m_ProjectionSubsetSize);\n  progress->RegisterInternalFilter(m_WeightFilter, frac);\n  progress->RegisterInternalFilter(m_RampFilter, frac);\n  progress->RegisterInternalFilter(m_BackProjectionFilter, frac);\n\n  for (unsigned int i = 0; i < nProj; i += m_ProjectionSubsetSize)\n  {\n    // After the first bp update, we need to use its output as input.\n    if (i)\n    {\n      typename TInputImage::Pointer pimg = m_BackProjectionFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      m_BackProjectionFilter->SetInput(pimg);\n\n      // Change projection subset\n      subsetRegion.SetIndex(Dimension - 1, i);\n      subsetRegion.SetSize(Dimension - 1, std::min(m_ProjectionSubsetSize, nProj - i));\n      m_ExtractFilter->SetExtractionRegion(subsetRegion);\n\n      // This is required to reset the full pipeline\n      m_BackProjectionFilter->GetOutput()->UpdateOutputInformation();\n      m_BackProjectionFilter->GetOutput()->PropagateRequestedRegion();\n    }\n    m_BackProjectionFilter->Update();\n  }\n\n  this->GraftOutput(m_BackProjectionFilter->GetOutput());\n  this->GenerateOutputInformation();\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::SetBackProjectionFilter(\n  BackProjectionFilterType * _arg)\n{\n  itkDebugMacro(\"setting BackProjectionFilter to \" << _arg);\n  if (this->m_BackProjectionFilter != _arg)\n  {\n    this->m_BackProjectionFilter = _arg;\n    m_BackProjectionFilter->SetInput(1, m_RampFilter->GetOutput());\n    this->Modified();\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkFDKConeBeamReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkFDKVarianceReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKVarianceReconstructionFilter_h\n#define rtkFDKVarianceReconstructionFilter_h\n\n#include \"rtkFDKWeightProjectionFilter.h\"\n#include \"rtkFFTVarianceRampImageFilter.h\"\n#include \"rtkFDKBackProjectionImageFilter.h\"\n#include \"rtkConfiguration.h\"\n\n#include <itkExtractImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class FDKVarianceReconstructionFilter\n * \\brief Implements reconstruction of the variance map of images reconstructed with FDK\n *\n * \\dot\n * digraph FDKVarianceReconstructionFilter {\n *  node [shape=box];\n *  1 [ label=\"rtk::FDKWeightProjectionFilter\" URL=\"\\ref rtk::FDKWeightProjectionFilter\"];\n *  2 [ label=\"rtk::FDKWeightProjectionFilter\" URL=\"\\ref rtk::FDKWeightProjectionFilter\"];\n *  3 [ label=\"rtk::FFTVarianceRampImageFilter\" URL=\"\\ref rtk::FFTVarianceRampImageFilter\"];\n *  4 [ label=\"rtk::FDKBackProjectionImageFilter\" URL=\"\\ref rtk::FDKBackProjectionImageFilter\"];\n *  1 -> 2;\n *  2 -> 3;\n *  3 -> 4;\n * }\n * \\enddot\n *\n * \\test rtkvariancereconstructiontest\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage, class TFFTPrecision = double>\nclass ITK_TEMPLATE_EXPORT FDKVarianceReconstructionFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FDKVarianceReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = FDKVarianceReconstructionFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using ExtractFilterType = itk::ExtractImageFilter<InputImageType, OutputImageType>;\n  using WeightFilterType = rtk::FDKWeightProjectionFilter<InputImageType, OutputImageType>;\n  using VarianceRampFilterType = rtk::FFTVarianceRampImageFilter<OutputImageType, OutputImageType, TFFTPrecision>;\n  using BackProjectionFilterType = rtk::FDKBackProjectionImageFilter<OutputImageType, OutputImageType>;\n  using BackProjectionFilterPointer = typename BackProjectionFilterType::Pointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FDKVarianceReconstructionFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Get pointer to the ramp filter used by the feldkamp reconstruction */\n  typename VarianceRampFilterType::Pointer\n  GetVarianceRampFilter()\n  {\n    return m_VarianceRampFilter;\n  }\n\n  /** Get / Set the number of cone-beam projection images processed\n      simultaneously. Default is 4. */\n  itkGetMacro(ProjectionSubsetSize, unsigned int);\n  itkSetMacro(ProjectionSubsetSize, unsigned int);\n\n  /** Get / Set and init the backprojection filter. The set function takes care\n   * of initializing the mini-pipeline and the ramp filter must therefore be\n   * created before calling this set function. */\n  itkGetMacro(BackProjectionFilter, BackProjectionFilterPointer);\n  virtual void\n  SetBackProjectionFilter(const BackProjectionFilterPointer _arg);\n\nprotected:\n  FDKVarianceReconstructionFilter();\n  ~FDKVarianceReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Pointers to each subfilter of this composite filter */\n  typename ExtractFilterType::Pointer      m_ExtractFilter;\n  typename WeightFilterType::Pointer       m_WeightFilter1;\n  typename WeightFilterType::Pointer       m_WeightFilter2;\n  typename VarianceRampFilterType::Pointer m_VarianceRampFilter;\n  BackProjectionFilterPointer              m_BackProjectionFilter;\n\nprivate:\n  /** Number of projections processed at a time. */\n  unsigned int m_ProjectionSubsetSize{ 16 };\n\n  /** Geometry propagated to subfilters of the mini-pipeline. */\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFDKVarianceReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFDKVarianceReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKVarianceReconstructionFilter_hxx\n#define rtkFDKVarianceReconstructionFilter_hxx\n\n#include \"rtkFDKVarianceReconstructionFilter.h\"\n\n#include <itkProgressAccumulator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nFDKVarianceReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::FDKVarianceReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Create each filter of the composite filter\n  m_ExtractFilter = ExtractFilterType::New();\n  m_WeightFilter1 = WeightFilterType::New();\n  m_WeightFilter2 = WeightFilterType::New();\n  m_VarianceRampFilter = VarianceRampFilterType::New();\n  this->SetBackProjectionFilter(BackProjectionFilterType::New());\n\n  // Permanent internal connections\n  m_WeightFilter1->SetInput(m_ExtractFilter->GetOutput());\n  m_WeightFilter2->SetInput(m_WeightFilter1->GetOutput());\n  m_VarianceRampFilter->SetInput(m_WeightFilter2->GetOutput());\n\n  // Default parameters\n  m_ExtractFilter->SetDirectionCollapseToSubmatrix();\n  m_WeightFilter1->InPlaceOn();\n  m_WeightFilter2->InPlaceOn();\n\n  // Default to one projection per subset when FFTW is not available\n#if !defined(USE_FFTWD)\n  if (typeid(TFFTPrecision).name() == typeid(double).name())\n    m_ProjectionSubsetSize = 2;\n#endif\n#if !defined(USE_FFTWF)\n  if (typeid(TFFTPrecision).name() == typeid(float).name())\n    m_ProjectionSubsetSize = 2;\n#endif\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKVarianceReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKVarianceReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput());\n  if (!inputPtr)\n    return;\n\n  // SR: is this useful?\n  m_BackProjectionFilter->SetInput(0, this->GetInput(0));\n  m_BackProjectionFilter->SetInPlace(this->GetInPlace());\n  m_ExtractFilter->SetInput(this->GetInput(1));\n  m_BackProjectionFilter->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  m_BackProjectionFilter->GetOutput()->PropagateRequestedRegion();\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKVarianceReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateOutputInformation()\n{\n  const unsigned int Dimension = this->InputImageDimension;\n\n  m_WeightFilter1->SetGeometry(m_Geometry);\n  m_WeightFilter2->SetGeometry(m_Geometry);\n  m_BackProjectionFilter->SetGeometry(m_Geometry);\n\n  // We only set the first sub-stack at that point, the rest will be\n  // requested in the GenerateData function\n  typename ExtractFilterType::InputImageRegionType projRegion;\n  projRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  unsigned int firstStackSize = std::min(m_ProjectionSubsetSize, (unsigned int)projRegion.GetSize(Dimension - 1));\n  projRegion.SetSize(Dimension - 1, firstStackSize);\n  m_ExtractFilter->SetExtractionRegion(projRegion);\n\n  // Run composite filter update\n  m_BackProjectionFilter->SetInput(0, this->GetInput(0));\n  m_BackProjectionFilter->SetInPlace(this->GetInPlace());\n  m_ExtractFilter->SetInput(this->GetInput(1));\n  m_BackProjectionFilter->UpdateOutputInformation();\n\n  // Update output information\n  this->GetOutput()->SetOrigin(m_BackProjectionFilter->GetOutput()->GetOrigin());\n  this->GetOutput()->SetSpacing(m_BackProjectionFilter->GetOutput()->GetSpacing());\n  this->GetOutput()->SetDirection(m_BackProjectionFilter->GetOutput()->GetDirection());\n  this->GetOutput()->SetLargestPossibleRegion(m_BackProjectionFilter->GetOutput()->GetLargestPossibleRegion());\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKVarianceReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateData()\n{\n  const unsigned int Dimension = this->InputImageDimension;\n\n  // The backprojection works on a small stack of projections, not the full stack\n  typename ExtractFilterType::InputImageRegionType subsetRegion;\n  subsetRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  unsigned int nProj = subsetRegion.GetSize(Dimension - 1);\n\n  // The progress accumulator tracks the progress of the pipeline\n  // Each filter is equally weighted across all iterations of the stack\n  auto progress = itk::ProgressAccumulator::New();\n  progress->SetMiniPipelineFilter(this);\n  auto frac = (1.0f / 4) / itk::Math::ceil(double(nProj) / m_ProjectionSubsetSize);\n  progress->RegisterInternalFilter(m_WeightFilter1, frac);\n  progress->RegisterInternalFilter(m_WeightFilter2, frac);\n  progress->RegisterInternalFilter(m_VarianceRampFilter, frac);\n  progress->RegisterInternalFilter(m_BackProjectionFilter, frac);\n\n  for (unsigned int i = 0; i < nProj; i += m_ProjectionSubsetSize)\n  {\n    // After the first bp update, we need to use its output as input.\n    if (i)\n    {\n      typename TInputImage::Pointer pimg = m_BackProjectionFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      m_BackProjectionFilter->SetInput(pimg);\n\n      // Change projection subset\n      subsetRegion.SetIndex(Dimension - 1, i);\n      subsetRegion.SetSize(Dimension - 1, std::min(m_ProjectionSubsetSize, nProj - i));\n      m_ExtractFilter->SetExtractionRegion(subsetRegion);\n\n      // This is required to reset the full pipeline\n      m_BackProjectionFilter->GetOutput()->UpdateOutputInformation();\n      m_BackProjectionFilter->GetOutput()->PropagateRequestedRegion();\n    }\n    m_BackProjectionFilter->Update();\n  }\n\n  this->GraftOutput(m_BackProjectionFilter->GetOutput());\n  this->GenerateOutputInformation();\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFDKVarianceReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::SetBackProjectionFilter(\n  const BackProjectionFilterPointer _arg)\n{\n  itkDebugMacro(\"setting BackProjectionFilter to \" << _arg);\n  if (this->m_BackProjectionFilter != _arg)\n  {\n    this->m_BackProjectionFilter = _arg;\n    m_BackProjectionFilter->SetInput(1, m_VarianceRampFilter->GetOutput());\n    this->Modified();\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkFDKVarianceReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkFDKWarpBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKWarpBackProjectionImageFilter_h\n#define rtkFDKWarpBackProjectionImageFilter_h\n\n#include \"rtkFDKBackProjectionImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class FDKWarpBackProjectionImageFilter\n * \\brief CPU version of the warp backprojection of motion-compensated FDK.\n *\n * The deformation is described by the TDeformation template parameter. This\n * type must implement the function SetFrame and returns a 3D deformation\n * vector field. FDKWarpBackProjectionImageFilter loops over the projections,\n * sets the frame number, updates the deformation and compose the resulting\n * deformation with the projection matrix. One thus obtain a warped\n * backprojection that is used in motion-compensated cone-beam CT\n * reconstruction. This has been described in [Rit et al, TMI, 2009] and\n * [Rit et al, Med Phys, 2009].\n *\n * \\test rtkmotioncompensatedfdktest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Projector\n */\ntemplate <class TInputImage, class TOutputImage, class TDeformation>\nclass ITK_TEMPLATE_EXPORT FDKWarpBackProjectionImageFilter\n  : public FDKBackProjectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FDKWarpBackProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = FDKWarpBackProjectionImageFilter;\n  using Superclass = FDKBackProjectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using InputPixelType = typename TInputImage::PixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n\n  using DeformationType = TDeformation;\n  using DeformationPointer = typename DeformationType::Pointer;\n\n  using GeometryType = rtk::ProjectionGeometry<TOutputImage::ImageDimension>;\n  using GeometryPointer = typename GeometryType::Pointer;\n  using ProjectionMatrixType = typename GeometryType::MatrixType;\n  using ProjectionImageType = itk::Image<InputPixelType, TInputImage::ImageDimension - 1>;\n  using ProjectionImagePointer = typename ProjectionImageType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(FDKWarpBackProjectionImageFilter);\n\n  /** Set the deformation. */\n  itkGetMacro(Deformation, DeformationPointer);\n  itkSetObjectMacro(Deformation, DeformationType);\n\nprotected:\n  FDKWarpBackProjectionImageFilter();\n  ~FDKWarpBackProjectionImageFilter() override = default;\n\n  void\n  GenerateData() override;\n\nprivate:\n  DeformationPointer m_Deformation;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFDKWarpBackProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFDKWarpBackProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKWarpBackProjectionImageFilter_hxx\n#define rtkFDKWarpBackProjectionImageFilter_hxx\n\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkLinearInterpolateImageFunction.h>\n\n#define BILINEAR_BACKPROJECTION\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TDeformation>\nFDKWarpBackProjectionImageFilter<TInputImage, TOutputImage, TDeformation>::FDKWarpBackProjectionImageFilter() = default;\n\ntemplate <class TInputImage, class TOutputImage, class TDeformation>\nvoid\nFDKWarpBackProjectionImageFilter<TInputImage, TOutputImage, TDeformation>::GenerateData()\n{\n  this->AllocateOutputs();\n  this->SetTranspose(true);\n\n  const unsigned int Dimension = TInputImage::ImageDimension;\n  const unsigned int nProj = this->GetInput(1)->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  const unsigned int iFirstProj = this->GetInput(1)->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n\n  // Initialize output region with input region in case the filter is not in\n  // place\n  this->GetMultiThreader()->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  if (this->GetInput() != this->GetOutput())\n  {\n\n    this->GetMultiThreader()->template ParallelizeImageRegion<TOutputImage::ImageDimension>(\n      this->GetOutput()->GetRequestedRegion(),\n      [this](const typename TOutputImage::RegionType & outputRegionForThread) {\n        // Iterators on volume input and output\n        itk::ImageRegionConstIterator<TInputImage> itIn(this->GetInput(), outputRegionForThread);\n        using OutputRegionIterator = itk::ImageRegionIteratorWithIndex<TOutputImage>;\n        OutputRegionIterator itOut(this->GetOutput(), outputRegionForThread);\n\n        itIn.GoToBegin();\n        while (!itIn.IsAtEnd())\n        {\n          itOut.Set(itIn.Get());\n          ++itIn;\n          ++itOut;\n        }\n      },\n      nullptr);\n  }\n\n  // Rotation center (assumed to be at 0 yet)\n  typename TInputImage::PointType rotCenterPoint;\n  rotCenterPoint.Fill(0.0);\n\n  // Warped point and interpolator for vector field\n  auto warpInterpolator = itk::LinearInterpolateImageFunction<typename TDeformation::OutputImageType, double>::New();\n  itk::Matrix<double, Dimension + 1, Dimension + 1> matrixVol =\n    GetPhysicalPointToIndexMatrix<TOutputImage>(this->GetOutput());\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    // Set the deformation\n    m_Deformation->SetFrame(iProj);\n    m_Deformation->Update();\n    warpInterpolator->SetInputImage(m_Deformation->GetOutput());\n\n    // Extract the current slice and create interpolator, could be any interpolation\n    ProjectionImagePointer projection = this->template GetProjection<ProjectionImageType>(iProj);\n    auto                   interpolator = itk::LinearInterpolateImageFunction<ProjectionImageType, double>::New();\n    interpolator->SetInputImage(projection);\n\n    // Index to index matrix normalized to have a correct backprojection weight\n    // (1 at the isocenter)\n    ProjectionMatrixType matrix(this->GetIndexToIndexProjectionMatrix(iProj).GetVnlMatrix() * matrixVol.GetVnlMatrix());\n    double               perspFactor = matrix[Dimension - 1][Dimension];\n    for (unsigned int j = 0; j < Dimension; j++)\n      perspFactor += matrix[Dimension - 1][j] * rotCenterPoint[j];\n    matrix /= perspFactor;\n\n    this->GetMultiThreader()->template ParallelizeImageRegion<TOutputImage::ImageDimension>(\n      this->GetOutput()->GetRequestedRegion(),\n      [this, warpInterpolator, interpolator, matrix](const typename TOutputImage::RegionType & outputRegionForThread) {\n        using OutputRegionIterator = itk::ImageRegionIteratorWithIndex<TOutputImage>;\n        OutputRegionIterator itOut(this->GetOutput(), outputRegionForThread);\n\n        // Go over each voxel\n        itOut.GoToBegin();\n        while (!itOut.IsAtEnd())\n        {\n          // Warp\n          typename TOutputImage::PointType point;\n          this->GetOutput()->TransformIndexToPhysicalPoint(itOut.GetIndex(), point);\n          if (warpInterpolator->IsInsideBuffer(point))\n            point = point + warpInterpolator->Evaluate(point);\n\n          // Compute projection index\n          itk::ContinuousIndex<double, TOutputImage::ImageDimension - 1> pointProj;\n          for (unsigned int i = 0; i < TOutputImage::ImageDimension - 1; i++)\n          {\n            pointProj[i] = matrix[i][TOutputImage::ImageDimension];\n            for (unsigned int j = 0; j < TOutputImage::ImageDimension; j++)\n              pointProj[i] += matrix[i][j] * point[j];\n          }\n\n          // Apply perspective\n          double perspFactor_local = matrix[TOutputImage::ImageDimension - 1][TOutputImage::ImageDimension];\n          for (unsigned int j = 0; j < TOutputImage::ImageDimension; j++)\n            perspFactor_local += matrix[TOutputImage::ImageDimension - 1][j] * point[j];\n          perspFactor_local = 1 / perspFactor_local;\n          for (unsigned int i = 0; i < TOutputImage::ImageDimension - 1; i++)\n            pointProj[i] = pointProj[i] * perspFactor_local;\n\n          // Interpolate if in projection\n          if (interpolator->IsInsideBuffer(pointProj))\n          {\n            itOut.Set(itOut.Get() +\n                      perspFactor_local * perspFactor_local * interpolator->EvaluateAtContinuousIndex(pointProj));\n          }\n\n          ++itOut;\n        }\n      },\n      nullptr);\n  }\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkFDKWeightProjectionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKWeightProjectionFilter_h\n#define rtkFDKWeightProjectionFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class FDKWeightProjectionFilter\n * \\brief Weighting of projections to correct for the divergence in\n * filtered backprojection reconstruction algorithms.\n * The weighting comprises:\n * - the 2D weighting of the FDK algorithm [Feldkamp, 1984],\n * - its modification described in [Rit and Clackdoyle, CT meeting, 2014] for\n *   tilted detector\n * - the correction of the ramp factor for divergent full scan,\n * - the angular weighting for the final 3D integral of FDK.\n * Note that SourceToDetectorDistance, SourceToDetectorIsocenter\n * SouceOffsets and ProjectionOffsets are accounted for on a per\n * projection basis but InPlaneRotation and OutOfPlaneRotation are not\n * accounted for.\n * \\author Simon Rit\n *\n * \\test rtkfdktest.cxx, rtkrampfiltertest.cxx, rtkdisplaceddetectortest.cxx,\n * rtkshortscantest.cxx, rtkfdkprojweightcompcudatest.cxx\n *\n * \\ingroup RTK InPlaceImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT FDKWeightProjectionFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FDKWeightProjectionFilter);\n\n  /** Standard class type alias. */\n  using Self = FDKWeightProjectionFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FDKWeightProjectionFilter);\n\n  /** Get/ Set geometry structure */\n  itkGetMacro(Geometry, ThreeDCircularProjectionGeometry::Pointer);\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\nprotected:\n  FDKWeightProjectionFilter() = default;\n  ~FDKWeightProjectionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  /** Angular weights for each projection */\n  std::vector<double> m_ConstantProjectionFactor;\n\n  /** Tilt angles with respect to the conventional situation */\n  std::vector<double> m_TiltAngles;\n\n  /** Geometrical description of the system */\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFDKWeightProjectionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFDKWeightProjectionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFDKWeightProjectionFilter_hxx\n#define rtkFDKWeightProjectionFilter_hxx\n\n\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFDKWeightProjectionFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFDKWeightProjectionFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  // Get angular weights from geometry\n  m_ConstantProjectionFactor = m_Geometry->GetAngularGaps(m_Geometry->GetSourceAngles());\n  m_TiltAngles = m_Geometry->GetTiltAngles();\n\n  for (unsigned int k = 0; k < m_ConstantProjectionFactor.size(); k++)\n  {\n    // Add correction factor for ramp filter\n    const double sdd = m_Geometry->GetSourceToDetectorDistances()[k];\n    if (sdd == 0.) // Parallel\n      m_ConstantProjectionFactor[k] *= 0.5;\n    else // Divergent\n    {\n      // See [Rit and Clackdoyle, CT meeting, 2014]\n      ThreeDCircularProjectionGeometry::HomogeneousVectorType sp;\n      sp = m_Geometry->GetSourcePosition(k);\n      sp[3] = 0.;\n      const double sid = m_Geometry->GetSourceToIsocenterDistances()[k];\n      m_ConstantProjectionFactor[k] *= itk::Math::abs(sdd) / (2. * sid * sid);\n      m_ConstantProjectionFactor[k] *= sp.GetNorm();\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFDKWeightProjectionFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Prepare point increment (TransformIndexToPhysicalPoint too slow)\n  typename InputImageType::PointType pointBase, pointIncrement;\n  typename InputImageType::IndexType index = outputRegionForThread.GetIndex();\n  this->GetInput()->TransformIndexToPhysicalPoint(index, pointBase);\n  for (int i = 0; i < 3; i++)\n    index[i]++;\n  this->GetInput()->TransformIndexToPhysicalPoint(index, pointIncrement);\n  for (int i = 0; i < 3; i++)\n    pointIncrement[i] -= pointBase[i];\n\n  // Iterators\n  itk::ImageRegionConstIterator<InputImageType> itI(this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<OutputImageType>     itO(this->GetOutput(), outputRegionForThread);\n  itI.GoToBegin();\n  itO.GoToBegin();\n\n  // Go over output, compute weights and avoid redundant computation\n  for (int k = outputRegionForThread.GetIndex(2);\n       k < outputRegionForThread.GetIndex(2) + (int)outputRegionForThread.GetSize(2);\n       k++)\n  {\n    const double sdd = m_Geometry->GetSourceToDetectorDistances()[k];\n    if (sdd != 0.) // Divergent\n    {\n      typename InputImageType::PointType point = pointBase;\n      point[1] = pointBase[1] + m_Geometry->GetProjectionOffsetsY()[k] - m_Geometry->GetSourceOffsetsY()[k];\n      const double cosa = cos(m_TiltAngles[k]);\n      const double sina = sin(m_TiltAngles[k]);\n      const double tana = tan(m_TiltAngles[k]);\n      const double sid = m_Geometry->GetSourceToIsocenterDistances()[k];\n      const double sdd2 = sdd * sdd;\n      const double RD = sdd - sid;\n\n      const double numpart1 = sdd * (cosa + tana * sina);\n      const double sddtana = sdd * tana;\n\n      for (unsigned int j = 0; j < outputRegionForThread.GetSize(1); j++, point[1] += pointIncrement[1])\n      {\n        point[0] = pointBase[0] + m_Geometry->GetProjectionOffsetsX()[k] + tana * RD;\n        const double sdd2y2 = sdd2 + point[1] * point[1];\n        for (unsigned int i = 0; i < outputRegionForThread.GetSize(0); i++, ++itI, ++itO, point[0] += pointIncrement[0])\n        {\n          const double denom = sqrt(sdd2y2 + pow(point[0] - sddtana, 2.));\n          const double cosGamma = (numpart1 - point[0] * sina) / denom;\n          itO.Set(itI.Get() * m_ConstantProjectionFactor[k] * cosGamma);\n        }\n      }\n    }\n    else // Parallel\n    {\n      double weight = m_ConstantProjectionFactor[k];\n      for (unsigned int j = 0; j < outputRegionForThread.GetSize(1); j++)\n      {\n        for (unsigned int i = 0; i < outputRegionForThread.GetSize(0); i++, ++itI, ++itO)\n          itO.Set(itI.Get() * weight);\n      }\n    }\n  }\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkFFTHilbertImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFFTHilbertImageFilter_h\n#define rtkFFTHilbertImageFilter_h\n\n#include <itkConceptChecking.h>\n#include \"rtkConfiguration.h\"\n#include \"rtkFFTProjectionsConvolutionImageFilter.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class FFTHilbertImageFilter\n * \\brief Implements the Hilbert transform.\n *\n * \\test rtkhilbertfiltertest.cxx\n *\n * \\author Aurélien Coussat\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage = TInputImage, class TFFTPrecision = double>\nclass ITK_EXPORT FFTHilbertImageFilter\n  : public rtk::FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FFTHilbertImageFilter);\n\n  /** Standard class type alias. */\n  using Self = FFTHilbertImageFilter;\n  using Superclass = rtk::FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using FFTPrecisionType = TFFTPrecision;\n  using IndexType = typename InputImageType::IndexType;\n  using SizeType = typename InputImageType::SizeType;\n\n  using FFTInputImageType = typename Superclass::FFTInputImageType;\n  using FFTInputImagePointer = typename FFTInputImageType::Pointer;\n  using FFTOutputImageType = typename Superclass::FFTOutputImageType;\n  using FFTOutputImagePointer = typename FFTOutputImageType::Pointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  itkGetMacro(PixelShift, double);\n  // The Set macro is redefined to clear the current FFT kernel when a parameter\n  // is modified.\n  virtual void\n  SetPixelShift(const double _arg)\n  {\n    itkDebugMacro(\"setting PixelShift to \" << _arg);\n    CLANG_PRAGMA_PUSH\n    CLANG_SUPPRESS_Wfloat_equal\n    if (this->m_PixelShift != _arg)\n    {\n      this->m_PixelShift = _arg;\n      this->Modified();\n      this->m_KernelFFT = nullptr;\n    }\n    CLANG_PRAGMA_POP\n  }\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FFTHilbertImageFilter);\n\nprotected:\n  FFTHilbertImageFilter() = default;\n  ~FFTHilbertImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  /** Create and return a pointer to one line of the Hilbert kernel in Fourier space.\n   *  Used in generate data functions.  */\n  void\n  UpdateFFTProjectionsConvolutionKernel(const SizeType s) override;\n\nprivate:\n  SizeType m_PreviousKernelUpdateSize;\n  double   m_PixelShift;\n\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFFTHilbertImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFFTHilbertImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFFTHilbertImageFilter_hxx\n#define rtkFFTHilbertImageFilter_hxx\n\n#include \"rtkFFTHilbertImageFilter.h\"\n#include \"itkForwardFFTImageFilter.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTHilbertImageFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateOutputInformation()\n{\n  FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateOutputInformation();\n\n  auto   origin = this->GetOutput()->GetOrigin();\n  double spacing = this->GetOutput()->GetSpacing()[0];\n  origin[0] += m_PixelShift * spacing;\n  this->GetOutput()->SetOrigin(origin);\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTHilbertImageFilter<TInputImage, TOutputImage, TFFTPrecision>::UpdateFFTProjectionsConvolutionKernel(const SizeType s)\n{\n  if (this->m_KernelFFT.GetPointer() != nullptr && s == this->m_PreviousKernelUpdateSize)\n  {\n    return;\n  }\n  m_PreviousKernelUpdateSize = s;\n\n  const int width = s[0];\n\n  // Allocate kernel\n  SizeType size;\n  size.Fill(1);\n  size[0] = width;\n  FFTInputImagePointer kernel = FFTInputImageType::New();\n  kernel->SetRegions(size);\n  kernel->Allocate();\n  kernel->FillBuffer(0.);\n\n  itk::ImageRegionIterator<FFTInputImageType> it(kernel, kernel->GetLargestPossibleRegion());\n\n  // Compute band-limited kernel in space domain\n  double    spacing = this->GetInput()->GetSpacing()[0];\n  IndexType ix;\n\n  while (!it.IsAtEnd())\n  {\n    ix = it.GetIndex();\n\n    double x = (ix[0] + m_PixelShift) * spacing;\n    if (x > (size[0] / 2) * spacing)\n      x -= size[0] * spacing;\n\n    if (x == 0.)\n    {\n      it.Set(0.);\n    }\n    else\n    {\n      double v = spacing * (1. - std::cos(itk::Math::pi * x / spacing)) / (itk::Math::pi * x);\n      it.Set(v);\n    }\n\n    ++it;\n  }\n\n  // FFT kernel\n  auto fftK = itk::RealToHalfHermitianForwardFFTImageFilter<FFTInputImageType, FFTOutputImageType>::New();\n  fftK->SetInput(kernel);\n  fftK->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  fftK->Update();\n\n  this->m_KernelFFT = fftK->GetOutput();\n  this->m_KernelFFT->DisconnectPipeline();\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkFFTProjectionsConvolutionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFFTProjectionsConvolutionImageFilter_h\n#define rtkFFTProjectionsConvolutionImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkConceptChecking.h>\n\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class FFTProjectionsConvolutionImageFilter\n * \\brief Base class for 1D or 2D FFT based convolution of projections\n *\n * The filter code is based on FFTConvolutionImageFilter by Gaetan Lehmann\n * (see https://hdl.handle.net/10380/3154).\n *\n * \\test rtkrampfiltertest.cxx, rtkscatterglaretest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nclass ITK_TEMPLATE_EXPORT FFTProjectionsConvolutionImageFilter\n  : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FFTProjectionsConvolutionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = FFTProjectionsConvolutionImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using RegionType = typename InputImageType::RegionType;\n  using IndexType = typename InputImageType::IndexType;\n  using SizeType = typename InputImageType::SizeType;\n\n  using FFTInputImageType = typename itk::Image<TFFTPrecision, TInputImage::ImageDimension>;\n  using FFTInputImagePointer = typename FFTInputImageType::Pointer;\n  using FFTOutputImageType = typename itk::Image<std::complex<TFFTPrecision>, TInputImage::ImageDimension>;\n  using FFTOutputImagePointer = typename FFTOutputImageType::Pointer;\n  using ZeroPadFactorsType = itk::Vector<int, 2>;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FFTProjectionsConvolutionImageFilter);\n\n  /**\n   * Set/Get the greatest prime factor allowed on the size of the padded image.\n   * The filter increase the size of the image to reach a size with the greatest\n   * prime factor smaller or equal to the specified value. The default value is\n   * 13, which is the greatest prime number for which the FFT are precomputed\n   * in FFTW, and thus gives very good performance.\n   * A greatest prime factor of 2 produce a size which is a power of 2, and thus\n   * is suitable for vnl base fft filters.\n   * A greatest prime factor of 1 or less - typically 0 - disable the extra padding.\n   *\n   * Warning: this parameter is not used (and useful) only when ITK is built with\n   * FFTW support.\n   */\n  itkGetConstMacro(GreatestPrimeFactor, int);\n  itkSetMacro(GreatestPrimeFactor, int);\n\n  /** Set/Get the percentage of the image widthfeathered with data to correct\n   * for truncation.\n   */\n  itkGetConstMacro(TruncationCorrection, double);\n  itkSetMacro(TruncationCorrection, double);\n\n  /** Set/Get the zero padding factors in x and y directions. Accepted values\n   * are either 1 and 2. The y value is only used if the convolution kernel is 2D.\n   */\n  itkGetConstMacro(ZeroPadFactors, ZeroPadFactorsType);\n  virtual void\n  SetZeroPadFactors(ZeroPadFactorsType _arg)\n  {\n    if (m_ZeroPadFactors != _arg)\n    {\n      m_ZeroPadFactors = _arg;\n      m_ZeroPadFactors[0] = std::max(m_ZeroPadFactors[0], 1);\n      m_ZeroPadFactors[1] = std::max(m_ZeroPadFactors[1], 1);\n      m_ZeroPadFactors[0] = std::min(m_ZeroPadFactors[0], 2);\n      m_ZeroPadFactors[1] = std::min(m_ZeroPadFactors[1], 2);\n      this->Modified();\n    }\n  }\n\n  itkConceptMacro(ImageDimensionCheck, (itk::Concept::SameDimensionOrMinusOne<Self::InputImageDimension, 3>));\n\nprotected:\n  FFTProjectionsConvolutionImageFilter();\n  ~FFTProjectionsConvolutionImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  void\n  AfterThreadedGenerateData() override;\n\n  void\n  ThreadedGenerateData(const RegionType & outputRegionForThread, ThreadIdType threadId) override;\n\n  /** Pad the inputRegion region of the input image and returns a pointer to the new padded image.\n   * Padding includes a correction for truncation [Ohnesorge, Med Phys, 2000].\n   * centralRegion is the region of the returned image which corresponds to inputRegion.\n   */\n  virtual FFTInputImagePointer\n  PadInputImageRegion(const RegionType & inputRegion);\n  RegionType\n  GetPaddedImageRegion(const RegionType & inputRegion);\n\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  bool\n  IsPrime(int n) const;\n\n  int\n  GreatestPrimeFactor(int n) const;\n\n  /** Creates and return a pointer to the convolution kernel. Can be 1D or 2D.\n   *  Used in generate data functions, must be implemented in daughter classes.  */\n  virtual void\n  UpdateFFTProjectionsConvolutionKernel(const SizeType size) = 0;\n\n  /** Pre compute weights for truncation correction in a lookup table. The index\n   * is the distance to the original image border.\n   * Careful: the function is not thread safe but it does nothing if the weights have\n   * already been computed.\n   */\n  virtual void\n                                      UpdateTruncationMirrorWeights();\n  typename std::vector<TFFTPrecision> m_TruncationMirrorWeights;\n\n  /** Must be set to fix whether the kernel is 1D or 2D. Will have an effect on\n   * the padded region and the input requested region. */\n  int m_KernelDimension{ 1 };\n\n  /**\n   * FFT of the convolution kernel that each daughter class must update.\n   */\n  FFTOutputImagePointer m_KernelFFT;\n\nprivate:\n  /** Percentage of the image width which is feathered with data to correct for truncation.\n   * 0 (default) means no correction.\n   */\n  double m_TruncationCorrection{ 0. };\n  int\n  GetTruncationCorrectionExtent();\n\n  /** Zero padding factors in x and y directions. Accepted values are either 1\n   * and 2. The y value is only used if the convolution kernel is 2D.\n   */\n  ZeroPadFactorsType m_ZeroPadFactors;\n\n  /**\n   * Greatest prime factor of the FFT input.\n   */\n  int m_GreatestPrimeFactor{ 2 };\n  int m_BackupNumberOfThreads{ 1 };\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFFTProjectionsConvolutionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFFTProjectionsConvolutionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFFTProjectionsConvolutionImageFilter_hxx\n#define rtkFFTProjectionsConvolutionImageFilter_hxx\n\n\n// Use local RTK FFTW files taken from Gaëtan Lehmann's code for\n// thread safety: https://hdl.handle.net/10380/3154\n#include <itkRealToHalfHermitianForwardFFTImageFilter.h>\n#include <itkHalfHermitianToRealInverseFFTImageFilter.h>\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::FFTProjectionsConvolutionImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n#if defined(USE_FFTWD)\n  if (typeid(TFFTPrecision).name() == typeid(double).name())\n    m_GreatestPrimeFactor = 13;\n#endif\n#if defined(USE_FFTWF)\n  if (typeid(TFFTPrecision).name() == typeid(float).name())\n    m_GreatestPrimeFactor = 13;\n#endif\n\n  m_ZeroPadFactors.Fill(2);\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateInputRequestedRegion()\n{\n  // call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  auto * input = const_cast<InputImageType *>(this->GetInput());\n  if (!input)\n    return;\n\n  // Compute input region (==requested region fully enlarged for dim 0)\n  RegionType inputRegion;\n  this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());\n  inputRegion.SetIndex(0, this->GetOutput()->GetLargestPossibleRegion().GetIndex(0));\n  inputRegion.SetSize(0, this->GetOutput()->GetLargestPossibleRegion().GetSize(0));\n\n  // Also enlarge along dim 1 if 2D kernel is used\n  if (m_KernelDimension == 2)\n  {\n    inputRegion.SetIndex(1, this->GetOutput()->GetLargestPossibleRegion().GetIndex(1));\n    inputRegion.SetSize(1, this->GetOutput()->GetLargestPossibleRegion().GetSize(1));\n  }\n  input->SetRequestedRegion(inputRegion);\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nint\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::GetTruncationCorrectionExtent()\n{\n  return itk::Math::floor(m_TruncationCorrection * this->GetInput()->GetRequestedRegion().GetSize(0));\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::BeforeThreadedGenerateData()\n{\n  UpdateTruncationMirrorWeights();\n\n  // If the following condition is met, multi-threading is left to the (i)fft\n  // filter. Otherwise, one splits the image and a separate fft is performed\n  // per thread.\n  auto         reqRegion = this->GetOutput()->GetRequestedRegion();\n  unsigned int nproj = reqRegion.GetNumberOfPixels() / (reqRegion.GetSize()[0] * reqRegion.GetSize()[1]);\n  if ((nproj == 1 && m_KernelDimension == 2) || (reqRegion.GetSize()[0] == reqRegion.GetNumberOfPixels()))\n  {\n    m_BackupNumberOfThreads = this->GetNumberOfWorkUnits();\n    this->SetNumberOfWorkUnits(1);\n  }\n  else\n    m_BackupNumberOfThreads = 1;\n\n  // Update FFT ramp kernel (if required)\n  RegionType paddedRegion = GetPaddedImageRegion(this->GetInput()->GetRequestedRegion());\n  UpdateFFTProjectionsConvolutionKernel(paddedRegion.GetSize());\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::AfterThreadedGenerateData()\n{\n  auto         reqRegion = this->GetOutput()->GetRequestedRegion();\n  unsigned int nproj = reqRegion.GetNumberOfPixels() / (reqRegion.GetSize()[0] * reqRegion.GetSize()[1]);\n  if ((nproj == 1 && m_KernelDimension == 2) || (reqRegion.GetSize()[0] == reqRegion.GetNumberOfPixels()))\n  {\n    this->SetNumberOfWorkUnits(m_BackupNumberOfThreads);\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::ThreadedGenerateData(\n  const RegionType & outputRegionForThread,\n  ThreadIdType       threadId)\n{\n  auto nproj = outputRegionForThread.GetNumberOfPixels() /\n               (outputRegionForThread.GetSize()[0] * outputRegionForThread.GetSize()[1]);\n\n  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels(), 100);\n\n  for (unsigned int i = 0; i < nproj; i++)\n  {\n    auto outputRegion = outputRegionForThread;\n    if (outputRegion.GetImageDimension() == 3)\n    {\n      outputRegion.SetSize(2, 1);\n      outputRegion.SetIndex(2, outputRegionForThread.GetIndex(2) + i);\n    }\n    else if (outputRegion.GetImageDimension() == 4)\n    {\n      outputRegion.SetSize(2, 1);\n      outputRegion.SetSize(3, 1);\n      outputRegion.SetIndex(2, outputRegionForThread.GetIndex(2) + i % outputRegionForThread.GetSize(2));\n      outputRegion.SetIndex(3, outputRegionForThread.GetIndex(3) + i / outputRegionForThread.GetSize(2));\n    }\n\n    // Pad image region enlarged along X\n    RegionType enlargedRegionX = outputRegion;\n    enlargedRegionX.SetIndex(0, this->GetInput()->GetRequestedRegion().GetIndex(0));\n    enlargedRegionX.SetSize(0, this->GetInput()->GetRequestedRegion().GetSize(0));\n    enlargedRegionX.SetIndex(1, this->GetInput()->GetRequestedRegion().GetIndex(1));\n    enlargedRegionX.SetSize(1, this->GetInput()->GetRequestedRegion().GetSize(1));\n    FFTInputImagePointer paddedImage;\n    paddedImage = PadInputImageRegion(enlargedRegionX);\n\n    // FFT padded image\n    using FFTType = itk::RealToHalfHermitianForwardFFTImageFilter<FFTInputImageType>;\n    auto fftI = FFTType::New();\n    fftI->SetInput(paddedImage);\n    fftI->SetNumberOfWorkUnits(m_BackupNumberOfThreads);\n    fftI->Update();\n\n    // Multiply line-by-line or projection-by-projection (depends on kernel size)\n    itk::ImageRegionIterator<typename FFTType::OutputImageType> itI(fftI->GetOutput(),\n                                                                    fftI->GetOutput()->GetLargestPossibleRegion());\n    itk::ImageRegionConstIterator<FFTOutputImageType> itK(m_KernelFFT, m_KernelFFT->GetLargestPossibleRegion());\n    itI.GoToBegin();\n    while (!itI.IsAtEnd())\n    {\n      itK.GoToBegin();\n      while (!itK.IsAtEnd())\n      {\n        itI.Set(itI.Get() * itK.Get());\n        ++itI;\n        ++itK;\n      }\n    }\n\n    // Inverse FFT image\n    auto ifft = itk::HalfHermitianToRealInverseFFTImageFilter<typename FFTType::OutputImageType>::New();\n    ifft->SetInput(fftI->GetOutput());\n    ifft->SetNumberOfWorkUnits(m_BackupNumberOfThreads);\n    ifft->SetReleaseDataFlag(true);\n    ifft->SetActualXDimensionIsOdd(paddedImage->GetLargestPossibleRegion().GetSize(0) % 2);\n    ifft->Update();\n\n    // Crop and paste result\n    itk::ImageRegionConstIterator<FFTInputImageType> itS(ifft->GetOutput(), outputRegion);\n    itk::ImageRegionIterator<OutputImageType>        itD(this->GetOutput(), outputRegion);\n    itS.GoToBegin();\n    itD.GoToBegin();\n    while (!itS.IsAtEnd())\n    {\n      itD.Set(itS.Get());\n      ++itS;\n      ++itD;\n      progress.CompletedPixel();\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\ntypename FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::FFTInputImagePointer\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::PadInputImageRegion(\n  const RegionType & inputRegion)\n{\n  UpdateTruncationMirrorWeights();\n  RegionType paddedRegion = GetPaddedImageRegion(inputRegion);\n\n  // Create padded image (spacing and origin do not matter)\n  FFTInputImagePointer paddedImage = FFTInputImageType::New();\n  paddedImage->SetRegions(paddedRegion);\n  paddedImage->Allocate();\n  paddedImage->FillBuffer(0);\n\n  const long next = std::min(inputRegion.GetIndex(0) - paddedRegion.GetIndex(0),\n                             (typename FFTInputImageType::IndexValueType)this->GetTruncationCorrectionExtent());\n  if (next)\n  {\n    typename FFTInputImageType::IndexType                 idx;\n    typename FFTInputImageType::IndexType                 iidx; // Reference point (SA / SE)\n    typename FFTInputImageType::IndexType::IndexValueType borderDist = 0, rightIdx = 0;\n\n    // Mirror left (equation 3a in [Ohnesorge et al, Med Phys, 2000])\n    RegionType leftRegion = inputRegion;\n    leftRegion.SetIndex(0, inputRegion.GetIndex(0) - next);\n    leftRegion.SetSize(0, next);\n    itk::ImageRegionIteratorWithIndex<FFTInputImageType> itLeft(paddedImage, leftRegion);\n    while (!itLeft.IsAtEnd())\n    {\n      iidx = itLeft.GetIndex();\n      iidx[0] = leftRegion.GetIndex(0) + leftRegion.GetSize(0) + 1;\n      TFFTPrecision SA = this->GetInput()->GetPixel(iidx);\n      for (unsigned int i = 0; i < leftRegion.GetSize(0); i++, ++itLeft)\n      {\n        idx = itLeft.GetIndex();\n        borderDist = inputRegion.GetIndex(0) - idx[0];\n        idx[0] = inputRegion.GetIndex(0) + borderDist;\n        itLeft.Set(m_TruncationMirrorWeights[borderDist] * (2.0 * SA - this->GetInput()->GetPixel(idx)));\n      }\n    }\n\n    // Mirror right (equation 3b in [Ohnesorge et al, Med Phys, 2000])\n    RegionType rightRegion = inputRegion;\n    rightRegion.SetIndex(0, inputRegion.GetIndex(0) + inputRegion.GetSize(0));\n    rightRegion.SetSize(0, next);\n    itk::ImageRegionIteratorWithIndex<FFTInputImageType> itRight(paddedImage, rightRegion);\n    while (!itRight.IsAtEnd())\n    {\n      iidx = itRight.GetIndex();\n      iidx[0] = rightRegion.GetIndex(0) - 1;\n      TFFTPrecision SE = this->GetInput()->GetPixel(iidx);\n      for (unsigned int i = 0; i < rightRegion.GetSize(0); i++, ++itRight)\n      {\n        idx = itRight.GetIndex();\n        rightIdx = inputRegion.GetIndex(0) + inputRegion.GetSize(0) - 1;\n        borderDist = idx[0] - rightIdx;\n        idx[0] = rightIdx - borderDist;\n        itRight.Set(m_TruncationMirrorWeights[borderDist] * (2.0 * SE - this->GetInput()->GetPixel(idx)));\n      }\n    }\n  }\n\n  // Copy central part\n  itk::ImageRegionConstIterator<InputImageType> itS(this->GetInput(), inputRegion);\n  itk::ImageRegionIterator<FFTInputImageType>   itD(paddedImage, inputRegion);\n  itS.GoToBegin();\n  itD.GoToBegin();\n  while (!itS.IsAtEnd())\n  {\n    itD.Set(itS.Get());\n    ++itS;\n    ++itD;\n  }\n\n  return paddedImage;\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\ntypename FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::RegionType\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::GetPaddedImageRegion(\n  const RegionType & inputRegion)\n{\n  RegionType paddedRegion = inputRegion;\n\n  // Set x padding\n  typename SizeType::SizeValueType xPaddedSize = m_ZeroPadFactors[0] * inputRegion.GetSize(0);\n  while (GreatestPrimeFactor(xPaddedSize) > m_GreatestPrimeFactor)\n    xPaddedSize++;\n  paddedRegion.SetSize(0, xPaddedSize);\n  long zeroext = ((long)xPaddedSize - (long)inputRegion.GetSize(0)) / 2;\n  paddedRegion.SetIndex(0, inputRegion.GetIndex(0) - zeroext);\n\n  // Set y padding. Padding along Y is only required if\n  // - there is some windowing in the Y direction\n  // - the DFT requires the size to be the product of given prime factors\n  typename SizeType::SizeValueType yPaddedSize = inputRegion.GetSize(1);\n  if (m_KernelDimension == 2)\n    yPaddedSize *= m_ZeroPadFactors[1];\n  while (GreatestPrimeFactor(yPaddedSize) > m_GreatestPrimeFactor)\n    yPaddedSize++;\n  paddedRegion.SetSize(1, yPaddedSize);\n  // TODO what's that in ScatterGlare long zeroexty = ((long)yPaddedSize - (long)inputRegion.GetSize(1)) / 2;\n  paddedRegion.SetIndex(1, inputRegion.GetIndex(1));\n\n  return paddedRegion;\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::PrintSelf(std::ostream & os,\n                                                                                          itk::Indent    indent) const\n{\n  Superclass::PrintSelf(os, indent);\n  os << indent << \"GreatestPrimeFactor: \" << m_GreatestPrimeFactor << std::endl;\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nbool\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::IsPrime(int n) const\n{\n  int last = (int)std::sqrt(double(n));\n\n  for (int x = 2; x <= last; x++)\n    if (n % x == 0)\n      return false;\n  return true;\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nint\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::GreatestPrimeFactor(int n) const\n{\n  int v = 2;\n\n  while (v <= n)\n    if (n % v == 0 && IsPrime(v))\n      n /= v;\n    else\n      v += 1;\n  return v;\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::UpdateTruncationMirrorWeights()\n{\n  const unsigned int next = this->GetTruncationCorrectionExtent();\n\n  if ((unsigned int)m_TruncationMirrorWeights.size() != next)\n  {\n    m_TruncationMirrorWeights.resize(next + 1);\n    for (unsigned int i = 0; i < next + 1; i++)\n      m_TruncationMirrorWeights[i] = pow(sin((next - i) * itk::Math::pi / (2 * next - 2)), 0.75);\n  }\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkFFTRampImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFFTRampImageFilter_h\n#define rtkFFTRampImageFilter_h\n\n#include <itkConceptChecking.h>\n#include \"rtkConfiguration.h\"\n#include \"rtkFFTProjectionsConvolutionImageFilter.h\"\n#include \"rtkMacro.h\"\n\n// The Set macro is redefined to clear the current FFT kernel when a parameter\n// is modified.\n// clang-format off\n#ifndef ITK_GCC_PRAGMA_PUSH\n#define ITK_GCC_PRAGMA_PUSH CLANG_PRAGMA_PUSH\n#endif\n#ifndef ITK_GCC_SUPPRESS_Wfloat_equal\n#define ITK_GCC_SUPPRESS_Wfloat_equal CLANG_SUPPRESS_Wfloat_equal\n#endif\n#ifndef ITK_GCC_PRAGMA_POP\n#define ITK_GCC_PRAGMA_POP CLANG_PRAGMA_POP\n#endif\n#undef itkSetMacro\n#define itkSetMacro(name, type)                     \\\n  virtual void Set##name(type _arg)                 \\\n  {                                                 \\\n    itkDebugMacro(\"setting \" #name \" to \" << _arg); \\\n    ITK_GCC_PRAGMA_PUSH                                 \\\n    ITK_GCC_SUPPRESS_Wfloat_equal                       \\\n    if (this->m_##name != _arg)                     \\\n    {                                               \\\n      this->m_##name = std::move(_arg);             \\\n      this->Modified();                             \\\n      this->m_KernelFFT = nullptr;                  \\\n    }                                               \\\n    ITK_GCC_PRAGMA_POP                                  \\\n  }                                                 \\\n  ITK_MACROEND_NOOP_STATEMENT\n// clang-format on\n\nnamespace rtk\n{\n\n/** \\class FFTRampImageFilter\n * \\brief Implements the ramp image filter of the filtered backprojection algorithm.\n *\n * The filter code is based on FFTProjectionsConvolutionImageFilter by Gaetan Lehmann\n * (see https://hdl.handle.net/10380/3154)\n *\n * \\test rtkrampfiltertest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage = TInputImage, class TFFTPrecision = double>\nclass ITK_TEMPLATE_EXPORT FFTRampImageFilter\n  : public rtk::FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FFTRampImageFilter);\n\n  /** Standard class type alias. */\n  using Self = FFTRampImageFilter;\n  using Superclass = rtk::FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using FFTPrecisionType = TFFTPrecision;\n  using IndexType = typename InputImageType::IndexType;\n  using SizeType = typename InputImageType::SizeType;\n\n  using FFTInputImageType = typename Superclass::FFTInputImageType;\n  using FFTInputImagePointer = typename FFTInputImageType::Pointer;\n  using FFTOutputImageType = typename Superclass::FFTOutputImageType;\n  using FFTOutputImagePointer = typename FFTOutputImageType::Pointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FFTRampImageFilter);\n\n  /** Set/Get the Hann window frequency. 0 (default) disables it */\n  itkGetConstMacro(HannCutFrequency, double);\n  itkSetMacro(HannCutFrequency, double);\n\n  /** Set/Get the Cosine Cut window frequency. 0 (default) disables it */\n  itkGetConstMacro(CosineCutFrequency, double);\n  itkSetMacro(CosineCutFrequency, double);\n\n  /** Set/Get the Hamming window frequency. 0 (default) disables it */\n  itkGetConstMacro(HammingFrequency, double);\n  itkSetMacro(HammingFrequency, double);\n\n  /** Set/Get the Hann window frequency in Y direction. 0 (default) disables it */\n  itkGetConstMacro(HannCutFrequencyY, double);\n  itkSetMacro(HannCutFrequencyY, double);\n\n  /** Set/Get the Ram-Lak window frequency (0...1). 0 (default) disable it.\n   * Equation and further explanation about Ram-Lak filter could be found in:\n   * 1. Fundamentals of 2D and 3D reconstruction (by Dr. Gunter Lauritsch).\n   *    https://campar.in.tum.de/twiki/pub/Chair/TeachingWs04IOIV/08CTReconstruction.pdf\n   * 2. Reconstruction.\n   *    http://oftankonyv.reak.bme.hu/tiki-index.php?page=Reconstruction\n   */\n  itkGetConstMacro(RamLakCutFrequency, double);\n  itkSetMacro(RamLakCutFrequency, double);\n\n  /** Set/Get the Shepp-Logan window frequency (0...1). 0 (default) disable it.\n   * Equation and further explanation about Shepp-Logan filter could be found in:\n   * 1. Fundamentals of 2D and 3D reconstruction (by Dr. Gunter Lauritsch).\n   *    https://campar.in.tum.de/twiki/pub/Chair/TeachingWs04IOIV/08CTReconstruction.pdf\n   * 2. Reconstruction.\n   *    http://oftankonyv.reak.bme.hu/tiki-index.php?page=Reconstruction\n   */\n  itkGetConstMacro(SheppLoganCutFrequency, double);\n  itkSetMacro(SheppLoganCutFrequency, double);\n\nprotected:\n  FFTRampImageFilter();\n  ~FFTRampImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Creates and return a pointer to one line of the ramp kernel in Fourier space.\n   *  Used in generate data functions.  */\n  void\n  UpdateFFTProjectionsConvolutionKernel(const SizeType s) override;\n\n  SizeType m_PreviousKernelUpdateSize;\n\nprivate:\n  /**\n   * Cut frequency of Hann, Cosine and Hamming windows. The first one which is\n   * non-zero is used.\n   */\n  double m_HannCutFrequency{ 0. };\n  double m_CosineCutFrequency{ 0. };\n  double m_HammingFrequency{ 0. };\n  double m_HannCutFrequencyY{ 0. };\n\n  /** Cut frequency of Ram-Lak and Shepp-Logan\n   */\n  double m_RamLakCutFrequency{ 0. };\n  double m_SheppLoganCutFrequency{ 0. };\n\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFFTRampImageFilter.hxx\"\n#endif\n\n// Rollback to the original definition of the Set macro\n// clang-format off\n#undef itkSetMacro\n#define itkSetMacro(name, type)                     \\\n  virtual void Set##name(type _arg)                 \\\n  {                                                 \\\n    itkDebugMacro(\"setting \" #name \" to \" << _arg); \\\n    ITK_GCC_PRAGMA_PUSH                                 \\\n    ITK_GCC_SUPPRESS_Wfloat_equal                       \\\n    if (this->m_##name != _arg)                     \\\n    {                                               \\\n      this->m_##name = std::move(_arg);             \\\n      this->Modified();                             \\\n    }                                               \\\n    ITK_GCC_PRAGMA_POP                                  \\\n  }                                                 \\\n  ITK_MACROEND_NOOP_STATEMENT\n// clang-format on\n#endif\n"
  },
  {
    "path": "include/rtkFFTRampImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFFTRampImageFilter_hxx\n#define rtkFFTRampImageFilter_hxx\n\n\n// Use local RTK FFTW files taken from Gaëtan Lehmann's code for\n// thread safety: https://hdl.handle.net/10380/3154\n#include <itkRealToHalfHermitianForwardFFTImageFilter.h>\n#include <itkHalfHermitianToRealInverseFFTImageFilter.h>\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nFFTRampImageFilter<TInputImage, TOutputImage, TFFTPrecision>::FFTRampImageFilter() = default;\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTRampImageFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateInputRequestedRegion()\n{\n  this->m_KernelDimension = (m_HannCutFrequencyY == 0.) ? 1 : 2;\n  Superclass::GenerateInputRequestedRegion();\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTRampImageFilter<TInputImage, TOutputImage, TFFTPrecision>::UpdateFFTProjectionsConvolutionKernel(const SizeType s)\n{\n  if (this->m_KernelFFT.GetPointer() != nullptr && s == this->m_PreviousKernelUpdateSize)\n  {\n    return;\n  }\n  m_PreviousKernelUpdateSize = s;\n\n  const int width = s[0];\n  const int height = s[1];\n\n  // Allocate kernel\n  SizeType size;\n  size.Fill(1);\n  size[0] = width;\n  FFTInputImagePointer kernel = FFTInputImageType::New();\n  kernel->SetRegions(size);\n  kernel->Allocate();\n  kernel->FillBuffer(0.);\n\n  // Compute kernel in space domain (see Kak & Slaney, chapter 3 equation 61\n  // page 72) although spacing is not squared according to equation 69 page 75\n  double    spacing = this->GetInput()->GetSpacing()[0];\n  IndexType ix, jx;\n  ix.Fill(0);\n  jx.Fill(0);\n  kernel->SetPixel(ix, 1. / (4. * spacing));\n  for (ix[0] = 1, jx[0] = size[0] - 1; ix[0] < typename IndexType::IndexValueType(size[0] / 2); ix[0] += 2, jx[0] -= 2)\n  {\n    double v = ix[0] * itk::Math::pi;\n    v = -1. / (v * v * spacing);\n    kernel->SetPixel(ix, v);\n    kernel->SetPixel(jx, v);\n  }\n\n  // FFT kernel\n  using FFTType = itk::RealToHalfHermitianForwardFFTImageFilter<FFTInputImageType, FFTOutputImageType>;\n  auto fftK = FFTType::New();\n  fftK->SetInput(kernel);\n  fftK->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  fftK->Update();\n  this->m_KernelFFT = fftK->GetOutput();\n\n  // Windowing (if enabled)\n  using IteratorType = itk::ImageRegionIteratorWithIndex<typename FFTType::OutputImageType>;\n  IteratorType itK(this->m_KernelFFT, this->m_KernelFFT->GetLargestPossibleRegion());\n\n  unsigned int n = this->m_KernelFFT->GetLargestPossibleRegion().GetSize(0);\n\n  itK.GoToBegin();\n  if (this->GetHannCutFrequency() > 0.)\n  {\n    const unsigned int ncut = itk::Math::Round<double>(n * std::min(1.0, this->GetHannCutFrequency()));\n    for (unsigned int i = 0; i < ncut; i++, ++itK)\n      itK.Set(itK.Get() * TFFTPrecision(0.5 * (1 + std::cos(itk::Math::pi * i / ncut))));\n  }\n  else if (this->GetCosineCutFrequency() > 0.)\n  {\n    const unsigned int ncut = itk::Math::Round<double>(n * std::min(1.0, this->GetCosineCutFrequency()));\n    for (unsigned int i = 0; i < ncut; i++, ++itK)\n      itK.Set(itK.Get() * TFFTPrecision(std::cos(0.5 * itk::Math::pi * i / ncut)));\n  }\n  else if (this->GetHammingFrequency() > 0.)\n  {\n    const unsigned int ncut = itk::Math::Round<double>(n * std::min(1.0, this->GetHammingFrequency()));\n    for (unsigned int i = 0; i < ncut; i++, ++itK)\n      itK.Set(itK.Get() * TFFTPrecision(0.54 + 0.46 * (std::cos(itk::Math::pi * i / ncut))));\n  }\n  else if (this->GetRamLakCutFrequency() > 0.)\n  {\n    const unsigned int ncut = itk::Math::Round<double>(n * std::min(1.0, this->GetRamLakCutFrequency()));\n    for (unsigned int i = 0; i < ncut; i++, ++itK)\n    {\n    }\n  }\n  else if (this->GetSheppLoganCutFrequency() > 0.)\n  {\n    const unsigned int ncut = itk::Math::Round<double>(n * std::min(1.0, this->GetSheppLoganCutFrequency()));\n    // sinc(0) --> is 1\n    ++itK;\n    for (unsigned int i = 1; i < ncut; i++, ++itK)\n    {\n      double x = 0.5 * itk::Math::pi * i / ncut;\n      itK.Set(itK.Get() * TFFTPrecision(std::sin(x) / x));\n    }\n  }\n  else\n  {\n    itK.GoToReverseBegin();\n    ++itK;\n  }\n\n  for (; !itK.IsAtEnd(); ++itK)\n  {\n    itK.Set(itK.Get() * TFFTPrecision(0.));\n  }\n\n  // Replicate and window if required\n  if (this->GetHannCutFrequencyY() > 0.)\n  {\n    size.Fill(1);\n    size[0] = this->m_KernelFFT->GetLargestPossibleRegion().GetSize(0);\n    size[1] = height;\n\n    const unsigned int ncut = itk::Math::Round<double>((height / 2 + 1) * std::min(1.0, this->GetHannCutFrequencyY()));\n\n    this->m_KernelFFT = FFTOutputImageType::New();\n    this->m_KernelFFT->SetRegions(size);\n    this->m_KernelFFT->Allocate();\n    this->m_KernelFFT->FillBuffer(0.);\n\n    IteratorType itTwoDK(this->m_KernelFFT, this->m_KernelFFT->GetLargestPossibleRegion());\n    for (unsigned int j = 0; j < ncut; j++)\n    {\n      itK.GoToBegin();\n      const TFFTPrecision win(0.5 * (1 + std::cos(itk::Math::pi * j / ncut)));\n      for (unsigned int i = 0; i < size[0]; ++itK, ++itTwoDK, i++)\n      {\n        itTwoDK.Set(win * itK.Get());\n      }\n    }\n    itTwoDK.GoToReverseBegin();\n    for (unsigned int j = 1; j < ncut; j++)\n    {\n      itK.GoToReverseBegin();\n      const TFFTPrecision win(0.5 * (1 + std::cos(itk::Math::pi * j / ncut)));\n      for (unsigned int i = 0; i < size[0]; --itK, --itTwoDK, i++)\n      {\n        itTwoDK.Set(win * itK.Get());\n      }\n    }\n  }\n  this->m_KernelFFT->DisconnectPipeline();\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkFFTVarianceRampImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFFTVarianceRampImageFilter_h\n#define rtkFFTVarianceRampImageFilter_h\n\n#include \"rtkFFTRampImageFilter.h\"\n#include \"rtkFFTProjectionsConvolutionImageFilter.h\"\n#include \"itkHalfHermitianToRealInverseFFTImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class FFTVarianceRampImageFilter\n * \\brief Implements the variance image filter of the filtered backprojection algorithm.\n *\n * \\test rtkvariancereconstructiontest\n *\n * \\author Simon Rit\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage = TInputImage, class TFFTPrecision = double>\nclass ITK_EXPORT FFTVarianceRampImageFilter : public rtk::FFTRampImageFilter<TInputImage, TOutputImage, TFFTPrecision>\n{\npublic:\n  typedef rtk::FFTRampImageFilter<TInputImage, TOutputImage, TFFTPrecision> Baseclass;\n\n  /** Standard class typedefs. */\n  typedef FFTVarianceRampImageFilter                                        Self;\n  typedef rtk::FFTRampImageFilter<TInputImage, TOutputImage, TFFTPrecision> Superclass;\n  typedef itk::SmartPointer<Self>                                           Pointer;\n  typedef itk::SmartPointer<const Self>                                     ConstPointer;\n\n  /** Some convenient typedefs. */\n  typedef typename Baseclass::InputImageType   InputImageType;\n  typedef typename Baseclass::OutputImageType  OutputImageType;\n  typedef typename Baseclass::FFTPrecisionType FFTPrecisionType;\n  typedef typename Baseclass::IndexType        IndexType;\n  typedef typename Baseclass::SizeType         SizeType;\n\n  typedef typename Baseclass::FFTInputImageType     FFTInputImageType;\n  typedef typename Baseclass::FFTInputImagePointer  FFTInputImagePointer;\n  typedef typename Baseclass::FFTOutputImageType    FFTOutputImageType;\n  typedef typename Baseclass::FFTOutputImagePointer FFTOutputImagePointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FFTVarianceRampImageFilter);\n\nprotected:\n  FFTVarianceRampImageFilter();\n  ~FFTVarianceRampImageFilter() {}\n\n  /** Creates and return a pointer to one line of the variance kernel in Fourier space.\n   *  Used in generate data functions.  */\n  void\n  UpdateFFTProjectionsConvolutionKernel(const SizeType size) override;\n\n  FFTVarianceRampImageFilter(const Self &); // purposely not implemented\n  void\n  operator=(const Self &); // purposely not implemented\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFFTVarianceRampImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFFTVarianceRampImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFFTVarianceRampImageFilter_hxx\n#define rtkFFTVarianceRampImageFilter_hxx\n\n#include \"rtkFFTVarianceRampImageFilter.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nFFTVarianceRampImageFilter<TInputImage, TOutputImage, TFFTPrecision>::FFTVarianceRampImageFilter() = default;\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nFFTVarianceRampImageFilter<TInputImage, TOutputImage, TFFTPrecision>::UpdateFFTProjectionsConvolutionKernel(\n  const SizeType s)\n{\n  if (this->GetHannCutFrequencyY() > 0.)\n  {\n    itkGenericExceptionMacro(<< \"Variance Ramp image filter is not implemented for HannCutFrequencyY>0.\");\n  }\n\n  if (this->m_KernelFFT.GetPointer() != nullptr && s == this->m_PreviousKernelUpdateSize)\n  {\n    return;\n  }\n\n  // Calculate the conventional ramp image filter Kernel\n  Superclass::UpdateFFTProjectionsConvolutionKernel(s);\n\n  // iFFT kernel\n  auto ifftK = itk::HalfHermitianToRealInverseFFTImageFilter<FFTOutputImageType, FFTInputImageType>::New();\n  ifftK->SetInput(this->m_KernelFFT);\n  ifftK->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  ifftK->Update();\n  using FFTType = itk::RealToHalfHermitianForwardFFTImageFilter<FFTInputImageType, FFTOutputImageType>;\n  typename FFTType::InputImageType::Pointer KernelIFFT = ifftK->GetOutput();\n\n  // calculate ratio g_C/g^2\n  itk::ImageRegionIteratorWithIndex<typename FFTType::InputImageType> itiK(KernelIFFT,\n                                                                           KernelIFFT->GetLargestPossibleRegion());\n  typename FFTType::InputImageType::PixelType                         sumgc = 0.;\n  typename FFTType::InputImageType::PixelType                         sumg2 = 0.;\n  typename FFTType::InputImageType::IndexType                         idxshifted;\n  const unsigned int widthFFT = KernelIFFT->GetLargestPossibleRegion().GetSize()[0];\n  for (; !itiK.IsAtEnd(); ++itiK)\n  {\n    idxshifted = itiK.GetIndex();\n    if (idxshifted[0] == 0)\n      idxshifted[0] = widthFFT - 1;\n    else\n      idxshifted[0] -= 1;\n\n    sumgc += itiK.Get() * KernelIFFT->GetPixel(idxshifted);\n    sumg2 += itiK.Get() * itiK.Get();\n  }\n  const typename FFTType::InputImageType::PixelType ratiogcg2 = sumgc / sumg2;\n\n  // numerical integration to calculate f_interp\n  const double aprecision = 0.00001;\n  double       finterp = 0.;\n  for (unsigned int i = 0; i < int(1. / aprecision); i++)\n  {\n    const double a = double(i) * aprecision;\n    finterp += (1 - a) * (1 - a) + 2 * ratiogcg2 * (1 - a) * a + a * a;\n  }\n  finterp *= aprecision;\n\n  // square kernel and multiply with finterp\n  itiK.GoToBegin();\n  for (; !itiK.IsAtEnd(); ++itiK)\n  {\n    itiK.Set(itiK.Get() * itiK.Get() * finterp);\n  }\n\n  // FFT kernel\n  auto fftK2 = FFTType::New();\n  fftK2->SetInput(KernelIFFT);\n  fftK2->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  fftK2->Update();\n  this->m_KernelFFT = fftK2->GetOutput();\n  this->m_KernelFFT->DisconnectPipeline();\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkFieldOfViewImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFieldOfViewImageFilter_h\n#define rtkFieldOfViewImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkConfiguration.h\"\n\nstruct _lprec;\n\nnamespace rtk\n{\n\n/** \\class FieldOfViewImageFilter\n * \\brief Computes the field of view mask for circular 3D geometry.\n *\n * Masks out the regions that are not included in our field of view or\n * creates the mask if m_Mask is true. Note that the 3 angle parameters are\n * assumed to be 0. in the circular geometry: GantryAngle, OutOfPlaneAngle and\n * InPlaneAngle. The rest is accounted for but the fov is assumed to be\n * cylindrical.\n *\n * \\test rtkfovtest.cxx, rtkfdktest.cxx, rtkmotioncompensatedfdktest.cxx\n *\n * \\author Marc Vila\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT FieldOfViewImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FieldOfViewImageFilter);\n\n  /** Standard class type alias. */\n  using Self = FieldOfViewImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using ProjectionsStackType = typename TInputImage::Superclass;\n  using ProjectionsStackPointer = typename ProjectionsStackType::Pointer;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryConstPointer = typename GeometryType::ConstPointer;\n  using FOVRadiusType = enum { RADIUSINF, RADIUSSUP, RADIUSBOTH };\n\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(FieldOfViewImageFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetConstObjectMacro(Geometry, GeometryType);\n  itkSetConstObjectMacro(Geometry, GeometryType);\n\n  /** Get / Set of the member Mask. If set, all the pixels in the field of view\n   * are set to InsideValue. The data value is kept otherwise. Pixels outside the mask\n   * are set to OutsideValue in any case. */\n  itkGetMacro(Mask, bool);\n  itkSetMacro(Mask, bool);\n\n  /** Get / Set the region of projection images, required to determine the\n    FOV radius. Note that only the geometric information is required, the\n    data are therefore not updated. */\n  itkGetMacro(ProjectionsStack, ProjectionsStackPointer);\n  itkSetObjectMacro(ProjectionsStack, ProjectionsStackType);\n\n  /** Assume that a displaced detector image filter, e.g.,\n   * rtk::DisplacedDetectorImageFilter, has been used. */\n  itkGetMacro(DisplacedDetector, bool);\n  itkSetMacro(DisplacedDetector, bool);\n\n  /** Inside value when Mask is true. 1 by default */\n  itkGetMacro(InsideValue, double);\n  itkSetMacro(InsideValue, double);\n\n  /** Outside value. 0 by default */\n  itkGetMacro(OutsideValue, double);\n  itkSetMacro(OutsideValue, double);\n\n  /** Computes the radius r and the center (x,z) of the disk perpendicular to\n   * the y-axis that is covered by:\n   * - if RADIUSINF: the half plane defined by the line from the source to the\n   *   two inferior x index corners which cover the opposite two corners.\n   * - if RADIUSSUP: the half plane defined by the line from the source to the\n   *   two superior x index corners which cover the opposite two corners.\n   * - if RADIUSBOTH: the fan defined by the pairs of half planes.\n   * Returns true if it managed to find such a disk and false otherwise.\n   * The function may be called without out computing the output, but\n   * m_Geometry and ProjectionsStack must be set.*/\n  virtual bool\n  ComputeFOVRadius(const FOVRadiusType type, double & x, double & z, double & r);\n\n  /** Add collimation constraints. This function is always called from\n   * ComputeFOVRadius but it has an effect only if the geometry has the\n   * m_CollimationUInf or m_CollimationUSup which are non infinity (default). */\n  void\n  AddCollimationConstraints(const FOVRadiusType type, _lprec * lp);\n\nprotected:\n  FieldOfViewImageFilter();\n  ~FieldOfViewImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  /** Generates a FOV mask which is applied to the reconstruction\n   * A call to this function will assume modification of the function.*/\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  GeometryConstPointer    m_Geometry{ nullptr };\n  bool                    m_Mask{ false };\n  ProjectionsStackPointer m_ProjectionsStack;\n  double                  m_Radius{ -1 };\n  double                  m_CenterX{ 0. };\n  double                  m_CenterZ{ 0. };\n  double                  m_HatTangentInf;\n  double                  m_HatTangentSup;\n  double                  m_HatHeightInf;\n  double                  m_HatHeightSup;\n  bool                    m_DisplacedDetector{ false };\n  double                  m_InsideValue{ 1. };\n  double                  m_OutsideValue{ 0. };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFieldOfViewImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFieldOfViewImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFieldOfViewImageFilter_hxx\n#define rtkFieldOfViewImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionConstIteratorWithIndex.h>\n\n#include \"lp_lib.h\"\n\n#include \"rtkProjectionsReader.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nFieldOfViewImageFilter<TInputImage, TOutputImage>::FieldOfViewImageFilter() = default;\n\ntemplate <class TInputImage, class TOutputImage>\nbool\nFieldOfViewImageFilter<TInputImage, TOutputImage>::ComputeFOVRadius(const FOVRadiusType type,\n                                                                    double &            x,\n                                                                    double &            z,\n                                                                    double &            r)\n{\n  m_ProjectionsStack->UpdateOutputInformation();\n  typename TInputImage::SizeType regSize;\n  regSize.Fill(1);\n  typename TInputImage::RegionType region = m_ProjectionsStack->GetLargestPossibleRegion();\n  region.SetSize(regSize);\n  auto dumImg = TInputImage::New();\n  dumImg->CopyInformation(m_ProjectionsStack);\n\n  // Build model for lpsolve with 3 variables: x, z and r\n  constexpr int Ncol = 3;\n  lprec *       lp = make_lp(0, Ncol);\n  if (lp == nullptr)\n    itkExceptionMacro(<< \"Couldn't construct 2 new models for the simplex solver\");\n\n  // Objective: maximize r\n  if (!set_obj(lp, 3, 1.))\n    itkExceptionMacro(<< \"Couldn't set objective in lpsolve\");\n  set_maxim(lp);\n\n  set_add_rowmode(lp, TRUE); // makes building the model faster if it is done rows by row\n\n  int  colno[Ncol] = { 1, 2, 3 };\n  REAL row[Ncol];\n  for (unsigned int iProj = 0; iProj < m_Geometry->GetGantryAngles().size(); iProj++)\n  {\n    constexpr unsigned int NCORNERS = 4;\n    double                 a[NCORNERS];\n    double                 b[NCORNERS];\n    double                 c[NCORNERS];\n    double                 d[NCORNERS];\n    using InputRegionIterator = ProjectionsRegionConstIteratorRayBased<TInputImage>;\n    InputRegionIterator *                   itIn = nullptr;\n    typename InputRegionIterator::PointType corners[NCORNERS];\n    for (unsigned int i = 0; i < NCORNERS; i++)\n    {\n      // Create image iterator with geometry for that particular pixel (== corner)\n      typename InputRegionIterator::PointType sourcePosition;\n      region.SetIndex(0,\n                      m_ProjectionsStack->GetLargestPossibleRegion().GetIndex()[0] +\n                        (i / 2) * (m_ProjectionsStack->GetLargestPossibleRegion().GetSize()[0] - 1));\n      region.SetIndex(1,\n                      m_ProjectionsStack->GetLargestPossibleRegion().GetIndex()[1] +\n                        (i % 2) * (m_ProjectionsStack->GetLargestPossibleRegion().GetSize()[1] - 1));\n      region.SetIndex(2, iProj);\n      dumImg->SetRegions(region);\n      dumImg->Allocate();\n      itIn = InputRegionIterator::New(dumImg, region, m_Geometry);\n\n      // Compute the equation of a line of the ax+by=c\n      // https://en.wikipedia.org/wiki/Linear_equation#Two-point_form\n      sourcePosition = itIn->GetSourcePosition();\n      corners[i] = itIn->GetPixelPosition();\n      delete itIn;\n\n      a[i] = corners[i][2] - sourcePosition[2];\n      b[i] = sourcePosition[0] - corners[i][0];\n      c[i] = sourcePosition[0] * corners[i][2] - corners[i][0] * sourcePosition[2];\n\n      // Then compute the coefficient in front of r as suggested in\n      // http://www.ifor.math.ethz.ch/teaching/lectures/intro_ss11/Exercises/solutionEx11-12.pdf\n      d[i] = std::sqrt(a[i] * a[i] + b[i] * b[i]);\n    }\n\n    // Check on corners\n    if (a[0] * corners[2][0] + b[0] * corners[2][2] >= c[0] && a[1] * corners[3][0] + b[1] * corners[3][2] >= c[1])\n    {\n      a[0] *= -1.;\n      b[0] *= -1.;\n      c[0] *= -1.;\n      a[1] *= -1.;\n      b[1] *= -1.;\n      c[1] *= -1.;\n    }\n    else if (a[2] * corners[0][0] + b[2] * corners[0][2] >= c[2] && a[3] * corners[1][0] + b[3] * corners[1][2] >= c[3])\n    {\n      a[2] *= -1.;\n      b[2] *= -1.;\n      c[2] *= -1.;\n      a[3] *= -1.;\n      b[3] *= -1.;\n      c[3] *= -1.;\n    }\n    else\n    {\n      itkExceptionMacro(<< \"Error computing the FOV, unhandled detector rotation.\");\n    }\n\n    // Now add the constraints of the form ax+by+dr<=c\n    if (type == RADIUSINF || type == RADIUSBOTH)\n    {\n      row[0] = a[0];\n      row[1] = b[0];\n      row[2] = d[0];\n      if (!add_constraintex(lp, 3, row, colno, LE, c[0]))\n        itkExceptionMacro(<< \"Couldn't add simplex constraint\");\n      row[0] = a[1];\n      row[1] = b[1];\n      row[2] = d[1];\n      if (!add_constraintex(lp, 3, row, colno, LE, c[1]))\n        itkExceptionMacro(<< \"Couldn't add simplex constraint\");\n    }\n    if (type == RADIUSSUP || type == RADIUSBOTH)\n    {\n      row[0] = a[2];\n      row[1] = b[2];\n      row[2] = d[2];\n      if (!add_constraintex(lp, 3, row, colno, LE, c[2]))\n        itkExceptionMacro(<< \"Couldn't add simplex constraint\");\n      row[0] = a[3];\n      row[1] = b[3];\n      row[2] = d[3];\n      if (!add_constraintex(lp, 3, row, colno, LE, c[3]))\n        itkExceptionMacro(<< \"Couldn't add simplex constraint\");\n    }\n  }\n\n  AddCollimationConstraints(type, lp);\n\n  set_add_rowmode(lp, FALSE); // rowmode should be turned off again when done building the model\n\n  if (!set_unbounded(lp, 1) || !set_unbounded(lp, 2))\n    itkExceptionMacro(<< \"Couldn't not set center to unbounded for simplex\");\n\n  set_verbose(lp, IMPORTANT);\n\n  int ret = solve(lp);\n  if (ret)\n  {\n    delete_lp(lp);\n    return false;\n  }\n  else\n  {\n    get_variables(lp, row);\n    x = row[0];\n    z = row[1];\n    r = row[2];\n  }\n\n  delete_lp(lp);\n  return true;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFieldOfViewImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFieldOfViewImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  // The radius of the FOV is computed with linear programming.\n  if (m_DisplacedDetector)\n  {\n    // Two radii are computed and the largest is selected.\n    if (!ComputeFOVRadius(RADIUSINF, m_CenterX, m_CenterZ, m_Radius))\n      m_Radius = -1.;\n\n    double x = NAN, z = NAN, r = NAN;\n    if (ComputeFOVRadius(RADIUSSUP, x, z, r) && r > m_Radius)\n    {\n      m_Radius = r;\n      m_CenterX = x;\n      m_CenterZ = z;\n    }\n  }\n  else\n  {\n    if (!ComputeFOVRadius(RADIUSBOTH, m_CenterX, m_CenterZ, m_Radius))\n      m_Radius = -1.;\n  }\n\n  // Compute projection stack indices of corners\n  m_ProjectionsStack->UpdateOutputInformation();\n  typename TInputImage::IndexType indexCorner1;\n  indexCorner1 = m_ProjectionsStack->GetLargestPossibleRegion().GetIndex();\n\n  typename TInputImage::IndexType indexCorner2;\n  indexCorner2 = indexCorner1 + m_ProjectionsStack->GetLargestPossibleRegion().GetSize();\n  for (unsigned int i = 0; i < TInputImage::GetImageDimension(); i++)\n    indexCorner2[i]--;\n\n  // To physical coordinates\n  typename TInputImage::PointType corner1, corner2;\n  m_ProjectionsStack->TransformIndexToPhysicalPoint(indexCorner1, corner1);\n  m_ProjectionsStack->TransformIndexToPhysicalPoint(indexCorner2, corner2);\n  for (unsigned int i = 0; i < TInputImage::GetImageDimension(); i++)\n    if (corner1[i] > corner2[i])\n      std::swap(corner1[i], corner2[i]);\n\n  // Go over projection stack, compute minimum radius and minimum tangent\n  m_HatHeightSup = itk::NumericTraits<double>::max();\n  m_HatHeightInf = itk::NumericTraits<double>::NonpositiveMin();\n  for (unsigned int k = 0; k < m_ProjectionsStack->GetLargestPossibleRegion().GetSize(2); k++)\n  {\n    const double sid = m_Geometry->GetSourceToIsocenterDistances()[k];\n    const double sdd = m_Geometry->GetSourceToDetectorDistances()[k];\n    double       mag = 1.; // Parallel\n    if (sdd != 0.)\n      mag = sid / sdd; // Divergent\n\n    const double projOffsetY = m_Geometry->GetProjectionOffsetsY()[k];\n    const double sourceOffsetY = m_Geometry->GetSourceOffsetsY()[k];\n    const double heightInf = sourceOffsetY + mag * (corner1[1] + projOffsetY - sourceOffsetY);\n    if (heightInf > m_HatHeightInf)\n    {\n      m_HatHeightInf = heightInf;\n      m_HatTangentInf = m_HatHeightInf / sid;\n      if (sdd == 0.) // Parallel\n        m_HatTangentInf = 0.;\n    }\n    const double heightSup = sourceOffsetY + mag * (corner2[1] + projOffsetY - sourceOffsetY);\n    if (heightSup < m_HatHeightSup)\n    {\n      m_HatHeightSup = heightSup;\n      m_HatTangentSup = m_HatHeightSup / sid;\n      if (sdd == 0.) // Parallel\n        m_HatTangentSup = 0.;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFieldOfViewImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  typename TInputImage::DirectionType d = this->GetInput()->GetDirection();\n  if (d[0][0] == 1. && d[0][1] == 0. && d[0][2] == 0. && d[1][0] == 0. && d[1][1] == 1. && d[1][2] == 0. &&\n      d[2][0] == 0. && d[2][1] == 0. && d[2][2] == 1.)\n\n  {\n    // Prepare point increment (TransformIndexToPhysicalPoint too slow)\n    typename TInputImage::PointType pointBase, pointIncrement;\n    typename TInputImage::IndexType index = outputRegionForThread.GetIndex();\n    this->GetInput()->TransformIndexToPhysicalPoint(index, pointBase);\n    for (unsigned int i = 0; i < TInputImage::GetImageDimension(); i++)\n      index[i]++;\n    this->GetInput()->TransformIndexToPhysicalPoint(index, pointIncrement);\n    for (unsigned int i = 0; i < TInputImage::GetImageDimension(); i++)\n      pointIncrement[i] -= pointBase[i];\n\n    // Iterators\n    using InputConstIterator = itk::ImageRegionConstIterator<TInputImage>;\n    InputConstIterator itIn(this->GetInput(0), outputRegionForThread);\n    itIn.GoToBegin();\n    using OutputIterator = itk::ImageRegionIterator<TOutputImage>;\n    OutputIterator itOut(this->GetOutput(), outputRegionForThread);\n    itOut.GoToBegin();\n\n    // Go over output, compute weights and avoid redundant computation\n    typename TInputImage::PointType point = pointBase;\n    for (unsigned int k = 0; k < outputRegionForThread.GetSize(2); k++)\n    {\n      double zsquare = m_CenterZ - point[2];\n      zsquare *= zsquare;\n      point[1] = pointBase[1];\n      for (unsigned int j = 0; j < outputRegionForThread.GetSize(1); j++)\n      {\n        point[0] = pointBase[0];\n        for (unsigned int i = 0; i < outputRegionForThread.GetSize(0); i++)\n        {\n          double xsquare = m_CenterX - point[0];\n          xsquare *= xsquare;\n          double radius = std::sqrt(xsquare + zsquare);\n          if (radius <= m_Radius && radius * m_HatTangentInf >= m_HatHeightInf - point[1] &&\n              radius * m_HatTangentSup <= m_HatHeightSup - point[1])\n          {\n            if (m_Mask)\n              itOut.Set(this->m_InsideValue);\n            else\n              itOut.Set(itIn.Get());\n          }\n          else\n            itOut.Set(this->m_OutsideValue);\n          ++itIn;\n          ++itOut;\n          point[0] += pointIncrement[0];\n        }\n        point[1] += pointIncrement[1];\n      }\n      point[2] += pointIncrement[2];\n    }\n  }\n  else\n  {\n    using InputConstIterator = itk::ImageRegionConstIteratorWithIndex<TInputImage>;\n    InputConstIterator itIn(this->GetInput(0), outputRegionForThread);\n\n    using OutputIterator = itk::ImageRegionIterator<TOutputImage>;\n    OutputIterator itOut(this->GetOutput(), outputRegionForThread);\n\n    typename TInputImage::PointType point;\n    while (!itIn.IsAtEnd())\n    {\n      this->GetInput()->TransformIndexToPhysicalPoint(itIn.GetIndex(), point);\n      double radius = std::sqrt(point[0] * point[0] + point[2] * point[2]);\n      if (radius <= m_Radius && point[1] <= m_HatHeightSup - radius * m_HatTangentSup &&\n          point[1] >= m_HatHeightInf - radius * m_HatTangentInf)\n      {\n        if (m_Mask)\n          itOut.Set(this->m_InsideValue);\n        else\n          itOut.Set(itIn.Get());\n      }\n      else\n        itOut.Set(this->m_OutsideValue);\n      ++itIn;\n      ++itOut;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nFieldOfViewImageFilter<TInputImage, TOutputImage>::AddCollimationConstraints(const FOVRadiusType type, _lprec * lp)\n{\n  constexpr int Ncol = 3;\n  int           colno[Ncol] = { 1, 2, 3 };\n  REAL          row[Ncol];\n  for (unsigned int iProj = 0; iProj < m_Geometry->GetGantryAngles().size(); iProj++)\n  {\n    const double X1 = m_Geometry->GetCollimationUInf()[iProj];\n    const double X2 = m_Geometry->GetCollimationUSup()[iProj];\n    if (X1 == std::numeric_limits<double>::max() && X2 == std::numeric_limits<double>::max())\n    {\n      continue;\n    }\n    if (X1 == std::numeric_limits<double>::max() || X2 == std::numeric_limits<double>::max())\n    {\n      itkWarningMacro(\"Having only one jaw that is not at the default value is unexpected.\");\n    }\n\n    // Compute 3D position of jaws\n    using PointType = typename GeometryType::VectorType;\n    typename GeometryType::HomogeneousVectorType sourceH = m_Geometry->GetSourcePosition(iProj);\n    PointType                                    source(0.);\n    source[0] = sourceH[0];\n    source[2] = sourceH[2];\n    double    sourceNorm = source.GetNorm();\n    PointType sourceDir = source / sourceNorm;\n\n    PointType v(0.);\n    v[1] = 1.;\n    PointType u = CrossProduct(v, sourceDir);\n\n    // Compute the equation of a line of the ax+by=c\n    // https://en.wikipedia.org/wiki/Linear_equation#Two-point_form\n    // Then compute the coefficient in front of r as suggested in\n    // http://www.ifor.math.ethz.ch/teaching/lectures/intro_ss11/Exercises/solutionEx11-12.pdf\n    PointType inf = u * -1. * X1;\n    double    aInf = inf[2] - source[2];\n    double    bInf = source[0] - inf[0];\n    double    cInf = source[0] * inf[2] - inf[0] * source[2];\n    double    dInf = std::sqrt(aInf * aInf + bInf * bInf);\n\n    PointType sup = u * X2;\n    double    aSup = sup[2] - source[2];\n    double    bSup = source[0] - sup[0];\n    double    cSup = source[0] * sup[2] - sup[0] * source[2];\n    double    dSup = std::sqrt(aSup * aSup + bSup * bSup);\n\n    // Check on corners\n    if (aInf * sup[0] + bInf * sup[2] >= cInf)\n    {\n      aInf *= -1.;\n      bInf *= -1.;\n      cInf *= -1.;\n    }\n    else if (aSup * inf[0] + bSup * inf[2] >= cSup)\n    {\n      aSup *= -1.;\n      bSup *= -1.;\n      cSup *= -1.;\n    }\n    else\n    {\n      itkExceptionMacro(<< \"Something's wrong with the jaw handling.\");\n    }\n\n    // Now add the constraints of the form ax+by+dr<=c\n    if (type == RADIUSINF || type == RADIUSBOTH)\n    {\n      row[0] = aInf;\n      row[1] = bInf;\n      row[2] = dInf;\n      if (!add_constraintex(lp, 3, row, colno, LE, cInf))\n        itkExceptionMacro(<< \"Couldn't add simplex constraint\");\n    }\n    if (type == RADIUSSUP || type == RADIUSBOTH)\n    {\n      row[0] = aSup;\n      row[1] = bSup;\n      row[2] = dSup;\n      if (!add_constraintex(lp, 3, row, colno, LE, cSup))\n        itkExceptionMacro(<< \"Couldn't add simplex constraint\");\n    }\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkFieldOfViewImageFilter_hxx\n"
  },
  {
    "path": "include/rtkForbildPhantomFileReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkForbildPhantomFileReader_h\n#define rtkForbildPhantomFileReader_h\n\n#include \"RTKExport.h\"\n#include <itkLightProcessObject.h>\n#include \"rtkGeometricPhantom.h\"\n\nnamespace rtk\n{\n\n/** \\class ForbildPhantomFileReader\n * \\brief Reads GeometricPhantom from a Forbild file\n *\n * See http://www.imp.uni-erlangen.de/phantoms/. In addition to the original\n * parameters, the parameter \"union=N\", allows defining the union with a previous\n * shape. For example, union=-1 will create a union with the previous shape.\n *\n * \\test rtkforbildtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT ForbildPhantomFileReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ForbildPhantomFileReader);\n\n  /** Standard class type alias. */\n  using Self = ForbildPhantomFileReader;\n  using Superclass = itk::Object;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  static constexpr unsigned int Dimension = ConvexShape::Dimension;\n  using GeometricPhantomPointer = GeometricPhantom::Pointer;\n  using ScalarType = ConvexShape::ScalarType;\n  using PointType = ConvexShape::PointType;\n  using VectorType = ConvexShape::VectorType;\n  using RotationMatrixType = ConvexShape::RotationMatrixType;\n  using ConvexShapeVectorType = GeometricPhantom::ConvexShapeVector;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ForbildPhantomFileReader);\n\n  /** Get / Set the object pointer to geometric phantom. */\n  itkGetModifiableObjectMacro(GeometricPhantom, GeometricPhantom);\n  itkSetObjectMacro(GeometricPhantom, GeometricPhantom);\n\n  /** Get/Set path to phantom definition file. */\n  itkGetStringMacro(Filename);\n  itkSetStringMacro(Filename);\n\n  /** do the actual parsing of the input file */\n  virtual void\n  GenerateOutputInformation();\n\nprotected:\n  /// Constructor\n  ForbildPhantomFileReader() = default;\n\n  /// Destructor\n  ~ForbildPhantomFileReader() override = default;\n\n  void\n  CreateForbildSphere(const std::string & s);\n  void\n  CreateForbildBox(const std::string & s);\n  void\n  CreateForbildCylinder(const std::string & s, const std::string & fig);\n  void\n  CreateForbildElliptCyl(const std::string & s, const std::string & fig);\n  void\n  CreateForbildEllipsoid(const std::string & s, const std::string & fig);\n  void\n  CreateForbildCone(const std::string & s, const std::string & fig);\n  void\n  CreateForbildTetrahedron(const std::string & s);\n  RotationMatrixType\n  ComputeRotationMatrixBetweenVectors(const VectorType & source, const VectorType & dest) const;\n\n  bool\n  FindParameterInString(const std::string & name, const std::string & s, ScalarType & param);\n  bool\n  FindVectorInString(const std::string & name, const std::string & s, VectorType & vec);\n  void\n  FindClipPlanes(const std::string & s);\n  void\n  FindUnions(const std::string & s);\n\nprivate:\n  GeometricPhantomPointer m_GeometricPhantom;\n  std::string             m_Filename;\n  PointType               m_Center;\n  ConvexShape::Pointer    m_ConvexShape;\n  ConvexShapeVectorType   m_Unions;\n  std::vector<int>        m_UnionWith;\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkForwardDifferenceGradientImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkForwardDifferenceGradientImageFilter_h\n#define rtkForwardDifferenceGradientImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkCovariantVector.h>\n#include <itkImageRegionIterator.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class ForwardDifferenceGradientImageFilter\n * \\brief Computes the gradient of an image using forward difference.\n *\n *\n * The second template parameter defines the value type used in the\n * derivative operator (defaults to float).  The third template\n * parameter defines the value type used for output image (defaults to\n * float).  The output image is defined as a covariant vector image\n * whose value type is specified as this third template parameter.\n *\n * The exact definition of the desired gradient filter can\n * be found in Chambolle, Antonin. \"An Algorithm for Total\n * Variation Minimization and Applications.\" J. Math. Imaging Vis. 20,\n * no. 1-2 (January 2004): 89-97.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\ntemplate <typename TInputImage,\n          typename TOperatorValueType = float,\n          typename TOuputValue = float,\n          typename TOuputImage =\n            itk::Image<itk::CovariantVector<TOuputValue, TInputImage::ImageDimension>, TInputImage::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT ForwardDifferenceGradientImageFilter\n  : public itk::ImageToImageFilter<TInputImage, TOuputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ForwardDifferenceGradientImageFilter);\n\n  /** Extract dimension from input image. */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n  static constexpr unsigned int OutputImageDimension = TOuputImage::ImageDimension;\n\n  /** Standard class type alias. */\n  using Self = ForwardDifferenceGradientImageFilter;\n\n  /** Convenient type alias for simplifying declarations. */\n  using InputImageType = TInputImage;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using OutputImageType = TOuputImage;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n\n  /** Standard class type alias. */\n  using Superclass = itk::ImageToImageFilter<InputImageType, OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ForwardDifferenceGradientImageFilter);\n\n  /** Image type alias support. */\n  using OperatorValueType = TOperatorValueType;\n  using OutputValueType = TOuputValue;\n  using InputPixelType = typename InputImageType::PixelType;\n  using CovariantVectorType = typename OutputImageType::PixelType;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n\n  /** ForwardDifferenceGradientImageFilter needs a larger input requested region than\n   * the output requested region.  As such, ForwardDifferenceGradientImageFilter needs\n   * to provide an implementation for GenerateInputRequestedRegion()\n   * in order to inform the pipeline execution model.\n   *\n   * \\sa ImageToImageFilter::GenerateInputRequestedRegion() */\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Use the image spacing information in calculations. Use this option if you\n   *  want derivatives in physical space. Default is UseImageSpacingOn. */\n  void\n  SetUseImageSpacingOn()\n  {\n    this->SetUseImageSpacing(true);\n  }\n\n  /** Ignore the image spacing. Use this option if you want derivatives in\n      isotropic pixel space.  Default is UseImageSpacingOn. */\n  void\n  SetUseImageSpacingOff()\n  {\n    this->SetUseImageSpacing(false);\n  }\n\n  /** Set/Get whether or not the filter will use the spacing of the input\n      image in its calculations */\n  itkSetMacro(UseImageSpacing, bool);\n  itkGetConstMacro(UseImageSpacing, bool);\n\n  /** Set along which dimensions the gradient computation should be\n      performed. The vector components at unprocessed dimensions contain\n      undetermined values */\n  void\n  SetDimensionsProcessed(bool * DimensionsProcessed);\n\n  /** Allows to change the default boundary condition */\n  void\n  OverrideBoundaryCondition(itk::ImageBoundaryCondition<TInputImage> * boundaryCondition);\n\n  // Begin concept checking\n  itkConceptMacro(InputConvertibleToOutputCheck, (itk::Concept::Convertible<InputPixelType, OutputValueType>));\n  itkConceptMacro(OutputHasNumericTraitsCheck, (itk::Concept::HasNumericTraits<OutputValueType>));\n  // End concept checking\n\n  /** The UseImageDirection flag determines whether image derivatives are\n   * computed with respect to the image grid or with respect to the physical\n   * space. When this flag is ON the derivatives are computed with respect to\n   * the coodinate system of physical space. The difference is whether we take\n   * into account the image Direction or not. The flag ON will take into\n   * account the image direction and will result in an extra matrix\n   * multiplication compared to the amount of computation performed when the\n   * flag is OFF.\n   * The default value of this flag is On.\n   */\n  itkSetMacro(UseImageDirection, bool);\n  itkGetConstMacro(UseImageDirection, bool);\n  itkBooleanMacro(UseImageDirection);\n\nprotected:\n  ForwardDifferenceGradientImageFilter();\n  ~ForwardDifferenceGradientImageFilter() override;\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  /** ForwardDifferenceGradientImageFilter can be implemented as a multithreaded filter.\n   * Therefore, this implementation provides a ThreadedGenerateData()\n   * routine which is called for each processing thread. The output\n   * image data is allocated automatically by the superclass prior to\n   * calling ThreadedGenerateData().  ThreadedGenerateData can only\n   * write to the portion of the output image specified by the\n   * parameter \"outputRegionForThread\"\n   *\n   * \\sa ImageToImageFilter::ThreadedGenerateData(),\n   *     ImageToImageFilter::GenerateData() */\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  void\n  GenerateOutputInformation() override;\n\nprivate:\n  //  // An overloaded method which may transform the gradient to a\n  //  // physical vector and converts to the correct output pixel type.\n  //  template <typename TValue>\n  //  void SetOutputPixel( ImageRegionIterator< VectorImage<TValue,OutputImageDimension> > &it, CovariantVectorType\n  //  &gradient )\n  //  {\n  //    if ( this->m_UseImageDirection )\n  //      {\n  //      CovariantVectorType physicalGradient;\n  //      it.GetImage()->TransformLocalVectorToPhysicalVector( gradient, physicalGradient );\n  //      it.Set( OutputPixelType( physicalGradient.GetDataPointer(), InputImageDimension, false ) );\n  //      }\n  //    else\n  //      {\n  //      it.Set( OutputPixelType( gradient.GetDataPointer(), InputImageDimension, false ) );\n  //      }\n  //  }\n\n  template <typename T>\n  void\n  SetOutputPixel(itk::ImageRegionIterator<T> & it, CovariantVectorType & gradient)\n  {\n    it.Value() = gradient;\n  }\n\n\n  bool m_UseImageSpacing;\n\n  // flag to take or not the image direction into account\n  // when computing the derivatives.\n  bool m_UseImageDirection;\n\n  // list of the dimensions along which the gradient has\n  // to be computed. The components on other dimensions\n  // are set to zero\n  bool m_DimensionsProcessed[TInputImage::ImageDimension];\n\n  itk::ImageBoundaryCondition<TInputImage, TInputImage> * m_BoundaryCondition;\n  bool                                                    m_IsBoundaryConditionOverriden;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkForwardDifferenceGradientImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkForwardDifferenceGradientImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkForwardDifferenceGradientImageFilter_hxx\n#define rtkForwardDifferenceGradientImageFilter_hxx\n\n#include <itkConstNeighborhoodIterator.h>\n#include <itkNeighborhoodInnerProduct.h>\n#include <itkImageRegionIterator.h>\n#include <itkForwardDifferenceOperator.h>\n#include <itkNeighborhoodAlgorithm.h>\n#include <itkOffset.h>\n#include <itkProgressReporter.h>\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <typename TInputImage, typename TOperatorValueType, typename TOuputValue, typename TOuputImage>\nForwardDifferenceGradientImageFilter<TInputImage, TOperatorValueType, TOuputValue, TOuputImage>::\n  ForwardDifferenceGradientImageFilter()\n{\n  // default boundary condition\n  m_BoundaryCondition = new itk::ZeroFluxNeumannBoundaryCondition<TInputImage>();\n  m_IsBoundaryConditionOverriden = false;\n\n  // default behaviour is to take into account both spacing and direction\n  this->m_UseImageSpacing = true;\n  this->m_UseImageDirection = true;\n\n  // default behaviour is to process all dimensions\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    m_DimensionsProcessed[dim] = true;\n  }\n}\n\n//\n// Destructor\n//\ntemplate <typename TInputImage, typename TOperatorValueType, typename TOuputValue, typename TOuputImage>\nForwardDifferenceGradientImageFilter<TInputImage, TOperatorValueType, TOuputValue, TOuputImage>::\n  ~ForwardDifferenceGradientImageFilter()\n{\n  delete m_BoundaryCondition;\n}\n\n// This should be handled by an itkMacro, but it doesn't seem to work with pointer types\ntemplate <typename TInputImage, typename TOperatorValueType, typename TOuputValue, typename TOuputImage>\nvoid\nForwardDifferenceGradientImageFilter<TInputImage, TOperatorValueType, TOuputValue, TOuputImage>::SetDimensionsProcessed(\n  bool * DimensionsProcessed)\n{\n  bool bModif = false;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    if (m_DimensionsProcessed[dim] != DimensionsProcessed[dim])\n    {\n      m_DimensionsProcessed[dim] = DimensionsProcessed[dim];\n      bModif = true;\n    }\n  }\n  if (bModif)\n    this->Modified();\n}\n\ntemplate <typename TInputImage, typename TOperatorValueType, typename TOuputValue, typename TOuputImage>\nvoid\nForwardDifferenceGradientImageFilter<TInputImage, TOperatorValueType, TOuputValue, TOuputImage>::\n  OverrideBoundaryCondition(itk::ImageBoundaryCondition<TInputImage> * boundaryCondition)\n{\n  delete m_BoundaryCondition;\n  m_BoundaryCondition = boundaryCondition;\n  m_IsBoundaryConditionOverriden = true;\n}\n\ntemplate <typename TInputImage, typename TOperatorValueType, typename TOuputValue, typename TOuputImage>\nvoid\nForwardDifferenceGradientImageFilter<TInputImage, TOperatorValueType, TOuputValue, TOuputImage>::\n  GenerateInputRequestedRegion()\n{\n  // call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // get pointers to the input and output\n  InputImagePointer  inputPtr = const_cast<InputImageType *>(this->GetInput());\n  OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n  {\n    return;\n  }\n\n  // Build an operator so that we can determine the kernel size\n  itk::ForwardDifferenceOperator<OperatorValueType, InputImageDimension> oper;\n  oper.SetDirection(0);\n  oper.CreateDirectional();\n  const itk::SizeValueType radius = oper.GetRadius()[0];\n\n  // get a copy of the input requested region (should equal the output\n  // requested region)\n  typename TInputImage::RegionType inputRequestedRegion = inputPtr->GetRequestedRegion();\n\n  // pad the input requested region by the operator radius\n  inputRequestedRegion.PadByRadius(radius);\n\n  // crop the input requested region at the input's largest possible region\n  if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))\n  {\n    inputPtr->SetRequestedRegion(inputRequestedRegion);\n    return;\n  }\n  else\n  {\n    // Couldn't crop the region (requested region is outside the largest\n    // possible region).  Throw an exception.\n\n    // store what we tried to request (prior to trying to crop)\n    inputPtr->SetRequestedRegion(inputRequestedRegion);\n\n    // build an exception\n    itk::InvalidRequestedRegionError e(__FILE__, __LINE__);\n    e.SetLocation(ITK_LOCATION);\n    e.SetDescription(\"Requested region is (at least partially) outside the largest possible region.\");\n    e.SetDataObject(inputPtr);\n    throw e;\n  }\n}\n\ntemplate <typename TInputImage, typename TOperatorValueType, typename TOuputValue, typename TOuputImage>\nvoid\nForwardDifferenceGradientImageFilter<TInputImage, TOperatorValueType, TOuputValue, TOuputImage>::\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)\n{\n\n  itk::NeighborhoodInnerProduct<InputImageType, OperatorValueType, OutputValueType> SIP;\n\n  // Get the input and output\n  OutputImageType *      outputImage = this->GetOutput();\n  const InputImageType * inputImage = this->GetInput();\n\n  // Generate a list of indices of the dimensions to process\n  std::vector<int> dimsToProcess;\n  //  std::vector<int> dimsNotToProcess;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n  {\n    if (m_DimensionsProcessed[dim])\n      dimsToProcess.push_back(dim);\n    //    else dimsNotToProcess.push_back(dim);\n  }\n\n  // Set up operators\n  itk::ForwardDifferenceOperator<OperatorValueType, InputImageDimension> op[InputImageDimension];\n\n  for (unsigned int i = 0; i < InputImageDimension; i++)\n  {\n    op[i].SetDirection(0);\n    op[i].CreateDirectional();\n\n    // Take into account the pixel spacing if necessary\n    if (m_UseImageSpacing == true)\n    {\n      if (this->GetInput()->GetSpacing()[i] == 0.0)\n      {\n        itkExceptionMacro(<< \"Image spacing cannot be zero.\");\n      }\n      else\n      {\n        op[i].ScaleCoefficients(1.0 / this->GetInput()->GetSpacing()[i]);\n      }\n    }\n  }\n\n  // Calculate iterator radius\n  itk::Size<InputImageDimension> radius;\n  for (unsigned int i = 0; i < InputImageDimension; ++i)\n  {\n    radius[i] = op[0].GetRadius()[0];\n  }\n\n  // Find the data-set boundary \"faces\"\n  itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>                        bC;\n  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType faceList =\n    bC(inputImage, outputRegionForThread, radius);\n\n  auto fit = faceList.begin();\n\n  // Initialize the x_slice array\n  auto nit = itk::ConstNeighborhoodIterator<InputImageType>(radius, inputImage, *fit);\n\n  std::slice               x_slice[InputImageDimension];\n  const itk::SizeValueType center = nit.Size() / 2;\n  for (unsigned int i = 0; i < InputImageDimension; ++i)\n  {\n    x_slice[i] = std::slice(center - nit.GetStride(i) * radius[i], op[i].GetSize()[0], nit.GetStride(i));\n  }\n\n  CovariantVectorType gradient(itk::NumericTraits<typename CovariantVectorType::ValueType>::ZeroValue());\n  // Process non-boundary face and then each of the boundary faces.\n  // These are N-d regions which border the edge of the buffer.\n  for (auto & currentFace : faceList)\n  {\n    nit = itk::ConstNeighborhoodIterator<InputImageType>(radius, inputImage, currentFace);\n    auto it = itk::ImageRegionIterator<OutputImageType>(outputImage, currentFace);\n    nit.OverrideBoundaryCondition(m_BoundaryCondition);\n    nit.GoToBegin();\n\n    while (!nit.IsAtEnd())\n    {\n      for (std::vector<int>::size_type i = 0; i < dimsToProcess.size(); ++i)\n      {\n        gradient[i] = SIP(x_slice[dimsToProcess[i]], nit, op[dimsToProcess[i]]);\n      }\n      //      for ( i = 0; i < dimsNotToProcess.size(); ++i )\n      //        {\n      //        gradient[dimsNotToProcess[i]] = 0;\n      //        }\n\n      // This method optionally performs a tansform for Physical\n      // coordinates and potential conversion to a different output\n      // pixel type.\n      this->SetOutputPixel(it, gradient);\n\n      ++nit;\n      ++it;\n    }\n  }\n}\n\ntemplate <typename TInputImage, typename TOperatorValueType, typename TOuputValue, typename TOuputImage>\nvoid\nForwardDifferenceGradientImageFilter<TInputImage, TOperatorValueType, TOuputValue, TOuputImage>::\n  GenerateOutputInformation()\n{\n  // this methods is overloaded so that if the output image is a\n  // VectorImage then the correct number of components are set.\n\n  Superclass::GenerateOutputInformation();\n  OutputImageType * output = this->GetOutput();\n\n  if (!output)\n  {\n    return;\n  }\n  if (output->GetNumberOfComponentsPerPixel() != InputImageDimension)\n  {\n    output->SetNumberOfComponentsPerPixel(InputImageDimension);\n  }\n}\n\n\n/**\n * Standard \"PrintSelf\" method\n */\ntemplate <typename TInputImage, typename TOperatorValueType, typename TOuputValue, typename TOuputImage>\nvoid\nForwardDifferenceGradientImageFilter<TInputImage, TOperatorValueType, TOuputValue, TOuputImage>::PrintSelf(\n  std::ostream & os,\n  itk::Indent    indent) const\n{\n  Superclass::PrintSelf(os, indent);\n\n  os << indent << \"UseImageSpacing: \" << (this->m_UseImageSpacing ? \"On\" : \"Off\") << std::endl;\n  os << indent << \"UseImageDirection = \" << (this->m_UseImageDirection ? \"On\" : \"Off\") << std::endl;\n}\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkForwardProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkForwardProjectionImageFilter_h\n#define rtkForwardProjectionImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class ForwardProjectionImageFilter\n * \\brief Base class for forward projection, i.e. accumulation along x-ray lines.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Projector\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT ForwardProjectionImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ForwardProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ForwardProjectionImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryPointer = typename GeometryType::ConstPointer;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ForwardProjectionImageFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetConstObjectMacro(Geometry, GeometryType);\n  itkSetConstObjectMacro(Geometry, GeometryType);\n\nprotected:\n  ForwardProjectionImageFilter()\n    : m_Geometry(nullptr)\n  {\n    this->SetNumberOfRequiredInputs(2);\n    this->SetInPlace(true);\n  };\n\n  ~ForwardProjectionImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Apply changes to the input image requested region. */\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\nprivate:\n  /** RTK geometry object */\n  GeometryPointer m_Geometry;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkForwardProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkForwardProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkForwardProjectionImageFilter_hxx\n#define rtkForwardProjectionImageFilter_hxx\n\n\n#include \"rtkHomogeneousMatrix.h\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkIdentityTransform.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nForwardProjectionImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nForwardProjectionImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the stack of projections in which we project\n  typename Superclass::InputImagePointer inputPtr0 = const_cast<TInputImage *>(this->GetInput(0));\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the volume to forward project\n  typename Superclass::InputImagePointer inputPtr1 = const_cast<TInputImage *>(this->GetInput(1));\n  if (!inputPtr1)\n    return;\n\n  typename TInputImage::RegionType reqRegion = inputPtr1->GetLargestPossibleRegion();\n  inputPtr1->SetRequestedRegion(reqRegion);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkForwardWarpImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkForwardWarpImageFilter_h\n#define rtkForwardWarpImageFilter_h\n\n#include <itkWarpImageFilter.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class ForwardWarpImageFilter\n * \\brief Warps an image using splat instead of interpolation\n *\n * Deforms an image using a Displacement Vector Field. Adjoint operator\n * of the itkWarpImageFilter\n *\n * \\test rtkfourdroostertest\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <class TInputImage,\n          class TOutputImage = TInputImage,\n          class TDVF = itk::Image<itk::CovariantVector<typename TInputImage::PixelType, TInputImage::ImageDimension>,\n                                  TInputImage::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT ForwardWarpImageFilter : public itk::WarpImageFilter<TInputImage, TOutputImage, TDVF>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ForwardWarpImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ForwardWarpImageFilter;\n  using Superclass = itk::WarpImageFilter<TInputImage, TOutputImage, TDVF>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Displacement type */\n  using DisplacementFieldType = TDVF;\n  using DisplacementFieldPointer = typename DisplacementFieldType::Pointer;\n  using DisplacementFieldConstPointer = typename DisplacementFieldType::ConstPointer;\n  using DisplacementType = typename DisplacementFieldType::PixelType;\n\n  /** Point type */\n  using CoordinateType = double;\n  using PointType = itk::Point<CoordinateType, Self::ImageDimension>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ForwardWarpImageFilter);\n\nprotected:\n  ForwardWarpImageFilter();\n  ~ForwardWarpImageFilter() override = default;\n\n  void\n  GenerateData() override;\n\n  // Redefine stuff that is private in the Superclass\n  void\n  Protected_EvaluateDisplacementAtPhysicalPoint(const PointType & point, DisplacementType & output);\n\n  bool m_Protected_DefFieldSizeSame;\n\n  typename TOutputImage::IndexType m_Protected_StartIndex;\n  typename TOutputImage::IndexType m_Protected_EndIndex;\n};\n\n} // end namespace rtk\n\n#ifndef rtk_MANUAL_INSTANTIATION\n#  include \"rtkForwardWarpImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkForwardWarpImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkForwardWarpImageFilter_hxx\n#define rtkForwardWarpImageFilter_hxx\n\n#include \"rtkHomogeneousMatrix.h\"\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIteratorWithIndex.h>\n#include <itkNeighborhoodIterator.h>\n#include <itkConstantBoundaryCondition.h>\n#include <itkLinearInterpolateImageFunction.h>\n#include <itkMacro.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TDVF>\nForwardWarpImageFilter<TInputImage, TOutputImage, TDVF>::ForwardWarpImageFilter()\n{\n  m_Protected_DefFieldSizeSame = false;\n  m_Protected_EndIndex.Fill(0);\n  m_Protected_StartIndex.Fill(0);\n}\n\ntemplate <class TInputImage, class TOutputImage, class TDVF>\nvoid\nForwardWarpImageFilter<TInputImage, TOutputImage, TDVF>::Protected_EvaluateDisplacementAtPhysicalPoint(\n  const PointType &  point,\n  DisplacementType & output)\n{\n\n  const DisplacementFieldType * fieldPtr = this->GetDisplacementField();\n\n  using ValueType = typename PointType::ValueType;\n  const itk::ContinuousIndex<double, TDVF::ImageDimension> index =\n    fieldPtr->template TransformPhysicalPointToContinuousIndex<ValueType, double>(point);\n  unsigned int dim = 0; // index over dimension\n  /**\n   * Compute base index = closest index below point\n   * Compute distance from point to base index\n   */\n  typename TDVF::IndexType baseIndex;\n  typename TDVF::IndexType neighIndex;\n  double                   distance[TDVF::ImageDimension];\n\n  for (dim = 0; dim < TDVF::ImageDimension; dim++)\n  {\n    baseIndex[dim] = itk::Math::Floor<typename TDVF::IndexValueType>(index[dim]);\n\n    if (baseIndex[dim] >= this->m_Protected_StartIndex[dim])\n    {\n      if (baseIndex[dim] < this->m_Protected_EndIndex[dim])\n      {\n        distance[dim] = index[dim] - static_cast<double>(baseIndex[dim]);\n      }\n      else\n      {\n        baseIndex[dim] = this->m_Protected_EndIndex[dim];\n        distance[dim] = 0.0;\n      }\n    }\n    else\n    {\n      baseIndex[dim] = this->m_Protected_StartIndex[dim];\n      distance[dim] = 0.0;\n    }\n  }\n\n  /**\n   * Interpolated value is the weight some of each of the surrounding\n   * neighbors. The weight for each neighbour is the fraction overlap\n   * of the neighbor pixel with respect to a pixel centered on point.\n   */\n  output.Fill(0);\n\n  double       totalOverlap = 0.0;\n  unsigned int numNeighbors(1 << TInputImage::ImageDimension);\n\n  for (unsigned int counter = 0; counter < numNeighbors; counter++)\n  {\n    double       overlap = 1.0;   // fraction overlap\n    unsigned int upper = counter; // each bit indicates upper/lower neighbour\n\n    // get neighbor index and overlap fraction\n    for (dim = 0; dim < TDVF::ImageDimension; dim++)\n    {\n      if (upper & 1)\n      {\n        neighIndex[dim] = baseIndex[dim] + 1;\n        overlap *= distance[dim];\n      }\n      else\n      {\n        neighIndex[dim] = baseIndex[dim];\n        overlap *= 1.0 - distance[dim];\n      }\n\n      upper >>= 1;\n    }\n\n    // get neighbor value only if overlap is not zero\n    if (overlap)\n    {\n      const DisplacementType input = fieldPtr->GetPixel(neighIndex);\n      for (unsigned int k = 0; k < TDVF::ImageDimension; k++)\n      {\n        output[k] += overlap * static_cast<double>(input[k]);\n      }\n      totalOverlap += overlap;\n    }\n\n    if (totalOverlap == 1.0)\n    {\n      // finished\n      break;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage, class TDVF>\nvoid\nForwardWarpImageFilter<TInputImage, TOutputImage, TDVF>::GenerateData()\n{\n  Superclass::BeforeThreadedGenerateData();\n  const DisplacementFieldType * fieldPtr = this->GetDisplacementField();\n\n  // Connect input image to interpolator\n  m_Protected_StartIndex = fieldPtr->GetBufferedRegion().GetIndex();\n  for (unsigned i = 0; i < TDVF::ImageDimension; i++)\n  {\n    m_Protected_EndIndex[i] = m_Protected_StartIndex[i] + fieldPtr->GetBufferedRegion().GetSize()[i] - 1;\n  }\n\n  typename Superclass::InputImageConstPointer inputPtr = this->GetInput();\n  typename Superclass::OutputImagePointer     outputPtr = this->GetOutput();\n\n  outputPtr->SetRegions(outputPtr->GetRequestedRegion());\n  outputPtr->Allocate();\n  outputPtr->FillBuffer(0);\n\n  // Allocate an image with the same metadata as the output\n  // to accumulate the weights during splat, and divide by the total weights at the end\n  auto accumulate = TOutputImage::New();\n  accumulate->SetRegions(outputPtr->GetRequestedRegion());\n  accumulate->Allocate();\n  accumulate->FillBuffer(0);\n\n  // iterator for the output image\n  itk::ImageRegionConstIteratorWithIndex<TOutputImage>       inputIt(inputPtr, inputPtr->GetBufferedRegion());\n  itk::ImageRegionConstIterator<const DisplacementFieldType> fieldIt(fieldPtr, fieldPtr->GetBufferedRegion());\n  typename TOutputImage::IndexType                           index;\n  typename TOutputImage::IndexType                           baseIndex;\n  typename TOutputImage::IndexType                           neighIndex;\n  double                                                     distance[TInputImage::ImageDimension];\n  typename TOutputImage::PointType                           point;\n  typename Superclass::DisplacementType                      displacement;\n  itk::NumericTraits<typename Superclass::DisplacementType>::SetLength(displacement, TInputImage::ImageDimension);\n\n  unsigned int numNeighbors(1 << TInputImage::ImageDimension);\n\n  // There is a bug in the ITK WarpImageFilter: m_DefFieldSizeSame\n  // is computed without taking origin, spacing and direction into\n  // account. So we perform a more thorough comparison between\n  // output and DVF than in itkWarpImageFilter::BeforeThreadedGenerateData()\n  bool skipEvaluateDisplacementAtContinuousIndex =\n    ((outputPtr->GetLargestPossibleRegion() == this->GetDisplacementField()->GetLargestPossibleRegion()) &&\n     (outputPtr->GetSpacing() == this->GetDisplacementField()->GetSpacing()) &&\n     (outputPtr->GetOrigin() == this->GetDisplacementField()->GetOrigin()) &&\n     (outputPtr->GetDirection() == this->GetDisplacementField()->GetDirection()));\n\n  while (!inputIt.IsAtEnd())\n  {\n    // get the input image index\n    index = inputIt.GetIndex();\n    inputPtr->TransformIndexToPhysicalPoint(index, point);\n\n    if (skipEvaluateDisplacementAtContinuousIndex)\n      displacement = fieldIt.Get();\n    else\n      this->Protected_EvaluateDisplacementAtPhysicalPoint(point, displacement);\n\n    for (unsigned int j = 0; j < TInputImage::ImageDimension; j++)\n      point[j] += displacement[j];\n\n    using ValueType = typename TOutputImage::PointType::ValueType;\n    itk::ContinuousIndex<double, TInputImage::ImageDimension> continuousIndexInOutput =\n      outputPtr->template TransformPhysicalPointToContinuousIndex<ValueType, double>(point);\n\n    // compute the base index in output, ie the closest index below point\n    // Check if the baseIndex is in the output's requested region, otherwise skip the splat part\n    bool skip = false;\n\n    for (unsigned int j = 0; j < TInputImage::ImageDimension; j++)\n    {\n      baseIndex[j] = itk::Math::Floor<int, double>(continuousIndexInOutput[j]);\n      distance[j] = continuousIndexInOutput[j] - static_cast<double>(baseIndex[j]);\n      if ((baseIndex[j] < outputPtr->GetRequestedRegion().GetIndex()[j] - 1) ||\n          (baseIndex[j] >=\n           outputPtr->GetRequestedRegion().GetIndex()[j] + (int)outputPtr->GetRequestedRegion().GetSize()[j]))\n        skip = true;\n    }\n\n    if (!skip)\n    {\n      // get the splat weights as the overlapping areas between\n      for (unsigned int counter = 0; counter < numNeighbors; counter++)\n      {\n        double       overlap = 1.0;   // fraction overlap\n        unsigned int upper = counter; // each bit indicates upper/lower neighbour\n\n        // get neighbor weights as the fraction of overlap\n        // of the neighbor pixels with a pixel centered on point\n        for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n        {\n          if (upper & 1)\n          {\n            neighIndex[dim] = baseIndex[dim] + 1;\n            overlap *= distance[dim];\n          }\n          else\n          {\n            neighIndex[dim] = baseIndex[dim];\n            overlap *= 1.0 - distance[dim];\n          }\n\n          upper >>= 1;\n        }\n\n        if (outputPtr->GetRequestedRegion().IsInside(neighIndex))\n        {\n          // Perform splat with this weight, both in output and in the temporary\n          // image that accumulates weights\n          outputPtr->SetPixel(neighIndex, outputPtr->GetPixel(neighIndex) + overlap * inputIt.Get());\n          accumulate->SetPixel(neighIndex, accumulate->GetPixel(neighIndex) + overlap);\n        }\n      }\n    }\n\n    ++inputIt;\n    ++fieldIt;\n  }\n\n  // Divide the output by the accumulated weights, if they are non-zero\n  itk::ImageRegionIterator<TOutputImage> outputIt(outputPtr, outputPtr->GetRequestedRegion());\n  itk::ImageRegionIterator<TOutputImage> accIt(accumulate, outputPtr->GetRequestedRegion());\n  while (!outputIt.IsAtEnd())\n  {\n    if (accIt.Get())\n      outputIt.Set(outputIt.Get() / accIt.Get());\n\n    ++outputIt;\n    ++accIt;\n  }\n\n  // Replace the holes with the weighted mean of their neighbors\n  itk::Size<TOutputImage::ImageDimension> radius;\n  radius.Fill(3);\n  unsigned int pixelsInNeighborhood = 1;\n  for (unsigned int dim = 0; dim < TOutputImage::ImageDimension; dim++)\n    pixelsInNeighborhood *= 2 * radius[dim] + 1;\n\n  itk::NeighborhoodIterator<TOutputImage> outputIt2(radius, outputPtr, outputPtr->GetRequestedRegion());\n  itk::NeighborhoodIterator<TOutputImage> accIt2(radius, accumulate, outputPtr->GetRequestedRegion());\n\n  itk::ZeroFluxNeumannBoundaryCondition<TInputImage> zeroFlux;\n  outputIt2.OverrideBoundaryCondition(&zeroFlux);\n\n  itk::ConstantBoundaryCondition<TInputImage> constant;\n  accIt2.OverrideBoundaryCondition(&constant);\n\n  while (!outputIt2.IsAtEnd())\n  {\n    if (!accIt2.GetCenterPixel())\n    {\n      // Compute the mean of the neighboring pixels, weighted by the accumulated weights\n      typename TOutputImage::PixelType value = 0;\n      typename TOutputImage::PixelType weight = 0;\n      for (unsigned int idx = 0; idx < pixelsInNeighborhood; idx++)\n      {\n        value += accIt2.GetPixel(idx) * outputIt2.GetPixel(idx);\n        weight += accIt2.GetPixel(idx);\n      }\n\n      // Replace the hole with this value, or zero (if all surrounding pixels were holes)\n      if (weight)\n        outputIt2.SetCenterPixel(value / weight);\n      else\n        outputIt2.SetCenterPixel(0);\n    }\n    ++outputIt2;\n    ++accIt2;\n  }\n\n  Superclass::AfterThreadedGenerateData();\n}\n\n} // end namespace rtk\n\n#endif // rtkForwardWarpImageFilter_hxx\n"
  },
  {
    "path": "include/rtkFourDConjugateGradientConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFourDConjugateGradientConeBeamReconstructionFilter_h\n#define rtkFourDConjugateGradientConeBeamReconstructionFilter_h\n\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n#include \"rtkConjugateGradientImageFilter.h\"\n#include \"rtkFourDReconstructionConjugateGradientOperator.h\"\n#include \"rtkProjectionStackToFourDImageFilter.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n#include <itkIterationReporter.h>\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaConjugateGradientImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n\n/** \\class FourDConjugateGradientConeBeamReconstructionFilter\n * \\brief Implements part of the 4D reconstruction by conjugate gradient\n *\n * See the reference paper: \"Cardiac C-arm computed tomography using\n * a 3D + time ROI reconstruction method with spatial and temporal regularization\"\n * by Mory et al.\n *\n * 4D conjugate gradient reconstruction consists in iteratively\n * minimizing the following cost function:\n *\n * \\f[ \\sum\\limits_{\\alpha} \\| R_\\alpha S_\\alpha x - p_\\alpha \\|_2^2 \\f]\n *\n * with\n * - \\f$ x \\f$ a 4D series of 3D volumes, each one being the reconstruction\n * at a given respiratory/cardiac phase\n * - \\f$ p_{\\alpha} \\f$ is the projection measured at angle \\f$ \\alpha \\f$\n * - \\f$ S_{\\alpha} \\f$ an interpolation operator which, from the 3D + time sequence f,\n * estimates the 3D volume through which projection \\f$ p_{\\alpha} \\f$ has been acquired\n * - \\f$ R_{\\alpha} \\f$ is the X-ray transform (the forward projection operator) for angle \\f$ \\alpha \\f$\n * - \\f$ D \\f$ the displaced detector weighting matrix\n *\n * \\dot\n * digraph FourDConjugateGradientConeBeamReconstructionFilter {\n *\n * Input0 [ label=\"Input 0 (Input: 4D sequence of volumes)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction: 4D sequence of volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * AfterInput0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * ConjugateGradient [ label=\"rtk::ConjugateGradientImageFilter\" URL=\"\\ref rtk::ConjugateGradientImageFilter\"];\n * PSTFD [ label=\"rtk::ProjectionStackToFourDImageFilter\" URL=\"\\ref rtk::ProjectionStackToFourDImageFilter\"];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n *\n * Input0 -> AfterInput0 [arrowhead=none];\n * AfterInput0 -> ConjugateGradient;\n * Input0 -> PSTFD;\n * Input1 -> Displaced;\n * Displaced -> PSTFD;\n * PSTFD -> ConjugateGradient;\n * ConjugateGradient -> Output;\n * }\n * \\enddot\n *\n * \\test rtkfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT FourDConjugateGradientConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FourDConjugateGradientConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = FourDConjugateGradientConeBeamReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = VolumeSeriesType;\n  using OutputImageType = VolumeSeriesType;\n  using VolumeType = ProjectionStackType;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using ForwardProjectionFilterType = ForwardProjectionImageFilter<VolumeType, ProjectionStackType>;\n  using BackProjectionFilterType = BackProjectionImageFilter<ProjectionStackType, VolumeType>;\n  using ConjugateGradientFilterType = ConjugateGradientImageFilter<VolumeSeriesType>;\n  using CGOperatorFilterType = FourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>;\n  using ProjStackToFourDFilterType = ProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>;\n  using DisplacedDetectorFilterType = DisplacedDetectorImageFilter<ProjectionStackType>;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUVolumeSeriesType =\n    typename itk::Image<typename VolumeSeriesType::PixelType, VolumeSeriesType::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using CudaConjugateGradientImageFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                ConjugateGradientImageFilter<VolumeSeriesType>,\n                                CudaConjugateGradientImageFilter<VolumeSeriesType>>;\n#else\n  using CudaConjugateGradientImageFilterType = ConjugateGradientImageFilter<VolumeSeriesType>;\n#endif\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FourDConjugateGradientConeBeamReconstructionFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetConstObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkSetConstObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Get / Set the number of iterations. Default is 3. */\n  itkGetMacro(NumberOfIterations, unsigned int);\n  itkSetMacro(NumberOfIterations, unsigned int);\n\n  /** Get / Set whether conjugate gradient should be performed on GPU */\n  itkGetMacro(CudaConjugateGradient, bool);\n  itkSetMacro(CudaConjugateGradient, bool);\n\n  /** Set/Get the 4D image to be updated.*/\n  void\n  SetInputVolumeSeries(const VolumeSeriesType * VolumeSeries);\n  typename VolumeSeriesType::ConstPointer\n  GetInputVolumeSeries();\n\n  /** Set/Get the stack of projections */\n  void\n  SetInputProjectionStack(const ProjectionStackType * Projections);\n  typename ProjectionStackType::ConstPointer\n  GetInputProjectionStack();\n\n  /** Pass the interpolation weights to subfilters */\n  void\n  SetWeights(const itk::Array2D<float> _arg);\n\n  /** Store the phase signal in a member variable */\n  virtual void\n  SetSignal(const std::vector<double> signal);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  FourDConjugateGradientConeBeamReconstructionFilter();\n  ~FourDConjugateGradientConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Pointers to each subfilter of this composite filter */\n  typename ForwardProjectionFilterType::Pointer m_ForwardProjectionFilter;\n  typename BackProjectionFilterType::Pointer    m_BackProjectionFilter;\n  typename BackProjectionFilterType::Pointer    m_BackProjectionFilterForB;\n  typename ConjugateGradientFilterType::Pointer m_ConjugateGradientFilter;\n  typename CGOperatorFilterType::Pointer        m_CGOperator;\n  typename ProjStackToFourDFilterType::Pointer  m_ProjStackToFourDFilter;\n  typename DisplacedDetectorFilterType::Pointer m_DisplacedDetectorFilter;\n\n  bool                m_CudaConjugateGradient;\n  std::vector<double> m_Signal;\n  bool                m_DisableDisplacedDetectorFilter;\n\n  // Iteration reporting\n  itk::IterationReporter m_IterationReporter;\n\nprivate:\n  /** Geometry object */\n  ThreeDCircularProjectionGeometry::ConstPointer m_Geometry;\n\n  /** Number of conjugate gradient descent iterations */\n  unsigned int m_NumberOfIterations;\n\n  /** Iteration reporter */\n  void\n  ReportProgress(itk::Object *, const itk::EventObject &);\n\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFourDConjugateGradientConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFourDConjugateGradientConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFourDConjugateGradientConeBeamReconstructionFilter_hxx\n#define rtkFourDConjugateGradientConeBeamReconstructionFilter_hxx\n\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n#include \"rtkJosephBackProjectionImageFilter.h\"\n\n#include <algorithm>\n\n#include <itkImageFileWriter.h>\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::\n  FourDConjugateGradientConeBeamReconstructionFilter()\n  : m_IterationReporter(this, 0, 1)\n{\n  this->SetNumberOfRequiredInputs(2); // 4D sequence, projections\n\n  // Set the default values of member parameters\n  m_NumberOfIterations = 3;\n  m_CudaConjugateGradient = false; // 4D volumes of usual size only fit on the largest GPUs\n\n  // Create the filters\n  m_CGOperator = CGOperatorFilterType::New();\n  m_ConjugateGradientFilter = ConjugateGradientFilterType::New();\n  m_ProjStackToFourDFilter = ProjStackToFourDFilterType::New();\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n\n  // Set parameters\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n  m_DisableDisplacedDetectorFilter = false;\n\n  // Memory management options\n  m_DisplacedDetectorFilter->ReleaseDataFlagOn();\n  m_ProjStackToFourDFilter->ReleaseDataFlagOn();\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetInputVolumeSeries(\n  const VolumeSeriesType * VolumeSeries)\n{\n  this->SetNthInput(0, const_cast<VolumeSeriesType *>(VolumeSeries));\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetInputProjectionStack(\n  const ProjectionStackType * Projections)\n{\n  this->SetNthInput(1, const_cast<ProjectionStackType *>(Projections));\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\ntypename VolumeSeriesType::ConstPointer\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetInputVolumeSeries()\n{\n  return static_cast<const VolumeSeriesType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\ntypename ProjectionStackType::ConstPointer\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetInputProjectionStack()\n{\n  return static_cast<const ProjectionStackType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetWeights(\n  const itk::Array2D<float> _arg)\n{\n  m_ProjStackToFourDFilter->SetWeights(_arg);\n  m_CGOperator->SetWeights(_arg);\n  this->Modified();\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n  m_ProjStackToFourDFilter->SetSignal(signal);\n  m_CGOperator->SetSignal(signal);\n  this->m_Signal = signal;\n  this->Modified();\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateOutputInformation()\n{\n  // Set the Conjugate Gradient filter (either on CPU or GPU depending on user's choice)\n  if (m_CudaConjugateGradient)\n  {\n    if (std::is_same<VolumeSeriesType, CPUVolumeSeriesType>::value)\n      itkGenericExceptionMacro(<< \"CudaConjugateGradient option only available with itk::CudaImage.\");\n    m_ConjugateGradientFilter = CudaConjugateGradientImageFilterType::New();\n  }\n\n  m_ConjugateGradientFilter->SetA(m_CGOperator.GetPointer());\n\n  // Set runtime connections\n  m_CGOperator->SetInputProjectionStack(this->GetInputProjectionStack());\n  m_ConjugateGradientFilter->SetX(this->GetInputVolumeSeries());\n  m_DisplacedDetectorFilter->SetInput(this->GetInputProjectionStack());\n\n  // Links with the m_BackProjectionFilter should be set here and not\n  // in the constructor, as m_BackProjectionFilter is set at runtime\n  m_ProjStackToFourDFilter->SetInputVolumeSeries(this->GetInputVolumeSeries());\n  m_ProjStackToFourDFilter->SetInputProjectionStack(m_DisplacedDetectorFilter->GetOutput());\n  m_ConjugateGradientFilter->SetB(m_ProjStackToFourDFilter->GetOutput());\n\n  // For the same reason, set geometry now\n  m_CGOperator->SetGeometry(this->GetGeometry());\n  m_ProjStackToFourDFilter->SetGeometry(this->GetGeometry());\n  m_DisplacedDetectorFilter->SetGeometry(this->GetGeometry());\n\n  // Set runtime parameters\n  m_ConjugateGradientFilter->SetNumberOfIterations(this->m_NumberOfIterations);\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n  m_CGOperator->SetDisableDisplacedDetectorFilter(m_DisableDisplacedDetectorFilter);\n\n  // Set forward projection filter\n  m_ForwardProjectionFilter = this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n  // Pass the ForwardProjection filter to the conjugate gradient operator\n  m_CGOperator->SetForwardProjectionFilter(m_ForwardProjectionFilter);\n  if (this->m_CurrentForwardProjectionConfiguration ==\n      ForwardProjectionType::FP_CUDARAYCAST) // The forward projection filter runs on GPU. It is most efficient to also\n                                             // run the interpolation on GPU, and to use GPU constant image sources\n  {\n    m_CGOperator->SetUseCudaInterpolation(true);\n    m_CGOperator->SetUseCudaSources(true);\n  }\n\n  // Set back projection filter\n  m_BackProjectionFilter = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  m_CGOperator->SetBackProjectionFilter(m_BackProjectionFilter);\n\n  m_BackProjectionFilterForB = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  // Pass the backprojection filter to the conjugate gradient operator and to the filter generating the B of AX=B\n  m_ProjStackToFourDFilter->SetBackProjectionFilter(m_BackProjectionFilterForB);\n  if (this->m_CurrentBackProjectionConfiguration ==\n      BackProjectionType::BP_CUDAVOXELBASED) // The back projection filter runs on GPU. It is most efficient to also run\n                                             // the splat on GPU, and to use GPU constant image sources\n  {\n    m_CGOperator->SetUseCudaSplat(true);\n    m_CGOperator->SetUseCudaSources(true);\n    m_ProjStackToFourDFilter->SetUseCudaSplat(true);\n    m_ProjStackToFourDFilter->SetUseCudaSources(true);\n  }\n\n  // Have the last filter calculate its output information\n  m_ConjugateGradientFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_ConjugateGradientFilter->GetOutput());\n}\n\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType,\n                                                   ProjectionStackType>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  this->m_ProjStackToFourDFilter->PropagateRequestedRegion(this->m_ProjStackToFourDFilter->GetOutput());\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateData()\n{\n  auto callbackCommand = itk::MemberCommand<Self>::New();\n  callbackCommand->SetCallbackFunction(this, &Self::ReportProgress);\n  m_ConjugateGradientFilter->AddObserver(itk::IterationEvent(), callbackCommand);\n\n  m_ProjStackToFourDFilter->Update();\n\n  if (!m_CudaConjugateGradient)\n    this->m_ProjStackToFourDFilter->GetOutput()->GetBufferPointer();\n\n  m_ConjugateGradientFilter->Update();\n\n  // Simply grafting the output of m_ConjugateGradientFilter to the main output\n  // is sufficient in most cases, but when this output is then disconnected and replugged,\n  // several images end up having the same CudaDataManager. The following solution is a\n  // workaround for this problem\n  typename VolumeSeriesType::Pointer pimg = m_ConjugateGradientFilter->GetOutput();\n  pimg->DisconnectPipeline();\n\n  this->GraftOutput(pimg);\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::ReportProgress(\n  itk::Object *            caller,\n  const itk::EventObject & event)\n{\n  {\n    if (!itk::IterationEvent().CheckEvent(&event))\n    {\n      return;\n    }\n    auto * cgCaller = dynamic_cast<rtk::ConjugateGradientImageFilter<VolumeSeriesType> *>(caller);\n    if (cgCaller)\n    {\n      this->GraftOutput(cgCaller->GetOutput());\n      m_IterationReporter.CompletedStep();\n    }\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkFourDConjugateGradientConeBeamReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkFourDROOSTERConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkFourDROOSTERConeBeamReconstructionFilter_h\n#define rtkFourDROOSTERConeBeamReconstructionFilter_h\n\n#include \"rtkFourDConjugateGradientConeBeamReconstructionFilter.h\"\n#include \"rtkTotalVariationDenoiseSequenceImageFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaLastDimensionTVDenoisingImageFilter.h\"\n#  include \"rtkCudaAverageOutOfROIImageFilter.h\"\n#else\n#  include \"rtkTotalVariationDenoisingBPDQImageFilter.h\"\n#  include \"rtkAverageOutOfROIImageFilter.h\"\n#endif\n#include \"rtkDaubechiesWaveletsDenoiseSequenceImageFilter.h\"\n#include \"rtkWarpSequenceImageFilter.h\"\n#include \"rtkUnwarpSequenceImageFilter.h\"\n#include \"rtkLastDimensionL0GradientDenoisingImageFilter.h\"\n#include \"rtkTotalNuclearVariationDenoisingBPDQImageFilter.h\"\n\n#include <itkThresholdImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkAddImageFilter.h>\n\n#include <itkResampleImageFilter.h>\n#include <itkNearestNeighborInterpolateImageFunction.h>\n#include <itkIdentityTransform.h>\n\n\nnamespace rtk\n{\n/** \\class FourDROOSTERConeBeamReconstructionFilter\n * \\brief Implements 4D RecOnstructiOn using Spatial and TEmporal\n * Regularization (short 4D ROOSTER)\n *\n * See the reference paper: \"Cardiac C-arm computed tomography using\n * a 3D + time ROI reconstruction method with spatial and temporal regularization\"\n * by Mory et al.\n *\n * 4D ROOSTER reconstruction consists in performing 4D Conjugate\n * Gradient reconstruction, then applying several regularization steps :\n * - Replacing all negative values by zero\n * - Averaging along time where no movement is expected\n * - Applying total variation denoising in space\n * - Applying wavelets denoising in space\n * - Applying total variation denoising in time\n * - Applying gradient's L0 norm denoising in time\n * - Applying total nuclear variation denoising\n * and starting over as many times as the number of main loop iterations desired.\n *\n * If both the displacement vector fields to a reference phase and from a reference phase are provided,\n * 4D ROOSTER performs the denoising in time the following way:\n * - each 3D volume of the sequence is warped to the reference phase using the first DVF\n * - denoising in time is applied on the warped sequence\n * - the difference sequence between the warped-then-denoised sequence and the warped sequence is computed\n * - that difference sequence is warped from the reference phase using the second DVF, and added to the output of\n * spatial denoising\n *\n * If only the displacement vector field to a reference phase is provided,\n * 4D ROOSTER performs total variation denoising in time the following way:\n * - each 3D volume of the sequence is warped to the reference phase using the first DVF\n * - denoising in time is applied on the warped sequence\n * - the warped-then-denoised sequence is warped from the reference phase by\n * an iterative procedure based on conjugate gradient. This significantly increases\n * computation time.\n *\n * \\dot\n * digraph FourDROOSTERConeBeamReconstructionFilter {\n *\n * PrimaryInput [label=\"Primary input (4D sequence of volumes)\"];\n * PrimaryInput [shape=Mdiamond];\n * InputProjectionStack [label=\"Input projection stack\"];\n * InputProjectionStack [shape=Mdiamond];\n * InputMotionMask [label=\"Input motion mask\"];\n * InputMotionMask [shape=Mdiamond];\n * InputDisplacementField [label=\"Input displacement field\"];\n * InputDisplacementField [shape=Mdiamond];\n * InputInverseDisplacementField [group=invwarp, label=\"Input inverse displacement field\"];\n * InputInverseDisplacementField [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction: 4D sequence of volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * FourDCG [ label=\"rtk::FourDConjugateGradientConeBeamReconstructionFilter\"\n *           URL=\"\\ref rtk::FourDConjugateGradientConeBeamReconstructionFilter\"];\n * Positivity [group=regul, label=\"itk::ThresholdImageFilter (positivity)\" URL=\"\\ref itk::ThresholdImageFilter\"];\n * Resample [group=regul, label=\"itk::ResampleImageFilter\" URL=\"\\ref itk::ResampleImageFilter\"];\n * MotionMask [group=regul, label=\"rtk::AverageOutOfROIImageFilter\" URL=\"\\ref rtk::AverageOutOfROIImageFilter\"];\n * TVSpace [group=regul, label=\"rtk::TotalVariationDenoisingBPDQImageFilter (in space)\"\n *          URL=\"\\ref rtk::TotalVariationDenoisingBPDQImageFilter\"];\n * Wavelets [group=regul, label=\"rtk::DaubechiesWaveletsDenoiseSequenceImageFilter (in space)\"\n *           URL=\"\\ref rtk::DaubechiesWaveletsDenoiseSequenceImageFilter\"];\n * Warp [group=regul, label=\"rtk::WarpSequenceImageFilter (direct field)\" URL=\"\\ref rtk::WarpSequenceImageFilter\"];\n * TVTime [group=regul, label=\"rtk::TotalVariationDenoisingBPDQImageFilter (along time)\"\n *         URL=\"\\ref rtk::TotalVariationDenoisingBPDQImageFilter\"];\n * L0Time [group=regul, label=\"rtk::LastDimensionL0GradientDenoisingImageFilter (along time)\"\n *         URL=\"\\ref rtk::LastDimensionL0GradientDenoisingImageFilter\"];\n * TNV [group=regul, label=\"rtk::TotalNuclearVariationDenoisingBPDQImageFilter\"\n *      URL=\"\\ref rtk::TotalNuclearVariationDenoisingBPDQImageFilter\"];\n * Unwarp [group=regul, label=\"rtk::UnwarpSequenceImageFilter\" URL=\"\\ref rtk::UnwarpSequenceImageFilter\"];\n * Subtract [group=invwarp, label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * InverseWarp [group=invwarp, label=\"rtk::WarpSequenceImageFilter (inverse field)\"\n *              URL=\"\\ref rtk::WarpSequenceImageFilter\"];\n * Add [group=invwarp, label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n *\n * AfterPrimaryInput [group=invisible, label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterFourDCG [group=invisible, label=\"m_PerformPositivity ?\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterPositivity [group=invisible, label=\"m_PerformMotionMask ?\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterMotionMask [group=invisible, label=\"m_PerformTVSpatialDenoising ?\",\n *                  fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterTVSpace [group=invisible, label=\"m_PerformWaveletsSpatialDenoising ?\",\n *               fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterWavelets [group=invisible, label=\"m_PerformWarping ?\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterWarp [group=invisible, label=\"m_PerformTVTemporalDenoising ?\", fixedsize=\"false\", width=0, height=0,\n * shape=none]; AfterTVTime [group=invisible, label=\"m_PerformL0TemporalDenoising ?\", fixedsize=\"false\", width=0,\n * height=0, shape=none]; AfterL0Time [group=invisible, label=\"m_ComputeInverseWarpingByConjugateGradient ?\",\n *              fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterTNV [group=invisible, label=\"m_PerformTNVDenoising ?\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterUnwarp [group=invisible, label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * InputDisplacementField -> Warp;\n * InputDisplacementField -> Unwarp;\n * InputInverseDisplacementField -> InverseWarp;\n *\n * PrimaryInput -> AfterPrimaryInput [arrowhead=none];\n * AfterPrimaryInput -> FourDCG;\n * InputProjectionStack -> FourDCG;\n * FourDCG -> AfterFourDCG;\n * AfterFourDCG -> Positivity [label=\"true\"];\n * Positivity -> AfterPositivity;\n * AfterPositivity -> MotionMask [label=\"true\"];\n * MotionMask -> AfterMotionMask;\n * InputMotionMask -> Resample;\n * Resample -> MotionMask;\n * AfterMotionMask -> TVSpace [label=\"true\"];\n * TVSpace -> AfterTVSpace;\n * AfterTVSpace -> Wavelets [label=\"true\"];\n * Wavelets -> AfterWavelets;\n * AfterWavelets -> Warp [label=\"true\"];\n * Warp -> AfterWarp;\n * AfterWarp -> TVTime [label=\"true\"];\n * TVTime -> AfterTVTime [arrowhead=none];\n * AfterTVTime -> L0Time [label=\"true\"];\n * L0Time -> AfterL0Time;\n * AfterL0Time -> TNV [label=\"true\"];\n * TNV -> AfterTNV;\n * AfterTNV -> Unwarp [label=\"true\"];\n * Unwarp -> AfterUnwarp\n * AfterUnwarp -> Output;\n * AfterUnwarp -> AfterPrimaryInput [style=dashed];\n *\n * AfterL0Time -> Subtract [label=\"false\"];\n * AfterWarp -> Subtract;\n * Subtract -> InverseWarp;\n * InverseWarp -> Add;\n * AfterWavelets -> Add;\n * Add -> AfterUnwarp;\n *\n * AfterFourDCG -> AfterPositivity  [label=\"false\"];\n * AfterPositivity -> AfterMotionMask [label=\"false\"];\n * AfterMotionMask -> AfterTVSpace [label=\"false\"];\n * AfterTVSpace -> AfterWavelets [label=\"false\"];\n * AfterWavelets -> AfterWarp [label=\"false\"];\n * AfterWarp -> AfterTVTime [label=\"false\"];\n * AfterTVTime -> AfterL0Time [label=\"false\"];\n * AfterL0Time -> AfterTNV [label=\"false\"];\n * AfterTNV -> AfterUnwarp [label=\"m_PerformWarping = false\"];\n *\n * // Invisible edges between the regularization filters\n * edge[style=invis];\n * Positivity -> MotionMask;\n * MotionMask -> TVSpace;\n * TVSpace -> Wavelets;\n * Wavelets -> Warp;\n * Warp -> TVTime;\n * TVTime -> L0Time;\n * L0Time -> TNV;\n * TNV -> Unwarp;\n *\n * InputInverseDisplacementField -> Subtract;\n * }\n * \\enddot\n *\n * \\test rtkfourdroostertest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT FourDROOSTERConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FourDROOSTERConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = FourDROOSTERConeBeamReconstructionFilter;\n  using Superclass = rtk::IterativeConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using VolumeType = ProjectionStackType;\n  using CovariantVectorForSpatialGradient =\n    itk::CovariantVector<typename VolumeSeriesType::ValueType, VolumeSeriesType::ImageDimension - 1>;\n  using CovariantVectorForTemporalGradient = itk::CovariantVector<typename VolumeSeriesType::ValueType, 1>;\n  using DVFVectorType = CovariantVectorForSpatialGradient;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUVolumeSeriesType =\n    typename itk::Image<typename VolumeSeriesType::PixelType, VolumeSeriesType::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using SpatialGradientImageType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                itk::Image<CovariantVectorForSpatialGradient, VolumeSeriesType::ImageDimension>,\n                                itk::CudaImage<CovariantVectorForSpatialGradient, VolumeSeriesType::ImageDimension>>;\n  using TemporalGradientImageType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                itk::Image<CovariantVectorForTemporalGradient, VolumeSeriesType::ImageDimension>,\n                                itk::CudaImage<CovariantVectorForTemporalGradient, VolumeSeriesType::ImageDimension>>;\n  using DVFSequenceImageType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>,\n                                itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension>>;\n  using DVFImageType = typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                                   itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension - 1>,\n                                                   itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension - 1>>;\n  using AverageOutOfROIFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                AverageOutOfROIImageFilter<VolumeSeriesType, VolumeType>,\n                                CudaAverageOutOfROIImageFilter>;\n  using TemporalTVDenoisingFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                TotalVariationDenoisingBPDQImageFilter<VolumeSeriesType, TemporalGradientImageType>,\n                                CudaLastDimensionTVDenoisingImageFilter>;\n#else\n  using SpatialGradientImageType = itk::Image<CovariantVectorForSpatialGradient, VolumeSeriesType::ImageDimension>;\n  using TemporalGradientImageType = itk::Image<CovariantVectorForTemporalGradient, VolumeSeriesType::ImageDimension>;\n  using DVFSequenceImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension - 1>;\n  using AverageOutOfROIFilterType = AverageOutOfROIImageFilter<VolumeSeriesType, VolumeType>;\n  using TemporalTVDenoisingFilterType =\n    TotalVariationDenoisingBPDQImageFilter<VolumeSeriesType, TemporalGradientImageType>;\n#endif\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(FourDROOSTERConeBeamReconstructionFilter);\n\n  /** The 4D image to be updated.*/\n  void\n  SetInputVolumeSeries(const VolumeSeriesType * VolumeSeries);\n  typename VolumeSeriesType::ConstPointer\n  GetInputVolumeSeries();\n\n  /** The stack of measured projections */\n  void\n  SetInputProjectionStack(const ProjectionStackType * Projection);\n  typename ProjectionStackType::Pointer\n  GetInputProjectionStack();\n\n  /** The region of interest outside of which all movement is removed */\n  void\n  SetMotionMask(const VolumeType * mask);\n  typename VolumeType::Pointer\n  GetMotionMask();\n\n  /** The motion vector fields used to warp the sequence before and after TV denoising along time */\n  void\n  SetDisplacementField(const DVFSequenceImageType * DVFs);\n  void\n  SetInverseDisplacementField(const DVFSequenceImageType * DVFs);\n  typename DVFSequenceImageType::Pointer\n  GetDisplacementField();\n  typename DVFSequenceImageType::Pointer\n  GetInverseDisplacementField();\n\n  using FourDCGFilterType =\n    rtk::FourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  using ThresholdFilterType = itk::ThresholdImageFilter<VolumeSeriesType>;\n  using ResampleFilterType = itk::ResampleImageFilter<VolumeType, VolumeType>;\n  using SpatialTVDenoisingFilterType = rtk::TotalVariationDenoiseSequenceImageFilter<VolumeSeriesType>;\n  using SpatialWaveletsDenoisingFilterType = rtk::DaubechiesWaveletsDenoiseSequenceImageFilter<VolumeSeriesType>;\n  using WarpSequenceFilterType =\n    rtk::WarpSequenceImageFilter<VolumeSeriesType, DVFSequenceImageType, VolumeType, DVFImageType>;\n  using UnwarpSequenceFilterType =\n    rtk::UnwarpSequenceImageFilter<VolumeSeriesType, DVFSequenceImageType, VolumeType, DVFImageType>;\n  using SubtractFilterType = itk::SubtractImageFilter<VolumeSeriesType, VolumeSeriesType>;\n  using AddFilterType = itk::AddImageFilter<VolumeSeriesType, VolumeSeriesType>;\n  using TemporalL0DenoisingFilterType = rtk::LastDimensionL0GradientDenoisingImageFilter<VolumeSeriesType>;\n  using TNVDenoisingFilterType =\n    rtk::TotalNuclearVariationDenoisingBPDQImageFilter<VolumeSeriesType, SpatialGradientImageType>;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** Pass the interpolation weights to SingleProjectionToFourDFilter */\n  virtual void\n  SetWeights(const itk::Array2D<float> _arg);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\n  // Regularization steps to perform\n  itkSetMacro(PerformPositivity, bool);\n  itkGetMacro(PerformPositivity, bool);\n  itkSetMacro(PerformMotionMask, bool);\n  itkGetMacro(PerformMotionMask, bool);\n  itkSetMacro(PerformTVSpatialDenoising, bool);\n  itkGetMacro(PerformTVSpatialDenoising, bool);\n  itkSetMacro(PerformWaveletsSpatialDenoising, bool);\n  itkGetMacro(PerformWaveletsSpatialDenoising, bool);\n  itkSetMacro(PerformWarping, bool);\n  itkGetMacro(PerformWarping, bool);\n  itkSetMacro(PerformTVTemporalDenoising, bool);\n  itkGetMacro(PerformTVTemporalDenoising, bool);\n  itkSetMacro(PerformL0TemporalDenoising, bool);\n  itkGetMacro(PerformL0TemporalDenoising, bool);\n  itkSetMacro(PerformTNVDenoising, bool);\n  itkGetMacro(PerformTNVDenoising, bool);\n  itkSetMacro(ComputeInverseWarpingByConjugateGradient, bool);\n  itkGetMacro(ComputeInverseWarpingByConjugateGradient, bool);\n  itkSetMacro(UseNearestNeighborInterpolationInWarping, bool);\n  itkGetMacro(UseNearestNeighborInterpolationInWarping, bool);\n  itkGetMacro(CudaConjugateGradient, bool);\n  itkSetMacro(CudaConjugateGradient, bool);\n\n  /** Set and Get for the UseCudaCyclicDeformation variable */\n  itkSetMacro(UseCudaCyclicDeformation, bool);\n  itkGetMacro(UseCudaCyclicDeformation, bool);\n\n  // Regularization parameters\n  itkSetMacro(GammaTVSpace, float);\n  itkGetMacro(GammaTVSpace, float);\n  itkSetMacro(GammaTVTime, float);\n  itkGetMacro(GammaTVTime, float);\n  itkSetMacro(GammaTNV, float);\n  itkGetMacro(GammaTNV, float);\n  itkSetMacro(LambdaL0Time, float);\n  itkGetMacro(LambdaL0Time, float);\n  itkSetMacro(SoftThresholdWavelets, float);\n  itkGetMacro(SoftThresholdWavelets, float);\n  itkSetMacro(PhaseShift, float);\n  itkGetMacro(PhaseShift, float);\n\n  /** Set the number of levels of the wavelets decomposition */\n  itkGetMacro(NumberOfLevels, unsigned int);\n  itkSetMacro(NumberOfLevels, unsigned int);\n\n  /** Sets the order of the Daubechies wavelet used to deconstruct/reconstruct the image pyramid */\n  itkGetMacro(Order, unsigned int);\n  itkSetMacro(Order, unsigned int);\n\n  // Iterations\n  itkSetMacro(MainLoop_iterations, int);\n  itkGetMacro(MainLoop_iterations, int);\n  itkSetMacro(CG_iterations, int);\n  itkGetMacro(CG_iterations, int);\n  itkSetMacro(TV_iterations, int);\n  itkGetMacro(TV_iterations, int);\n  itkSetMacro(L0_iterations, int);\n  itkGetMacro(L0_iterations, int);\n\n  // Geometry\n  itkSetConstObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkGetConstObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Store the phase signal in a member variable */\n  virtual void\n  SetSignal(const std::vector<double> signal);\n\nprotected:\n  FourDROOSTERConeBeamReconstructionFilter();\n  ~FourDROOSTERConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  // Inputs are not supposed to occupy the same physical space,\n  // so there is nothing to verify\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename FourDCGFilterType::Pointer                  m_FourDCGFilter;\n  typename ThresholdFilterType::Pointer                m_PositivityFilter;\n  typename ResampleFilterType::Pointer                 m_ResampleFilter;\n  typename AverageOutOfROIFilterType::Pointer          m_AverageOutOfROIFilter;\n  typename SpatialTVDenoisingFilterType::Pointer       m_TVDenoisingSpace;\n  typename SpatialWaveletsDenoisingFilterType::Pointer m_WaveletsDenoisingSpace;\n  typename WarpSequenceFilterType::Pointer             m_Warp;\n  typename TemporalTVDenoisingFilterType::Pointer      m_TVDenoisingTime;\n  typename UnwarpSequenceFilterType::Pointer           m_Unwarp;\n  typename WarpSequenceFilterType::Pointer             m_InverseWarp;\n  typename SubtractFilterType::Pointer                 m_SubtractFilter;\n  typename AddFilterType::Pointer                      m_AddFilter;\n  typename TemporalL0DenoisingFilterType::Pointer      m_L0DenoisingTime;\n  typename TNVDenoisingFilterType::Pointer             m_TNVDenoising;\n\n  // Booleans :\n  // should warping be performed ?\n  // should conjugate gradient be performed on GPU ?\n  // should wavelets replace TV in spatial denoising ?\n  bool m_PerformPositivity;\n  bool m_PerformMotionMask;\n  bool m_PerformTVSpatialDenoising;\n  bool m_PerformWaveletsSpatialDenoising;\n  bool m_PerformWarping;\n  bool m_PerformTVTemporalDenoising;\n  bool m_PerformL0TemporalDenoising;\n  bool m_PerformTNVDenoising;\n  bool m_ComputeInverseWarpingByConjugateGradient;\n  bool m_UseNearestNeighborInterpolationInWarping; // Default is false, linear interpolation is used instead\n  bool m_CudaConjugateGradient;\n  bool m_UseCudaCyclicDeformation;\n  bool m_DisableDisplacedDetectorFilter;\n\n  // Regularization parameters\n  float m_GammaTVSpace;\n  float m_GammaTVTime;\n  float m_GammaTNV;\n  float m_LambdaL0Time;\n  float m_SoftThresholdWavelets;\n  float m_PhaseShift;\n  bool  m_DimensionsProcessedForTVSpace[VolumeSeriesType::ImageDimension];\n  bool  m_DimensionsProcessedForTVTime[VolumeSeriesType::ImageDimension];\n\n  typename itk::ImageToImageFilter<VolumeSeriesType, VolumeSeriesType>::Pointer m_DownstreamFilter;\n\n  /** Information for the wavelets denoising filter */\n  unsigned int m_Order;\n  unsigned int m_NumberOfLevels;\n\n  // Iterations\n  int m_MainLoop_iterations;\n  int m_CG_iterations;\n  int m_TV_iterations;\n  int m_L0_iterations;\n\n  // Geometry\n  typename rtk::ThreeDCircularProjectionGeometry::ConstPointer m_Geometry;\n\n  // Signal\n  std::vector<double> m_Signal;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFourDROOSTERConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFourDROOSTERConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkFourDROOSTERConeBeamReconstructionFilter_hxx\n#define rtkFourDROOSTERConeBeamReconstructionFilter_hxx\n\n#include <itkImageFileWriter.h>\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType,\n                                         ProjectionStackType>::FourDROOSTERConeBeamReconstructionFilter()\n{\n  //   this->SetNumberOfRequiredInputs(2);\n\n  // Set the default values of member parameters\n  m_GammaTVSpace = 0.00005;\n  m_GammaTVTime = 0.0002;\n  m_GammaTNV = 0.0002;\n  m_LambdaL0Time = 0.005;\n  m_SoftThresholdWavelets = 0.001;\n\n  m_TV_iterations = 10;\n  m_MainLoop_iterations = 10;\n  m_CG_iterations = 4;\n  m_L0_iterations = 5;\n\n  // Default pipeline: 4DCG, positivity, motion mask, spatial TV, temporal TV\n  m_PerformPositivity = true;\n  m_PerformMotionMask = true;\n  m_PerformTVSpatialDenoising = true;\n  m_PerformWaveletsSpatialDenoising = false;\n  m_PerformWarping = false;\n  m_PerformTVTemporalDenoising = true;\n  m_PerformL0TemporalDenoising = false;\n  m_PerformTNVDenoising = false;\n  m_ComputeInverseWarpingByConjugateGradient = true;\n\n  // Other parameters\n  m_UseNearestNeighborInterpolationInWarping = false;\n  m_PhaseShift = 0;\n  m_CudaConjugateGradient = false; // 4D volumes of usual size only fit on the largest GPUs\n  m_UseCudaCyclicDeformation = false;\n  m_Order = 5;\n  m_NumberOfLevels = 3;\n  m_DisableDisplacedDetectorFilter = false;\n\n  // Create the filters\n  m_FourDCGFilter = FourDCGFilterType::New();\n  m_PositivityFilter = ThresholdFilterType::New();\n  m_ResampleFilter = ResampleFilterType::New();\n  m_AverageOutOfROIFilter = AverageOutOfROIFilterType::New();\n  m_TVDenoisingTime = TemporalTVDenoisingFilterType::New();\n  m_TVDenoisingSpace = SpatialTVDenoisingFilterType::New();\n  m_WaveletsDenoisingSpace = SpatialWaveletsDenoisingFilterType::New();\n  m_Warp = WarpSequenceFilterType::New();\n  m_Unwarp = UnwarpSequenceFilterType::New();\n  m_InverseWarp = WarpSequenceFilterType::New();\n  m_SubtractFilter = SubtractFilterType::New();\n  m_AddFilter = AddFilterType::New();\n  m_L0DenoisingTime = TemporalL0DenoisingFilterType::New();\n  m_TNVDenoising = TNVDenoisingFilterType::New();\n\n  // Initialize downstream filter\n  m_DownstreamFilter = m_FourDCGFilter;\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetInputVolumeSeries(\n  const VolumeSeriesType * VolumeSeries)\n{\n  this->SetPrimaryInput(const_cast<VolumeSeriesType *>(VolumeSeries));\n  //   this->SetPrimaryInputName(\"VolumeSeries\");\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetInputProjectionStack(\n  const ProjectionStackType * Projection)\n{\n  this->SetInput(\"ProjectionStack\", const_cast<ProjectionStackType *>(Projection));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetMotionMask(const VolumeType * mask)\n{\n  this->SetInput(\"MotionMask\", const_cast<VolumeType *>(mask));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetDisplacementField(\n  const DVFSequenceImageType * DVFs)\n{\n  this->SetInput(\"DisplacementField\", const_cast<DVFSequenceImageType *>(DVFs));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetInverseDisplacementField(\n  const DVFSequenceImageType * DVFs)\n{\n  this->SetInput(\"InverseDisplacementField\", const_cast<DVFSequenceImageType *>(DVFs));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename VolumeSeriesType::ConstPointer\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetInputVolumeSeries()\n{\n  return static_cast<const VolumeSeriesType *>(this->itk::ProcessObject::GetInput(\"Primary\"));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename ProjectionStackType::Pointer\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetInputProjectionStack()\n{\n  return static_cast<ProjectionStackType *>(this->itk::ProcessObject::GetInput(\"ProjectionStack\"));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename FourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::VolumeType::Pointer\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetMotionMask()\n{\n  return static_cast<VolumeType *>(this->itk::ProcessObject::GetInput(\"MotionMask\"));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename FourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::DVFSequenceImageType::Pointer\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetDisplacementField()\n{\n  return static_cast<DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(\"DisplacementField\"));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename FourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::DVFSequenceImageType::Pointer\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetInverseDisplacementField()\n{\n  return static_cast<DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(\"InverseDisplacementField\"));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetWeights(\n  const itk::Array2D<float> _arg)\n{\n  m_FourDCGFilter->SetWeights(_arg);\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n  m_FourDCGFilter->SetSignal(signal);\n  this->m_Signal = signal;\n  this->Modified();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Let the 4DCG subfilters compute the requested regions for the projections\n  // stack and the input volume\n  m_FourDCGFilter->PropagateRequestedRegion(m_FourDCGFilter->GetOutput());\n\n  // Set the requested region to the full input for all regularization steps\n  if (m_PerformMotionMask)\n  {\n    typename VolumeType::Pointer motionMaskPtr = this->GetMotionMask();\n    motionMaskPtr->SetRequestedRegionToLargestPossibleRegion();\n  }\n  else\n  {\n    this->RemoveInput(\"MotionMask\");\n  }\n\n  if (m_PerformWarping)\n  {\n    typename DVFSequenceImageType::Pointer DisplacementFieldPtr = this->GetDisplacementField();\n    DisplacementFieldPtr->SetRequestedRegionToLargestPossibleRegion();\n\n    if (!m_ComputeInverseWarpingByConjugateGradient)\n    {\n      typename DVFSequenceImageType::Pointer InverseDisplacementFieldPtr = this->GetInverseDisplacementField();\n      InverseDisplacementFieldPtr->SetRequestedRegionToLargestPossibleRegion();\n    }\n    else\n    {\n      this->RemoveInput(\"InverseDisplacementField\");\n    }\n  }\n  else\n  {\n    // If the filter is used with m_PerformWarping = true, and then with\n    // m_PerformWarping = false, it keeps requesting a region of the\n    // input DVF, which by default may be larger than the largest\n    // possible region of the DVF (it is the largest possible region of\n    // the first input, and the sizes do not necessarily match).\n    // This occurs, for example, in the fourdroostercudatest.\n    this->RemoveInput(\"DisplacementField\");\n    this->RemoveInput(\"InverseDisplacementField\");\n  }\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateOutputInformation()\n{\n  const int Dimension = VolumeType::ImageDimension;\n\n  // Set projection filters\n  m_FourDCGFilter->SetForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n  m_FourDCGFilter->SetBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n\n  // The 4D conjugate gradient filter is the only part that must be in the pipeline\n  // whatever was the user wants\n  m_FourDCGFilter->SetInputVolumeSeries(this->GetInputVolumeSeries());\n  m_FourDCGFilter->SetInputProjectionStack(this->GetInputProjectionStack());\n  m_FourDCGFilter->SetGeometry(this->m_Geometry);\n  m_FourDCGFilter->SetNumberOfIterations(this->m_CG_iterations);\n  m_FourDCGFilter->SetCudaConjugateGradient(this->GetCudaConjugateGradient());\n  m_FourDCGFilter->SetDisableDisplacedDetectorFilter(m_DisableDisplacedDetectorFilter);\n  m_DownstreamFilter = m_FourDCGFilter;\n\n  // Plug the positivity filter if requested\n  if (m_PerformPositivity)\n  {\n    m_PositivityFilter->SetInPlace(true);\n\n    m_PositivityFilter->SetOutsideValue(0.0);\n    m_PositivityFilter->ThresholdBelow(0.0);\n    m_PositivityFilter->SetInput(m_DownstreamFilter->GetOutput());\n\n    m_DownstreamFilter = m_PositivityFilter;\n  }\n\n  // Etc..\n  if (m_PerformMotionMask)\n  {\n    m_AverageOutOfROIFilter->SetInPlace(true);\n\n    m_AverageOutOfROIFilter->SetInput(m_DownstreamFilter->GetOutput());\n    m_ResampleFilter->SetInput(this->GetMotionMask());\n    m_AverageOutOfROIFilter->SetROI(m_ResampleFilter->GetOutput());\n\n    // Set the resample filter\n    m_ResampleFilter->SetInterpolator(itk::NearestNeighborInterpolateImageFunction<VolumeType, double>::New());\n    m_ResampleFilter->SetTransform(itk::IdentityTransform<double, Dimension>::New());\n    typename VolumeType::SizeType      VolumeSize;\n    typename VolumeType::SpacingType   VolumeSpacing;\n    typename VolumeType::PointType     VolumeOrigin;\n    typename VolumeType::DirectionType VolumeDirection;\n    VolumeSize.Fill(0);\n    VolumeSpacing.Fill(0);\n    VolumeOrigin.Fill(0);\n    VolumeDirection.Fill(0);\n    for (int i = 0; i < Dimension; i++)\n    {\n      VolumeSize[i] = this->GetInputVolumeSeries()->GetLargestPossibleRegion().GetSize()[i];\n      VolumeSpacing[i] = this->GetInputVolumeSeries()->GetSpacing()[i];\n      VolumeOrigin[i] = this->GetInputVolumeSeries()->GetOrigin()[i];\n      for (int j = 0; j < Dimension; j++)\n      {\n        VolumeDirection(i, j) = this->GetInputVolumeSeries()->GetDirection()(i, j);\n      }\n    }\n    m_ResampleFilter->SetSize(VolumeSize);\n    m_ResampleFilter->SetOutputSpacing(VolumeSpacing);\n    m_ResampleFilter->SetOutputOrigin(VolumeOrigin);\n    m_ResampleFilter->SetOutputDirection(VolumeDirection);\n\n    m_DownstreamFilter = m_AverageOutOfROIFilter;\n  }\n\n  if (m_PerformTVSpatialDenoising)\n  {\n    m_DownstreamFilter->ReleaseDataFlagOn();\n\n    m_TVDenoisingSpace->SetInput(m_DownstreamFilter->GetOutput());\n    m_TVDenoisingSpace->SetNumberOfIterations(this->m_TV_iterations);\n    m_TVDenoisingSpace->SetGamma(this->m_GammaTVSpace);\n    m_DimensionsProcessedForTVSpace[0] = true;\n    m_DimensionsProcessedForTVSpace[1] = true;\n    m_DimensionsProcessedForTVSpace[2] = true;\n    m_DimensionsProcessedForTVSpace[3] = false;\n    m_TVDenoisingSpace->SetDimensionsProcessed(this->m_DimensionsProcessedForTVSpace);\n\n    m_DownstreamFilter = m_TVDenoisingSpace;\n  }\n\n  if (m_PerformWaveletsSpatialDenoising)\n  {\n    m_DownstreamFilter->ReleaseDataFlagOn();\n\n    m_WaveletsDenoisingSpace->SetInput(m_DownstreamFilter->GetOutput());\n    m_WaveletsDenoisingSpace->SetOrder(m_Order);\n    m_WaveletsDenoisingSpace->SetThreshold(m_SoftThresholdWavelets);\n    m_WaveletsDenoisingSpace->SetNumberOfLevels(m_NumberOfLevels);\n\n    m_DownstreamFilter = m_WaveletsDenoisingSpace;\n  }\n\n  if (m_PerformWarping)\n  {\n    m_DownstreamFilter->ReleaseDataFlagOff();\n\n    m_Warp->SetInput(m_DownstreamFilter->GetOutput());\n    m_Warp->SetDisplacementField(this->GetDisplacementField());\n    m_Warp->SetPhaseShift(m_PhaseShift);\n    m_Warp->SetUseNearestNeighborInterpolationInWarping(m_UseNearestNeighborInterpolationInWarping);\n    m_Warp->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n\n    m_DownstreamFilter = m_Warp;\n  }\n\n  if (m_PerformTVTemporalDenoising)\n  {\n    m_DownstreamFilter->ReleaseDataFlagOff();\n\n    if (m_PerformWarping && !m_ComputeInverseWarpingByConjugateGradient)\n      m_TVDenoisingTime->SetInPlace(false);\n    else\n      m_TVDenoisingTime->SetInPlace(true);\n\n    m_TVDenoisingTime->SetInput(m_DownstreamFilter->GetOutput());\n    m_TVDenoisingTime->SetNumberOfIterations(this->m_TV_iterations);\n    m_TVDenoisingTime->SetGamma(this->m_GammaTVTime);\n    m_DimensionsProcessedForTVTime[0] = false;\n    m_DimensionsProcessedForTVTime[1] = false;\n    m_DimensionsProcessedForTVTime[2] = false;\n    m_DimensionsProcessedForTVTime[3] = true;\n    m_TVDenoisingTime->SetDimensionsProcessed(this->m_DimensionsProcessedForTVTime);\n    m_TVDenoisingTime->SetBoundaryConditionToPeriodic();\n\n    m_DownstreamFilter = m_TVDenoisingTime;\n  }\n\n  if (m_PerformL0TemporalDenoising)\n  {\n    m_DownstreamFilter->ReleaseDataFlagOff();\n\n    if (m_PerformWarping && !m_ComputeInverseWarpingByConjugateGradient && !m_PerformTVTemporalDenoising)\n      m_L0DenoisingTime->SetInPlace(false);\n    else\n      m_L0DenoisingTime->SetInPlace(true);\n\n    m_L0DenoisingTime->SetInPlace(false);\n\n    m_L0DenoisingTime->SetInput(m_DownstreamFilter->GetOutput());\n    m_L0DenoisingTime->SetNumberOfIterations(this->m_L0_iterations);\n    m_L0DenoisingTime->SetLambda(this->m_LambdaL0Time);\n\n    m_DownstreamFilter = m_L0DenoisingTime;\n  }\n\n  if (m_PerformTNVDenoising)\n  {\n    m_DownstreamFilter->ReleaseDataFlagOff();\n\n    if (m_PerformWarping && !m_ComputeInverseWarpingByConjugateGradient && !m_PerformTVTemporalDenoising &&\n        !m_PerformL0TemporalDenoising)\n      m_TNVDenoising->SetInPlace(false);\n    else\n      m_TNVDenoising->SetInPlace(true);\n\n    m_TNVDenoising->SetInput(m_DownstreamFilter->GetOutput());\n    m_TNVDenoising->SetNumberOfIterations(this->m_TV_iterations);\n    m_TNVDenoising->SetGamma(this->m_GammaTNV);\n\n    m_DownstreamFilter = m_TNVDenoising;\n  }\n\n  if (m_PerformWarping)\n  {\n    if (m_ComputeInverseWarpingByConjugateGradient)\n    {\n      m_DownstreamFilter->ReleaseDataFlagOn();\n\n      m_Unwarp->SetNumberOfIterations(4);\n      m_Unwarp->SetInput(m_DownstreamFilter->GetOutput());\n      m_Unwarp->SetDisplacementField(this->GetDisplacementField());\n      m_Unwarp->SetPhaseShift(m_PhaseShift);\n      m_Unwarp->SetUseNearestNeighborInterpolationInWarping(m_UseNearestNeighborInterpolationInWarping);\n      m_Unwarp->SetCudaConjugateGradient(this->GetCudaConjugateGradient());\n      m_Unwarp->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n\n      m_DownstreamFilter = m_Unwarp;\n    }\n    else\n    {\n      m_DownstreamFilter->ReleaseDataFlagOff();\n\n      // Compute the correction performed by temporal TV and/or temporal L0 and/or TNV\n      m_SubtractFilter->SetInput1(m_DownstreamFilter->GetOutput());\n      m_SubtractFilter->SetInput2(m_Warp->GetOutput());\n\n      // Deform only that correction with the inverse field\n      m_InverseWarp->SetInput(0, m_SubtractFilter->GetOutput());\n      m_InverseWarp->SetDisplacementField(this->GetInverseDisplacementField());\n      m_InverseWarp->SetPhaseShift(m_PhaseShift);\n      m_InverseWarp->SetUseNearestNeighborInterpolationInWarping(m_UseNearestNeighborInterpolationInWarping);\n      m_InverseWarp->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n\n      // Add the deformed correction to the spatially denoised image to get the output\n      m_AddFilter->SetInput1(m_InverseWarp->GetOutput());\n      m_AddFilter->SetInput2(m_Warp->GetInput());\n\n      m_DownstreamFilter = m_AddFilter;\n\n      m_Warp->ReleaseDataFlagOff();\n      m_SubtractFilter->ReleaseDataFlagOn();\n      m_InverseWarp->ReleaseDataFlagOn();\n      m_AddFilter->ReleaseDataFlagOff();\n    }\n  }\n\n  // Have the last filter calculate its output information\n  m_DownstreamFilter->ReleaseDataFlagOff();\n  m_DownstreamFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_DownstreamFilter->GetOutput());\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateData()\n{\n  // Declare the pointer that will be used to plug the output back as input\n  typename VolumeSeriesType::Pointer pimg;\n\n  itk::IterationReporter iterationReporter(this, 0, 1);\n\n  for (int i = 0; i < m_MainLoop_iterations; i++)\n  {\n    // After the first iteration, we need to use the output as input\n    if (i > 0)\n    {\n      pimg = m_DownstreamFilter->GetOutput();\n\n      pimg->DisconnectPipeline();\n      m_FourDCGFilter->SetInputVolumeSeries(pimg);\n\n      // The input volume is no longer needed on the GPU, so we transfer it back to the CPU\n      this->GetInputVolumeSeries()->GetBufferPointer();\n    }\n\n    m_DownstreamFilter->Update();\n    this->GraftOutput(m_DownstreamFilter->GetOutput());\n    iterationReporter.CompletedStep();\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkFourDReconstructionConjugateGradientOperator.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkFourDReconstructionConjugateGradientOperator_h\n#define rtkFourDReconstructionConjugateGradientOperator_h\n\n#include \"rtkConjugateGradientOperator.h\"\n\n#include <itkArray2D.h>\n#include <itkMultiplyImageFilter.h>\n\n#include \"rtkConstantImageSource.h\"\n#include \"rtkInterpolatorWithKnownWeightsImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkSplatWithKnownWeightsImageFilter.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaInterpolateImageFilter.h\"\n#  include \"rtkCudaSplatImageFilter.h\"\n#  include \"rtkCudaConstantVolumeSource.h\"\n#  include \"rtkCudaConstantVolumeSeriesSource.h\"\n#  include \"rtkCudaDisplacedDetectorImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class FourDReconstructionConjugateGradientOperator\n * \\brief Implements part of the 4D reconstruction by conjugate gradient\n *\n * See the reference paper: \"Cardiac C-arm computed tomography using\n * a 3D + time ROI reconstruction method with spatial and temporal regularization\"\n * by Mory et al.\n *\n * 4D conjugate gradient reconstruction consists in iteratively\n * minimizing the following cost function:\n *\n * Sum_over_theta || sqrt(D) (R_theta S_theta f - p_theta) ||_2^2\n *\n * with\n * - f a 4D series of 3D volumes, each one being the reconstruction\n * at a given respiratory/cardiac phase\n * - p_theta is the projection measured at angle theta\n * - S_theta an interpolation operator which, from the 3D + time sequence f,\n * estimates the 3D volume through which projection p_theta has been acquired\n * - R_theta is the X-ray transform (the forward projection operator) for angle theta\n * - D the displaced detector weighting matrix\n *\n * Computing the gradient of this cost function yields:\n *\n * S_theta^T R_theta^T D R_theta S_theta f - S_theta^T R_theta^T D p_theta\n *\n * where A^T means the adjoint of operator A.\n *\n * FourDReconstructionConjugateGradientOperator implements S_theta^T R_theta^T D R_theta S_theta.\n * It can be achieved by a FourDToProjectionStackImageFilter followed by\n * a DisplacedDetectorFilter and ProjectionStackToFourDImageFilter (simple implementation), or\n * by assembling the internal pipelines of these filters, and removing\n * the unnecessary filters in the middle (a PasteImageFilter and an ExtractImageFilter), which\n * results in performance gain and easier GPU memory management.\n * The current implementation is the optimized one.\n *\n * \\dot\n * digraph FourDReconstructionConjugateGradientOperator {\n *\n * Input0 [ label=\"Input 0 (Input: 4D sequence of volumes)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (Projection weights)\"];\n * Input2 [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction: 4D sequence of volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * SourceVol [ label=\"rtk::ConstantImageSource (volume)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * SourceVol2 [ label=\"rtk::ConstantImageSource (volume)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * SourceProj [ label=\"rtk::ConstantImageSource (projections)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * Source4D [ label=\"rtk::ConstantImageSource (4D)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ForwardProj [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * Interpolation [ label=\"InterpolatorWithKnownWeightsImageFilter\"\n *                 URL=\"\\ref rtk::InterpolatorWithKnownWeightsImageFilter\"];\n * BackProj [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * Splat [ label=\"rtk::SplatWithKnownWeightsImageFilter\" URL=\"\\ref rtk::SplatWithKnownWeightsImageFilter\"];\n * AfterSplat [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterInput0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterSource4D [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n *\n * Input0 -> Interpolation;\n * SourceVol -> Interpolation;\n * Interpolation -> ForwardProj;\n * SourceVol2 -> BackProj;\n * ForwardProj -> Displaced;\n * Displaced -> BackProj;\n * BackProj -> Splat;\n * Splat -> AfterSplat[arrowhead=none];\n * AfterSplat -> Output;\n * AfterSplat -> AfterSource4D[style=dashed, constraint=false];\n * Source4D -> AfterSource4D[arrowhead=none];\n * AfterSource4D -> Splat;\n * SourceProj -> ForwardProj;\n * }\n * \\enddot\n *\n * \\test rtkfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT FourDReconstructionConjugateGradientOperator\n  : public ConjugateGradientOperator<VolumeSeriesType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FourDReconstructionConjugateGradientOperator);\n\n  /** Standard class type alias. */\n  using Self = FourDReconstructionConjugateGradientOperator;\n  using Superclass = ConjugateGradientOperator<VolumeSeriesType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using VolumeType = ProjectionStackType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(FourDReconstructionConjugateGradientOperator);\n\n  /** Set/Get the 4D image to be updated.*/\n  void\n  SetInputVolumeSeries(const VolumeSeriesType * VolumeSeries);\n  typename VolumeSeriesType::ConstPointer\n  GetInputVolumeSeries();\n\n  /** Set/Get the stack of projections */\n  void\n  SetInputProjectionStack(const ProjectionStackType * Projections);\n  typename ProjectionStackType::ConstPointer\n  GetInputProjectionStack();\n\n  using BackProjectionFilterType = BackProjectionImageFilter<ProjectionStackType, ProjectionStackType>;\n  using ForwardProjectionFilterType = ForwardProjectionImageFilter<ProjectionStackType, ProjectionStackType>;\n  using InterpolationFilterType = InterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>;\n  using SplatFilterType = SplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>;\n  using ConstantVolumeSourceType = ConstantImageSource<VolumeType>;\n  using ConstantProjectionStackSourceType = ConstantImageSource<ProjectionStackType>;\n  using ConstantVolumeSeriesSourceType = ConstantImageSource<VolumeSeriesType>;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUProjectionStackType =\n    typename itk::Image<typename ProjectionStackType::PixelType, ProjectionStackType::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using DisplacedDetectorFilterType =\n    typename std::conditional_t<std::is_same_v<ProjectionStackType, CPUProjectionStackType>,\n                                DisplacedDetectorImageFilter<ProjectionStackType>,\n                                CudaDisplacedDetectorImageFilter>;\n  using CudaInterpolateImageFilterType =\n    typename std::conditional_t<std::is_same_v<ProjectionStackType, CPUProjectionStackType>,\n                                InterpolationFilterType,\n                                CudaInterpolateImageFilter>;\n  using CudaSplatImageFilterType = typename std::\n    conditional_t<std::is_same_v<ProjectionStackType, CPUProjectionStackType>, SplatFilterType, CudaSplatImageFilter>;\n  using CudaConstantVolumeSourceType =\n    typename std::conditional_t<std::is_same_v<ProjectionStackType, CPUProjectionStackType>,\n                                ConstantVolumeSourceType,\n                                CudaConstantVolumeSource>;\n  using CudaConstantVolumeSeriesSourceType =\n    typename std::conditional_t<std::is_same_v<ProjectionStackType, CPUProjectionStackType>,\n                                ConstantVolumeSeriesSourceType,\n                                CudaConstantVolumeSeriesSource>;\n#else\n  using DisplacedDetectorFilterType = DisplacedDetectorImageFilter<ProjectionStackType>;\n  using CudaInterpolateImageFilterType = InterpolationFilterType;\n  using CudaSplatImageFilterType = SplatFilterType;\n  using CudaConstantVolumeSourceType = ConstantVolumeSourceType;\n  using CudaConstantVolumeSeriesSourceType = ConstantVolumeSeriesSourceType;\n#endif\n\n  /** Pass the backprojection filter to ProjectionStackToFourD*/\n  void\n  SetBackProjectionFilter(BackProjectionFilterType * _arg);\n\n  /** Pass the forward projection filter to FourDToProjectionStack */\n  void\n  SetForwardProjectionFilter(ForwardProjectionFilterType * _arg);\n\n  /** Pass the geometry to all filters needing it */\n  itkSetConstObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Use CUDA interpolation/splat filters */\n  itkSetMacro(UseCudaInterpolation, bool);\n  itkGetMacro(UseCudaInterpolation, bool);\n  itkSetMacro(UseCudaSplat, bool);\n  itkGetMacro(UseCudaSplat, bool);\n  itkSetMacro(UseCudaSources, bool);\n  itkGetMacro(UseCudaSources, bool);\n\n  /** Macros that take care of implementing the Get and Set methods for Weights.*/\n  itkGetMacro(Weights, itk::Array2D<float>);\n  itkSetMacro(Weights, itk::Array2D<float>);\n\n  /** Store the phase signal in a member variable */\n  virtual void\n  SetSignal(const std::vector<double> signal);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  FourDReconstructionConjugateGradientOperator();\n  ~FourDReconstructionConjugateGradientOperator() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Builds the pipeline and computes output information */\n  void\n  GenerateOutputInformation() override;\n\n  /** Computes the requested region of input images */\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Initialize the ConstantImageSourceFilter */\n  void\n  InitializeConstantSources();\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename BackProjectionFilterType::Pointer          m_BackProjectionFilter;\n  typename ForwardProjectionFilterType::Pointer       m_ForwardProjectionFilter;\n  typename InterpolationFilterType::Pointer           m_InterpolationFilter;\n  typename SplatFilterType::Pointer                   m_SplatFilter;\n  typename ConstantVolumeSourceType::Pointer          m_ConstantVolumeSource1;\n  typename ConstantVolumeSourceType::Pointer          m_ConstantVolumeSource2;\n  typename ConstantProjectionStackSourceType::Pointer m_ConstantProjectionStackSource;\n  typename ConstantVolumeSeriesSourceType::Pointer    m_ConstantVolumeSeriesSource;\n  typename DisplacedDetectorFilterType::Pointer       m_DisplacedDetectorFilter;\n\n  ThreeDCircularProjectionGeometry::ConstPointer m_Geometry;\n  bool                                           m_UseCudaInterpolation;\n  bool                                           m_UseCudaSplat;\n  bool                                           m_UseCudaSources;\n  itk::Array2D<float>                            m_Weights;\n  std::vector<double>                            m_Signal;\n  bool                                           m_DisableDisplacedDetectorFilter;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFourDReconstructionConjugateGradientOperator.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFourDReconstructionConjugateGradientOperator.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkFourDReconstructionConjugateGradientOperator_hxx\n#define rtkFourDReconstructionConjugateGradientOperator_hxx\n\n#include \"rtkGeneralPurposeFunctions.h\"\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType,\n                                             ProjectionStackType>::FourDReconstructionConjugateGradientOperator()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set default behavior\n  m_UseCudaInterpolation = false;\n  m_UseCudaSplat = false;\n  m_UseCudaSources = false;\n\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n  m_DisableDisplacedDetectorFilter = false;\n\n  // Set memory management flags\n  m_DisplacedDetectorFilter->SetInPlace(true);\n  m_DisplacedDetectorFilter->ReleaseDataFlagOn();\n}\n\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::SetInputVolumeSeries(\n  const VolumeSeriesType * VolumeSeries)\n{\n  this->SetNthInput(0, const_cast<VolumeSeriesType *>(VolumeSeries));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::SetInputProjectionStack(\n  const ProjectionStackType * Projections)\n{\n  this->SetNthInput(1, const_cast<ProjectionStackType *>(Projections));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename VolumeSeriesType::ConstPointer\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::GetInputVolumeSeries()\n{\n  return static_cast<const VolumeSeriesType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename ProjectionStackType::ConstPointer\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::GetInputProjectionStack()\n{\n  return static_cast<const ProjectionStackType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::SetBackProjectionFilter(\n  BackProjectionFilterType * _arg)\n{\n  m_BackProjectionFilter = _arg;\n  this->Modified();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::SetForwardProjectionFilter(\n  ForwardProjectionFilterType * _arg)\n{\n  m_ForwardProjectionFilter = _arg;\n  this->Modified();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n  this->m_Signal = signal;\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::InitializeConstantSources()\n{\n  unsigned int Dimension = 3;\n\n  // Configure the constant volume sources\n  typename VolumeType::SizeType      ConstantVolumeSourceSize;\n  typename VolumeType::SpacingType   ConstantVolumeSourceSpacing;\n  typename VolumeType::PointType     ConstantVolumeSourceOrigin;\n  typename VolumeType::DirectionType ConstantVolumeSourceDirection;\n\n  ConstantVolumeSourceSize.Fill(0);\n  ConstantVolumeSourceSpacing.Fill(0);\n  ConstantVolumeSourceOrigin.Fill(0);\n\n  for (unsigned int i = 0; i < Dimension; i++)\n  {\n    ConstantVolumeSourceSize[i] = GetInputVolumeSeries()->GetLargestPossibleRegion().GetSize()[i];\n    ConstantVolumeSourceSpacing[i] = GetInputVolumeSeries()->GetSpacing()[i];\n    ConstantVolumeSourceOrigin[i] = GetInputVolumeSeries()->GetOrigin()[i];\n  }\n  ConstantVolumeSourceDirection.SetIdentity();\n\n  m_ConstantVolumeSource1->SetOrigin(ConstantVolumeSourceOrigin);\n  m_ConstantVolumeSource1->SetSpacing(ConstantVolumeSourceSpacing);\n  m_ConstantVolumeSource1->SetDirection(ConstantVolumeSourceDirection);\n  m_ConstantVolumeSource1->SetSize(ConstantVolumeSourceSize);\n  m_ConstantVolumeSource1->SetConstant(0.);\n\n  m_ConstantVolumeSource2->SetOrigin(ConstantVolumeSourceOrigin);\n  m_ConstantVolumeSource2->SetSpacing(ConstantVolumeSourceSpacing);\n  m_ConstantVolumeSource2->SetDirection(ConstantVolumeSourceDirection);\n  m_ConstantVolumeSource2->SetSize(ConstantVolumeSourceSize);\n  m_ConstantVolumeSource2->SetConstant(0.);\n\n  // Configure the constant projection stack source\n  m_ConstantProjectionStackSource->SetInformationFromImage(this->GetInputProjectionStack());\n  typename ProjectionStackType::SizeType ConstantProjectionStackSourceSize =\n    this->GetInputProjectionStack()->GetLargestPossibleRegion().GetSize();\n  ConstantProjectionStackSourceSize[Dimension - 1] = 1;\n  m_ConstantProjectionStackSource->SetSize(ConstantProjectionStackSourceSize);\n  m_ConstantProjectionStackSource->SetConstant(0.);\n\n  // Configure the constant volume series source\n  m_ConstantVolumeSeriesSource->SetInformationFromImage(this->GetInputVolumeSeries());\n  m_ConstantVolumeSeriesSource->SetConstant(0.);\n\n  // Configure memory management options\n  m_ConstantProjectionStackSource->ReleaseDataFlagOn();\n  m_ConstantVolumeSeriesSource->ReleaseDataFlagOn();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::GenerateOutputInformation()\n{\n  // Set runtime parameters\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n\n  // Create the interpolation filter and the displaced detector filter\n  // (first on CPU, and overwrite with the GPU version if CUDA requested)\n  m_InterpolationFilter = InterpolationFilterType::New();\n  if (m_UseCudaInterpolation)\n  {\n    if (std::is_same_v<ProjectionStackType, CPUProjectionStackType>)\n      itkGenericExceptionMacro(<< \"UseCudaInterpolation option only available with itk::CudaImage.\");\n    m_InterpolationFilter = CudaInterpolateImageFilterType::New();\n  }\n\n  // Create the splat filter (first on CPU, and overwrite with the GPU version if CUDA requested)\n  m_SplatFilter = SplatFilterType::New();\n  if (m_UseCudaSplat)\n  {\n    if (std::is_same_v<ProjectionStackType, CPUProjectionStackType>)\n      itkGenericExceptionMacro(<< \"UseCudaSplat option only available with itk::CudaImage.\");\n    m_SplatFilter = CudaSplatImageFilterType::New();\n  }\n\n  // Create the constant sources (first on CPU, and overwrite with the GPU version if CUDA requested)\n  m_ConstantVolumeSource1 = ConstantVolumeSourceType::New();\n  m_ConstantVolumeSource2 = ConstantVolumeSourceType::New();\n  m_ConstantProjectionStackSource = ConstantProjectionStackSourceType::New();\n  m_ConstantVolumeSeriesSource = ConstantVolumeSeriesSourceType::New();\n  if (m_UseCudaSources)\n  {\n    if (std::is_same_v<ProjectionStackType, CPUProjectionStackType>)\n      itkGenericExceptionMacro(<< \"UseCudaSources option only available with itk::CudaImage.\");\n    m_ConstantVolumeSource1 = CudaConstantVolumeSourceType::New();\n    m_ConstantVolumeSource2 = CudaConstantVolumeSourceType::New();\n    m_ConstantProjectionStackSource = CudaConstantVolumeSourceType::New();\n    m_ConstantVolumeSeriesSource = CudaConstantVolumeSeriesSourceType::New();\n  }\n\n  // Initialize sources\n  this->InitializeConstantSources();\n\n  // Set runtime connections\n  m_InterpolationFilter->SetInputVolume(m_ConstantVolumeSource1->GetOutput());\n  m_InterpolationFilter->SetInputVolumeSeries(this->GetInputVolumeSeries());\n\n  m_ForwardProjectionFilter->SetInput(0, m_ConstantProjectionStackSource->GetOutput());\n  m_ForwardProjectionFilter->SetInput(1, m_InterpolationFilter->GetOutput());\n\n  m_DisplacedDetectorFilter->SetInput(m_ForwardProjectionFilter->GetOutput());\n\n  m_BackProjectionFilter->SetInput(0, m_ConstantVolumeSource2->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_DisplacedDetectorFilter->GetOutput());\n  m_BackProjectionFilter->SetInPlace(false);\n\n  m_SplatFilter->SetInputVolumeSeries(m_ConstantVolumeSeriesSource->GetOutput());\n  m_SplatFilter->SetInputVolume(m_BackProjectionFilter->GetOutput());\n\n  m_InterpolationFilter->SetWeights(m_Weights);\n  m_SplatFilter->SetWeights(m_Weights);\n  m_InterpolationFilter->SetProjectionNumber(0);\n  m_SplatFilter->SetProjectionNumber(0);\n\n  // Set geometry\n  m_BackProjectionFilter->SetGeometry(this->m_Geometry.GetPointer());\n  m_ForwardProjectionFilter->SetGeometry(this->m_Geometry);\n  m_DisplacedDetectorFilter->SetGeometry(this->m_Geometry);\n\n  // Have the last filter calculate its output information\n  m_SplatFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_SplatFilter->GetOutput());\n}\n\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::GenerateInputRequestedRegion()\n{\n  // Let the internal filters compute the input requested region\n  m_SplatFilter->PropagateRequestedRegion(m_SplatFilter->GetOutput());\n  this->m_ForwardProjectionFilter->PropagateRequestedRegion(this->m_ForwardProjectionFilter->GetOutput());\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::GenerateData()\n{\n  int Dimension = ProjectionStackType::ImageDimension;\n\n  // Prepare the index for the constant projection stack source\n  typename ProjectionStackType::RegionType sourceRegion = this->GetInputProjectionStack()->GetLargestPossibleRegion();\n  typename ProjectionStackType::SizeType   sourceSize = sourceRegion.GetSize();\n  typename ProjectionStackType::IndexType  sourceIndex = sourceRegion.GetIndex();\n\n  int NumberProjs = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  int FirstProj = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n\n  // Divide the stack of projections into slabs of projections of identical phase\n  std::vector<int>          firstProjectionInSlabs;\n  std::vector<unsigned int> sizeOfSlabs;\n  firstProjectionInSlabs.push_back(FirstProj);\n  if (NumberProjs == 1)\n    sizeOfSlabs.push_back(1);\n  else\n  {\n    for (int proj = FirstProj + 1; proj < FirstProj + NumberProjs; proj++)\n    {\n      if (itk::Math::abs(m_Signal[proj] - m_Signal[proj - 1]) > 1e-4)\n      {\n        // Compute the number of projections in the current slab\n        sizeOfSlabs.push_back(proj - firstProjectionInSlabs[firstProjectionInSlabs.size() - 1]);\n\n        // Update the index of the first projection in the next slab\n        firstProjectionInSlabs.push_back(proj);\n      }\n    }\n    sizeOfSlabs.push_back(NumberProjs - firstProjectionInSlabs[firstProjectionInSlabs.size() - 1]);\n  }\n\n  bool                               firstSlabProcessed = false;\n  typename VolumeSeriesType::Pointer pimg;\n\n  // Process the projections in order\n  for (unsigned int slab = 0; slab < firstProjectionInSlabs.size(); slab++)\n  {\n    // Set the projection stack source\n    sourceIndex[Dimension - 1] = firstProjectionInSlabs[slab];\n    sourceSize[Dimension - 1] = sizeOfSlabs[slab];\n    this->m_ConstantProjectionStackSource->SetIndex(sourceIndex);\n    this->m_ConstantProjectionStackSource->SetSize(sourceSize);\n\n    // Set the Interpolation filter\n    m_InterpolationFilter->SetProjectionNumber(firstProjectionInSlabs[slab]);\n    m_SplatFilter->SetProjectionNumber(firstProjectionInSlabs[slab]);\n\n    // After the first update, we need to use the output as input.\n    if (firstSlabProcessed)\n    {\n      pimg = this->m_SplatFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      this->m_SplatFilter->SetInputVolumeSeries(pimg);\n    }\n\n    // Update the last filter\n    m_SplatFilter->Update();\n\n    // Update condition\n    firstSlabProcessed = true;\n  }\n\n  // Graft its output\n  this->GraftOutput(m_SplatFilter->GetOutput());\n\n  // Release the data in internal filters\n  pimg->ReleaseData();\n  m_ConstantVolumeSource1->GetOutput()->ReleaseData();\n  m_ConstantVolumeSource2->GetOutput()->ReleaseData();\n  m_ConstantVolumeSeriesSource->GetOutput()->ReleaseData();\n  m_ConstantProjectionStackSource->GetOutput()->ReleaseData();\n  m_DisplacedDetectorFilter->GetOutput()->ReleaseData();\n  m_InterpolationFilter->GetOutput()->ReleaseData();\n  m_BackProjectionFilter->GetOutput()->ReleaseData();\n  m_ForwardProjectionFilter->GetOutput()->ReleaseData();\n\n  // Send the input back onto the CPU\n  this->GetInputVolumeSeries()->GetBufferPointer();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkFourDSARTConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFourDSARTConeBeamReconstructionFilter_h\n#define rtkFourDSARTConeBeamReconstructionFilter_h\n\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkAddImageAdaptor.h>\n#include <itkAddImageFilter.h>\n#include <itkDivideOrZeroOutImageFilter.h>\n#include <itkThresholdImageFilter.h>\n\n#include \"rtkRayBoxIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n#include \"rtkProjectionStackToFourDImageFilter.h\"\n#include \"rtkFourDToProjectionStackImageFilter.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class FourDSARTConeBeamReconstructionFilter\n * \\brief Implements the 4D Simultaneous Algebraic Reconstruction Technique\n *\n * FourDSARTConeBeamReconstructionFilter is a composite filter. The pipeline\n * is essentially the same as in SARTConeBeamReconstructionFilter, with\n * the ForwardProjectionImageFilter replaced by 4DToProjectionStackImageFilter\n * and the BackProjectionImageFilter replaced by ProjectionStackTo4DImageFilter.\n *\n * \\dot\n * digraph FourDSARTConeBeamReconstructionFilter {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * FourDToProjectionStack [ label=\"rtk::FourDToProjectionStackImageFilter\"\n *                          URL=\"\\ref rtk::FourDToProjectionStackImageFilter\"];\n * Extract [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n * MultiplyByZero [ label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * AfterExtract [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * MultiplyByLambda [ label=\"itk::MultiplyImageFilter (by lambda)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * Divide [ label=\"itk::DivideOrZeroOutImageFilter\" URL=\"\\ref itk::DivideOrZeroOutImageFilter\"];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n * ConstantProjectionStack [ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ExtractConstantProjection [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n * RayBox [ label=\"rtk::RayBoxIntersectionImageFilter\" URL=\"\\ref rtk::RayBoxIntersectionImageFilter\"];\n * ConstantVolume [ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ProjectionStackToFourD [ label=\"rtk::ProjectionStackToFourDImageFilter\"\n *                          URL=\"\\ref rtk::ProjectionStackToFourDImageFilter\"];\n * Add [ label=\"itk::AddImageFilter (accumulates corrections)\" URL=\"\\ref itk::AddImageFilter\"];\n * Add2 [ label=\"itk::AddImageFilter (adds correction to current 4D volume)\" URL=\"\\ref itk::AddImageFilter\"];\n * OutofInput0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Threshold [ label=\"itk::ThresholdImageFilter\" URL=\"\\ref itk::ThresholdImageFilter\"];\n * OutofThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * OutofBP [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * BeforeAdd [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * BeforeAdd2 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Input0 -> OutofInput0 [arrowhead=none];\n * OutofInput0 -> FourDToProjectionStack;\n * OutofInput0 -> Add2;\n * BeforeAdd -> Add;\n * ConstantVolume -> BeforeAdd [arrowhead=none];\n * OutofInput0 -> ProjectionStackToFourD;\n * Extract -> AfterExtract[arrowhead=none];\n * AfterExtract -> MultiplyByZero;\n * AfterExtract -> Subtract;\n * MultiplyByZero -> FourDToProjectionStack;\n * Input1 -> Extract;\n * FourDToProjectionStack -> Subtract;\n * Subtract -> MultiplyByLambda;\n * MultiplyByLambda -> Divide;\n * ConstantProjectionStack -> ExtractConstantProjection;\n * ExtractConstantProjection -> RayBox;\n * RayBox -> Divide;\n * Divide -> Displaced;\n * Displaced -> ProjectionStackToFourD;\n * ProjectionStackToFourD -> Add;\n * Add -> BeforeAdd2 [arrowhead=none];\n * BeforeAdd2 -> Add2;\n * BeforeAdd2 -> BeforeAdd [style=dashed, constraint=false];\n * Add2 -> Threshold;\n * Threshold -> OutofThreshold [arrowhead=none];\n * OutofThreshold -> OutofInput0 [headport=\"se\", style=dashed];\n * OutofThreshold -> Output;\n * }\n * \\enddot\n *\n * \\test rtkfourdsarttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT FourDSARTConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FourDSARTConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = FourDSARTConeBeamReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = VolumeSeriesType;\n  using OutputImageType = VolumeSeriesType;\n  using VolumeType = ProjectionStackType;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using ExtractFilterType = itk::ExtractImageFilter<ProjectionStackType, ProjectionStackType>;\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<ProjectionStackType, ProjectionStackType>;\n  using FourDToProjectionStackFilterType =\n    rtk::FourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>;\n  using SubtractFilterType = itk::SubtractImageFilter<ProjectionStackType, ProjectionStackType>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<ProjectionStackType, ProjectionStackType, ProjectionStackType>;\n  using AddFilterType = itk::AddImageFilter<VolumeSeriesType, VolumeSeriesType>;\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<VolumeType, VolumeType>;\n  using ProjectionStackToFourDFilterType =\n    rtk::ProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>;\n  using RayBoxIntersectionFilterType = rtk::RayBoxIntersectionImageFilter<ProjectionStackType, ProjectionStackType>;\n  using DivideFilterType =\n    itk::DivideOrZeroOutImageFilter<ProjectionStackType, ProjectionStackType, ProjectionStackType>;\n  using DisplacedDetectorFilterType = rtk::DisplacedDetectorImageFilter<ProjectionStackType>;\n  using ConstantVolumeSeriesSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n  using ConstantProjectionStackSourceType = rtk::ConstantImageSource<ProjectionStackType>;\n  using ThresholdFilterType = itk::ThresholdImageFilter<VolumeSeriesType>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(FourDSARTConeBeamReconstructionFilter);\n\n  /** The 4D image to be updated.*/\n  void\n  SetInputVolumeSeries(const VolumeSeriesType * VolumeSeries);\n  typename VolumeSeriesType::ConstPointer\n  GetInputVolumeSeries();\n\n  /** The stack of measured projections */\n  void\n  SetInputProjectionStack(const ProjectionStackType * Projection);\n  typename ProjectionStackType::Pointer\n  GetInputProjectionStack();\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Get / Set the number of iterations. Default is 3. */\n  itkGetMacro(NumberOfIterations, unsigned int);\n  itkSetMacro(NumberOfIterations, unsigned int);\n\n  /** Get / Set the number of projections per subset. Default is 1. */\n  itkGetMacro(NumberOfProjectionsPerSubset, unsigned int);\n  itkSetMacro(NumberOfProjectionsPerSubset, unsigned int);\n\n  /** Get / Set the convergence factor. Default is 0.3. */\n  itkGetMacro(Lambda, double);\n  itkSetMacro(Lambda, double);\n\n  /** Get / Set the positivity enforcement behaviour */\n  itkGetMacro(EnforcePositivity, bool);\n  itkSetMacro(EnforcePositivity, bool);\n\n  /** Pass the interpolation weights to subfilters */\n  void\n  SetWeights(const itk::Array2D<float> _arg);\n\n  /** Store the phase signal in a member variable */\n  virtual void\n  SetSignal(const std::vector<double> signal);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  FourDSARTConeBeamReconstructionFilter();\n  ~FourDSARTConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Pointers to each subfilter of this composite filter */\n  typename ExtractFilterType::Pointer                 m_ExtractFilter;\n  typename ExtractFilterType::Pointer                 m_ExtractFilterRayBox;\n  typename MultiplyFilterType::Pointer                m_ZeroMultiplyFilter;\n  typename ForwardProjectionFilterType::Pointer       m_ForwardProjectionFilter;\n  typename FourDToProjectionStackFilterType::Pointer  m_FourDToProjectionStackFilter;\n  typename SubtractFilterType::Pointer                m_SubtractFilter;\n  typename AddFilterType::Pointer                     m_AddFilter;\n  typename AddFilterType::Pointer                     m_AddFilter2;\n  typename MultiplyFilterType::Pointer                m_MultiplyFilter;\n  typename BackProjectionFilterType::Pointer          m_BackProjectionFilter;\n  typename ProjectionStackToFourDFilterType::Pointer  m_ProjectionStackToFourDFilter;\n  typename RayBoxIntersectionFilterType::Pointer      m_RayBoxFilter;\n  typename DivideFilterType::Pointer                  m_DivideFilter;\n  typename DisplacedDetectorFilterType::Pointer       m_DisplacedDetectorFilter;\n  typename ConstantProjectionStackSourceType::Pointer m_ConstantProjectionStackSource;\n  typename ConstantVolumeSeriesSourceType::Pointer    m_ConstantVolumeSeriesSource;\n  typename ThresholdFilterType::Pointer               m_ThresholdFilter;\n\n  /** Miscellaneous member variables */\n  std::vector<unsigned int> m_ProjectionsOrder;\n  bool                      m_ProjectionsOrderInitialized;\n  bool                      m_EnforcePositivity;\n  std::vector<double>       m_Signal;\n  bool                      m_DisableDisplacedDetectorFilter;\n\nprivate:\n  /** Number of projections processed before the volume is updated (1 for SART,\n   * several for OS-SART, all for SIRT) */\n  unsigned int m_NumberOfProjectionsPerSubset;\n\n  /** Geometry object */\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n\n  /** Number of iterations */\n  unsigned int m_NumberOfIterations;\n\n  /** Convergence factor according to Andersen's publications which relates\n   * to the step size of the gradient descent. Default 0.3, Must be in (0,2). */\n  double m_Lambda;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFourDSARTConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFourDSARTConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkFourDSARTConeBeamReconstructionFilter_hxx\n#define rtkFourDSARTConeBeamReconstructionFilter_hxx\n\n#include \"rtkGeneralPurposeFunctions.h\"\n\n#include <algorithm>\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::FourDSARTConeBeamReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set default parameters\n  m_EnforcePositivity = false;\n  m_NumberOfIterations = 3;\n  m_Lambda = 0.3;\n  m_ProjectionsOrderInitialized = false;\n\n  // Create each filter of the composite filter\n  m_ExtractFilter = ExtractFilterType::New();\n  m_ZeroMultiplyFilter = MultiplyFilterType::New();\n  m_SubtractFilter = SubtractFilterType::New();\n  m_AddFilter = AddFilterType::New();\n  m_AddFilter2 = AddFilterType::New();\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_ConstantVolumeSeriesSource = ConstantVolumeSeriesSourceType::New();\n  m_FourDToProjectionStackFilter = FourDToProjectionStackFilterType::New();\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n  m_ProjectionStackToFourDFilter = ProjectionStackToFourDFilterType::New();\n\n  // Create the filters required for correct weighting of the difference\n  // projection\n  m_ExtractFilterRayBox = ExtractFilterType::New();\n  m_RayBoxFilter = RayBoxIntersectionFilterType::New();\n  m_DivideFilter = DivideFilterType::New();\n  m_ConstantProjectionStackSource = ConstantProjectionStackSourceType::New();\n\n  // Create the filter that enforces positivity\n  m_ThresholdFilter = ThresholdFilterType::New();\n\n  // Permanent internal connections\n  m_ZeroMultiplyFilter->SetInput1(itk::NumericTraits<typename InputImageType::PixelType>::ZeroValue());\n  m_ZeroMultiplyFilter->SetInput2(m_ExtractFilter->GetOutput());\n\n  m_MultiplyFilter->SetInput1(itk::NumericTraits<typename InputImageType::PixelType>::ZeroValue());\n  m_MultiplyFilter->SetInput2(m_SubtractFilter->GetOutput());\n\n  m_ExtractFilterRayBox->SetInput(m_ConstantProjectionStackSource->GetOutput());\n  m_RayBoxFilter->SetInput(m_ExtractFilterRayBox->GetOutput());\n  m_DivideFilter->SetInput1(m_MultiplyFilter->GetOutput());\n  m_DivideFilter->SetInput2(m_RayBoxFilter->GetOutput());\n  m_DisplacedDetectorFilter->SetInput(m_DivideFilter->GetOutput());\n\n  // Default parameters\n  m_ExtractFilter->SetDirectionCollapseToSubmatrix();\n  m_ExtractFilterRayBox->SetDirectionCollapseToSubmatrix();\n  m_NumberOfProjectionsPerSubset = 1; // Default is the SART behavior\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n  m_DisableDisplacedDetectorFilter = false;\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetInputVolumeSeries(\n  const VolumeSeriesType * VolumeSeries)\n{\n  this->SetNthInput(0, const_cast<VolumeSeriesType *>(VolumeSeries));\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetInputProjectionStack(\n  const ProjectionStackType * Projection)\n{\n  this->SetNthInput(1, const_cast<ProjectionStackType *>(Projection));\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\ntypename VolumeSeriesType::ConstPointer\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetInputVolumeSeries()\n{\n  return static_cast<const VolumeSeriesType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\ntypename ProjectionStackType::Pointer\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GetInputProjectionStack()\n{\n  return static_cast<ProjectionStackType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetWeights(const itk::Array2D<float> _arg)\n{\n  m_ProjectionStackToFourDFilter->SetWeights(_arg);\n  m_FourDToProjectionStackFilter->SetWeights(_arg);\n  this->Modified();\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n  m_ProjectionStackToFourDFilter->SetSignal(signal);\n  m_FourDToProjectionStackFilter->SetSignal(signal);\n  this->m_Signal = signal;\n  this->Modified();\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<VolumeSeriesType *>(this->GetInput());\n\n  if (!inputPtr)\n    return;\n\n  if (m_EnforcePositivity)\n  {\n    m_ThresholdFilter->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n    m_ThresholdFilter->GetOutput()->PropagateRequestedRegion();\n  }\n  else\n  {\n    m_AddFilter2->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n    m_AddFilter2->GetOutput()->PropagateRequestedRegion();\n  }\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateOutputInformation()\n{\n  const unsigned int Dimension = ProjectionStackType::ImageDimension;\n  unsigned int numberOfProjections = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetSize(Dimension - 1);\n\n  // Set forward projection filter\n  m_ForwardProjectionFilter = this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n  m_FourDToProjectionStackFilter->SetForwardProjectionFilter(m_ForwardProjectionFilter);\n\n  // Set back projection filter\n  m_BackProjectionFilter = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  m_ProjectionStackToFourDFilter->SetBackProjectionFilter(m_BackProjectionFilter);\n\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n\n  if (!m_ProjectionsOrderInitialized)\n  {\n    // Fill and shuffle randomly the projection order.\n    // Should be tunable with other solutions.\n    m_ProjectionsOrder.clear();\n    for (unsigned int i = 0; i < numberOfProjections; i++)\n    {\n      m_ProjectionsOrder.push_back(i);\n    }\n\n    std::shuffle(m_ProjectionsOrder.begin(), m_ProjectionsOrder.end(), Superclass::m_DefaultRandomEngine);\n    m_ProjectionsOrderInitialized = true;\n  }\n\n  // We only set the first sub-stack at that point, the rest will be\n  // requested in the GenerateData function\n  typename ProjectionStackType::RegionType projRegion;\n  projRegion = this->GetInputProjectionStack()->GetLargestPossibleRegion();\n  projRegion.SetSize(Dimension - 1, 1);\n  projRegion.SetIndex(Dimension - 1, m_ProjectionsOrder[0]);\n  m_ExtractFilter->SetExtractionRegion(projRegion);\n  m_ExtractFilterRayBox->SetExtractionRegion(projRegion);\n\n  // Links with the forward and back projection filters should be set here\n  // and not in the constructor, as these filters are set at runtime\n  m_ConstantVolumeSeriesSource->SetInformationFromImage(const_cast<VolumeSeriesType *>(this->GetInput(0)));\n  m_ConstantVolumeSeriesSource->SetConstant(0);\n  m_ConstantVolumeSeriesSource->UpdateOutputInformation();\n\n  m_ProjectionStackToFourDFilter->SetInputVolumeSeries(this->GetInputVolumeSeries());\n  m_ProjectionStackToFourDFilter->SetInputProjectionStack(m_DisplacedDetectorFilter->GetOutput());\n  m_ProjectionStackToFourDFilter->SetSignal(this->m_Signal);\n\n  m_AddFilter->SetInput1(m_ProjectionStackToFourDFilter->GetOutput());\n  m_AddFilter->SetInput2(m_ConstantVolumeSeriesSource->GetOutput());\n\n  m_AddFilter2->SetInput1(m_AddFilter->GetOutput());\n  m_AddFilter2->SetInput2(this->GetInputVolumeSeries());\n\n  m_ExtractFilter->SetInput(this->GetInputProjectionStack());\n\n  m_FourDToProjectionStackFilter->SetInputProjectionStack(m_ZeroMultiplyFilter->GetOutput());\n  m_FourDToProjectionStackFilter->SetInputVolumeSeries(this->GetInputVolumeSeries());\n\n  m_SubtractFilter->SetInput2(m_FourDToProjectionStackFilter->GetOutput());\n  m_SubtractFilter->SetInput1(m_ExtractFilter->GetOutput());\n\n  m_FourDToProjectionStackFilter->SetGeometry(this->m_Geometry);\n  m_ProjectionStackToFourDFilter->SetGeometry(this->m_Geometry);\n  m_DisplacedDetectorFilter->SetGeometry(this->m_Geometry);\n\n  m_ConstantProjectionStackSource->SetInformationFromImage(\n    const_cast<ProjectionStackType *>(this->GetInputProjectionStack().GetPointer()));\n  m_ConstantProjectionStackSource->SetConstant(0);\n  m_ConstantProjectionStackSource->UpdateOutputInformation();\n\n  // Create the m_RayBoxFiltersectionImageFilter\n  m_RayBoxFilter->SetGeometry(this->GetGeometry());\n  itk::Vector<double, 3> Corner1, Corner2;\n\n  Corner1[0] = this->GetInput(0)->GetOrigin()[0];\n  Corner1[1] = this->GetInput(0)->GetOrigin()[1];\n  Corner1[2] = this->GetInput(0)->GetOrigin()[2];\n  Corner2[0] = this->GetInput(0)->GetOrigin()[0] +\n               this->GetInput(0)->GetLargestPossibleRegion().GetSize()[0] * this->GetInput(0)->GetSpacing()[0];\n  Corner2[1] = this->GetInput(0)->GetOrigin()[1] +\n               this->GetInput(0)->GetLargestPossibleRegion().GetSize()[1] * this->GetInput(0)->GetSpacing()[1];\n  Corner2[2] = this->GetInput(0)->GetOrigin()[2] +\n               this->GetInput(0)->GetLargestPossibleRegion().GetSize()[2] * this->GetInput(0)->GetSpacing()[2];\n\n  m_RayBoxFilter->SetBoxMin(Corner1);\n  m_RayBoxFilter->SetBoxMax(Corner2);\n\n  m_RayBoxFilter->UpdateOutputInformation();\n  m_ExtractFilter->UpdateOutputInformation();\n  m_ZeroMultiplyFilter->UpdateOutputInformation();\n  m_FourDToProjectionStackFilter->UpdateOutputInformation();\n\n  m_DivideFilter->UpdateOutputInformation();\n\n\n  if (m_EnforcePositivity)\n  {\n    m_ThresholdFilter->SetOutsideValue(0);\n    m_ThresholdFilter->ThresholdBelow(0);\n    m_ThresholdFilter->SetInput(m_AddFilter2->GetOutput());\n\n    // Update output information\n    m_ThresholdFilter->UpdateOutputInformation();\n    this->GetOutput()->SetOrigin(m_ThresholdFilter->GetOutput()->GetOrigin());\n    this->GetOutput()->SetSpacing(m_ThresholdFilter->GetOutput()->GetSpacing());\n    this->GetOutput()->SetDirection(m_ThresholdFilter->GetOutput()->GetDirection());\n    this->GetOutput()->SetLargestPossibleRegion(m_ThresholdFilter->GetOutput()->GetLargestPossibleRegion());\n  }\n  else\n  {\n    // Update output information\n    m_AddFilter2->UpdateOutputInformation();\n    this->GetOutput()->SetOrigin(m_AddFilter2->GetOutput()->GetOrigin());\n    this->GetOutput()->SetSpacing(m_AddFilter2->GetOutput()->GetSpacing());\n    this->GetOutput()->SetDirection(m_AddFilter2->GetOutput()->GetDirection());\n    this->GetOutput()->SetLargestPossibleRegion(m_AddFilter2->GetOutput()->GetLargestPossibleRegion());\n  }\n\n  // Set memory management flags\n  m_ZeroMultiplyFilter->ReleaseDataFlagOn();\n  m_FourDToProjectionStackFilter->ReleaseDataFlagOn();\n  m_SubtractFilter->ReleaseDataFlagOn();\n  m_MultiplyFilter->ReleaseDataFlagOn();\n  m_RayBoxFilter->ReleaseDataFlagOn();\n  m_DivideFilter->ReleaseDataFlagOn();\n}\n\ntemplate <class VolumeSeriesType, class ProjectionStackType>\nvoid\nFourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateData()\n{\n  const unsigned int Dimension = ProjectionStackType::ImageDimension;\n\n  typename ProjectionStackType::RegionType subsetRegion;\n  subsetRegion = this->GetInputProjectionStack()->GetLargestPossibleRegion();\n  unsigned int nProj = subsetRegion.GetSize(Dimension - 1);\n  subsetRegion.SetSize(Dimension - 1, 1);\n\n  m_MultiplyFilter->SetInput1((const float)m_Lambda / (double)m_NumberOfProjectionsPerSubset);\n\n  // Create the zero projection stack used as input by RayBoxIntersectionFilter\n  m_ConstantProjectionStackSource->Update();\n\n  // Declare the image used in the main loop\n  typename VolumeSeriesType::Pointer pimg;\n  typename VolumeSeriesType::Pointer pimg2;\n\n  itk::IterationReporter iterationReporter(this, 0, 1);\n\n  // For each iteration, go over each projection\n  for (unsigned int iter = 0; iter < m_NumberOfIterations; iter++)\n  {\n    unsigned int projectionsProcessedInSubset = 0;\n\n    for (unsigned int i = 0; i < nProj; i++)\n    {\n      // When we reach the number of projections per subset:\n      // - plug the output of the pipeline back into the Forward projection filter\n      // - set the input of the Back projection filter to zero\n      // - reset the projectionsProcessedInSubset to zero\n      if (projectionsProcessedInSubset == m_NumberOfProjectionsPerSubset)\n      {\n        if (m_EnforcePositivity)\n          pimg2 = m_ThresholdFilter->GetOutput();\n        else\n          pimg2 = m_AddFilter2->GetOutput();\n\n        pimg2->DisconnectPipeline();\n\n        m_FourDToProjectionStackFilter->SetInputVolumeSeries(pimg2);\n        m_AddFilter2->SetInput2(pimg2);\n        m_AddFilter->SetInput2(m_ConstantVolumeSeriesSource->GetOutput());\n\n        projectionsProcessedInSubset = 0;\n      }\n\n      // Otherwise, just plug the output of the add filter\n      // back as its input\n      else\n      {\n        if (i)\n        {\n          pimg = m_AddFilter->GetOutput();\n          pimg->DisconnectPipeline();\n          m_AddFilter->SetInput2(pimg);\n        }\n        else\n        {\n          m_AddFilter->SetInput2(m_ConstantVolumeSeriesSource->GetOutput());\n        }\n      }\n\n      // Change projection subset\n      subsetRegion.SetIndex(Dimension - 1, m_ProjectionsOrder[i]);\n      m_ExtractFilter->SetExtractionRegion(subsetRegion);\n      m_ExtractFilterRayBox->SetExtractionRegion(subsetRegion);\n\n      // This is required to reset the full pipeline\n      m_ProjectionStackToFourDFilter->GetOutput()->UpdateOutputInformation();\n      m_ProjectionStackToFourDFilter->GetOutput()->PropagateRequestedRegion();\n\n      m_AddFilter->Update();\n\n      projectionsProcessedInSubset++;\n      if ((projectionsProcessedInSubset == m_NumberOfProjectionsPerSubset) || (i == nProj - 1))\n      {\n        m_AddFilter2->SetInput1(m_AddFilter->GetOutput());\n        m_AddFilter2->Update();\n\n        if (m_EnforcePositivity)\n        {\n          m_ThresholdFilter->Update();\n        }\n      }\n\n      if (m_EnforcePositivity)\n      {\n        this->GraftOutput(m_ThresholdFilter->GetOutput());\n      }\n      else\n      {\n        this->GraftOutput(m_AddFilter2->GetOutput());\n      }\n    }\n    iterationReporter.CompletedStep();\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkFourDSARTConeBeamReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkFourDToProjectionStackImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkFourDToProjectionStackImageFilter_h\n#define rtkFourDToProjectionStackImageFilter_h\n\n#include <itkExtractImageFilter.h>\n#include <itkPasteImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n\n#include \"rtkConstantImageSource.h\"\n#include \"rtkInterpolatorWithKnownWeightsImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class FourDToProjectionStackImageFilter\n * \\brief Implements part of the 4D reconstruction by conjugate gradient\n *\n * See the reference paper: \"Cardiac C-arm computed tomography using\n * a 3D + time ROI reconstruction method with spatial and temporal regularization\"\n * by Mory et al.\n *\n * 4D conjugate gradient reconstruction consists in iteratively\n * minimizing the following cost function:\n *\n * Sum_over_theta || R_theta S_theta f - p_theta ||_2^2\n *\n * with\n * - f a 4D series of 3D volumes, each one being the reconstruction\n * at a given respiratory/cardiac phase\n * - p_theta is the projection measured at angle theta\n * - S_theta an interpolation operator which, from the 3D + time sequence f,\n * estimates the 3D volume through which projection p_theta has been acquired\n * - R_theta is the X-ray transform (the forward projection operator) for angle theta\n *\n * Computing the gradient of this cost function yields:\n *\n * S_theta^T R_theta^T R_theta S_theta f - S_theta^T R_theta^T p_theta\n *\n * where A^T means the adjoint of operator A.\n *\n * FourDToProjectionStackImageFilter implements R_theta S_theta.\n *\n * \\dot\n * digraph FourDToProjectionStackImageFilter {\n *\n * Input1 [label=\"Input 1 (Input: 4D sequence of volumes)\"];\n * Input1 [shape=Mdiamond];\n * Input0 [ label=\"Input 0 (Projections)\"];\n * Input0 [shape=Mdiamond];\n * Output [label=\"Output (Output projections)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * FourDSource [ label=\"rtk::ConstantImageSource (4D volume)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ProjectionSource [ label=\"rtk::ConstantImageSource (projections)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ForwardProj [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * Interpolation [ label=\"rtk::InterpolatorWithKnownWeightsImageFilter\"\n *                 URL=\"\\ref rtk::InterpolatorWithKnownWeightsImageFilter\"];\n * BeforePaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Paste [ label=\"itk::PasteImageFilter\" URL=\"\\ref itk::PasteImageFilter\"];\n * AfterPaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * ProjectionSource -> ForwardProj;\n * BeforePaste -> Paste;\n * FourDSource -> Interpolation;\n * Input1 -> Interpolation;\n * Interpolation -> ForwardProj;\n * Input0 -> BeforePaste[arrowhead=none];\n * ForwardProj -> Paste;\n * Paste -> AfterPaste[arrowhead=none];\n * AfterPaste -> Output;\n * AfterPaste -> BeforePaste [style=dashed, constraint=false];\n * }\n * \\enddot\n *\n * \\test rtkfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nclass ITK_TEMPLATE_EXPORT FourDToProjectionStackImageFilter\n  : public itk::ImageToImageFilter<ProjectionStackType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(FourDToProjectionStackImageFilter);\n\n  /** Standard class type alias. */\n  using Self = FourDToProjectionStackImageFilter;\n  using Superclass = itk::ImageToImageFilter<ProjectionStackType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using VolumeType = ProjectionStackType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(FourDToProjectionStackImageFilter);\n\n  /** The 4D image to be updated.*/\n  void\n  SetInputVolumeSeries(const VolumeSeriesType * VolumeSeries);\n\n  /** The image that will be backprojected, then added, with coefficients, to each 3D volume of the 4D image.\n   * It is 3D because the ForwardProjection filters need it, but the third dimension, which is the number of\n   * projections, is 1  */\n  void\n  SetInputProjectionStack(const ProjectionStackType * Projection);\n\n  /** Typedefs for the sub filters */\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<ProjectionStackType, ProjectionStackType>;\n  using PasteFilterType = itk::PasteImageFilter<ProjectionStackType, ProjectionStackType>;\n  using InterpolatorFilterType = rtk::InterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>;\n  using ConstantVolumeSourceType = rtk::ConstantImageSource<VolumeType>;\n  using ConstantProjectionStackSourceType = rtk::ConstantImageSource<ProjectionStackType>;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n\n  /** Set the ForwardProjection filter */\n  void\n  SetForwardProjectionFilter(ForwardProjectionFilterType * _arg);\n\n  /** Pass the geometry to SingleProjectionToFourDFilter */\n  itkSetObjectMacro(Geometry, GeometryType);\n\n  /** Pass the interpolation weights to SingleProjectionToFourDFilter */\n  void\n  SetWeights(const itk::Array2D<float> _arg);\n\n  /** Initializes the empty volume source, set it and update it */\n  void\n  InitializeConstantVolumeSource();\n\n  /** Store the phase signal in a member variable */\n  virtual void\n  SetSignal(const std::vector<double> signal);\n\nprotected:\n  FourDToProjectionStackImageFilter();\n  ~FourDToProjectionStackImageFilter() override = default;\n\n  typename VolumeSeriesType::ConstPointer\n  GetInputVolumeSeries();\n  typename ProjectionStackType::Pointer\n  GetInputProjectionStack();\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename PasteFilterType::Pointer                   m_PasteFilter;\n  typename InterpolatorFilterType::Pointer            m_InterpolationFilter;\n  typename ConstantVolumeSourceType::Pointer          m_ConstantVolumeSource;\n  typename ConstantProjectionStackSourceType::Pointer m_ConstantProjectionStackSource;\n  typename ForwardProjectionFilterType::Pointer       m_ForwardProjectionFilter;\n\n  /** Other member variables */\n  itk::Array2D<float>                                               m_Weights;\n  GeometryType::Pointer                                             m_Geometry;\n  typename ConstantProjectionStackSourceType::OutputImageRegionType m_PasteRegion;\n  std::vector<double>                                               m_Signal;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkFourDToProjectionStackImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkFourDToProjectionStackImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkFourDToProjectionStackImageFilter_hxx\n#define rtkFourDToProjectionStackImageFilter_hxx\n\n#include \"rtkGeneralPurposeFunctions.h\"\n\nnamespace rtk\n{\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::FourDToProjectionStackImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Create the filters that can be created (all but the forward projection filter)\n  m_PasteFilter = PasteFilterType::New();\n  m_InterpolationFilter = InterpolatorFilterType::New();\n  m_ConstantVolumeSource = ConstantVolumeSourceType::New();\n  m_ConstantProjectionStackSource = ConstantProjectionStackSourceType::New();\n\n  // Set parameters\n  m_PasteFilter->SetInPlace(true);\n\n  // Set memory management flags\n  m_InterpolationFilter->ReleaseDataFlagOn();\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nvoid\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::SetInputProjectionStack(\n  const ProjectionStackType * Projection)\n{\n  this->SetNthInput(0, const_cast<ProjectionStackType *>(Projection));\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nvoid\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::SetInputVolumeSeries(\n  const VolumeSeriesType * VolumeSeries)\n{\n  this->SetNthInput(1, const_cast<VolumeSeriesType *>(VolumeSeries));\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\ntypename ProjectionStackType::Pointer\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::GetInputProjectionStack()\n{\n  return static_cast<ProjectionStackType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\ntypename VolumeSeriesType::ConstPointer\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::GetInputVolumeSeries()\n{\n  return static_cast<const VolumeSeriesType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nvoid\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::SetForwardProjectionFilter(\n  ForwardProjectionFilterType * _arg)\n{\n  m_ForwardProjectionFilter = _arg;\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nvoid\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::SetWeights(const itk::Array2D<float> _arg)\n{\n  m_Weights = _arg;\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nFourDToProjectionStackImageFilter<VolumeSeriesType, ProjectionStackType>::SetSignal(const std::vector<double> signal)\n{\n  this->m_Signal = signal;\n  this->Modified();\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nvoid\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::InitializeConstantVolumeSource()\n{\n  // Set the volume source\n  int VolumeDimension = VolumeType::ImageDimension;\n\n  typename VolumeType::SizeType constantVolumeSourceSize;\n  constantVolumeSourceSize.Fill(0);\n  for (int i = 0; i < VolumeDimension; i++)\n    constantVolumeSourceSize[i] = GetInputVolumeSeries()->GetLargestPossibleRegion().GetSize()[i];\n\n  typename VolumeType::SpacingType constantVolumeSourceSpacing;\n  constantVolumeSourceSpacing.Fill(0);\n  for (int i = 0; i < VolumeDimension; i++)\n    constantVolumeSourceSpacing[i] = GetInputVolumeSeries()->GetSpacing()[i];\n\n  typename VolumeType::PointType constantVolumeSourceOrigin;\n  constantVolumeSourceOrigin.Fill(0);\n  for (int i = 0; i < VolumeDimension; i++)\n    constantVolumeSourceOrigin[i] = GetInputVolumeSeries()->GetOrigin()[i];\n\n  typename VolumeType::DirectionType constantVolumeSourceDirection;\n  constantVolumeSourceDirection.SetIdentity();\n\n  m_ConstantVolumeSource->SetOrigin(constantVolumeSourceOrigin);\n  m_ConstantVolumeSource->SetSpacing(constantVolumeSourceSpacing);\n  m_ConstantVolumeSource->SetDirection(constantVolumeSourceDirection);\n  m_ConstantVolumeSource->SetSize(constantVolumeSourceSize);\n  m_ConstantVolumeSource->SetConstant(0.);\n  m_ConstantVolumeSource->Update();\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nvoid\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::GenerateOutputInformation()\n{\n  this->InitializeConstantVolumeSource();\n\n  int ProjectionStackDimension = ProjectionStackType::ImageDimension;\n  m_PasteRegion = this->GetInputProjectionStack()->GetLargestPossibleRegion();\n  m_PasteRegion.SetSize(ProjectionStackDimension - 1, 1);\n\n  // Set the projection stack source\n  m_ConstantProjectionStackSource->SetInformationFromImage(this->GetInputProjectionStack());\n  m_ConstantProjectionStackSource->SetSize(m_PasteRegion.GetSize());\n  m_ConstantProjectionStackSource->SetConstant(0.);\n\n  // Connect the filters\n  m_InterpolationFilter->SetInputVolumeSeries(this->GetInputVolumeSeries());\n  m_InterpolationFilter->SetInputVolume(m_ConstantVolumeSource->GetOutput());\n  m_PasteFilter->SetDestinationImage(this->GetInputProjectionStack());\n\n  // Connections with the Forward projection filter can only be set at runtime\n  m_ForwardProjectionFilter->SetInput(0, m_ConstantProjectionStackSource->GetOutput());\n  m_ForwardProjectionFilter->SetInput(1, m_InterpolationFilter->GetOutput());\n  m_PasteFilter->SetSourceImage(m_ForwardProjectionFilter->GetOutput());\n\n  // Set runtime parameters\n  m_InterpolationFilter->SetWeights(m_Weights);\n  m_InterpolationFilter->SetProjectionNumber(m_PasteRegion.GetIndex(ProjectionStackDimension - 1));\n  m_ForwardProjectionFilter->SetGeometry(m_Geometry);\n  m_PasteFilter->SetSourceRegion(m_PasteRegion);\n  m_PasteFilter->SetDestinationIndex(m_PasteRegion.GetIndex());\n\n  // Have the last filter calculate its output information\n  m_PasteFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_PasteFilter->GetOutput());\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nvoid\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the stack of projections we update\n  typename ProjectionStackType::Pointer inputPtr0 = const_cast<ProjectionStackType *>(this->GetInput(0));\n  if (!inputPtr0)\n  {\n    return;\n  }\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the volume series\n  typename VolumeSeriesType::Pointer inputPtr1 = static_cast<VolumeSeriesType *>(this->itk::ProcessObject::GetInput(1));\n  inputPtr1->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename ProjectionStackType, typename VolumeSeriesType>\nvoid\nFourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::GenerateData()\n{\n  int ProjectionStackDimension = ProjectionStackType::ImageDimension;\n\n  int NumberProjs = this->GetInputProjectionStack()->GetRequestedRegion().GetSize(ProjectionStackDimension - 1);\n  int FirstProj = this->GetInputProjectionStack()->GetRequestedRegion().GetIndex(ProjectionStackDimension - 1);\n\n  bool firstProjectionProcessed = false;\n\n  // Process the projections in order\n  for (int proj = FirstProj; proj < FirstProj + NumberProjs; proj++)\n  {\n    // After the first update, we need to use the output as input.\n    if (firstProjectionProcessed)\n    {\n      typename ProjectionStackType::Pointer pimg = this->m_PasteFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      this->m_PasteFilter->SetDestinationImage(pimg);\n    }\n\n    // Update the paste region\n    this->m_PasteRegion.SetIndex(ProjectionStackDimension - 1, proj);\n\n    // Set the projection stack source\n    this->m_ConstantProjectionStackSource->SetIndex(this->m_PasteRegion.GetIndex());\n\n    // Set the Paste Filter. Since its output has been disconnected\n    // we need to set its RequestedRegion manually (it will never\n    // be updated by a downstream filter)\n    m_PasteFilter->SetSourceRegion(m_PasteRegion);\n    m_PasteFilter->SetDestinationIndex(m_PasteRegion.GetIndex());\n    m_PasteFilter->GetOutput()->SetRequestedRegion(m_PasteFilter->GetDestinationImage()->GetLargestPossibleRegion());\n\n    // Set the Interpolation filter\n    m_InterpolationFilter->SetProjectionNumber(proj);\n\n    // Update the last filter\n    m_PasteFilter->Update();\n\n    // Update condition\n    firstProjectionProcessed = true;\n  }\n\n  // Graft its output\n  this->GraftOutput(m_PasteFilter->GetOutput());\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkGeneralPurposeFunctions.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkGeneralPurposeFunctions_h\n#define rtkGeneralPurposeFunctions_h\n\n#include <vector>\n\n\n#include \"math.h\"\n\n#include <itkMacro.h>\n#include <itkImageFileWriter.h>\n#include <itkMath.h>\n\nnamespace rtk\n{\n\n/** \\brief A few functions that are used either in the applications or for debugging purposes\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\nstatic inline std::vector<double>\nReadSignalFile(std::string filename)\n{\n  std::vector<double> signalVector;\n  std::ifstream       is(filename.c_str());\n  if (!is.is_open())\n  {\n    itkGenericExceptionMacro(<< \"Could not open signal file \" << filename);\n  }\n\n  double      value = NAN;\n  std::string s;\n  while (getline(is, s))\n  {\n    if (!s.empty())\n    {\n      std::istringstream tmp(s);\n      tmp >> value;\n      if (itk::Math::Round<double>(value * 100) / 100 == 1)\n        signalVector.push_back(0);\n      else\n        signalVector.push_back(itk::Math::Round<double>(value * 100) / 100);\n    }\n  }\n\n  return signalVector;\n}\n\ntemplate <typename ImageType>\nvoid\nWriteImage(typename ImageType::ConstPointer input, std::string name)\n{\n  // Create an itk::ImageFileWriter\n  using WriterType = itk::ImageFileWriter<ImageType>;\n  auto writer = WriterType::New();\n  writer->SetInput(input);\n  writer->SetFileName(name);\n  writer->Update();\n}\n\n} // namespace rtk\n\n#endif // rtkGeneralPurposeFunctions_h\n"
  },
  {
    "path": "include/rtkGeometricPhantom.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkGeometricPhantom_h\n#define rtkGeometricPhantom_h\n\n#include \"RTKExport.h\"\n#include \"rtkConvexShape.h\"\n\nnamespace rtk\n{\n/** \\class GeometricPhantom\n * \\brief Container for a geometric phantom, i.e., a set of ConvexShapes.\n *\n * \\test rtkforbildtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n *\n */\nclass RTK_EXPORT GeometricPhantom : public itk::DataObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(GeometricPhantom);\n\n  /** Standard class type alias. */\n  using Self = GeometricPhantom;\n  using Superclass = itk::DataObject;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using ConvexShapePointer = ConvexShape::Pointer;\n  using ConvexShapeVector = std::vector<ConvexShapePointer>;\n  using PointType = ConvexShape::PointType;\n  using VectorType = ConvexShape::VectorType;\n  using ScalarType = ConvexShape::ScalarType;\n  using RotationMatrixType = ConvexShape::RotationMatrixType;\n\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(GeometricPhantom);\n\n  /** Rescale object along each direction by a 3D vector. */\n  virtual void\n  Rescale(const VectorType & r);\n\n  /** Translate object by a given 3D vector. */\n  virtual void\n  Translate(const VectorType & t);\n\n  /** Rotate object according to a 3D rotation matrix. */\n  virtual void\n  Rotate(const RotationMatrixType & r);\n\n  /** Get reference to vector of objects. */\n  itkGetConstReferenceMacro(ConvexShapes, ConvexShapeVector);\n\n  /** Add convex object to phantom. */\n  void\n  AddConvexShape(const ConvexShape * co);\n\n  /** Add clipping plane to the object. The plane is defined by the equation\n   * dir * (x,y,z)' + pos = 0. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n\nprotected:\n  GeometricPhantom() = default;\n  ~GeometricPhantom() override = default;\n\nprivate:\n  ConvexShapeVector       m_ConvexShapes;\n  std::vector<VectorType> m_PlaneDirections;\n  std::vector<ScalarType> m_PlanePositions;\n};\n\n} // namespace rtk\n#endif // rtkGeometricPhantom_h\n"
  },
  {
    "path": "include/rtkGetNewtonUpdateImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkGetNewtonUpdateImageFilter_h\n#define rtkGetNewtonUpdateImageFilter_h\n\n#include \"itkImageToImageFilter.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class GetNewtonUpdateImageFilter\n * \\brief Computes update from gradient and Hessian in Newton's method\n *\n * This filter takes in inputs the gradient G (input 1) and the Hessian H (input 2)\n * of a cost function, and computes the update U (output), by U = H^{-1} * G.\n * In Newton's method, the quantity to add to the current iterate in order to get the next\n * iterate is actually -U, so the minus operation has to be handled downstream.\n * It is assumed that the cost function is separable, so that each pixel can be processed\n * independently and has its own small G, H and U\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <class TGradient,\n          class THessian = itk::Image<itk::Vector<typename TGradient::PixelType::ValueType,\n                                                  TGradient::PixelType::Dimension * TGradient::PixelType::Dimension>,\n                                      TGradient::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT GetNewtonUpdateImageFilter : public itk::ImageToImageFilter<TGradient, TGradient>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(GetNewtonUpdateImageFilter);\n\n  /** Standard class type alias. */\n  using Self = GetNewtonUpdateImageFilter;\n  using Superclass = itk::ImageToImageFilter<TGradient, TGradient>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(GetNewtonUpdateImageFilter);\n\n  /** Convenient parameters extracted from template types */\n  static constexpr unsigned int nChannels = TGradient::PixelType::Dimension;\n\n  /** Convenient type alias */\n  using dataType = typename TGradient::PixelType::ValueType;\n\n  /** Set methods for all inputs, since they have different types */\n  void\n  SetInputGradient(const TGradient * gradient);\n  void\n  SetInputHessian(const THessian * hessian);\n\nprotected:\n  GetNewtonUpdateImageFilter();\n  ~GetNewtonUpdateImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  DynamicThreadedGenerateData(const typename TGradient::RegionType & outputRegionForThread) override;\n\n  /** Getters for the inputs */\n  typename TGradient::ConstPointer\n  GetInputGradient();\n  typename THessian::ConstPointer\n  GetInputHessian();\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkGetNewtonUpdateImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkGetNewtonUpdateImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkGetNewtonUpdateImageFilter_hxx\n#define rtkGetNewtonUpdateImageFilter_hxx\n\n#include \"itkImageRegionIteratorWithIndex.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"vnl/vnl_inverse.h\"\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <class TGradient, class THessian>\nGetNewtonUpdateImageFilter<TGradient, THessian>::GetNewtonUpdateImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n}\n\ntemplate <class TGradient, class THessian>\nvoid\nGetNewtonUpdateImageFilter<TGradient, THessian>::SetInputGradient(const TGradient * gradient)\n{\n  this->SetNthInput(0, const_cast<TGradient *>(gradient));\n}\n\ntemplate <class TGradient, class THessian>\nvoid\nGetNewtonUpdateImageFilter<TGradient, THessian>::SetInputHessian(const THessian * hessian)\n{\n  this->SetNthInput(1, const_cast<THessian *>(hessian));\n}\n\ntemplate <class TGradient, class THessian>\ntypename TGradient::ConstPointer\nGetNewtonUpdateImageFilter<TGradient, THessian>::GetInputGradient()\n{\n  return static_cast<const TGradient *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <class TGradient, class THessian>\ntypename THessian::ConstPointer\nGetNewtonUpdateImageFilter<TGradient, THessian>::GetInputHessian()\n{\n  return static_cast<const THessian *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <class TGradient, class THessian>\nvoid\nGetNewtonUpdateImageFilter<TGradient, THessian>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get the requested regions on both outputs (should be identical)\n  typename TGradient::RegionType outputRequested = this->GetOutput()->GetRequestedRegion();\n\n  // Get pointers to the inputs\n  typename TGradient::Pointer input1Ptr = const_cast<TGradient *>(this->GetInputGradient().GetPointer());\n  typename THessian::Pointer  input2Ptr = const_cast<THessian *>(this->GetInputHessian().GetPointer());\n\n  // The first and second input must have the same requested region as the outputs\n  input1Ptr->SetRequestedRegion(outputRequested);\n  input2Ptr->SetRequestedRegion(outputRequested);\n}\n\ntemplate <class TGradient, class THessian>\nvoid\nGetNewtonUpdateImageFilter<TGradient, THessian>::DynamicThreadedGenerateData(\n  const typename TGradient::RegionType & outputRegionForThread)\n{\n  // Create iterators for all inputs and outputs\n  itk::ImageRegionIterator<TGradient>      outIt(this->GetOutput(), outputRegionForThread);\n  itk::ImageRegionConstIterator<TGradient> gradIt(this->GetInputGradient(), outputRegionForThread);\n  itk::ImageRegionConstIterator<THessian>  hessIt(this->GetInputHessian(), outputRegionForThread);\n\n  itk::Vector<dataType, nChannels> forOutput;\n\n  while (!outIt.IsAtEnd())\n  {\n    // Make a vnl matrix out of the values read in input 2 (the hessian, but stored in a vector)\n    vnl_matrix<dataType> hessian = vnl_matrix<dataType>(hessIt.Get().GetDataPointer(), nChannels, nChannels);\n    vnl_matrix<dataType> regul = vnl_matrix<dataType>(nChannels, nChannels, 0);\n    regul.fill_diagonal(1e-8);\n\n    // Invert the hessian, multiply by the gradient, and write it in output\n    forOutput.SetVnlVector(vnl_inverse(hessian + regul) * gradIt.Get().GetVnlVector());\n    outIt.Set(forOutput);\n\n    ++outIt;\n    ++gradIt;\n    ++hessIt;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkGgoArgsInfoManager.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkGgoArgsInfoManager_h\n#define rtkGgoArgsInfoManager_h\n\n#include \"rtkConfiguration.h\"\n#ifdef RTK_PROBE_EACH_FILTER\n#  include \"rtkGlobalResourceProbe.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class args_info_manager\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <class TArgsInfo, class TCleanupFunction = void (*)(TArgsInfo *)>\nclass ITK_TEMPLATE_EXPORT args_info_manager\n{\npublic:\n  args_info_manager(TArgsInfo & args_info, TCleanupFunction cf)\n  {\n    this->args_info_pointer = &args_info;\n    this->cleanup_function = cf;\n#ifdef RTK_PROBE_EACH_FILTER\n    rtk::GlobalResourceProbe::GetInstance()->SetVerbose(args_info.verbose_flag);\n#endif\n  }\n  ~args_info_manager() { this->cleanup_function(this->args_info_pointer); }\n\nprivate:\n  TArgsInfo *      args_info_pointer;\n  TCleanupFunction cleanup_function;\n};\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkGgoFunctions.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// #ifndef RTKGGOFUNCTIONS_H\n// #define RTKGGOFUNCTIONS_H\n\n#ifndef rtkGgoFunctions_h\n#define rtkGgoFunctions_h\n\n#include \"rtkMacro.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkIOFactories.h\"\n#include \"rtkProjectionsReader.h\"\n#include <itkRegularExpressionSeriesFileNames.h>\n#include <itksys/RegularExpression.hxx>\n\nnamespace rtk\n{\n\n/** \\brief Create 3D image from gengetopt specifications.\n *\n * This function sets a ConstantImageSource object from command line options stored in ggo struct.\n *  The image is not buffered to allow streaming. The image is filled with zeros.\n *  The required options in the ggo struct are:\n *     - size: image size in pixels\n *     - spacing: image spacing in coordinate units\n *     - origin: image origin in coordinate units\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <class TConstantImageSourceType, class TArgsInfo>\nvoid\nSetConstantImageSourceFromGgo(TConstantImageSourceType * source, const TArgsInfo & args_info)\n{\n  using ImageType = typename TConstantImageSourceType::OutputImageType;\n\n  const unsigned int Dimension = ImageType::GetImageDimension();\n\n  typename ImageType::SizeType imageSize;\n  if (args_info.dimension_given)\n  {\n    itkGenericOutputMacro(\n      \"Warning: --dimension is deprecated and will be removed in a future release. Use --size instead.\");\n    imageSize.Fill(args_info.dimension_arg[0]);\n    for (unsigned int i = 0; i < std::min(args_info.dimension_given, Dimension); i++)\n    {\n      imageSize[i] = args_info.dimension_arg[i];\n    }\n  }\n  imageSize.Fill(args_info.size_arg[0]);\n  for (unsigned int i = 0; i < std::min(args_info.size_given, Dimension); i++)\n    imageSize[i] = args_info.size_arg[i];\n\n  typename ImageType::SpacingType imageSpacing;\n  imageSpacing.Fill(args_info.spacing_arg[0]);\n  for (unsigned int i = 0; i < std::min(args_info.spacing_given, Dimension); i++)\n    imageSpacing[i] = args_info.spacing_arg[i];\n\n  typename ImageType::PointType imageOrigin;\n  for (unsigned int i = 0; i < Dimension; i++)\n    imageOrigin[i] = imageSpacing[i] * (imageSize[i] - 1) * -0.5;\n  for (unsigned int i = 0; i < std::min(args_info.origin_given, Dimension); i++)\n    imageOrigin[i] = args_info.origin_arg[i];\n\n  typename ImageType::DirectionType imageDirection;\n  if (args_info.direction_given)\n    for (unsigned int i = 0; i < Dimension; i++)\n      for (unsigned int j = 0; j < Dimension; j++)\n        imageDirection[i][j] = args_info.direction_arg[i * Dimension + j];\n  else\n    imageDirection.SetIdentity();\n\n  source->SetOrigin(imageOrigin);\n  source->SetSpacing(imageSpacing);\n  source->SetDirection(imageDirection);\n  source->SetSize(imageSize);\n  source->SetConstant({});\n\n  // Copy output image information from an existing file, if requested\n  // Overwrites parameters given in command line, if any\n  if (args_info.like_given)\n  {\n    using LikeReaderType = itk::ImageFileReader<ImageType>;\n    auto likeReader = LikeReaderType::New();\n    likeReader->SetFileName(args_info.like_arg);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(likeReader->UpdateOutputInformation());\n    source->SetInformationFromImage(likeReader->GetOutput());\n  }\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(source->UpdateOutputInformation());\n}\n\n/** \\brief Read a stack of 2D projections from gengetopt specifications.\n *\n * This function sets a ProjectionsReader object from command line options stored in ggo struct.\n * The projections are not buffered to allow streaming.\n * The required options in the ggo struct are:\n *     - verbose\n *     - path: path containing projections\n *     - regexp: regular expression to select projection files in path\n *     - nsort: boolean to (des-)activate the numeric sort for expression matches\n *     - submatch: index of the submatch that will be used to sort matches\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <class TArgsInfo>\nconst std::vector<std::string>\nGetProjectionsFileNamesFromGgo(const TArgsInfo & args_info)\n{\n  // Generate file names\n  auto names = itk::RegularExpressionSeriesFileNames::New();\n  names->SetDirectory(args_info.path_arg);\n  names->SetNumericSort(args_info.nsort_flag);\n  names->SetRegularExpression(args_info.regexp_arg);\n  names->SetSubMatch(args_info.submatch_arg);\n\n  if (args_info.verbose_flag)\n    std::cout << \"Regular expression matches \" << names->GetFileNames().size() << \" file(s)...\" << std::endl;\n\n  // Check submatch in file names\n  if (args_info.submatch_given)\n  {\n    // Check that the submatch number returns something relevant\n    itksys::RegularExpression reg;\n    if (!reg.compile(args_info.regexp_arg))\n    {\n      itkGenericExceptionMacro(<< \"Error compiling regular expression \" << args_info.regexp_arg);\n    }\n\n    // Store the full filename and the selected sub expression match\n    for (const std::string & name : names->GetFileNames())\n    {\n      reg.find(name);\n      if (reg.match(args_info.submatch_arg) == std::string(\"\"))\n      {\n        itkGenericExceptionMacro(<< \"Cannot find submatch \" << args_info.submatch_arg << \" in \" << name\n                                 << \" from regular expression \" << args_info.regexp_arg);\n      }\n    }\n  }\n\n  std::vector<std::string> fileNames = names->GetFileNames();\n  rtk::RegisterIOFactories();\n  std::vector<size_t> idxtopop;\n  size_t              i = 0;\n  for (const auto & fn : fileNames)\n  {\n    itk::ImageIOBase::Pointer imageio =\n      itk::ImageIOFactory::CreateImageIO(fn.c_str(), itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n\n    if (imageio.IsNull())\n    {\n      std::cerr << \"Ignoring file: \" << fn << \"\\n\";\n      idxtopop.push_back(i);\n    }\n    i++;\n  }\n  std::reverse(idxtopop.begin(), idxtopop.end());\n  for (const auto & id : idxtopop)\n  {\n    fileNames.erase(fileNames.begin() + id);\n  }\n\n  return fileNames;\n}\n\ntemplate <class TProjectionsReaderType, class TArgsInfo>\nvoid\nSetProjectionsReaderFromGgo(TProjectionsReaderType * reader, const TArgsInfo & args_info)\n{\n  const std::vector<std::string> fileNames = GetProjectionsFileNamesFromGgo(args_info);\n\n  // Vector component extraction\n  if (args_info.component_given)\n  {\n    reader->SetVectorComponent(args_info.component_arg);\n  }\n\n  // Change image information\n  const unsigned int Dimension = TProjectionsReaderType::OutputImageType::GetImageDimension();\n  typename TProjectionsReaderType::OutputImageDirectionType direction;\n  if (args_info.newdirection_given)\n  {\n    direction.Fill(args_info.newdirection_arg[0]);\n    for (unsigned int i = 0; i < args_info.newdirection_given; i++)\n      direction[i / Dimension][i % Dimension] = args_info.newdirection_arg[i];\n    reader->SetDirection(direction);\n  }\n  typename TProjectionsReaderType::OutputImageSpacingType spacing;\n  if (args_info.newspacing_given)\n  {\n    spacing.Fill(args_info.newspacing_arg[0]);\n    for (unsigned int i = 0; i < args_info.newspacing_given; i++)\n      spacing[i] = args_info.newspacing_arg[i];\n    reader->SetSpacing(spacing);\n  }\n  typename TProjectionsReaderType::OutputImagePointType origin;\n  if (args_info.neworigin_given)\n  {\n    origin.Fill(args_info.neworigin_arg[0]);\n    for (unsigned int i = 0; i < args_info.neworigin_given; i++)\n      origin[i] = args_info.neworigin_arg[i];\n    reader->SetOrigin(origin);\n  }\n\n  // Crop boundaries\n  typename TProjectionsReaderType::OutputImageSizeType upperCrop, lowerCrop;\n  upperCrop.Fill(0);\n  lowerCrop.Fill(0);\n  for (unsigned int i = 0; i < args_info.lowercrop_given; i++)\n    lowerCrop[i] = args_info.lowercrop_arg[i];\n  reader->SetLowerBoundaryCropSize(lowerCrop);\n  for (unsigned int i = 0; i < args_info.uppercrop_given; i++)\n    upperCrop[i] = args_info.uppercrop_arg[i];\n  reader->SetUpperBoundaryCropSize(upperCrop);\n\n  // Conditional median\n  typename TProjectionsReaderType::MedianRadiusType medianRadius;\n  medianRadius.Fill(0);\n  for (unsigned int i = 0; i < args_info.radius_given; i++)\n    medianRadius[i] = args_info.radius_arg[i];\n  reader->SetMedianRadius(medianRadius);\n  if (args_info.multiplier_given)\n    reader->SetConditionalMedianThresholdMultiplier(args_info.multiplier_arg);\n\n  // Shrink / Binning\n  typename TProjectionsReaderType::ShrinkFactorsType binFactors;\n  binFactors.Fill(1);\n  for (unsigned int i = 0; i < args_info.binning_given; i++)\n    binFactors[i] = args_info.binning_arg[i];\n  reader->SetShrinkFactors(binFactors);\n\n  // Boellaard scatter correction\n  if (args_info.spr_given)\n    reader->SetScatterToPrimaryRatio(args_info.spr_arg);\n  if (args_info.nonneg_given)\n    reader->SetNonNegativityConstraintThreshold(args_info.nonneg_arg);\n  if (args_info.airthres_given)\n    reader->SetAirThreshold(args_info.airthres_arg);\n\n  // I0 and IDark\n  if (args_info.i0_given)\n    reader->SetI0(args_info.i0_arg);\n  reader->SetIDark(args_info.idark_arg);\n\n  // Line integral flag\n  if (args_info.nolineint_flag)\n    reader->ComputeLineIntegralOff();\n\n  // Water precorrection\n  if (args_info.wpc_given)\n  {\n    std::vector<double> coeffs;\n    coeffs.assign(args_info.wpc_arg, args_info.wpc_arg + args_info.wpc_given);\n    reader->SetWaterPrecorrectionCoefficients(coeffs);\n  }\n\n  // Pass list to projections reader\n  reader->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateOutputInformation());\n}\n\n/** \\brief Set the correct RTK backprojection type from gengetopt\n * Given a gengetopt bp_arg option from the rtkprojectors_section.ggo, will\n * set the corresponding enum value from rtk::IterativeConeBeamReconstructionFilter\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <class TArgsInfo, class TIterativeReconstructionFilter>\nvoid\nSetBackProjectionFromGgo(const TArgsInfo & args_info, TIterativeReconstructionFilter * recon)\n{\n  typename TIterativeReconstructionFilter::VolumeType::Pointer attenuationMap;\n  using VolumeType = typename TIterativeReconstructionFilter::VolumeType;\n  if (args_info.attenuationmap_given)\n  {\n    // Read an existing image to initialize the attenuation map\n    attenuationMap = itk::ReadImage<VolumeType>(args_info.attenuationmap_arg);\n  }\n\n  switch (args_info.bp_arg)\n  {\n    case (-1): // bp__NULL, keep default\n      break;\n    case (0): // bp_arg_VoxelBasedBackProjection\n      recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_VOXELBASED);\n      break;\n    case (1): // bp_arg_Joseph\n      recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_JOSEPH);\n      break;\n    case (2): // bp_arg_CudaVoxelBased\n      recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_CUDAVOXELBASED);\n      break;\n    case (3): // bp_arg_CudaRayCast\n      recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_CUDARAYCAST);\n      if (args_info.step_given)\n        recon->SetStepSize(args_info.step_arg);\n      break;\n    case (4): // bp_arg_JosephAttenuated\n      recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_JOSEPHATTENUATED);\n      if (args_info.attenuationmap_given)\n        recon->SetAttenuationMap(attenuationMap);\n      break;\n    case (5): // bp_arg_RotationBased\n      recon->SetBackProjectionFilter(TIterativeReconstructionFilter::BP_ZENG);\n      if (args_info.sigmazero_given)\n        recon->SetSigmaZero(args_info.sigmazero_arg);\n      if (args_info.alphapsf_given)\n        recon->SetAlphaPSF(args_info.alphapsf_arg);\n      if (args_info.attenuationmap_given)\n        recon->SetAttenuationMap(attenuationMap);\n      break;\n  }\n}\n\n/** \\brief Set the correct RTK forward projection type from gengetopt\n * Given a gengetopt fp_arg option from the rtkprojectors_section.ggo, will\n * set the corresponding enum value from rtk::IterativeConeBeamReconstructionFilter\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <class TArgsInfo, class TIterativeReconstructionFilter>\nvoid\nSetForwardProjectionFromGgo(const TArgsInfo & args_info, TIterativeReconstructionFilter * recon)\n{\n  typename TIterativeReconstructionFilter::VolumeType::Pointer attenuationMap;\n  using VolumeType = typename TIterativeReconstructionFilter::VolumeType;\n  if (args_info.attenuationmap_given)\n  {\n    // Read an existing image to initialize the attenuation map\n    attenuationMap = itk::ReadImage<VolumeType>(args_info.attenuationmap_arg);\n  }\n  using ClipImageType = itk::Image<double, TIterativeReconstructionFilter::VolumeType::ImageDimension>;\n  typename ClipImageType::Pointer inferiorClipImage, superiorClipImage;\n  if (args_info.inferiorclipimage_given)\n  {\n    // Read an existing image to initialize the attenuation map\n    inferiorClipImage = itk::ReadImage<ClipImageType>(args_info.inferiorclipimage_arg);\n  }\n  if (args_info.superiorclipimage_given)\n  {\n    // Read an existing image to initialize the attenuation map\n    superiorClipImage = itk::ReadImage<ClipImageType>(args_info.superiorclipimage_arg);\n  }\n\n  switch (args_info.fp_arg)\n  {\n    case (-1): // fp__NULL, keep default\n      break;\n    case (0): // fp_arg_Joseph\n      recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_JOSEPH);\n      if (args_info.superiorclipimage_given)\n        recon->SetSuperiorClipImage(superiorClipImage);\n      if (args_info.inferiorclipimage_given)\n        recon->SetInferiorClipImage(inferiorClipImage);\n      break;\n    case (1): // fp_arg_CudaRayCast\n      recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_CUDARAYCAST);\n      if (args_info.step_given)\n        recon->SetStepSize(args_info.step_arg);\n      break;\n    case (2): // fp_arg_JosephAttenuated\n      recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_JOSEPHATTENUATED);\n      if (args_info.superiorclipimage_given)\n        recon->SetSuperiorClipImage(superiorClipImage);\n      if (args_info.inferiorclipimage_given)\n        recon->SetInferiorClipImage(inferiorClipImage);\n      if (args_info.attenuationmap_given)\n        recon->SetAttenuationMap(attenuationMap);\n      break;\n    case (3): // fp_arg_RotationBased\n      recon->SetForwardProjectionFilter(TIterativeReconstructionFilter::FP_ZENG);\n      if (args_info.sigmazero_given)\n        recon->SetSigmaZero(args_info.sigmazero_arg);\n      if (args_info.alphapsf_given)\n        recon->SetAlphaPSF(args_info.alphapsf_arg);\n      if (args_info.attenuationmap_given)\n        recon->SetAttenuationMap(attenuationMap);\n      break;\n  }\n}\n\n} // namespace rtk\n\n#endif // rtkGgoFunctions_h\n"
  },
  {
    "path": "include/rtkGlobalResourceProbe.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkGlobalResourceProbe_h\n#define rtkGlobalResourceProbe_h\n\n#include <itkProcessObject.h>\n#include \"rtkResourceProbesCollector.h\"\n#include \"rtkWatcherForResourceProbe.h\"\n#include \"RTKExport.h\"\n#include <mutex>\n\nnamespace rtk\n{\n/** \\class GlobalResourceProbe\n * \\brief\n *\n * \\ingroup RTK OSSystemObjects\n * \\ingroup RTK ITKCommon\n */\n\nclass RTK_EXPORT GlobalResourceProbe : public itk::Object\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(GlobalResourceProbe);\n\n  /** Standard class type alias. */\n  using Self = GlobalResourceProbe;\n  using Superclass = itk::Object;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(GlobalResourceProbe);\n\n  /** This is a singleton pattern New.  There will only be ONE\n   * reference to a GlobalResourceProbe object per process.  Clients that\n   * call this must call Delete on the object so that the reference\n   * counting will work.   The single instance will be unreferenced when\n   * the program exits. */\n  static Pointer\n  New();\n\n  /** Return the singleton instance with no reference counting. */\n  static Pointer\n  GetInstance();\n\n  /** Set / Get macro for verbosity */\n  itkSetMacro(Verbose, bool);\n  itkGetMacro(Verbose, bool);\n\n  /** Start a probe with a particular name. If the time probe does not\n   * exist, it will be created */\n  virtual void\n  Start(const char * id);\n\n  /** Stop a time probe identified with a name */\n  virtual void\n  Stop(const char * id);\n\n  /** Report the summary of results from the probes */\n  virtual void\n  Report(std::ostream & os = std::cout) const;\n\n  /** Destroy the set of probes. New probes can be created after invoking this\n    method. */\n  virtual void\n  Clear();\n\n  /** Create a new watcher and store it */\n  virtual void\n  Watch(itk::ProcessObject * o);\n\n  /** Remove a watcher */\n  virtual void\n  Remove(const rtk::WatcherForResourceProbe * w);\n\nprotected:\n  GlobalResourceProbe();\n  ~GlobalResourceProbe() override;\n  void\n       PrintSelf(std::ostream & os, Indent indent) const override;\n  bool m_Verbose;\n\n  ResourceProbesCollector                     m_ResourceProbesCollector;\n  std::vector<rtk::WatcherForResourceProbe *> m_Watchers;\n\nprivate:\n  static Pointer m_Instance;\n  std::mutex     m_Mutex;\n};\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkHilbertImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkHilbertImageFilter_h\n#define rtkHilbertImageFilter_h\n\n#include <itkImageToImageFilter.h>\n\nnamespace rtk\n{\n/** \\class HilbertImageFilter\n *\n * \\brief Computes the complex analytic signal of a 1D signal\n *\n * The function reproduces the Matlab function \"hilbert\" which computes the\n * analytic signal using the Hilbert transform. In Matlab's code, references\n * are made to:\n * [Oppenheim and Schafer, Discrete-Time signal processing, 1998]\n * [Marple, IEEE Trans Sig Proc, 1999]\n *\n * \\test rtkamsterdamshroudtest\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT HilbertImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(HilbertImageFilter);\n\n  /** Standard class type alias. */\n  using Self = HilbertImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(HilbertImageFilter);\n\nprotected:\n  HilbertImageFilter() = default;\n  ~HilbertImageFilter() override = default;\n\n  void\n  GenerateData() override;\n\n}; // end of class\n\n} // end of namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkHilbertImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkHilbertImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkHilbertImageFilter_hxx\n#define rtkHilbertImageFilter_hxx\n\n\n#include <itkConfigure.h>\n#include <itkForwardFFTImageFilter.h>\n#include <itkComplexToComplexFFTImageFilter.h>\n#include <itkImageRegionIteratorWithIndex.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nHilbertImageFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  // Take the FFT of the input\n  auto fftFilt = itk::ForwardFFTImageFilter<TInputImage, TOutputImage>::New();\n  fftFilt->SetInput(this->GetInput());\n  fftFilt->Update();\n\n  TOutputImage * fft = fftFilt->GetOutput();\n\n  // Weights according to\n  // [Marple, IEEE Trans Sig Proc, 1999]\n  auto it = itk::ImageRegionIteratorWithIndex<TOutputImage>(fft, fft->GetLargestPossibleRegion());\n  it.Set(it.Get());\n  ++it;\n  int n = fft->GetLargestPossibleRegion().GetSize()[0];\n  for (int i = 1; i < n / 2 - 1; i++, ++it)\n    it.Set(2. * it.Get());\n  if (n % 2 == 1) // Odd\n    it.Set(2. * it.Get());\n  else\n    it.Set(1. * it.Get());\n  typename TOutputImage::PixelType val = 0.;\n  while (!it.IsAtEnd())\n  {\n    val = it.Get();\n    it.Set(0.);\n    ++it;\n  }\n\n  // Inverse FFT (although I had to set it to FORWARD to obtain the same as in Matlab,\n  // I really don't know why)\n#if !defined(USE_FFTWD)\n  if (typeid(typename TOutputImage::PixelType).name() == typeid(double).name())\n  {\n    itkExceptionMacro(<< \"FFTW with double has not been activated in ITK, cannot run.\");\n  }\n#endif\n#if !defined(USE_FFTWF)\n  if (typeid(typename TOutputImage::PixelType).name() == typeid(float).name())\n  {\n    itkExceptionMacro(<< \"FFTW with float has not been activated in ITK, cannot run.\");\n  }\n#endif\n\n  using InverseFFTFilterType = typename itk::ComplexToComplexFFTImageFilter<TOutputImage>;\n  auto invFilt = InverseFFTFilterType::New();\n  invFilt->SetTransformDirection(InverseFFTFilterType::TransformDirectionEnum::FORWARD);\n  invFilt->SetInput(fft);\n  invFilt->Update();\n\n  this->GraftOutput(invFilt->GetOutput());\n}\n\n} // end of namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkHisImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkHisImageIO_h\n#define rtkHisImageIO_h\n\n// itk include\n#include <itkImageIOBase.h>\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class HisImageIO\n * \\brief Class for reading His Image file format\n *\n * The his image file format is used by Perkin Elmer flat panels.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT HisImageIO : public itk::ImageIOBase\n{\npublic:\n  /** Standard class type alias. */\n  using Self = HisImageIO;\n  using Superclass = itk::ImageIOBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using PixelType = signed short int;\n\n  HisImageIO()\n    : Superclass()\n  {\n    ;\n  }\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(HisImageIO);\n\n  /*-------- This part of the interface deals with reading data. ------ */\n  void\n  ReadImageInformation() override;\n\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n\n  void\n  Read(void * buffer) override;\n\n  /*-------- This part of the interfaces deals with writing data. ----- */\n  virtual void\n  WriteImageInformation(bool /*keepOfStream*/)\n  {\n    ;\n  }\n\n  void\n  WriteImageInformation() override\n  {\n    WriteImageInformation(false);\n  }\n\n  bool\n  CanWriteFile(const char * filename) override;\n\n  void\n  Write(const void * buffer) override;\n\nprotected:\n  int m_HeaderSize;\n\n}; // end class HisImageIO\n} // namespace rtk\n\n#endif /* end #define rtkHisImageIO_h */\n"
  },
  {
    "path": "include/rtkHisImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkHisImageIOFactory_h\n#define rtkHisImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkHisImageIO.h\"\n#include \"rtkMacro.h\"\n\n// itk include\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class HisImageIOFactory\n * \\brief ITK factory for His file I/O.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT HisImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(HisImageIOFactory);\n\n  /** Standard class type alias. */\n  using Self = HisImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"His ImageIO Factory, allows the loading of His images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(HisImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\nprotected:\n  HisImageIOFactory();\n  ~HisImageIOFactory() override = default;\n  using myProductType = HisImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif /* end #define rtkHisImageIOFactory_h */\n"
  },
  {
    "path": "include/rtkHncImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkHncImageIO_h\n#define rtkHncImageIO_h\n\n// itk include\n#include <itkImageIOBase.h>\n#include \"itksys/SystemTools.hxx\"\n\n#if defined(_MSC_VER) && (_MSC_VER < 1600)\n// SR: taken from\n// #include \"msinttypes/stdint.h\"\n#else\n#  include <cstdint>\n#endif\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class HncImageIO\n *\n * Reads Hnc files (file format used by Varian for Obi raw data).\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT HncImageIO : public itk::ImageIOBase\n{\npublic:\n  /** Standard class type alias. */\n  using Self = HncImageIO;\n  using Superclass = itk::ImageIOBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using PixelType = unsigned short int;\n\n  typedef struct hnc_header\n  {\n    char         sFileType[32];\n    unsigned int FileLength;\n    char         sChecksumSpec[4];\n    unsigned int nCheckSum;\n    char         sCreationDate[8];\n    char         sCreationTime[8];\n    char         sPatientID[16];\n    unsigned int nPatientSer;\n    char         sSeriesID[16];\n    unsigned int nSeriesSer;\n    char         sSliceID[16];\n    unsigned int nSliceSer;\n    unsigned int SizeX;\n    unsigned int SizeY;\n    double       dSliceZPos;\n    char         sModality[16];\n    unsigned int nWindow;\n    unsigned int nLevel;\n    unsigned int nPixelOffset;\n    char         sImageType[4];\n    double       dGantryRtn;\n    double       dSAD;\n    double       dSFD;\n    double       dCollX1;\n    double       dCollX2;\n    double       dCollY1;\n    double       dCollY2;\n    double       dCollRtn;\n    double       dFieldX;\n    double       dFieldY;\n    double       dBladeX1;\n    double       dBladeX2;\n    double       dBladeY1;\n    double       dBladeY2;\n    double       dIDUPosLng;\n    double       dIDUPosLat;\n    double       dIDUPosVrt;\n    double       dIDUPosRtn;\n    double       dPatientSupportAngle;\n    double       dTableTopEccentricAngle;\n    double       dCouchVrt;\n    double       dCouchLng;\n    double       dCouchLat;\n    double       dIDUResolutionX;\n    double       dIDUResolutionY;\n    double       dImageResolutionX;\n    double       dImageResolutionY;\n    double       dEnergy;\n    double       dDoseRate;\n    double       dXRayKV;\n    double       dXRayMA;\n    double       dMetersetExposure;\n    double       dAcqAdjustment;\n    double       dCTProjectionAngle;\n    double       dCTNormChamber;\n    double       dGatingTimeTag;\n    double       dGating4DInfoX;\n    double       dGating4DInfoY;\n    double       dGating4DInfoZ;\n    double       dGating4DInfoTime;\n  } Hnc_header;\n\n  HncImageIO()\n    : Superclass()\n  {}\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(HncImageIO);\n\n  /*-------- This part of the interface deals with reading data. ------ */\n  void\n  ReadImageInformation() override;\n\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n\n  void\n  Read(void * buffer) override;\n\n  /*-------- This part of the interfaces deals with writing data. ----- */\n  virtual void\n  WriteImageInformation(bool /*keepOfStream*/)\n  {}\n\n  void\n  WriteImageInformation() override\n  {\n    WriteImageInformation(false);\n  }\n\n  bool\n  CanWriteFile(const char * filename) override;\n\n  void\n  Write(const void * buffer) override;\n\n}; // end class HncImageIO\n\n} // namespace rtk\n\n#endif /* end #define rtkHncImageIO_h */\n"
  },
  {
    "path": "include/rtkHncImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkHncImageIOFactory_h\n#define rtkHncImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkHncImageIO.h\"\n\n// itk include\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class HncImageIOFactory\n *\n * Factory for Hnc files (file format used by Varian for Obi raw data).\n *\n * \\author Geoff Hugo, VCU\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT HncImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  /** Standard class type alias. */\n  using Self = HncImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"Hnc ImageIO Factory, allows the loading of Hnc images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(HncImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\n  HncImageIOFactory(const Self &) = delete;\n  void\n  operator=(const Self &) = delete;\n\nprotected:\n  HncImageIOFactory();\n  ~HncImageIOFactory() override = default;\n  using myProductType = HncImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif // rtkHncImageIOFactory_h\n"
  },
  {
    "path": "include/rtkHndImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkHndImageIO_h\n#define rtkHndImageIO_h\n\n// itk include\n#include <itkImageIOBase.h>\n\n#if defined(_MSC_VER) && (_MSC_VER < 1600)\n// SR: taken from\n// #include \"msinttypes/stdint.h\"\n#else\n#  include <cstdint>\n#endif\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\nnamespace rtk\n{\n\n/** \\class HndImageIO\n * \\brief Class for reading Hnd Image file format\n *\n * Reads Hnd files (file format used by Varian for Obi raw data).\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT HndImageIO : public itk::ImageIOBase\n{\npublic:\n  /** Standard class type alias. */\n  using Self = HndImageIO;\n  using Superclass = itk::ImageIOBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using PixelType = signed short int;\n\n  typedef struct hnd_header\n  {\n    char         sFileType[32];\n    unsigned int FileLength;\n    char         sChecksumSpec[4];\n    unsigned int nCheckSum;\n    char         sCreationDate[8];\n    char         sCreationTime[8];\n    char         sPatientID[16];\n    unsigned int nPatientSer;\n    char         sSeriesID[16];\n    unsigned int nSeriesSer;\n    char         sSliceID[16];\n    unsigned int nSliceSer;\n    unsigned int SizeX;\n    unsigned int SizeY;\n    double       dSliceZPos;\n    char         sModality[16];\n    unsigned int nWindow;\n    unsigned int nLevel;\n    unsigned int nPixelOffset;\n    char         sImageType[4];\n    double       dGantryRtn;\n    double       dSAD;\n    double       dSFD;\n    double       dCollX1;\n    double       dCollX2;\n    double       dCollY1;\n    double       dCollY2;\n    double       dCollRtn;\n    double       dFieldX;\n    double       dFieldY;\n    double       dBladeX1;\n    double       dBladeX2;\n    double       dBladeY1;\n    double       dBladeY2;\n    double       dIDUPosLng;\n    double       dIDUPosLat;\n    double       dIDUPosVrt;\n    double       dIDUPosRtn;\n    double       dPatientSupportAngle;\n    double       dTableTopEccentricAngle;\n    double       dCouchVrt;\n    double       dCouchLng;\n    double       dCouchLat;\n    double       dIDUResolutionX;\n    double       dIDUResolutionY;\n    double       dImageResolutionX;\n    double       dImageResolutionY;\n    double       dEnergy;\n    double       dDoseRate;\n    double       dXRayKV;\n    double       dXRayMA;\n    double       dMetersetExposure;\n    double       dAcqAdjustment;\n    double       dCTProjectionAngle;\n    double       dCTNormChamber;\n    double       dGatingTimeTag;\n    double       dGating4DInfoX;\n    double       dGating4DInfoY;\n    double       dGating4DInfoZ;\n    double       dGating4DInfoTime;\n  } Hnd_header;\n\n  HndImageIO()\n    : Superclass()\n  {}\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(HndImageIO);\n\n  /*-------- This part of the interface deals with reading data. ------ */\n  void\n  ReadImageInformation() override;\n\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n\n  void\n  Read(void * buffer) override;\n\n  /*-------- This part of the interfaces deals with writing data. ----- */\n  virtual void\n  WriteImageInformation(bool /*keepOfStream*/)\n  {}\n\n  void\n  WriteImageInformation() override\n  {\n    WriteImageInformation(false);\n  }\n\n  bool\n  CanWriteFile(const char * filename) override;\n\n  void\n  Write(const void * buffer) override;\n\n}; // end class HndImageIO\n\n} // namespace rtk\n\n#endif /* end #define rtkHndImageIO_h */\n"
  },
  {
    "path": "include/rtkHndImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// #ifndef ITKHNDIMAGEIOFACTORY_H\n// #define ITKHNDIMAGEIOFACTORY_H\n\n#ifndef rtkHndImageIOFactory_h\n#define rtkHndImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkHndImageIO.h\"\n\n// itk include\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class HndImageIOFactory\n * \\brief ITK factory for Hnd file I/O.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT HndImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(HndImageIOFactory);\n\n  /** Standard class type alias. */\n  using Self = HndImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"His ImageIO Factory, allows the loading of His images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(HndImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\nprotected:\n  HndImageIOFactory();\n  ~HndImageIOFactory() override = default;\n  using myProductType = HndImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif // rtkHndImageIOFactory_h\n"
  },
  {
    "path": "include/rtkHomogeneousMatrix.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkHomogeneousMatrix_h\n#define rtkHomogeneousMatrix_h\n\n#include <itkMatrix.h>\n#include <itkImage.h>\n\nnamespace rtk\n{\n\n//--------------------------------------------------------------------\n/** \\brief Get IndexToPhysicalPoint matrix from an image (no accessor provided by ITK).\n *\n * The returned matrix is in homogeneous format.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\n// template <class TPixel, unsigned int VImageDimension>\ntemplate <class TImageType>\nitk::Matrix<double, TImageType::ImageDimension + 1, TImageType::ImageDimension + 1>\nGetIndexToPhysicalPointMatrix(const TImageType * image)\n{\n  const unsigned int Dimension = TImageType::ImageDimension;\n\n  itk::Matrix<double, Dimension + 1, Dimension + 1> matrix;\n  matrix.Fill(0.0);\n\n  itk::Index<Dimension>         index;\n  itk::Point<double, Dimension> point;\n\n  for (unsigned int j = 0; j < Dimension; j++)\n  {\n    index.Fill(0);\n    index[j] = 1;\n    image->TransformIndexToPhysicalPoint(index, point);\n    for (unsigned int i = 0; i < Dimension; i++)\n      matrix[i][j] = point[i] - image->GetOrigin()[i];\n  }\n  for (unsigned int i = 0; i < Dimension; i++)\n    matrix[i][Dimension] = image->GetOrigin()[i];\n  matrix[Dimension][Dimension] = 1.0;\n\n  return matrix;\n};\n\n//--------------------------------------------------------------------\n/** \\brief Get PhysicalPointToIndex matrix from an image (no accessor provided by ITK).\n *\n * The returned matrix is in homogeneous format.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\n// template <class TPixel, unsigned int VImageDimension>\ntemplate <class TImageType>\nitk::Matrix<double, TImageType::ImageDimension + 1, TImageType::ImageDimension + 1>\nGetPhysicalPointToIndexMatrix(const TImageType * image)\n{\n  using MatrixType = itk::Matrix<double, TImageType::ImageDimension + 1, TImageType::ImageDimension + 1>;\n  return MatrixType(GetIndexToPhysicalPointMatrix<TImageType>(image).GetInverse());\n};\n\n} // namespace rtk\n\n#endif // rtkHomogeneousMatrix_h\n"
  },
  {
    "path": "include/rtkI0EstimationProjectionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkI0EstimationProjectionFilter_h\n#define rtkI0EstimationProjectionFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkConfiguration.h\"\n\n#include <mutex>\n#include <vector>\n#include <string>\n\nnamespace rtk\n{\n/** \\class I0EstimationProjectionFilter\n *\n * \\brief Estimate the I0 value from the projection histograms\n *\n * \\author Sebastien Brousmiche\n *\n * \\test rtkI0estimationtest.cxx\n *\n * \\ingroup RTK InPlaceImageFilter\n */\n\ntemplate <class TInputImage = itk::Image<unsigned short, 3>,\n          class TOutputImage = TInputImage,\n          unsigned char bitShift = 2>\nclass ITK_TEMPLATE_EXPORT I0EstimationProjectionFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(I0EstimationProjectionFilter);\n\n  /** Standard class type alias. */\n  using Self = I0EstimationProjectionFilter<TInputImage, TOutputImage, bitShift>;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(I0EstimationProjectionFilter);\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using ImagePointer = typename InputImageType::Pointer;\n  using ImageConstPointer = typename InputImageType::ConstPointer;\n  using OutputImageRegionType = typename Superclass::OutputImageRegionType;\n  using InputImagePixelType = typename InputImageType::PixelType;\n\n  itkConceptMacro(InputImagePixelTypeIsInteger, (itk::Concept::IsInteger<InputImagePixelType>));\n\n  /** Main Output: estimation result. */\n  itkGetMacro(I0, InputImagePixelType);\n  itkGetMacro(I0fwhm, InputImagePixelType);\n  itkGetMacro(I0rls, InputImagePixelType);\n\n  /** Maximum encodable detector value if different from (2^16-1). The default\n   * is the minimum between 2^24-1 and the numerical limit of the input pixel\n   * type. This allows to limit histogram size to 2^(24-bitShift)-1. */\n  itkSetMacro(MaxPixelValue, InputImagePixelType);\n  itkGetMacro(MaxPixelValue, InputImagePixelType);\n\n  /** Expected I0 value (as a result of a detector calibration) */\n  itkSetMacro(ExpectedI0, InputImagePixelType);\n  itkGetMacro(ExpectedI0, InputImagePixelType);\n\n  /** RSL estimate coefficient */\n  itkSetMacro(Lambda, float);\n  itkGetMacro(Lambda, float);\n\n  /** Write Histograms in a csv file\n   * Is false by default */\n  itkSetMacro(Reset, bool);\n  itkGetConstMacro(Reset, bool);\n  itkBooleanMacro(Reset);\n\n  /** Write Histograms in a csv file\n   * Is false by default */\n  itkSetMacro(SaveHistograms, bool);\n  itkGetConstMacro(SaveHistograms, bool);\n  itkBooleanMacro(SaveHistograms);\n\nprotected:\n  I0EstimationProjectionFilter();\n  ~I0EstimationProjectionFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  void\n  ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, ThreadIdType threadId) override;\n\n  void\n  AfterThreadedGenerateData() override;\n\nprivate:\n  // Input variables\n  InputImagePixelType m_ExpectedI0;    // Expected I0 value (as a result of a\n                                       // detector calibration)\n  InputImagePixelType m_MaxPixelValue; // Maximum encodable detector value if\n                                       // different from (2^16-1)\n  float m_Lambda;                      // RLS coefficient\n  bool  m_SaveHistograms;              // Save histograms in a output file\n  bool  m_Reset;                       // Reset counters\n\n  // Secondary inputs\n  std::vector<unsigned int>::size_type m_NBins; // Histogram size, computed\n                                                // from m_MaxPixelValue and bitshift\n\n  // Main variables\n  std::vector<unsigned int> m_Histogram; // compressed (bitshifted) histogram\n  InputImagePixelType       m_I0;        // I0 estimate with no a priori for\n                                         // each new image\n  InputImagePixelType m_I0rls;           // Updated RLS estimate\n  InputImagePixelType m_I0fwhm;          // FWHM of the I0 mode\n\n  // Secondary variables\n  unsigned int m_Np;                    // Number of previously analyzed\n                                        // images\n  InputImagePixelType m_Imin, m_Imax;   // Define the range of consistent\n                                        // pixels in histogram\n  unsigned int m_DynThreshold;          // Detector values with a frequency of\n                                        // less than dynThreshold outside\n                                        // min/max are discarded\n  unsigned int m_LowBound, m_HighBound; // Lower/Upper bounds of the I0 mode\n                                        // at half width\n\n  std::mutex m_Mutex;\n  int        m_Nsync;\n  int        m_Nthreads;\n};\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkI0EstimationProjectionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkI0EstimationProjectionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkI0EstimationProjectionFilter_hxx\n#define rtkI0EstimationProjectionFilter_hxx\n\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n#include <algorithm>\n#include <fstream>\n\nnamespace rtk\n{\ntemplate <class TInputImage, class TOutputImage, unsigned char bitShift>\nI0EstimationProjectionFilter<TInputImage, TOutputImage, bitShift>::I0EstimationProjectionFilter()\n{\n  this->DynamicMultiThreadingOff();\n  this->SetNumberOfWorkUnits(itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads());\n\n  m_MaxPixelValue = (InputImagePixelType)((1 << 24) - 1);\n  m_ExpectedI0 = m_MaxPixelValue;\n  m_SaveHistograms = false;\n  m_Reset = false;\n\n  m_I0 = 0;\n  m_I0fwhm = 0;\n  m_Np = 0;\n  m_I0rls = 0.;\n  m_Lambda = 0.8;\n  m_DynThreshold = 20;\n\n  m_Imin = 0;\n  m_Imax = m_MaxPixelValue;\n}\n\ntemplate <class TInputImage, class TOutputImage, unsigned char bitShift>\nvoid\nI0EstimationProjectionFilter<TInputImage, TOutputImage, bitShift>::BeforeThreadedGenerateData()\n{\n  m_NBins = (std::vector<unsigned int>::size_type)((m_MaxPixelValue + 1) >> bitShift);\n  m_Imax = m_MaxPixelValue;\n  m_Histogram.resize(m_NBins, 0);\n\n  auto it = m_Histogram.begin();\n\n  for (; it != m_Histogram.end(); ++it)\n  {\n    *it = 0;\n  }\n\n  m_Nthreads = this->GetNumberOfWorkUnits();\n  m_Nsync = 0;\n\n  if (m_Reset)\n  {\n    m_Np = 0;\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage, unsigned char bitShift>\nvoid\nI0EstimationProjectionFilter<TInputImage, TOutputImage, bitShift>::ThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread,\n  ThreadIdType                  itkNotUsed(threadId))\n{\n  itk::ImageRegionConstIterator<InputImageType> itIn(this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<InputImageType>      itOut(this->GetOutput(), outputRegionForThread);\n\n  itIn.GoToBegin();\n  itOut.GoToBegin();\n  if (this->GetInput() != this->GetOutput()) // If not in place, copy is required\n  {\n    while (!itIn.IsAtEnd())\n    {\n      itOut.Set(itIn.Get());\n      ++itIn;\n      ++itOut;\n    }\n  }\n\n  // Computation of region histogram\n\n  std::vector<unsigned int> m_thHisto; // Per-thread histogram\n  m_thHisto.resize(m_NBins, 0);\n\n  // Fill in its own histogram\n  itIn.GoToBegin();\n  while (!itIn.IsAtEnd())\n  {\n    m_thHisto[itIn.Get() >> bitShift]++;\n    ++itIn;\n  }\n\n  // Merge into global histogram\n  m_Mutex.lock();\n  {\n    // Add its results to shared histogram\n    for (unsigned int i = 0; i < m_NBins; ++i)\n    {\n      m_Histogram[i] += m_thHisto[i];\n    }\n\n    // The last thread has to do something more\n    ++m_Nsync;\n    if (m_Nsync >= m_Nthreads)\n    {\n      // RMQ 1 : there might be pixels outside the min-max region. They are\n      // supposed to be inconsistents (unused detector lines, dead pixels,...)\n\n      // Search for upper bound of the histogram : gives the highest intensity\n      // value\n      m_Imax = m_NBins - 1;\n      while ((m_Histogram[m_Imax] <= m_DynThreshold) && (m_Imax > 0))\n      {\n        --m_Imax;\n      }\n      while ((m_Histogram[m_Imax] == 0) && (m_Imax < m_NBins)) // Get back\n                                                               // to zero\n      {\n        ++m_Imax;\n      }\n\n      // Search for lower bound of the histogram: gives the lowest intensity\n      // value\n      m_Imin = 0;\n      while ((m_Histogram[m_Imin] <= m_DynThreshold) && (m_Imin < m_Imax))\n      {\n        ++m_Imin;\n      }\n      while ((m_Histogram[m_Imin] == 0) && (m_Imin > 0)) // Get back to\n                                                         // zero\n      {\n        --m_Imin;\n      }\n\n      m_Imin = (m_Imin << bitShift);\n      m_Imax = (m_Imax << bitShift);\n\n      // If Imax near zero - Potentially no exposure\n      // If Imin near Imax - problem to be fixed - No object\n      // If Imax very close to MaxPixelValue then possible saturation\n    }\n  }\n  m_Mutex.unlock();\n}\n\ntemplate <class TInputImage, class TOutputImage, unsigned char bitShift>\nvoid\nI0EstimationProjectionFilter<TInputImage, TOutputImage, bitShift>::AfterThreadedGenerateData()\n{\n  // Search for the background mode in the last quarter of the histogram\n\n  unsigned int        startIdx = (3 * (m_Imax >> 2)) >> bitShift;\n  unsigned int        idx = startIdx;\n  unsigned int        maxId = startIdx;\n  InputImagePixelType maxVal = m_Histogram[startIdx];\n\n  while (idx < (unsigned int)(m_Imax >> bitShift))\n  {\n    if (m_Histogram[idx] >= maxVal)\n    {\n      maxVal = m_Histogram[idx];\n      maxId = idx;\n    }\n    ++idx;\n  }\n  m_I0 = InputImagePixelType((maxId) << bitShift);\n  m_I0rls = (m_Np > 1) ? (InputImagePixelType)((float)(m_I0rls * m_Lambda) + (float)(m_I0) * (1. - m_Lambda)) : m_I0;\n\n  // If estimated I0 at the boundaries, either startIdx or Imax then we missed\n  // smth or no background mode\n\n  auto         widthval = (InputImagePixelType)(float)(maxVal >> 1);\n  unsigned int lowBound = maxId;\n  while ((m_Histogram[lowBound] > widthval) && (lowBound > 0))\n  {\n    lowBound--;\n  }\n\n  unsigned int highBound = maxId;\n  while ((m_Histogram[highBound] > widthval) && (highBound < m_Imax))\n  {\n    highBound++;\n  }\n\n  unsigned int peakFwhm = ((highBound - lowBound) << bitShift);\n  m_I0fwhm = peakFwhm;\n\n  m_LowBound = (lowBound << bitShift);\n  m_HighBound = (highBound << bitShift);\n\n  ++m_Np;\n\n  if (m_SaveHistograms)\n  {\n    std::ofstream paramFile;\n    paramFile.open(\"i0est_histogram.csv\", std::ofstream::out | std::ofstream::app);\n    std::vector<unsigned int>::const_iterator itf = m_Histogram.begin();\n    for (; itf != m_Histogram.end(); ++itf)\n    {\n      paramFile << *itf << \",\";\n    }\n    paramFile.close();\n  }\n}\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkIOFactories.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkIOFactories_h\n#define rtkIOFactories_h\n\n#include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** Register all rtk IO factories. */\nvoid RTK_EXPORT\nRegisterIOFactories();\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkImagXGeometryReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkImagXGeometryReader_h\n#define rtkImagXGeometryReader_h\n\n#include <itkLightProcessObject.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\n#include <vector>\n\nnamespace rtk\n{\n\n/** \\class ImagXGeometryReader\n *\n * Creates a 3D circular geometry from the IBA data set.\n *\n * \\test rtkimagxtest.cxx\n *\n * \\author Marc Vila, C. Mory, S. Brousmiche (IBA)\n *\n * \\ingroup RTK IOFilters\n */\ntemplate <typename TInputImage>\nclass ITK_TEMPLATE_EXPORT ImagXGeometryReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ImagXGeometryReader);\n\n  /** Standard type alias */\n  using Self = ImagXGeometryReader;\n  using Superclass = itk::LightProcessObject;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ImagXGeometryReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Get the pointer to the generated geometry object. */\n  itkGetMacro(Geometry, GeometryType::Pointer);\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using InputImageRegionType = typename InputImageType::RegionType;\n  using InputImagePixelType = typename InputImageType::PixelType;\n  using FileNamesContainer = std::vector<std::string>;\n\n  /** Set the iMagX calibration xml file\n   */\n  itkGetMacro(CalibrationXMLFileName, std::string);\n  itkSetMacro(CalibrationXMLFileName, std::string);\n\n  /** Set the iMagX room setup xml file*/\n  itkGetMacro(RoomXMLFileName, std::string);\n  itkSetMacro(RoomXMLFileName, std::string);\n\n  /** Set the vector of strings that contains the projection file names. Files\n   * are processed in sequential order. */\n  void\n  SetProjectionsFileNames(const FileNamesContainer & name)\n  {\n    if (m_ProjectionsFileNames != name)\n    {\n      m_ProjectionsFileNames = name;\n      this->Modified();\n    }\n  }\n  const FileNamesContainer &\n  GetProjectionsFileNames() const\n  {\n    return m_ProjectionsFileNames;\n  }\n\nprotected:\n  ImagXGeometryReader()\n    : m_Geometry(nullptr)\n    , m_CalibrationXMLFileName(\"\")\n    , m_RoomXMLFileName(\"\") {};\n\n  ~ImagXGeometryReader() override = default;\n\n\nprivate:\n  void\n  GenerateData() override;\n\n  // DICOM tag for AI versions\n  static const std::string m_AI_VERSION_1p2;\n  static const std::string m_AI_VERSION_1p5;\n  static const std::string m_AI_VERSION_2pX;\n\n  // DICOM tags depend on AI version\n  std::string\n  getAIversion();\n\n  // Structure containing the flexmap (for AI versions >= 2.0)\n  struct FlexmapType\n  {\n    bool               isValid;\n    std::string        activeArcName;\n    std::string        activeGeocalUID;\n    float              sid, sdd, sourceToNozzleOffsetAngle;\n    float              constantDetectorOffset, xMinus, xPlus;\n    bool               isCW;\n    std::vector<float> anglesDeg;  // Gantry angles [deg]\n    std::vector<float> Px, Py, Pz, // Detector translations\n      Rx, Ry, Rz,                  // Detector rotations\n      Tx, Ty, Tz;                  // Source translations\n  };\n\n  FlexmapType\n  GetGeometryForAI2p1();\n\n  struct InterpResultType\n  {\n    int   id0, id1; // indices of angles just below and above the target angle\n    float a0, a1;   // weights (1/distance) to angles below and above\n  };\n\n  InterpResultType\n  interpolate(const std::vector<float> & flexAngles, bool bIsCW, float angleDegree);\n\n  // Structure containing the calibration models (for AI versions < 2.0)\n  struct CalibrationModelType\n  {\n    bool               isValid;\n    float              sid, sdd, sourceToNozzleOffsetAngle;\n    std::vector<float> Px, Py, Pz, // Detector translations model\n      Rx, Ry, Rz,                  // Detector rotations model\n      Tx, Ty, Tz;                  // Source translations model\n\n    CalibrationModelType()\n    {\n      sourceToNozzleOffsetAngle = -90.f;\n      Px = std::vector<float>(5, 0.f);\n      Py = std::vector<float>(5, 0.f);\n      Pz = std::vector<float>(5, 0.f);\n      Rx = std::vector<float>(5, 0.f);\n      Ry = std::vector<float>(5, 0.f);\n      Rz = std::vector<float>(5, 0.f);\n      Tx = std::vector<float>(5, 0.f);\n      Ty = std::vector<float>(5, 0.f);\n      Tz = std::vector<float>(5, 0.f);\n    }\n  };\n\n  CalibrationModelType\n  GetGeometryForAI1p5();\n\n  CalibrationModelType\n  GetGeometryForAI1p5FromXMLFiles();\n\n  bool\n  isCW(const std::vector<float> & angles);\n\n  std::vector<float>\n  getInterpolatedValue(const InterpResultType &   ires,\n                       const std::vector<float> & Dx,\n                       const std::vector<float> & Dy,\n                       const std::vector<float> & Dz);\n\n  // Evaluate the calibration models for a given angle\n  std::vector<float>\n  getDeformations(float                      gantryAngle,\n                  const std::vector<float> & Dx,\n                  const std::vector<float> & Dy,\n                  const std::vector<float> & Dz);\n\n  void\n  addEntryToGeometry(float                gantryAngleDegree,\n                     float                nozzleToRadAngleOffset,\n                     float                sid,\n                     float                sdd,\n                     std::vector<float> & detTrans,\n                     std::vector<float> & detRot,\n                     std::vector<float> & srcTrans);\n\n  void\n  addEntryToGeometry(const FlexmapType & f, float gantryAngle);\n\n  void\n  addEntryToGeometry(const CalibrationModelType & c, float gantryAngle);\n\n  GeometryType::Pointer m_Geometry;\n  std::string           m_CalibrationXMLFileName;\n  std::string           m_RoomXMLFileName;\n  FileNamesContainer    m_ProjectionsFileNames;\n};\n\n} // namespace rtk\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkImagXGeometryReader.hxx\"\n#endif\n\n#endif // rtkImagXGeometryReader_h\n"
  },
  {
    "path": "include/rtkImagXGeometryReader.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkImagXGeometryReader_hxx\n#define rtkImagXGeometryReader_hxx\n\n\n#include \"rtkMacro.h\"\n#include \"rtkImagXXMLFileReader.h\"\n#include <itkDOMNodeXMLReader.h>\n#include <itkImageFileReader.h>\n#include <itkGDCMImageIO.h>\n\n#include <string>\n#include <istream>\n#include <iterator>\n\nnamespace rtk\n{\ntemplate <typename TInputImage>\nconst std::string ImagXGeometryReader<TInputImage>::m_AI_VERSION_1p2 = \"IMAGX:1.2\";\n\ntemplate <typename TInputImage>\nconst std::string ImagXGeometryReader<TInputImage>::m_AI_VERSION_1p5 = \"IMAGX:1.6\";\n\ntemplate <typename TInputImage>\nconst std::string ImagXGeometryReader<TInputImage>::m_AI_VERSION_2pX = \"adaPTinsight: 2\";\n\ntemplate <typename TInputImage>\ntypename ImagXGeometryReader<TInputImage>::FlexmapType\nImagXGeometryReader<TInputImage>::GetGeometryForAI2p1()\n{\n  FlexmapType F;\n\n  F.isValid = false;\n\n  // Read the dcmdump of the geocal tag (3001,1018)\n\n  auto readerXML = itk::DOMNodeXMLReader::New();\n  readerXML->SetFileName(m_CalibrationXMLFileName);\n  readerXML->Update();\n  const itk::DOMNodeXMLReader::OutputType * XMLFile = readerXML->GetOutput();\n\n  itk::DOMNode::ConstChildrenListType list_child;\n  XMLFile->GetAllChildren(list_child);\n\n  bool                             arcFound = false;\n  bool                             FPOffsetfFound = false;\n  bool                             gantryParametersFound = false;\n  itk::DOMNode::AttributesListType list;\n  for (const auto & child : list_child)\n  {\n    std::string tagName = child->GetName();\n\n    // 1. From all available arcs, find the active one\n    if (!tagName.compare(\"arc\") && !arcFound)\n    {\n      list.clear();\n      child->GetAllAttributes(list);\n      for (const auto & element : list)\n      {\n        std::string subTagName = element.first.c_str();\n        std::string tagValue = element.second.c_str();\n        if (!subTagName.compare(\"name\"))\n        {\n          F.activeArcName = tagValue;\n        }\n        else if (!subTagName.compare(\"geoCalModelUid\"))\n        {\n          F.activeGeocalUID = tagValue;\n        }\n        else if (!subTagName.compare(\"active\") && tagValue == \"true\")\n        {\n          arcFound = true;\n        }\n      }\n    }\n\n    // 2. Check detector offset values in MINUS/PLUS positions\n    if (!tagName.compare(\"FPOffsets\"))\n    {\n      bool xPlusFound = false;\n      bool xMinusFound = false;\n      list.clear();\n      child->GetAllAttributes(list);\n      for (const auto & element : list)\n      {\n        std::string subTagName = element.first.c_str();\n        std::string tagValue = element.second.c_str();\n        if (!subTagName.compare(\"xPlus\"))\n        {\n          F.xPlus = std::stod(tagValue.c_str());\n          xPlusFound = true;\n        }\n        else if (!subTagName.compare(\"xMinus\"))\n        {\n          F.xMinus = std::stod(tagValue.c_str());\n          xMinusFound = true;\n        }\n      }\n\n      FPOffsetfFound = xPlusFound & xMinusFound;\n    }\n\n    // 3. Get gantry parameters\n    if (!tagName.compare(\"gantryParameters\"))\n    {\n      bool sidFound = false;\n      bool sadFound = false;\n      bool angleOffsetFound = false;\n      list.clear();\n      child->GetAllAttributes(list);\n      for (const auto & element : list)\n      {\n        std::string subTagName = element.first.c_str();\n        std::string subTagValue = element.second.c_str();\n        if (!subTagName.compare(\"sid\"))\n        {\n          F.sdd = std::stod(subTagValue.c_str());\n          sidFound = true;\n        }\n        else if (!subTagName.compare(\"sad\"))\n        {\n          F.sid = std::stod(subTagValue.c_str());\n          sadFound = true;\n        }\n        else if (!subTagName.compare(\"sourceToNozzleOffsetAngle\"))\n        {\n          F.sourceToNozzleOffsetAngle = 0; // std::stod(subTagValue.c_str());\n          angleOffsetFound = true;\n        }\n      }\n      gantryParametersFound = sidFound & sadFound & angleOffsetFound;\n    }\n  }\n\n  // Depending on arc found\n  bool flexmapFoundAndLoaded = false;\n  if (arcFound)\n  {\n    std::cout << \"Found active arc '\" << F.activeArcName << \"' linked to geocal UID '\" << F.activeGeocalUID << \"'\"\n              << std::endl;\n\n    // Parse tag and check if 'PLUS' or 'MINUS'\n    F.constantDetectorOffset = 0.f;\n    if (F.activeArcName.find(\"PLUS\") != std::string::npos)\n    {\n      F.constantDetectorOffset = F.xPlus;\n    }\n    else if (F.activeArcName.find(\"MINUS\") != std::string::npos)\n    {\n      F.constantDetectorOffset = F.xMinus;\n    }\n\n    // Get flexmap\n    for (const auto & child : list_child)\n    {\n      if (child->GetName() == \"geometricalCalibrationModels\")\n      {\n        itk::DOMNode::ConstChildrenListType list_geocals;\n        child->GetAllChildren(list_geocals);\n\n        for (const auto & list_geocal : list_geocals)\n        {\n          if (list_geocal->GetName() == \"geoCalModel\")\n          {\n            list.clear();\n            list_geocal->GetAllAttributes(list);\n            for (const auto & element : list)\n            {\n              std::string tagName = element.first.c_str();\n              std::string tagValue = element.second.c_str();\n              if (tagName == \"uid\" && tagValue == F.activeGeocalUID)\n              {\n                flexmapFoundAndLoaded = true;\n              }\n            }\n          }\n\n          if (flexmapFoundAndLoaded)\n          {\n            itk::DOMNode::ConstChildrenListType list_flexmap;\n            list_geocal->GetAllChildren(list_flexmap);\n\n            for (const auto & flexmap : list_flexmap)\n            {\n              std::string        str = dynamic_cast<const itk::DOMTextNode *>(flexmap)->GetText();\n              std::stringstream  iss(str);\n              std::vector<float> v;\n              while (iss.good())\n              {\n                std::string substr;\n                std::getline(iss, substr, ',');\n                v.push_back(std::stod(substr.c_str()));\n              }\n\n              if (v.size() == 10)\n              {\n                F.anglesDeg.push_back(v[0]);\n                F.Tx.push_back(v[1]);\n                F.Ty.push_back(v[2]);\n                F.Tz.push_back(v[3]);\n                F.Px.push_back(v[4] + F.constantDetectorOffset);\n                F.Py.push_back(v[5]);\n                F.Pz.push_back(v[6]);\n                F.Rx.push_back(v[7]);\n                F.Ry.push_back(v[8]);\n                F.Rz.push_back(v[9]);\n              }\n            }\n            flexmapFoundAndLoaded = false; // One flexmap already loaded\n          }\n\n          if (F.anglesDeg.empty())\n          {\n            flexmapFoundAndLoaded = false;\n          }\n        }\n      }\n    }\n  }\n\n  F.isCW = this->isCW(F.anglesDeg); // Needed for flexmap sampling\n  F.isValid = arcFound & FPOffsetfFound & gantryParametersFound & flexmapFoundAndLoaded;\n\n  return F;\n}\n\ntemplate <typename TInputImage>\nbool\nImagXGeometryReader<TInputImage>::isCW(const std::vector<float> & angles)\n{\n  std::vector<float> cp;\n  std::copy(angles.begin(), angles.end(), std::back_inserter(cp));\n  std::nth_element(cp.begin(), cp.begin() + cp.size() / 2, cp.end());\n\n  return (cp[cp.size() / 2] >= 0.f) ? true : false;\n}\n\ntemplate <typename TInputImage>\ntypename ImagXGeometryReader<TInputImage>::CalibrationModelType\nImagXGeometryReader<TInputImage>::GetGeometryForAI1p5()\n{\n  CalibrationModelType Cm;\n\n  Cm.isValid = false;\n\n  // Create and set ImageIO\n  itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(m_ProjectionsFileNames[0].c_str(),\n                                                                         itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n  imageIO = itk::GDCMImageIO::New();\n  dynamic_cast<itk::GDCMImageIO *>(imageIO.GetPointer())->LoadPrivateTagsOn();\n\n  // Define, create and set projection reader\n  using ReaderType = itk::ImageFileReader<TInputImage>;\n  auto reader = ReaderType::New();\n  reader->SetImageIO(imageIO);\n  reader->SetFileName(m_ProjectionsFileNames[0]);\n  reader->UpdateOutputInformation();\n\n  // Read room setup parameters in the DICOM info of the first projection\n  std::string roomSetupTagKey = \"3001|0012\";\n  std::string roomSetupInfo;\n  dynamic_cast<itk::GDCMImageIO *>(imageIO.GetPointer())->GetValueFromTag(roomSetupTagKey, roomSetupInfo);\n\n  // Extract SID, SDD and angle offset from the roomSetupInfo\n  auto               parser = itk::DOMNodeXMLReader::New();\n  std::istringstream is(roomSetupInfo);\n  parser->Update(is);\n\n  Cm.sid = std::stod(parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"Distances\")->GetAttribute(\"sid\").c_str());\n  Cm.sdd = std::stod(parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"Distances\")->GetAttribute(\"sdd\").c_str());\n  Cm.sourceToNozzleOffsetAngle =\n    std::stod(parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"AngleOffset\")->GetAttribute(\"projection\").c_str());\n\n  // Read calibration model's parameters in the DICOM info of the first projection\n  std::string calibrationTagKey = \"3001|0013\";\n  std::string calibrationInfo;\n  dynamic_cast<itk::GDCMImageIO *>(imageIO.GetPointer())->GetValueFromTag(calibrationTagKey, calibrationInfo);\n\n  // Extract calibration model's parameters from calibrationInfo\n  is.clear();\n  is.str(calibrationInfo);\n  parser->Update(is);\n\n  itk::DOMNode::AttributesListType listPx, listPy, listPz, listRx, listRy, listRz, listTx, listTy, listTz;\n  parser->GetOutput()\n    ->GetChild(\"Axis\")\n    ->GetChild(\"DetectorTranslation\")\n    ->GetChild(\"Px\")\n    ->GetAllAttributes(listPx, true);\n  parser->GetOutput()\n    ->GetChild(\"Axis\")\n    ->GetChild(\"DetectorTranslation\")\n    ->GetChild(\"Py\")\n    ->GetAllAttributes(listPy, true);\n  parser->GetOutput()\n    ->GetChild(\"Axis\")\n    ->GetChild(\"DetectorTranslation\")\n    ->GetChild(\"Pz\")\n    ->GetAllAttributes(listPz, true);\n  parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"DetectorRotation\")->GetChild(\"Rx\")->GetAllAttributes(listRx, true);\n  parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"DetectorRotation\")->GetChild(\"Ry\")->GetAllAttributes(listRy, true);\n  parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"DetectorRotation\")->GetChild(\"Rz\")->GetAllAttributes(listRz, true);\n  parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"SourceTranslation\")->GetChild(\"Tx\")->GetAllAttributes(listTx, true);\n  parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"SourceTranslation\")->GetChild(\"Ty\")->GetAllAttributes(listTy, true);\n  parser->GetOutput()->GetChild(\"Axis\")->GetChild(\"SourceTranslation\")->GetChild(\"Tz\")->GetAllAttributes(listTz, true);\n\n  for (unsigned int i = 0; i < 5; i++)\n  {\n    listPx.pop_front();\n    Cm.Px[i] = std::stod(listPx.front().second.c_str());\n    listPy.pop_front();\n    Cm.Py[i] = std::stod(listPy.front().second.c_str());\n    listPz.pop_front();\n    Cm.Pz[i] = std::stod(listPz.front().second.c_str());\n    listRx.pop_front();\n    Cm.Rx[i] = std::stod(listRx.front().second.c_str());\n    listRy.pop_front();\n    Cm.Ry[i] = std::stod(listRy.front().second.c_str());\n    listRz.pop_front();\n    Cm.Rz[i] = std::stod(listRz.front().second.c_str());\n    listTx.pop_front();\n    Cm.Tx[i] = std::stod(listTx.front().second.c_str());\n    listTy.pop_front();\n    Cm.Ty[i] = std::stod(listTy.front().second.c_str());\n    listTz.pop_front();\n    Cm.Tz[i] = std::stod(listTz.front().second.c_str());\n  }\n\n  Cm.isValid = true;\n  return Cm;\n}\n\ntemplate <typename TInputImage>\ntypename ImagXGeometryReader<TInputImage>::CalibrationModelType\nImagXGeometryReader<TInputImage>::GetGeometryForAI1p5FromXMLFiles()\n{\n  CalibrationModelType C;\n\n  C.isValid = true;\n\n  // Only for AI version less than 2.0\n  // Reading iMagX calibration file\n  // iMagX axisName parameter\n  std::string axisName, sid_s, sdd_s;\n\n  auto readerXML = itk::DOMNodeXMLReader::New();\n  readerXML->SetFileName(m_CalibrationXMLFileName);\n  readerXML->Update();\n  const itk::DOMNodeXMLReader::OutputType * XMLFile = readerXML->GetOutput();\n\n  itk::DOMNode::AttributesListType    list;\n  itk::DOMNode::ConstChildrenListType list_child;\n  XMLFile->GetAllChildren(list_child);\n\n  for (const auto & child : list_child)\n  {\n    child->GetAllAttributes(list);\n    for (auto & element : list)\n    {\n      if (element.first.c_str() == std::string(\"axis\"))\n        axisName = element.second.c_str();\n    }\n\n    // If cbct axis then extract deformation model parameters\n    if (axisName == std::string(\"CBCT\"))\n    {\n      itk::DOMNode::ConstChildrenListType list_child2;\n      child->GetAllChildren(list_child2);\n      for (const auto & child2 : list_child2)\n      {\n        itk::DOMNode::ConstChildrenListType list_child3;\n        child2->GetAllChildren(list_child3);\n        unsigned int p = 0;\n        for (unsigned int n = 0; n < list_child3.size(); n++, p++)\n        {\n          itk::DOMNode::AttributesListType list2;\n          list_child3[n]->GetAllAttributes(list2);\n          unsigned int m = 0;\n          for (auto & element : list2)\n          {\n            if ((list_child3[n]->GetName() == std::string(\"Px\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Px[m - 1] = std::stod(element.second.c_str());\n            else if ((list_child3[n]->GetName() == std::string(\"Py\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Py[m - 1] = std::stod(element.second.c_str());\n            else if ((list_child3[n]->GetName() == std::string(\"Pz\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Pz[m - 1] = std::stod(element.second.c_str());\n            else if ((list_child3[n]->GetName() == std::string(\"Rx\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Rx[m - 1] = std::stod(element.second.c_str());\n            else if ((list_child3[n]->GetName() == std::string(\"Ry\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Ry[m - 1] = std::stod(element.second.c_str());\n            else if ((list_child3[n]->GetName() == std::string(\"Rz\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Rz[m - 1] = std::stod(element.second.c_str());\n            else if ((list_child3[n]->GetName() == std::string(\"Tx\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Tx[m - 1] = std::stod(element.second.c_str());\n            else if ((list_child3[n]->GetName() == std::string(\"Ty\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Ty[m - 1] = std::stod(element.second.c_str());\n            else if ((list_child3[n]->GetName() == std::string(\"Tz\")) && (element.first.c_str() != std::string(\"MSE\")))\n              C.Tz[m - 1] = std::stod(element.second.c_str());\n\n            ++m;\n          }\n        }\n      }\n    }\n  }\n  list.clear();\n  list_child.clear();\n\n  // Reading iMagX room setup for SID and SDD\n  readerXML->SetFileName(m_RoomXMLFileName);\n  readerXML->Update();\n\n  XMLFile = readerXML->GetOutput();\n  XMLFile->GetAllChildren(list_child);\n\n  for (const auto & child : list_child)\n  {\n    child->GetAllAttributes(list);\n    for (auto & element : list)\n    {\n      if (element.first.c_str() == std::string(\"axis\"))\n        axisName = element.second.c_str();\n    }\n\n    // If cbct axis then extract sdd and sid parameters\n    if (axisName == std::string(\"CBCT\"))\n    {\n      itk::DOMNode::ConstChildrenListType list_child2;\n      child->GetAllChildren(list_child2);\n      for (const auto & child2 : list_child2)\n      {\n        itk::DOMNode::AttributesListType list2;\n        child2->GetAllAttributes(list2);\n        for (auto & element : list2)\n        {\n          if (element.first.c_str() == std::string(\"sdd\"))\n            sdd_s = element.second.c_str();\n          if (element.first.c_str() == std::string(\"sid\"))\n            sid_s = element.second.c_str();\n        }\n      }\n    }\n  }\n  C.sid = std::stod(sid_s.c_str());\n  C.sdd = std::stod(sdd_s.c_str());\n\n  return C;\n}\n\ntemplate <typename TInputImage>\nstd::string\nImagXGeometryReader<TInputImage>::getAIversion()\n{\n  // Create and set ImageIO\n  itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(m_ProjectionsFileNames[0].c_str(),\n                                                                         itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n\n  imageIO = itk::GDCMImageIO::New();\n  dynamic_cast<itk::GDCMImageIO *>(imageIO.GetPointer())->LoadPrivateTagsOn();\n\n  // Define, create and set projection reader\n  using ReaderType = itk::ImageFileReader<TInputImage>;\n  auto reader = ReaderType::New();\n  reader->SetImageIO(imageIO);\n  reader->SetFileName(m_ProjectionsFileNames[0]);\n  reader->UpdateOutputInformation();\n\n  // Read room setup parameters in the DICOM info of the first projection\n  std::string AIVersionTagKey = \"0018|1020\";\n  std::string AIVersion = \"\";\n  dynamic_cast<itk::GDCMImageIO *>(imageIO.GetPointer())->GetValueFromTag(AIVersionTagKey, AIVersion);\n\n  return AIVersion;\n}\n\ntemplate <typename TInputImage>\nvoid\nImagXGeometryReader<TInputImage>::GenerateData()\n{\n  const std::string version = getAIversion();\n\n  bool isImagX1p2 = (version.find(m_AI_VERSION_1p2) != std::string::npos);\n  bool isImagX1p5 = (version.find(m_AI_VERSION_1p5) != std::string::npos);\n  bool isImagX2pX = (version.find(m_AI_VERSION_2pX) != std::string::npos);\n\n  if (!isImagX1p2 && !isImagX1p5 && !isImagX2pX)\n  {\n    itkExceptionMacro(\"Unknown AI version : \" << version);\n  }\n\n  std::string          gantryAngleTag;\n  FlexmapType          flex;\n  CalibrationModelType calibModel;\n  if (isImagX2pX)\n  {\n    gantryAngleTag = \"300a|011e\"; // Warning: CBCT tube angle!\n    if (!m_CalibrationXMLFileName.empty())\n    {\n      flex = GetGeometryForAI2p1();\n    }\n    else\n    {\n      itkExceptionMacro(\"With AI2.1, you need to provide a calibration file (XML)\");\n    }\n  }\n  else if ((isImagX1p5 || isImagX1p2) && m_CalibrationXMLFileName.empty() &&\n           m_RoomXMLFileName.empty()) // Read geocal from projections\n  {\n    gantryAngleTag = \"300a|011e\"; // Nozzle angle\n    calibModel = GetGeometryForAI1p5();\n  }\n  else if ((isImagX1p5 || isImagX1p2) && !m_CalibrationXMLFileName.empty() && !m_RoomXMLFileName.empty())\n  {\n    gantryAngleTag = \"300a|011e\"; // Nozzle angle\n    calibModel = GetGeometryForAI1p5FromXMLFiles();\n  }\n\n  // Create new RTK geometry object\n  m_Geometry = GeometryType::New();\n\n  // Projection matrices\n  for (auto & m_ProjectionsFileName : m_ProjectionsFileNames)\n  {\n    itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(\n      m_ProjectionsFileNames[0].c_str(), itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n    using ReaderType = itk::ImageFileReader<TInputImage>;\n    auto reader = ReaderType::New();\n    reader->SetFileName(m_ProjectionsFileName);\n    imageIO = itk::GDCMImageIO::New();\n\n    reader->SetImageIO(imageIO);\n    reader->UpdateOutputInformation();\n\n    // Reading Gantry Angle\n    std::string labelId, value;\n    itk::GDCMImageIO::GetLabelFromTag(gantryAngleTag, labelId);\n    dynamic_cast<itk::GDCMImageIO *>(imageIO.GetPointer())->GetValueFromTag(gantryAngleTag, value);\n\n    if (isImagX1p5 || isImagX1p2) // Using CalibModel\n    {\n      float gantryAngle = std::stod(value.c_str());\n      addEntryToGeometry(calibModel, gantryAngle);\n    }\n    else if (isImagX2pX) // Using flexmap\n    {\n      float cbctTubeAngle = std::stod(value.c_str());\n      float gantryAngle =\n        cbctTubeAngle; // Warning: no correction by sourceToNozzleOffsetAngle as radiographic angle read\n      gantryAngle = (gantryAngle > 180.f) ? (gantryAngle - 360.f) : gantryAngle;\n      gantryAngle = (gantryAngle < -180.f) ? (gantryAngle + 360.f) : gantryAngle;\n      addEntryToGeometry(flex, gantryAngle);\n    }\n  }\n}\n\ntemplate <typename TInputImage>\nvoid\nImagXGeometryReader<TInputImage>::addEntryToGeometry(float                gantryAngleDegree,\n                                                     float                nozzleToRadAngleOffset,\n                                                     float                sid,\n                                                     float                sdd,\n                                                     std::vector<float> & detTrans,\n                                                     std::vector<float> & detRot,\n                                                     std::vector<float> & srcTrans)\n{\n  float deg2rad = float(itk::Math::pi) / 180.f;\n\n  // Conversion from iMagX geometry to RTK geometry standard\n  float aid = sid - sdd;\n  float sidp = srcTrans[2] + sid;\n  float Pzp = detTrans[2] + aid;\n  float bx = detRot[0] * deg2rad;\n  float by = detRot[1] * deg2rad;\n  float bz = detRot[2] * deg2rad;\n\n  float gAngle = gantryAngleDegree + detRot[1];\n  float outOfPlaneAngle = detRot[0];\n  float inPlaneAngle = detRot[2];\n  float sourceToIsocenterDistance = cos(bx) * (cos(by) * sidp + sin(by) * srcTrans[0]) - sin(bx) * srcTrans[1];\n  float sourceToDetectorDistance =\n    sourceToIsocenterDistance - cos(bx) * (cos(by) * Pzp + sin(by) * detTrans[0]) + sin(bx * detTrans[1]);\n\n  float fac11 = cos(by) * sidp + sin(by) * srcTrans[0];\n  float fac12 = sin(bx) * fac11 + cos(bx) * srcTrans[1];\n  float fac13 = -sin(by) * sidp + cos(by) * srcTrans[0];\n  float sourceOffsetX = sin(bz) * fac12 + cos(bz) * fac13;\n  float sourceOffsetY = cos(bz) * fac12 - sin(bz) * fac13;\n\n  float fac21 = cos(by) * Pzp + sin(by) * detTrans[0];\n  float fac22 = sin(bx) * fac21 + cos(bx) * detTrans[1];\n  float fac23 = -sin(by) * Pzp + cos(by) * detTrans[0];\n  float projectionOffsetX = sin(bz) * fac22 + cos(bz) * fac23;\n  float projectionOffsetY = cos(bz) * fac22 - sin(bz) * fac23;\n\n  m_Geometry->AddProjection(sourceToIsocenterDistance,\n                            sourceToDetectorDistance,\n                            gAngle + nozzleToRadAngleOffset,\n                            projectionOffsetX,\n                            projectionOffsetY,\n                            outOfPlaneAngle,\n                            inPlaneAngle,\n                            sourceOffsetX,\n                            sourceOffsetY);\n}\n\ntemplate <typename TInputImage>\ntypename ImagXGeometryReader<TInputImage>::InterpResultType\nImagXGeometryReader<TInputImage>::interpolate(const std::vector<float> & flexAngles, bool bIsCW, float angleDegree)\n{\n  const int N = static_cast<int>(flexAngles.size());\n\n  InterpResultType ires;\n\n  ires.id0 = 0;\n  ires.id1 = 0;\n  ires.a0 = 1.f;\n  ires.a1 = 0.f;\n  if (N == 1)\n  {\n    return ires;\n  }\n\n  // Index of the closest angle in flexmap\n  int   idc = 0;\n  float minv = std::numeric_limits<float>::max();\n  float delta = 0.f; // to closest angle in flexmap\n  for (int i = 0; i < N; ++i)\n  {\n    float absdelta = itk::Math::abs(angleDegree - flexAngles[i]);\n    if (absdelta <= minv)\n    {\n      idc = i;\n      minv = absdelta;\n      delta = angleDegree - flexAngles[i];\n    }\n  }\n\n  // Clipping\n  if (idc == 0 && ((delta < 0.f && bIsCW) || (delta > 0.f && !bIsCW)))\n  {\n    ires.id0 = 0;\n    ires.id1 = 0;\n    ires.a0 = 1.f;\n    ires.a1 = 0.f;\n    return ires;\n  }\n  else if (idc == N - 1 && ((delta > 0.f && bIsCW) || (delta < 0.f && !bIsCW)))\n  {\n    ires.id0 = N - 1;\n    ires.id1 = N - 1;\n    ires.a0 = 1.f;\n    ires.a1 = 0.f;\n    return ires;\n  }\n\n  // Interpolation\n  if (bIsCW)\n  {\n    if (delta > 0.f)\n    {\n      float a = itk::Math::abs(delta / (flexAngles[idc + 1] - flexAngles[idc]));\n      ires.id0 = idc;\n      ires.id1 = idc + 1;\n      ires.a0 = 1.f - a;\n      ires.a1 = a;\n    }\n    else if (delta < 0.f)\n    {\n      float a = itk::Math::abs(delta / (flexAngles[idc] - flexAngles[idc - 1]));\n      ires.id0 = idc - 1;\n      ires.id1 = idc;\n      ires.a0 = a;\n      ires.a1 = 1.f - a;\n    }\n  }\n  else\n  {\n    if (delta < 0.f)\n    {\n      float a = itk::Math::abs(delta / (flexAngles[idc + 1] - flexAngles[idc]));\n      ires.id0 = idc;\n      ires.id1 = idc + 1;\n      ires.a0 = 1.f - a;\n      ires.a1 = a;\n    }\n    else if (delta > 0.f)\n    {\n      float a = itk::Math::abs(delta / (flexAngles[idc] - flexAngles[idc - 1]));\n      ires.id0 = idc - 1;\n      ires.id1 = idc;\n      ires.a0 = a;\n      ires.a1 = 1.f - a;\n    }\n  }\n\n  return ires;\n}\n\ntemplate <typename TInputImage>\nstd::vector<float>\nImagXGeometryReader<TInputImage>::getInterpolatedValue(const InterpResultType &   ires,\n                                                       const std::vector<float> & Dx,\n                                                       const std::vector<float> & Dy,\n                                                       const std::vector<float> & Dz)\n{\n  std::vector<float> d;\n\n  d.resize(3);\n  d[0] = ires.a0 * Dx[ires.id0] + ires.a1 * Dx[ires.id1];\n  d[1] = ires.a0 * Dy[ires.id0] + ires.a1 * Dy[ires.id1];\n  d[2] = ires.a0 * Dz[ires.id0] + ires.a1 * Dz[ires.id1];\n  return d;\n}\n\ntemplate <typename TInputImage>\nvoid\nImagXGeometryReader<TInputImage>::addEntryToGeometry(const FlexmapType & f, float gantryAngle)\n{\n  // Deformation obtained by sampling the flexmap\n\n  InterpResultType ires = interpolate(f.anglesDeg, f.isCW, gantryAngle);\n\n  // Detector translation deformations\n  std::vector<float> detTrans = this->getInterpolatedValue(ires, f.Px, f.Py, f.Pz);\n\n  // Detector rotation deformations\n  std::vector<float> detRot = this->getInterpolatedValue(ires, f.Rx, f.Ry, f.Rz);\n\n  // Source translation deformations\n  std::vector<float> srcTrans = this->getInterpolatedValue(ires, f.Tx, f.Ty, f.Tz);\n\n  // Add new entry to RTK geometry\n  addEntryToGeometry(gantryAngle, f.sourceToNozzleOffsetAngle, f.sid, f.sdd, detTrans, detRot, srcTrans);\n}\n\ntemplate <typename TInputImage>\nstd::vector<float>\nImagXGeometryReader<TInputImage>::getDeformations(float                      gantryAngle,\n                                                  const std::vector<float> & Dx,\n                                                  const std::vector<float> & Dy,\n                                                  const std::vector<float> & Dz)\n{\n  std::vector<float> d;\n\n  d.resize(3);\n  float gRad = gantryAngle * std::acos(-1.f) / 180.f;\n  d[0] = Dx[0] + Dx[1] * gantryAngle + Dx[2] * std::cos(Dx[3] * gRad + Dx[4]);\n  d[1] = Dy[0] + Dy[1] * gantryAngle + Dy[2] * std::cos(Dy[3] * gRad + Dy[4]);\n  d[2] = Dz[0] + Dz[1] * gantryAngle + Dz[2] * std::cos(Dz[3] * gRad + Dz[4]);\n  return d;\n}\n\ntemplate <typename TInputImage>\nvoid\nImagXGeometryReader<TInputImage>::addEntryToGeometry(const CalibrationModelType & c, float gantryAngle)\n{\n  // Deformation computation following model: (a0 + a1*t) + a2*cos(a3*t + a4)\n\n  // Detector translation deformations\n  std::vector<float> detTrans = this->getDeformations(gantryAngle, c.Px, c.Py, c.Pz);\n\n  // Detector rotation deformations\n  std::vector<float> detRot = this->getDeformations(gantryAngle, c.Rx, c.Ry, c.Rz);\n\n  // Source translation deformations\n  std::vector<float> srcTrans = this->getDeformations(gantryAngle, c.Tx, c.Ty, c.Tz);\n\n  // Add new entry to RTK geometry\n  addEntryToGeometry(gantryAngle, c.sourceToNozzleOffsetAngle, c.sid, c.sdd, detTrans, detRot, srcTrans);\n}\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkImagXImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkImagXImageIO_h\n#define rtkImagXImageIO_h\n\n#include <itkImageIOBase.h>\n#include <fstream>\n#include <cstring>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class ImagXImageIO\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT ImagXImageIO : public itk::ImageIOBase\n{\npublic:\n  /** Standard class type alias. */\n  using Self = ImagXImageIO;\n  using Superclass = itk::ImageIOBase;\n  using Pointer = itk::SmartPointer<Self>;\n\n  ImagXImageIO()\n    : Superclass()\n  {}\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ImagXImageIO);\n\n  /*-------- This part of the interface deals with reading data. ------ */\n  void\n  ReadImageInformation() override;\n\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n\n  void\n  Read(void * buffer) override;\n\n  /*-------- This part of the interfaces deals with writing data. ----- */\n  virtual void\n  WriteImageInformation(bool keepOfStream);\n\n  void\n  WriteImageInformation() override\n  {\n    WriteImageInformation(false);\n  }\n  bool\n  CanWriteFile(const char * filename) override;\n\n  void\n  Write(const void * buffer) override;\n\nprotected:\n  std::string m_RawFileName;\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkImagXImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkImagXImageIOFactory_h\n#define rtkImagXImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkImagXImageIO.h\"\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class ImagXImageIOFactory\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT ImagXImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ImagXImageIOFactory);\n\n  /** Standard class type alias. */\n  using Self = ImagXImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"ImagX ImageIO Factory, allows the loading of ImagX images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ImagXImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\nprotected:\n  ImagXImageIOFactory();\n  ~ImagXImageIOFactory() override = default;\n  using myProductType = ImagXImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkImagXXMLFileReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkImagXXMLFileReader_h\n#define rtkImagXXMLFileReader_h\n\n#ifdef _MSC_VER\n#  pragma warning(disable : 4786)\n#endif\n\n#include <itkXMLFile.h>\n#include <itkMetaDataDictionary.h>\n\n#include <map>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class ImagXXMLFileReader\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT ImagXXMLFileReader : public itk::XMLReader<itk::MetaDataDictionary>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ImagXXMLFileReader);\n\n  /** Standard type alias */\n  using Self = ImagXXMLFileReader;\n  using Superclass = itk::XMLReader<itk::MetaDataDictionary>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ImagXXMLFileReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Determine if a file can be read */\n  int\n  CanReadFile(const char * name) override;\n\nprotected:\n  ImagXXMLFileReader() { m_OutputObject = &m_Dictionary; }\n  ~ImagXXMLFileReader() override = default;\n\n  void\n  StartElement(const char * name, const char ** atts) override;\n\n  void\n  EndElement(const char * name) override;\n\n  void\n  CharacterDataHandler(const char * inData, int inLength) override;\n\nprivate:\n  itk::MetaDataDictionary m_Dictionary;\n  std::string             m_CurCharacterData;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkImageToVectorImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkImageToVectorImageFilter_h\n#define rtkImageToVectorImageFilter_h\n\n#include \"rtkMacro.h\"\n\n#include <itkImageToImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\nnamespace rtk\n{\n/** \\class ImageToVectorImageFilter\n * \\brief Re-writes an image as a vector image\n *\n * Depending on the dimensions of the input and output images, the filter\n * can have two different behaviors:\n *  - if the dimensions match, the channels of the input image are\n * obtained by slicing the last dimension. With an input image of size (X, Y*N),\n * the output is an N-components vector image of size (X,Y)\n *  - if the input image dimension equals the output dimension plus one,\n * the additional dimension of the input image is assumed to contain the channels.\n * With an input image of size (X,Y,N), the output is an N-components\n * vector image of size (X, Y).\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\ntemplate <typename InputImageType, typename OutputImageType>\nclass ITK_TEMPLATE_EXPORT ImageToVectorImageFilter : public itk::ImageToImageFilter<InputImageType, OutputImageType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ImageToVectorImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ImageToVectorImageFilter;\n  using Superclass = itk::ImageToImageFilter<InputImageType, OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ImageToVectorImageFilter);\n\n  /** When the input and output dimensions are equal, the filter\n   * cannot guess the number of channels. Set/Get methods to\n   * pass it */\n  itkSetMacro(NumberOfChannels, unsigned int);\n  itkGetMacro(NumberOfChannels, unsigned int);\n\nprotected:\n  ImageToVectorImageFilter();\n  ~ImageToVectorImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,\n                       itk::ThreadIdType             itkNotUsed(threadId)) override;\n\n  /** Splits the OutputRequestedRegion along the first direction, not the last */\n  const itk::ImageRegionSplitterBase *\n                                             GetImageRegionSplitter() const override;\n  itk::ImageRegionSplitterDirection::Pointer m_Splitter;\n\n  unsigned int m_NumberOfChannels;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkImageToVectorImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkImageToVectorImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkImageToVectorImageFilter_hxx\n#define rtkImageToVectorImageFilter_hxx\n\n\n#include <itkObjectFactory.h>\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkVariableLengthVector.h>\n\nnamespace rtk\n{\n\ntemplate <typename InputImageType, typename OutputImageType>\nImageToVectorImageFilter<InputImageType, OutputImageType>::ImageToVectorImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n\n  m_NumberOfChannels = 1;\n\n  // Set the direction along which the output requested region should NOT be split\n  m_Splitter = itk::ImageRegionSplitterDirection::New();\n  m_Splitter->SetDirection(OutputImageType::ImageDimension - 1);\n}\n\ntemplate <typename InputImageType, typename OutputImageType>\nconst itk::ImageRegionSplitterBase *\nImageToVectorImageFilter<InputImageType, OutputImageType>::GetImageRegionSplitter() const\n{\n  return m_Splitter;\n}\n\ntemplate <typename InputImageType, typename OutputImageType>\nvoid\nImageToVectorImageFilter<InputImageType, OutputImageType>::GenerateOutputInformation()\n{\n  const unsigned int InputDimension = InputImageType::ImageDimension;\n  const unsigned int OutputDimension = OutputImageType::ImageDimension;\n\n  if (!((OutputDimension == InputDimension) || ((OutputDimension + 1) == InputDimension)))\n    itkGenericExceptionMacro(<< \"In ImageToVectorImageFilter : input and output image dimensions are not compatible\");\n\n  typename OutputImageType::SizeType      outputSize;\n  typename OutputImageType::IndexType     outputIndex;\n  typename OutputImageType::RegionType    outputRegion;\n  typename OutputImageType::SpacingType   outputSpacing;\n  typename OutputImageType::PointType     outputOrigin;\n  typename OutputImageType::DirectionType outputDirection;\n\n  // In all cases\n  for (unsigned int dim = 0; dim < OutputDimension; dim++)\n  {\n    outputSize[dim] = this->GetInput()->GetLargestPossibleRegion().GetSize()[dim];\n    outputIndex[dim] = this->GetInput()->GetLargestPossibleRegion().GetIndex()[dim];\n    outputSpacing[dim] = this->GetInput()->GetSpacing()[dim];\n    outputOrigin[dim] = this->GetInput()->GetOrigin()[dim];\n    for (unsigned int j = 0; j < OutputDimension; j++)\n      outputDirection[dim][j] = this->GetInput()->GetDirection()[dim][j];\n  }\n\n  // Set vector length and size of output, depending on the input and output dimensions\n  if ((OutputDimension + 1) == InputDimension)\n  {\n    // No need to set the size, it should already be correct, thanks to the previous block of code\n    m_NumberOfChannels = this->GetInput()->GetLargestPossibleRegion().GetSize()[InputDimension - 1];\n    this->GetOutput()->SetVectorLength(m_NumberOfChannels);\n  }\n  else\n  {\n    // Can't guess vector length, must use the user-provided one\n    outputSize[OutputDimension - 1] =\n      this->GetInput()->GetLargestPossibleRegion().GetSize()[OutputDimension - 1] / this->m_NumberOfChannels;\n    this->GetOutput()->SetVectorLength(this->m_NumberOfChannels);\n  }\n\n  outputRegion.SetSize(outputSize);\n  outputRegion.SetIndex(outputIndex);\n  this->GetOutput()->SetLargestPossibleRegion(outputRegion);\n  this->GetOutput()->SetSpacing(outputSpacing);\n  this->GetOutput()->SetOrigin(outputOrigin);\n  this->GetOutput()->SetDirection(outputDirection);\n}\n\ntemplate <typename InputImageType, typename OutputImageType>\nvoid\nImageToVectorImageFilter<InputImageType, OutputImageType>::GenerateInputRequestedRegion()\n{\n  typename InputImageType::Pointer inputPtr = const_cast<InputImageType *>(this->GetInput());\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename InputImageType, typename OutputImageType>\nvoid\nImageToVectorImageFilter<InputImageType, OutputImageType>::ThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread,\n  itk::ThreadIdType             itkNotUsed(threadId))\n{\n  const unsigned int InputDimension = InputImageType::ImageDimension;\n  const unsigned int OutputDimension = OutputImageType::ImageDimension;\n\n  typename InputImageType::SizeType   inputSize;\n  typename InputImageType::IndexType  inputIndex;\n  typename InputImageType::RegionType inputRegion;\n\n  inputSize.Fill(0);\n  inputIndex.Fill(0);\n  for (unsigned int dim = 0; dim < OutputDimension; dim++)\n  {\n    inputSize[dim] = outputRegionForThread.GetSize()[dim];\n    inputIndex[dim] = outputRegionForThread.GetIndex()[dim];\n  }\n\n  // In all cases, the input's last dimension should be fully traversed\n  inputSize[InputDimension - 1] = this->GetInput()->GetLargestPossibleRegion().GetSize()[InputDimension - 1];\n\n  inputRegion.SetSize(inputSize);\n  inputRegion.SetIndex(inputIndex);\n\n  // Actual copy is the same in both cases\n  itk::ImageRegionConstIterator<InputImageType> inIt(this->GetInput(), inputRegion);\n  itk::ImageRegionIterator<OutputImageType>     outIt(this->GetOutput(), outputRegionForThread);\n  for (unsigned int channel = 0; channel < this->m_NumberOfChannels; channel++)\n  {\n    outIt.GoToBegin();\n    while (!outIt.IsAtEnd())\n    {\n      itk::VariableLengthVector<typename InputImageType::PixelType> vector = outIt.Get();\n      vector[channel] = inIt.Get();\n      outIt.Set(vector);\n      ++inIt;\n      ++outIt;\n    }\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkImportImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkImportImageFilter_h\n#define rtkImportImageFilter_h\n\n#include \"itkImageSource.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class ImportImageFilter\n * \\brief Import data from a standard C array into an itk::Image\n *\n * ImportImageFilter provides a mechanism for importing data into a TImage.\n * ImportImageFilter is an image source, so it behaves like any other pipeline\n * object.\n *\n * This class is templated over the image type of the output image, unlike\n * itk::ImportImageFilter which is templated over the pixel type and the dimension\n * and is therefore incompatible with itk::CudaImage.\n *\n * \\author Marc Vila\n *\n * \\ingroup RTK\n **/\n\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT ImportImageFilter : public itk::ImageSource<TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ImportImageFilter);\n\n  /** Typedef for the output image.   */\n  using OutputImagePointer = typename TImage::Pointer;\n  using SpacingType = typename TImage::SpacingType;\n  using OriginType = typename TImage::PointType;\n\n  /** Standard class type alias. */\n  using Self = ImportImageFilter;\n  using Superclass = itk::ImageSource<TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ImportImageFilter);\n\n  /** Index type alias support. An index is used to access pixel values. */\n  using IndexType = itk::Index<TImage::ImageDimension>;\n\n  /** Size type alias support. A size is used to define region bounds. */\n  using SizeType = itk::Size<TImage::ImageDimension>;\n  using SizeValueType = typename SizeType::SizeValueType;\n\n  /** Region type alias support. A region is used to specify a\n   * subset of an image. */\n  using RegionType = itk::ImageRegion<TImage::ImageDimension>;\n\n  /** Type of the output image pixel type. */\n  using PixelType = typename TImage::PixelType;\n\n  /** Get the pointer from which the image data is imported. */\n  PixelType *\n  GetImportPointer();\n\n  /** Set the pointer from which the image data is imported.  \"num\" is\n   * the number of pixels in the block of memory. If\n   * \"LetFilterManageMemory\" is false, then the this filter will\n   * not free the memory in its destructor and the application providing the\n   * buffer retains the responsibility of freeing the memory for this image\n   * data.  If \"LetFilterManageMemory\" is true, then this class\n   * will free the memory when this object is destroyed. */\n  void\n  SetImportPointer(PixelType * ptr, SizeValueType num, bool LetFilterManageMemory);\n\n  /** Set the region object that defines the size and starting index\n   * for the imported image. This will serve as the LargestPossibleRegion,\n   * the BufferedRegion, and the RequestedRegion.\n   * \\sa ImageRegion */\n  void\n  SetRegion(const RegionType & region)\n  {\n    if (m_Region != region)\n    {\n      m_Region = region;\n      this->Modified();\n    }\n  }\n\n  /** Get the region object that defines the size and starting index\n   * for the imported image. This will serve as the LargestPossibleRegion,\n   * the BufferedRegion, and the RequestedRegion.\n   * \\sa ImageRegion */\n  const RegionType &\n  GetRegion() const\n  {\n    return m_Region;\n  }\n\n  /** Set the spacing (size of a pixel) of the image.\n   * \\sa GetSpacing() */\n  itkSetMacro(Spacing, SpacingType);\n  itkGetConstReferenceMacro(Spacing, SpacingType);\n  itkSetVectorMacro(Spacing, const float, TImage::ImageDimension);\n\n  /** Set the origin of the image.\n   * \\sa GetOrigin() */\n  itkSetMacro(Origin, OriginType);\n  itkGetConstReferenceMacro(Origin, OriginType);\n  itkSetVectorMacro(Origin, const float, TImage::ImageDimension);\n\n  using DirectionType = itk::Matrix<double, TImage::ImageDimension, TImage::ImageDimension>;\n\n  /** Set the direction of the image\n   * \\sa GetDirection() */\n  virtual void\n  SetDirection(const DirectionType & direction);\n\n  /**  Get the direction of the image\n   * \\sa SetDirection */\n  itkGetConstReferenceMacro(Direction, DirectionType);\n\nprotected:\n  ImportImageFilter();\n  ~ImportImageFilter() override;\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  /** This filter does not actually \"produce\" any data, rather it \"wraps\"\n   * the user supplied data into an itk::Image.  */\n  void\n  GenerateData() override;\n\n  /** This is a source, so it must set the spacing, size, and largest possible\n   * region for the output image that it will produce.\n   * \\sa ProcessObject::GenerateOutputInformation() */\n  void\n  GenerateOutputInformation() override;\n\n  /** This filter can only produce the amount of data that it is given,\n   * so we must override ProcessObject::EnlargeOutputRequestedRegion()\n   * (The default implementation of a source produces the amount of\n   * data requested.  This source, however, can only produce what it is\n   * given.)\n   *\n   * \\sa ProcessObject::EnlargeOutputRequestedRegion() */\n  void\n  EnlargeOutputRequestedRegion(itk::DataObject * output) override;\n\nprivate:\n  RegionType    m_Region;\n  SpacingType   m_Spacing;\n  OriginType    m_Origin;\n  DirectionType m_Direction;\n\n  PixelType *   m_ImportPointer;\n  bool          m_FilterManageMemory;\n  SizeValueType m_Size;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkImportImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkImportImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkImportImageFilter_hxx\n#define rtkImportImageFilter_hxx\n\n#include <itkObjectFactory.h>\n#ifdef RTK_USE_CUDA\n#  include <itkCudaImage.h>\n#endif\n\nnamespace rtk\n{\n/**\n *\n */\ntemplate <typename TImage>\nImportImageFilter<TImage>::ImportImageFilter()\n{\n  unsigned int idx = 0;\n\n  for (idx = 0; idx < TImage::ImageDimension; ++idx)\n  {\n    m_Spacing[idx] = 1.0;\n    m_Origin[idx] = 0.0;\n  }\n  m_Direction.SetIdentity();\n\n  m_ImportPointer = nullptr;\n  m_FilterManageMemory = false;\n  m_Size = 0;\n}\n\n/**\n *\n */\ntemplate <typename TImage>\nImportImageFilter<TImage>::~ImportImageFilter()\n{\n  if (m_ImportPointer && m_FilterManageMemory)\n  {\n    delete[] m_ImportPointer;\n  }\n}\n\n/**\n *\n */\ntemplate <typename TImage>\nvoid\nImportImageFilter<TImage>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  int i = 0;\n\n  this->Superclass::PrintSelf(os, indent);\n\n  if (m_ImportPointer)\n  {\n    os << indent << \"Imported pointer: (\" << m_ImportPointer << \")\" << std::endl;\n  }\n  else\n  {\n    os << indent << \"Imported pointer: (None)\" << std::endl;\n  }\n  os << indent << \"Import buffer size: \" << m_Size << std::endl;\n  os << indent << \"Import buffer size: \" << m_Size << std::endl;\n  os << indent << \"Filter manages memory: \" << (m_FilterManageMemory ? \"true\" : \"false\") << std::endl;\n\n  os << indent << \"Spacing: [\";\n  for (i = 0; i < static_cast<int>(TImage::ImageDimension) - 1; i++)\n  {\n    os << m_Spacing[i] << \", \";\n  }\n  os << m_Spacing[i] << \"]\" << std::endl;\n\n  os << indent << \"Origin: [\";\n  for (i = 0; i < static_cast<int>(TImage::ImageDimension) - 1; i++)\n  {\n    os << m_Origin[i] << \", \";\n  }\n  os << m_Origin[i] << \"]\" << std::endl;\n  os << indent << \"Direction: \" << std::endl << this->GetDirection() << std::endl;\n}\n\n/**\n *\n */\ntemplate <typename TImage>\nvoid\nImportImageFilter<TImage>::SetImportPointer(PixelType * ptr, SizeValueType num, bool LetFilterManageMemory)\n{\n  if (ptr != m_ImportPointer)\n  {\n    if (m_ImportPointer && m_FilterManageMemory)\n    {\n      delete[] m_ImportPointer;\n    }\n    m_ImportPointer = ptr;\n    this->Modified();\n  }\n  m_FilterManageMemory = LetFilterManageMemory;\n  m_Size = num;\n}\n\n/**\n *\n */\ntemplate <typename TImage>\ntypename TImage::PixelType *\nImportImageFilter<TImage>::GetImportPointer()\n{\n  return m_ImportPointer;\n}\n\n/**\n *\n */\ntemplate <typename TImage>\nvoid\nImportImageFilter<TImage>::EnlargeOutputRequestedRegion(itk::DataObject * output)\n{\n  // call the superclass' implementation of this method\n  Superclass::EnlargeOutputRequestedRegion(output);\n\n  // get pointer to the output\n  OutputImagePointer outputPtr = this->GetOutput();\n\n  // set the requested region to the largest possible region (in this case\n  // the amount of data that we have)\n  outputPtr->SetRequestedRegion(outputPtr->GetLargestPossibleRegion());\n}\n\n/**\n *\n */\ntemplate <typename TImage>\nvoid\nImportImageFilter<TImage>::GenerateOutputInformation()\n{\n  // call the superclass' implementation of this method\n  Superclass::GenerateOutputInformation();\n\n  // get pointer to the output\n  OutputImagePointer outputPtr = this->GetOutput();\n\n  // we need to compute the output spacing, the output origin, the\n  // output image size, and the output image start index\n  outputPtr->SetSpacing(m_Spacing);\n  outputPtr->SetOrigin(m_Origin);\n  outputPtr->SetDirection(m_Direction);\n  outputPtr->SetLargestPossibleRegion(m_Region);\n}\n\n/**\n *\n */\ntemplate <typename TImage>\nvoid\nImportImageFilter<TImage>::GenerateData()\n{\n  // Normally, GenerateData() allocates memory.  However, the application\n  // provides the memory for this filter via the SetImportPointer() method.\n  // Therefore, this filter does not call outputPtr->Allocate().\n\n  // get pointer to the output\n  OutputImagePointer outputPtr = this->GetOutput();\n\n  // the output buffer size is set to the size specified by the user via the\n  // SetRegion() method.\n  outputPtr->SetBufferedRegion(outputPtr->GetLargestPossibleRegion());\n\n  // pass the pointer down to the container during each Update() since\n  // a call to Initialize() causes the container to forget the\n  // pointer.  Note that we tell the container NOT to manage the\n  // memory itself.  This filter will properly manage the memory (as\n  // opposed to the container) if the user wants it to.\n  outputPtr->GetPixelContainer()->SetImportPointer(m_ImportPointer, m_Size, false);\n\n#ifdef RTK_USE_CUDA\n  using TCudaImage = itk::CudaImage<typename TImage::PixelType, TImage::ImageDimension>;\n  if (TCudaImage * cudaOutputPtr = dynamic_cast<TCudaImage *>(outputPtr.GetPointer()))\n  {\n    cudaOutputPtr->GetModifiableDataManager()->SetBufferSize(m_Size * sizeof(typename TImage::PixelType));\n    cudaOutputPtr->GetModifiableDataManager()->SetImagePointer(cudaOutputPtr);\n    cudaOutputPtr->GetModifiableDataManager()->SetCPUBufferPointer(m_ImportPointer);\n    cudaOutputPtr->GetModifiableDataManager()->SetGPUDirtyFlag(true);\n    cudaOutputPtr->GetModifiableDataManager()->SetCPUDirtyFlag(false);\n  }\n#endif\n}\n\n//----------------------------------------------------------------------------\ntemplate <typename TImage>\nvoid\nImportImageFilter<TImage>::SetDirection(const DirectionType & direction)\n{\n  bool modified = false;\n\n  for (unsigned int r = 0; r < TImage::ImageDimension; r++)\n  {\n    for (unsigned int c = 0; c < TImage::ImageDimension; c++)\n    {\n      if (m_Direction[r][c] != direction[r][c])\n      {\n        m_Direction[r][c] = direction[r][c];\n        modified = true;\n      }\n    }\n  }\n  if (modified)\n  {\n    this->Modified();\n  }\n}\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkInterpolatorWithKnownWeightsImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkInterpolatorWithKnownWeightsImageFilter_h\n#define rtkInterpolatorWithKnownWeightsImageFilter_h\n\n#include \"itkInPlaceImageFilter.h\"\n#include \"itkArray2D.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class InterpolatorWithKnownWeightsImageFilter\n * \\brief Interpolates (linearly) in a 3D+t sequence of volumes to get a 3D volume\n *\n * See the reference paper: \"Cardiac C-arm computed tomography using\n * a 3D + time ROI reconstruction method with spatial and temporal regularization\"\n * by Mory et al.\n *\n * 4D conjugate gradient reconstruction consists in iteratively\n * minimizing the following cost function:\n *\n * Sum_over_theta || R_theta S_theta f - p_theta ||_2^2\n *\n * with\n * - f a 4D series of 3D volumes, each one being the reconstruction\n * at a given respiratory/cardiac phase\n * - p_theta is the projection measured at angle theta\n * - S_theta an interpolation operator which, from the 3D + time sequence f,\n * estimates the 3D volume through which projection p_theta has been acquired\n * - R_theta is the X-ray transform (the forward projection operator) for angle theta\n *\n * Computing the gradient of this cost function yields:\n *\n * S_theta^T R_theta^T R_theta S_theta f - S_theta^T R_theta^T p_theta\n *\n * where A^T means the adjoint of operator A.\n *\n * InterpolatorWithKnownWeightsImageFilter implements S_theta.\n *\n *\n * \\test rtkfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <typename VolumeType, typename VolumeSeriesType>\nclass ITK_TEMPLATE_EXPORT InterpolatorWithKnownWeightsImageFilter\n  : public itk::InPlaceImageFilter<VolumeType, VolumeType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(InterpolatorWithKnownWeightsImageFilter);\n\n  /** Standard class type alias. */\n  using Self = InterpolatorWithKnownWeightsImageFilter;\n  using Superclass = itk::ImageToImageFilter<VolumeType, VolumeType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(InterpolatorWithKnownWeightsImageFilter);\n\n  /** The 3D image to be updated.*/\n  void\n  SetInputVolume(const VolumeType * Volume);\n\n  /** The 4D image that will be interpolated, with coefficients, generate a 3D volume.*/\n  void\n  SetInputVolumeSeries(const VolumeSeriesType * VolumeSeries);\n\n  /** Macros that take care of implementing the Get and Set methods for Weights and ProjectionNumber.*/\n  itkGetMacro(Weights, itk::Array2D<float>);\n  itkSetMacro(Weights, itk::Array2D<float>);\n\n  itkGetMacro(ProjectionNumber, int);\n  void\n  SetProjectionNumber(int n);\n\nprotected:\n  InterpolatorWithKnownWeightsImageFilter();\n  ~InterpolatorWithKnownWeightsImageFilter() override = default;\n\n  typename VolumeType::ConstPointer\n  GetInputVolume();\n  typename VolumeSeriesType::Pointer\n  GetInputVolumeSeries();\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  DynamicThreadedGenerateData(const typename VolumeType::RegionType & outputRegionForThread) override;\n\n  itk::Array2D<float> m_Weights;\n  int                 m_ProjectionNumber;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkInterpolatorWithKnownWeightsImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkInterpolatorWithKnownWeightsImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkInterpolatorWithKnownWeightsImageFilter_hxx\n#define rtkInterpolatorWithKnownWeightsImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include \"itkObjectFactory.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n\nnamespace rtk\n{\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\nInterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::InterpolatorWithKnownWeightsImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n  m_ProjectionNumber = 0;\n}\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\nvoid\nInterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::SetInputVolume(const VolumeType * Volume)\n{\n  this->SetNthInput(0, const_cast<VolumeType *>(Volume));\n}\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\nvoid\nInterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::SetInputVolumeSeries(\n  const VolumeSeriesType * VolumeSeries)\n{\n  this->SetNthInput(1, const_cast<VolumeSeriesType *>(VolumeSeries));\n}\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\ntypename VolumeType::ConstPointer\nInterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::GetInputVolume()\n{\n  return static_cast<const VolumeType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\ntypename VolumeSeriesType::Pointer\nInterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::GetInputVolumeSeries()\n{\n  return static_cast<VolumeSeriesType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\nvoid\nInterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::SetProjectionNumber(int n)\n{\n  // Check whether the weights change from the old projection number to the new one\n  for (unsigned int row = 0; row < m_Weights.rows(); row++)\n  {\n    if (m_Weights[row][m_ProjectionNumber] != m_Weights[row][n])\n      this->Modified();\n  }\n\n  // Change the member variable whatever the result\n  m_ProjectionNumber = n;\n}\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\nvoid\nInterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::GenerateInputRequestedRegion()\n{\n  // Call the superclass implementation\n  Superclass::GenerateInputRequestedRegion();\n\n  // Set the requested region of the first input to that of the output\n  typename VolumeType::Pointer inputPtr0 = const_cast<VolumeType *>(this->GetInputVolume().GetPointer());\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Compute the smallest possible requested region of the second input\n  // Note that for some projections, the requested frames are 0 and n-1,\n  // which implies that the whole input is loaded\n  typename VolumeSeriesType::Pointer inputPtr1 =\n    const_cast<VolumeSeriesType *>(this->GetInputVolumeSeries().GetPointer());\n  if (!inputPtr1)\n    return;\n\n  // For a single projection number, only two volumes from the volume stack are required\n  // to compute the output. Unfortunately, if the projection requires the first and last\n  // volumes (which happens for a projection with phase close to one, since the motion\n  // is assumed to be cyclic), the requested region will have to be the entire input volume stack\n  // (an ITK region must be a rectangle, it cannot have \"holes\").\n  // Therefore, the peak memory usage is unchanged whether the input is streamed or not,\n  // and the overhead processing time brought by streaming is significant. So we do not stream.\n  // The code for computing the smallest input requested region is, however, left as a comment,\n  // in case it might prove useful in the future.\n  typename VolumeSeriesType::IndexValueType mini =\n    inputPtr1->GetLargestPossibleRegion().GetIndex(VolumeSeriesType::ImageDimension - 1);\n  typename VolumeSeriesType::IndexValueType maxi =\n    mini + inputPtr1->GetLargestPossibleRegion().GetSize(VolumeSeriesType::ImageDimension - 1) - 1;\n\n  //  // Find the minimum and maximum indices of the required frames\n  //  // Initialize the minimum to the highest possible value, and the\n  //  // maximum to the lowest possible value\n  //  typename VolumeSeriesType::IndexValueType maxi =\n  //      inputPtr1->GetLargestPossibleRegion().GetIndex(VolumeSeriesType::ImageDimension - 1);\n  //  typename VolumeSeriesType::IndexValueType mini =\n  //      maxi + inputPtr1->GetLargestPossibleRegion().GetSize(VolumeSeriesType::ImageDimension - 1);\n  //  for (unsigned int frame=0; frame<m_Weights.rows(); frame++)\n  //    {\n  //    if (m_Weights[frame][m_ProjectionNumber] != 0)\n  //      {\n  //      if (frame < mini) mini = frame;\n  //      if (frame > maxi) maxi = frame;\n  //      }\n  //    }\n\n  typename VolumeSeriesType::RegionType requested = inputPtr1->GetLargestPossibleRegion();\n  for (unsigned int dim = 0; dim < VolumeSeriesType::ImageDimension - 1; ++dim)\n  {\n    requested.SetSize(dim, this->GetOutput()->GetRequestedRegion().GetSize(dim));\n    requested.SetIndex(dim, this->GetOutput()->GetRequestedRegion().GetIndex(dim));\n  }\n  requested.SetSize(VolumeSeriesType::ImageDimension - 1, maxi - mini + 1);\n  requested.SetIndex(VolumeSeriesType::ImageDimension - 1, mini);\n\n  // Set the requested region\n  inputPtr1->SetRequestedRegion(requested);\n}\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\nvoid\nInterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::DynamicThreadedGenerateData(\n  const typename VolumeType::RegionType & outputRegionForThread)\n{\n  typename VolumeType::ConstPointer  volume = this->GetInputVolume();\n  typename VolumeSeriesType::Pointer volumeSeries = this->GetInputVolumeSeries();\n\n  unsigned int Dimension = volume->GetImageDimension();\n\n  typename VolumeSeriesType::RegionType volumeSeriesRegion;\n  typename VolumeSeriesType::SizeType   volumeSeriesSize;\n  typename VolumeSeriesType::IndexType  volumeSeriesIndex;\n\n\n  float weight = NAN;\n\n  // Initialize output region with input region in case the filter is not in\n  // place\n  itk::ImageRegionIterator<VolumeType> itOut(this->GetOutput(), outputRegionForThread);\n  if (this->GetInput() != this->GetOutput())\n  {\n    itk::ImageRegionConstIterator<VolumeType> itIn(volume, outputRegionForThread);\n    while (!itOut.IsAtEnd())\n    {\n      itOut.Set(itIn.Get());\n      ++itOut;\n      ++itIn;\n    }\n  }\n\n  // Compute the weighted sum of frames (with known weights) to get the output\n  for (unsigned int frame = 0; frame < m_Weights.rows(); frame++)\n  {\n    weight = m_Weights[frame][m_ProjectionNumber];\n    if (weight != 0)\n    {\n      volumeSeriesRegion = volumeSeries->GetRequestedRegion();\n      volumeSeriesSize = volumeSeriesRegion.GetSize();\n      volumeSeriesIndex = volumeSeriesRegion.GetIndex();\n\n      typename VolumeType::SizeType  outputRegionSize = outputRegionForThread.GetSize();\n      typename VolumeType::IndexType outputRegionIndex = outputRegionForThread.GetIndex();\n\n      for (unsigned int i = 0; i < Dimension; i++)\n      {\n        volumeSeriesSize[i] = outputRegionSize[i];\n        volumeSeriesIndex[i] = outputRegionIndex[i];\n      }\n      volumeSeriesSize[Dimension] = 1;\n      volumeSeriesIndex[Dimension] = frame;\n\n      volumeSeriesRegion.SetSize(volumeSeriesSize);\n      volumeSeriesRegion.SetIndex(volumeSeriesIndex);\n\n      // Iterators\n      itk::ImageRegionIterator<VolumeSeriesType> itVolumeSeries(volumeSeries, volumeSeriesRegion);\n      itOut.GoToBegin();\n\n      while (!itOut.IsAtEnd())\n      {\n        itOut.Set(itOut.Get() + weight * itVolumeSeries.Get());\n        ++itVolumeSeries;\n        ++itOut;\n      }\n    }\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkIntersectionOfConvexShapes.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkIntersectionOfConvexShapes_h\n#define rtkIntersectionOfConvexShapes_h\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n#include \"rtkConvexShape.h\"\n\nnamespace rtk\n{\n\n/** \\class IntersectionOfConvexShapes\n * \\brief Defines a shape as the intersection of several ConvexShape\n *\n * \\test rtkforbildtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT IntersectionOfConvexShapes : public ConvexShape\n{\npublic:\n  /** Standard class type alias. */\n  using Self = IntersectionOfConvexShapes;\n  using Superclass = ConvexShape;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  static constexpr unsigned int Dimension = Superclass::Dimension;\n  using ConvexShapePointer = ConvexShape::Pointer;\n  using ConvexShapeVector = std::vector<ConvexShapePointer>;\n  using ScalarType = Superclass::ScalarType;\n  using PointType = Superclass::PointType;\n  using VectorType = Superclass::VectorType;\n  using RotationMatrixType = Superclass::RotationMatrixType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(IntersectionOfConvexShapes);\n\n  /** See rtk::ConvexShape::IsInside. */\n  bool\n  IsInside(const PointType & point) const override;\n\n  /** See rtk::ConvexShape::IsIntersectedByRay. */\n  bool\n  IsIntersectedByRay(const PointType &  rayOrigin,\n                     const VectorType & rayDirection,\n                     ScalarType &       nearDist,\n                     ScalarType &       farDist) const override;\n\n  /** Add convex object to phantom. */\n  void\n  AddConvexShape(const ConvexShape * co);\n  itkGetConstReferenceMacro(ConvexShapes, ConvexShapeVector);\n  virtual void\n  SetConvexShapes(const ConvexShapeVector & _arg);\n\n  /** Rescale object along each direction by a 3D vector. */\n  void\n  Rescale(const VectorType & r) override;\n\n  /** Translate object by a given 3D vector. */\n  void\n  Translate(const VectorType & t) override;\n\n  /** Rotate object according to a 3D rotation matrix. */\n  void\n  Rotate(const RotationMatrixType & r) override;\n\n  itk::LightObject::Pointer\n  InternalClone() const override;\n\nprivate:\n  IntersectionOfConvexShapes();\n\n  ConvexShapeVector m_ConvexShapes;\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkIterationCommands.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkIterationCommands_h\n#define rtkIterationCommands_h\n\n#include <itkImageFileWriter.h>\n\nnamespace rtk\n{\n\n/** \\class IterationCommand\n * \\brief Abstract superclass to all iteration callbacks.\n * Derived classes must implement the Run() method. Run() can be triggered\n * only once in every n iterations.\n *\n * \\author Aurélien Coussat\n *\n * \\ingroup RTK\n *\n */\ntemplate <typename TCaller>\nclass ITK_TEMPLATE_EXPORT IterationCommand : public itk::Command\n{\npublic:\n  /** Standard class typedefs. */\n  typedef IterationCommand        Self;\n  typedef itk::Command            Superclass;\n  typedef itk::SmartPointer<Self> Pointer;\n\n  itkSetMacro(TriggerEvery, unsigned int);\n\n  void\n  Execute(itk::Object * caller, const itk::EventObject & event) override\n  {\n    Execute((const itk::Object *)caller, event);\n  }\n\n  void\n  Execute(const itk::Object * caller, const itk::EventObject & event) override\n  {\n    const auto * cCaller = dynamic_cast<const TCaller *>(caller);\n    if (cCaller)\n    {\n      if (itk::EndEvent().CheckEvent(&event))\n      {\n        End(cCaller);\n        return;\n      }\n      if (itk::IterationEvent().CheckEvent(&event))\n      {\n        ++m_IterationCount;\n        if ((m_IterationCount % m_TriggerEvery) == 0)\n        {\n          Run(cCaller);\n        }\n      }\n    } // TODO fail when cast fails\n  }\n\nprotected:\n  /** How many times this command has been executed. */\n  unsigned int m_IterationCount = 0;\n\n  /** Trigger the callback every n iterations. */\n  unsigned int m_TriggerEvery = 1;\n\n  /** Callback function to be redefined by derived classes. */\n  virtual void\n  Run(const TCaller * caller) = 0;\n\n  /** Callback function executed when filter concludes. */\n  virtual void\n  End(const TCaller * itkNotUsed(caller))\n  { /* Default implementation: do nothing */\n  }\n};\n\n/** \\class VerboseIterationCommand\n * \\brief Outputs to standard output when an iteration completes.\n *\n * \\author Aurélien Coussat\n *\n * \\ingroup RTK\n *\n */\ntemplate <typename TCaller>\nclass ITK_TEMPLATE_EXPORT VerboseIterationCommand : public IterationCommand<TCaller>\n{\npublic:\n  /** Standard class typedefs. */\n  typedef VerboseIterationCommand   Self;\n  typedef IterationCommand<TCaller> Superclass;\n  typedef itk::SmartPointer<Self>   Pointer;\n  itkNewMacro(Self);\n\nprotected:\n  void\n  Run(const TCaller * itkNotUsed(caller)) override\n  {\n    // TODO allow string personnalization?\n    std::cout << \"\\rIteration \" << this->m_IterationCount << \" completed.\" << std::flush;\n  }\n\n  void\n  End(const TCaller * itkNotUsed(caller)) override\n  {\n    std::cout << std::endl; // new line when execution ends\n  }\n};\n\n/** \\class OutputIterationCommand\n * \\brief Output intermediate iterations in a file.\n * This class is useful to check convergence of an iterative method\n * and to avoid starting over similar computations when testing\n * hyperparameters of an iterative algorithm.\n *\n * \\author Aurélien Coussat\n *\n * \\ingroup RTK\n *\n */\ntemplate <typename TCaller, typename TOutputImage>\nclass ITK_TEMPLATE_EXPORT OutputIterationCommand : public IterationCommand<TCaller>\n{\npublic:\n  /** Standard class typedefs. */\n  typedef OutputIterationCommand    Self;\n  typedef IterationCommand<TCaller> Superclass;\n  typedef itk::SmartPointer<Self>   Pointer;\n  itkNewMacro(Self);\n\n  itkSetMacro(FileFormat, std::string);\n\nprotected:\n  /** Output file name, where %d is the current iteration number */\n  std::string m_FileFormat;\n\n  void\n  Run(const TCaller * caller) override\n  {\n    typedef itk::ImageFileWriter<TOutputImage> WriterType;\n    auto                                       writer = WriterType::New();\n\n    char         buffer[1024];\n    unsigned int size = snprintf(buffer, 1024, m_FileFormat.c_str(), this->m_IterationCount);\n    writer->SetFileName(std::string(buffer, size));\n\n    writer->SetInput(caller->GetOutput());\n    writer->Update();\n  }\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkIterativeConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkIterativeConeBeamReconstructionFilter_h\n#define rtkIterativeConeBeamReconstructionFilter_h\n\n#include <itkPixelTraits.h>\n\n// Forward projection filters\n#include \"rtkConfiguration.h\"\n#include \"rtkJosephForwardAttenuatedProjectionImageFilter.h\"\n#include \"rtkZengForwardProjectionImageFilter.h\"\n// Back projection filters\n#include \"rtkJosephBackAttenuatedProjectionImageFilter.h\"\n#include \"rtkZengBackProjectionImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaForwardProjectionImageFilter.h\"\n#  include \"rtkCudaBackProjectionImageFilter.h\"\n#  include \"rtkCudaRayCastBackProjectionImageFilter.h\"\n#endif\n\n#include <random>\n#include <algorithm>\n\nnamespace rtk\n{\n\n/** \\class IterativeConeBeamReconstructionFilter\n * \\brief Mother class for cone beam reconstruction filters which\n * need runtime selection of their forward and back projection filters\n *\n * IterativeConeBeamReconstructionFilter defines methods to set the forward\n * and/or back projection filter(s) of a IterativeConeBeamReconstructionFilter\n * at runtime\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <class TOutputImage, class ProjectionStackType = TOutputImage>\nclass ITK_TEMPLATE_EXPORT IterativeConeBeamReconstructionFilter\n  : public itk::ImageToImageFilter<TOutputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(IterativeConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = IterativeConeBeamReconstructionFilter;\n  using Superclass = itk::ImageToImageFilter<TOutputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias */\n  using VolumeType = ProjectionStackType;\n  using TClipImageType = itk::Image<double, VolumeType::ImageDimension>;\n  typedef enum\n  {\n    FP_JOSEPH = 0,\n    FP_CUDARAYCAST = 2,\n    FP_JOSEPHATTENUATED = 3,\n    FP_ZENG = 4\n  } ForwardProjectionType;\n  typedef enum\n  {\n    BP_VOXELBASED = 0,\n    BP_JOSEPH = 1,\n    BP_CUDAVOXELBASED = 2,\n    BP_CUDARAYCAST = 4,\n    BP_JOSEPHATTENUATED = 5,\n    BP_ZENG = 6\n  } BackProjectionType;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<VolumeType, ProjectionStackType>;\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<ProjectionStackType, VolumeType>;\n  using ForwardProjectionPointerType = typename ForwardProjectionFilterType::Pointer;\n  using BackProjectionPointerType = typename BackProjectionFilterType::Pointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(IterativeConeBeamReconstructionFilter);\n\n  /** Accessors to forward and backprojection types. */\n  virtual void\n  SetForwardProjectionFilter(ForwardProjectionType fwtype);\n  ForwardProjectionType\n  GetForwardProjectionFilter()\n  {\n    return m_CurrentForwardProjectionConfiguration;\n  }\n  virtual void\n  SetBackProjectionFilter(BackProjectionType bptype);\n  BackProjectionType\n  GetBackProjectionFilter()\n  {\n    return m_CurrentBackProjectionConfiguration;\n  }\n\n  /** Set/Get the attenuation map for SPECT reconstruction.\n   * */\n  void\n  SetAttenuationMap(const VolumeType * attenuationMap)\n  {\n    // Process object is not const-correct so the const casting is required.\n    this->SetNthInput(2, const_cast<VolumeType *>(attenuationMap));\n  }\n  typename VolumeType::ConstPointer\n  GetAttenuationMap()\n  {\n    return static_cast<const VolumeType *>(this->itk::ProcessObject::GetInput(2));\n  }\n\n  /** Set/Get the inferior clip image. Each pixel of the image\n   ** corresponds to the value of the inferior clip of the ray\n   ** emitted from that pixel. */\n  void\n  SetInferiorClipImage(const TClipImageType * inferiorClipImage)\n  {\n    // Process object is not const-correct so the const casting is required.\n    this->SetInput(\"InferiorClipImage\", const_cast<TClipImageType *>(inferiorClipImage));\n  }\n  typename TClipImageType::ConstPointer\n  GetInferiorClipImage()\n  {\n    return static_cast<const TClipImageType *>(this->itk::ProcessObject::GetInput(\"InferiorClipImage\"));\n  }\n\n  /** Set/Get the superior clip image. Each pixel of the image\n   ** corresponds to the value of the superior clip of the ray\n   ** emitted from that pixel. */\n  void\n  SetSuperiorClipImage(const TClipImageType * superiorClipImage)\n  {\n    // Process object is not const-correct so the const casting is required.\n    this->SetInput(\"SuperiorClipImage\", const_cast<TClipImageType *>(superiorClipImage));\n  }\n  typename TClipImageType::ConstPointer\n  GetSuperiorClipImage()\n  {\n    return static_cast<const TClipImageType *>(this->itk::ProcessObject::GetInput(\"SuperiorClipImage\"));\n  }\n\n  /** Get / Set the sigma zero of the PSF. Default is 1.5417233052142099 */\n  itkGetMacro(SigmaZero, double);\n  itkSetMacro(SigmaZero, double);\n\n  /** Get / Set the alpha of the PSF. Default is 0.016241189545787734 */\n  itkGetMacro(AlphaPSF, double);\n  itkSetMacro(AlphaPSF, double);\n\n  /** Get / Set step size along ray (in mm). Default is 1 mm. */\n  itkGetConstMacro(StepSize, double);\n  itkSetMacro(StepSize, double);\n\nprotected:\n  IterativeConeBeamReconstructionFilter();\n  ~IterativeConeBeamReconstructionFilter() override = default;\n\n  /** Creates and returns an instance of the back projection filter.\n   * To be used in SetBackProjectionFilter. */\n  virtual BackProjectionPointerType\n  InstantiateBackProjectionFilter(int bptype);\n\n  /** Creates and returns an instance of the forward projection filter.\n   * To be used in SetForwardProjectionFilter. */\n  virtual ForwardProjectionPointerType\n  InstantiateForwardProjectionFilter(int fwtype);\n\n  /** Internal variables storing the current forward\n    and back projection methods */\n  ForwardProjectionType m_CurrentForwardProjectionConfiguration;\n  BackProjectionType    m_CurrentBackProjectionConfiguration;\n\n  /** A random generating engine is needed to use the C++17 comliant code for std::shuffle.\n   */\n  std::default_random_engine m_DefaultRandomEngine = std::default_random_engine{};\n\n  /** PSF correction coefficients */\n  double m_SigmaZero{ 1.5417233052142099 };\n  double m_AlphaPSF{ 0.016241189545787734 };\n\n  /** Step size along ray (in mm). */\n  double m_StepSize{ 1.0 };\n\n  /** Instantiate forward and back projectors using SFINAE. */\n  using CPUImageType =\n    typename itk::Image<typename ProjectionStackType::PixelType, ProjectionStackType::ImageDimension>;\n  template <typename ImageType>\n  using EnableCudaScalarAndVectorType = typename std::enable_if<\n    !std::is_same_v<CPUImageType, ImageType> &&\n    std::is_same_v<typename itk::PixelTraits<typename ImageType::PixelType>::ValueType, float> &&\n    (itk::PixelTraits<typename ImageType::PixelType>::Dimension == 1 ||\n     itk::PixelTraits<typename ImageType::PixelType>::Dimension == 2 ||\n     itk::PixelTraits<typename ImageType::PixelType>::Dimension == 3)>::type;\n  template <typename ImageType>\n  using DisableCudaScalarAndVectorType = typename std::enable_if<\n    std::is_same_v<CPUImageType, ImageType> ||\n    !std::is_same_v<typename itk::PixelTraits<typename ImageType::PixelType>::ValueType, float> ||\n    (itk::PixelTraits<typename ImageType::PixelType>::Dimension != 1 &&\n     itk::PixelTraits<typename ImageType::PixelType>::Dimension != 2 &&\n     itk::PixelTraits<typename ImageType::PixelType>::Dimension != 3)>::type;\n  template <typename ImageType>\n  using EnableCudaScalarType = typename std::enable_if<\n    !std::is_same_v<CPUImageType, ImageType> &&\n    std::is_same_v<typename itk::PixelTraits<typename ImageType::PixelType>::ValueType, float> &&\n    itk::PixelTraits<typename ImageType::PixelType>::Dimension == 1>::type;\n  template <typename ImageType>\n  using DisableCudaScalarType = typename std::enable_if<\n    std::is_same_v<CPUImageType, ImageType> ||\n    !std::is_same_v<typename itk::PixelTraits<typename ImageType::PixelType>::ValueType, float> ||\n    itk::PixelTraits<typename ImageType::PixelType>::Dimension != 1>::type;\n  template <typename ImageType>\n  using EnableVectorType =\n    typename std::enable_if<itk::PixelTraits<typename ImageType::PixelType>::Dimension != 1>::type;\n  template <typename ImageType>\n  using DisableVectorType =\n    typename std::enable_if<itk::PixelTraits<typename ImageType::PixelType>::Dimension == 1>::type;\n\n  template <typename ImageType, EnableCudaScalarAndVectorType<ImageType> * = nullptr>\n  ForwardProjectionPointerType\n  InstantiateCudaForwardProjection()\n  {\n    ForwardProjectionPointerType fw;\n#ifdef RTK_USE_CUDA\n    fw = CudaForwardProjectionImageFilter<ImageType, ImageType>::New();\n    dynamic_cast<rtk::CudaForwardProjectionImageFilter<ImageType, ImageType> *>(fw.GetPointer())\n      ->SetStepSize(m_StepSize);\n#endif\n    return fw;\n  }\n\n\n  template <typename ImageType, DisableCudaScalarAndVectorType<ImageType> * = nullptr>\n  ForwardProjectionPointerType\n  InstantiateCudaForwardProjection()\n  {\n    itkGenericExceptionMacro(\n      << \"CudaRayCastBackProjectionImageFilter only available with 3D CudaImage of float or itk::Vector<float,3>.\");\n    return nullptr;\n  }\n\n\n  template <typename ImageType, EnableVectorType<ImageType> * = nullptr>\n  ForwardProjectionPointerType\n  InstantiateJosephForwardAttenuatedProjection()\n  {\n    itkGenericExceptionMacro(<< \"JosephForwardAttenuatedProjectionImageFilter only available with scalar pixel types.\");\n    return nullptr;\n  }\n\n\n  template <typename ImageType, DisableVectorType<ImageType> * = nullptr>\n  ForwardProjectionPointerType\n  InstantiateJosephForwardAttenuatedProjection()\n  {\n    ForwardProjectionPointerType fw;\n    fw = JosephForwardAttenuatedProjectionImageFilter<VolumeType, ProjectionStackType>::New();\n    if (this->GetAttenuationMap().IsNotNull())\n    {\n      fw->SetInput(2, this->GetAttenuationMap());\n    }\n    else\n    {\n      itkExceptionMacro(<< \"Set Joseph attenuated forward projection filter but no attenuation map is given\");\n      return nullptr;\n    }\n    if (this->GetSuperiorClipImage().IsNotNull())\n    {\n      dynamic_cast<rtk::JosephForwardAttenuatedProjectionImageFilter<VolumeType, ProjectionStackType> *>(\n        fw.GetPointer())\n        ->SetSuperiorClipImage(this->GetSuperiorClipImage());\n    }\n    if (this->GetInferiorClipImage().IsNotNull())\n    {\n      dynamic_cast<rtk::JosephForwardAttenuatedProjectionImageFilter<VolumeType, ProjectionStackType> *>(\n        fw.GetPointer())\n        ->SetInferiorClipImage(this->GetInferiorClipImage());\n    }\n    return fw;\n  }\n\n  template <typename ImageType, EnableVectorType<ImageType> * = nullptr>\n  ForwardProjectionPointerType\n  InstantiateZengForwardProjection()\n  {\n    itkGenericExceptionMacro(<< \"JosephForwardAttenuatedProjectionImageFilter only available with scalar pixel types.\");\n    return nullptr;\n  }\n\n\n  template <typename ImageType, DisableVectorType<ImageType> * = nullptr>\n  ForwardProjectionPointerType\n  InstantiateZengForwardProjection()\n  {\n    ForwardProjectionPointerType fw;\n    fw = ZengForwardProjectionImageFilter<VolumeType, ProjectionStackType>::New();\n    if (this->GetAttenuationMap().IsNotNull())\n    {\n      fw->SetInput(2, this->GetAttenuationMap());\n    }\n    dynamic_cast<rtk::ZengForwardProjectionImageFilter<VolumeType, ProjectionStackType> *>(fw.GetPointer())\n      ->SetSigmaZero(m_SigmaZero);\n    dynamic_cast<rtk::ZengForwardProjectionImageFilter<VolumeType, ProjectionStackType> *>(fw.GetPointer())\n      ->SetAlpha(m_AlphaPSF);\n    return fw;\n  }\n\n  template <typename ImageType, EnableCudaScalarAndVectorType<ImageType> * = nullptr>\n  BackProjectionPointerType\n  InstantiateCudaBackProjection()\n  {\n    BackProjectionPointerType bp;\n#ifdef RTK_USE_CUDA\n    bp = CudaBackProjectionImageFilter<ImageType>::New();\n#endif\n    return bp;\n  }\n\n\n  template <typename ImageType, DisableCudaScalarAndVectorType<ImageType> * = nullptr>\n  BackProjectionPointerType\n  InstantiateCudaBackProjection()\n  {\n    itkGenericExceptionMacro(\n      << \"CudaBackProjectionImageFilter only available with 3D CudaImage of float or itk::Vector<float,3>.\");\n    return nullptr;\n  }\n\n\n  template <typename ImageType, EnableCudaScalarType<ImageType> * = nullptr>\n  BackProjectionPointerType\n  InstantiateCudaRayCastBackProjection()\n  {\n    BackProjectionPointerType bp;\n#ifdef RTK_USE_CUDA\n    bp = CudaRayCastBackProjectionImageFilter::New();\n    dynamic_cast<rtk::CudaRayCastBackProjectionImageFilter *>(bp.GetPointer())->SetStepSize(m_StepSize);\n#endif\n    return bp;\n  }\n\n\n  template <typename ImageType, DisableCudaScalarType<ImageType> * = nullptr>\n  BackProjectionPointerType\n  InstantiateCudaRayCastBackProjection()\n  {\n    itkGenericExceptionMacro(<< \"CudaRayCastBackProjectionImageFilter only available with 3D CudaImage of float.\");\n    return nullptr;\n  }\n\n\n  template <typename ImageType, EnableVectorType<ImageType> * = nullptr>\n  BackProjectionPointerType\n  InstantiateJosephBackAttenuatedProjection()\n  {\n    itkGenericExceptionMacro(<< \"JosephBackAttenuatedProjectionImageFilter only available with scalar pixel types.\");\n    return nullptr;\n  }\n\n\n  template <typename ImageType, DisableVectorType<ImageType> * = nullptr>\n  BackProjectionPointerType\n  InstantiateJosephBackAttenuatedProjection()\n  {\n    BackProjectionPointerType bp;\n    bp = JosephBackAttenuatedProjectionImageFilter<ImageType, ImageType>::New();\n    if (this->GetAttenuationMap().IsNotNull())\n    {\n      bp->SetInput(2, this->GetAttenuationMap());\n      return bp;\n    }\n    else\n    {\n      itkExceptionMacro(<< \"Set Joseph attenuated backprojection filter but no attenuation map is given\");\n      return nullptr;\n    }\n  }\n\n  template <typename ImageType, EnableVectorType<ImageType> * = nullptr>\n  BackProjectionPointerType\n  InstantiateZengBackProjection()\n  {\n    itkGenericExceptionMacro(<< \"JosephBackAttenuatedProjectionImageFilter only available with scalar pixel types.\");\n    return nullptr;\n  }\n\n\n  template <typename ImageType, DisableVectorType<ImageType> * = nullptr>\n  BackProjectionPointerType\n  InstantiateZengBackProjection()\n  {\n    BackProjectionPointerType bp;\n    bp = ZengBackProjectionImageFilter<ImageType, ImageType>::New();\n    if (this->GetAttenuationMap().IsNotNull())\n    {\n      bp->SetInput(2, this->GetAttenuationMap());\n    }\n    dynamic_cast<rtk::ZengBackProjectionImageFilter<VolumeType, ProjectionStackType> *>(bp.GetPointer())\n      ->SetSigmaZero(m_SigmaZero);\n    dynamic_cast<rtk::ZengBackProjectionImageFilter<VolumeType, ProjectionStackType> *>(bp.GetPointer())\n      ->SetAlpha(m_AlphaPSF);\n    return bp;\n  }\n\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkIterativeConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkIterativeConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkIterativeConeBeamReconstructionFilter_hxx\n#define rtkIterativeConeBeamReconstructionFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <class TOutputImage, class ProjectionStackType>\nIterativeConeBeamReconstructionFilter<TOutputImage, ProjectionStackType>::IterativeConeBeamReconstructionFilter()\n{\n  m_CurrentForwardProjectionConfiguration = FP_JOSEPH;\n  m_CurrentBackProjectionConfiguration = BP_VOXELBASED;\n}\n\ntemplate <class TOutputImage, class ProjectionStackType>\ntypename IterativeConeBeamReconstructionFilter<TOutputImage, ProjectionStackType>::ForwardProjectionPointerType\nIterativeConeBeamReconstructionFilter<TOutputImage, ProjectionStackType>::InstantiateForwardProjectionFilter(int fwtype)\n{\n  ForwardProjectionPointerType fw;\n  switch (fwtype)\n  {\n    case (FP_JOSEPH):\n      fw = JosephForwardProjectionImageFilter<VolumeType, ProjectionStackType>::New();\n      if (this->GetSuperiorClipImage().IsNotNull())\n      {\n        dynamic_cast<rtk::JosephForwardProjectionImageFilter<VolumeType, ProjectionStackType> *>(fw.GetPointer())\n          ->SetSuperiorClipImage(this->GetSuperiorClipImage());\n      }\n      if (this->GetInferiorClipImage().IsNotNull())\n      {\n        dynamic_cast<rtk::JosephForwardProjectionImageFilter<VolumeType, ProjectionStackType> *>(fw.GetPointer())\n          ->SetInferiorClipImage(this->GetInferiorClipImage());\n      }\n      break;\n    case (FP_CUDARAYCAST):\n      fw = InstantiateCudaForwardProjection<ProjectionStackType>();\n      break;\n    case (FP_JOSEPHATTENUATED):\n      fw = InstantiateJosephForwardAttenuatedProjection<ProjectionStackType>();\n      break;\n    case (FP_ZENG):\n      fw = InstantiateZengForwardProjection<ProjectionStackType>();\n      break;\n    default:\n      itkGenericExceptionMacro(<< \"Unhandled --fp value.\");\n  }\n  return fw;\n}\n\ntemplate <class TOutputImage, class ProjectionStackType>\ntypename IterativeConeBeamReconstructionFilter<TOutputImage, ProjectionStackType>::BackProjectionPointerType\nIterativeConeBeamReconstructionFilter<TOutputImage, ProjectionStackType>::InstantiateBackProjectionFilter(int bptype)\n{\n  BackProjectionPointerType bp;\n  switch (bptype)\n  {\n    case (BP_VOXELBASED):\n      bp = BackProjectionImageFilter<ProjectionStackType, VolumeType>::New();\n      break;\n    case (BP_JOSEPH):\n      bp = JosephBackProjectionImageFilter<ProjectionStackType, VolumeType>::New();\n      break;\n    case (BP_CUDAVOXELBASED):\n      bp = InstantiateCudaBackProjection<ProjectionStackType>();\n      break;\n    case (BP_CUDARAYCAST):\n      bp = InstantiateCudaRayCastBackProjection<ProjectionStackType>();\n      break;\n    case (BP_JOSEPHATTENUATED):\n      bp = InstantiateJosephBackAttenuatedProjection<ProjectionStackType>();\n      break;\n    case (BP_ZENG):\n      bp = InstantiateZengBackProjection<ProjectionStackType>();\n      break;\n    default:\n      itkGenericExceptionMacro(<< \"Unhandled --bp value.\");\n  }\n  return bp;\n}\n\ntemplate <class TOutputImage, class ProjectionStackType>\nvoid\nIterativeConeBeamReconstructionFilter<TOutputImage, ProjectionStackType>::SetForwardProjectionFilter(\n  ForwardProjectionType fwtype)\n{\n  if (m_CurrentForwardProjectionConfiguration != fwtype)\n  {\n    m_CurrentForwardProjectionConfiguration = fwtype;\n    this->Modified();\n  }\n}\n\ntemplate <class TOutputImage, class ProjectionStackType>\nvoid\nIterativeConeBeamReconstructionFilter<TOutputImage, ProjectionStackType>::SetBackProjectionFilter(\n  BackProjectionType bptype)\n{\n  if (m_CurrentBackProjectionConfiguration != bptype)\n  {\n    m_CurrentBackProjectionConfiguration = bptype;\n    this->Modified();\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkIterativeConeBeamReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkIterativeFDKConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkIterativeFDKConeBeamReconstructionFilter_h\n#define rtkIterativeFDKConeBeamReconstructionFilter_h\n\n#include <itkMultiplyImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkThresholdImageFilter.h>\n#include <itkDivideOrZeroOutImageFilter.h>\n\n#include \"rtkConstantImageSource.h\"\n#include \"rtkParkerShortScanImageFilter.h\"\n#include \"rtkDisplacedDetectorForOffsetFieldOfViewImageFilter.h\"\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n#include \"rtkRayBoxIntersectionImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class IterativeFDKConeBeamReconstructionFilter\n * \\brief Implements the Iterative FDK\n *\n * IterativeFDKConeBeamReconstructionFilter is a composite filter which combines\n * the different steps of the iterative FDK cone-beam reconstruction, mainly:\n * - FDK reconstruction,\n * - Forward projection,\n * - Difference between the calculated projections and the input ones,\n * - Multiplication by a small constant\n * This \"projections correction\" is used at the next iteration to improve the FDK.\n *\n * \\dot\n * digraph IterativeFDKConeBeamReconstructionFilter {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n * Parker [ label=\"rtk::ParkerShortScanImageFilter\" URL=\"\\ref rtk::ParkerShortScanImageFilter\"];\n * FDK [ label=\"rtk::FDKConeBeamReconstructionFilter\" URL=\"\\ref rtk::FDKConeBeamReconstructionFilter\"];\n * Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * Multiply [ label=\"itk::MultiplyImageFilter (by lambda)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * ConstantProjectionStack [ label=\"rtk::ConstantImageSource (projections)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ForwardProjection [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * RayBox [ label=\"rtk::RayBoxIntersectionImageFilter\" URL=\"\\ref rtk::RayBoxIntersectionImageFilter\"];\n * Threshold [ label=\"itk::ThresholdImageFilter\" URL=\"\\ref itk::ThresholdImageFilter\"];\n * Divide [ label=\"itk::DivideOrZeroOutImageFilter\" URL=\"\\ref itk::DivideOrZeroOutImageFilter\"];\n *\n * AfterInput1 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterInput0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterConstantSource [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterDivide [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * Input1 -> AfterInput1 [arrowhead=none];\n * AfterInput1 -> Displaced;\n * Displaced -> Parker;\n * Parker -> FDK;\n * Input0 -> AfterInput0;\n * AfterInput0 -> FDK;\n * ConstantProjectionStack -> AfterConstantSource [arrowhead=none];\n * AfterConstantSource -> ForwardProjection;\n * AfterConstantSource -> RayBox;\n * RayBox -> Divide;\n * FDK -> Threshold;\n * Threshold -> AfterThreshold [arrowhead=none];\n * AfterThreshold -> ForwardProjection;\n * AfterInput1 -> Subtract;\n * ForwardProjection -> Subtract;\n * Subtract -> Multiply;\n * Multiply -> Divide;\n * AfterThreshold -> Output;\n * AfterThreshold -> AfterInput0 [style=dashed, constraint=false];\n * Divide -> AfterDivide;\n * AfterDivide -> AfterInput1 [style=dashed, constraint=false];\n * }\n * \\enddot\n *\n * \\test rtkiterativefdktest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage, class TFFTPrecision = double>\nclass ITK_TEMPLATE_EXPORT IterativeFDKConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(IterativeFDKConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = IterativeFDKConeBeamReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using DisplacedDetectorFilterType = rtk::DisplacedDetectorImageFilter<OutputImageType, OutputImageType>;\n  using ParkerFilterType = rtk::ParkerShortScanImageFilter<OutputImageType, OutputImageType>;\n  using FDKFilterType = rtk::FDKConeBeamReconstructionFilter<OutputImageType, OutputImageType, TFFTPrecision>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<OutputImageType, OutputImageType, OutputImageType>;\n  using SubtractFilterType = itk::SubtractImageFilter<OutputImageType, OutputImageType>;\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  using ThresholdFilterType = itk::ThresholdImageFilter<OutputImageType>;\n  using DivideFilterType = itk::DivideOrZeroOutImageFilter<OutputImageType>;\n  using RayBoxIntersectionFilterType = rtk::RayBoxIntersectionImageFilter<OutputImageType, OutputImageType>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(IterativeFDKConeBeamReconstructionFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Get / Set the number of iterations. Default is 3. */\n  itkGetMacro(NumberOfIterations, unsigned int);\n  itkSetMacro(NumberOfIterations, unsigned int);\n\n  /** Get / Set the convergence factor. Default is 0.3. */\n  itkGetMacro(Lambda, double);\n  itkSetMacro(Lambda, double);\n\n  /** Get / Set the positivity enforcement behaviour */\n  itkGetMacro(EnforcePositivity, bool);\n  itkSetMacro(EnforcePositivity, bool);\n\n  /** Select the backprojection filter */\n  void\n  SetBackProjectionFilter(BackProjectionType itkNotUsed(_arg)) override\n  {\n    itkExceptionMacro(<< \"Backprojection cannot be changed\");\n  }\n\n  /** Get / Set the truncation correction */\n  itkGetMacro(TruncationCorrection, double);\n  itkSetMacro(TruncationCorrection, double);\n\n  /** Get / Set the Hann cut frequency */\n  itkGetMacro(HannCutFrequency, double);\n  itkSetMacro(HannCutFrequency, double);\n\n  /** Get / Set the Hann cut frequency on axis Y */\n  itkGetMacro(HannCutFrequencyY, double);\n  itkSetMacro(HannCutFrequencyY, double);\n\n  /** Get / Set the number of iterations. Default is 3. */\n  itkGetMacro(ProjectionSubsetSize, unsigned int);\n  itkSetMacro(ProjectionSubsetSize, unsigned int);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  IterativeFDKConeBeamReconstructionFilter();\n  ~IterativeFDKConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Pointers to each subfilter of this composite filter */\n  typename Superclass::ForwardProjectionPointerType m_ForwardProjectionFilter;\n  typename DisplacedDetectorFilterType::Pointer     m_DisplacedDetectorFilter;\n  typename ParkerFilterType::Pointer                m_ParkerFilter;\n  typename FDKFilterType::Pointer                   m_FDKFilter;\n  typename ThresholdFilterType::Pointer             m_ThresholdFilter;\n  typename SubtractFilterType::Pointer              m_SubtractFilter;\n  typename MultiplyFilterType::Pointer              m_MultiplyFilter;\n  typename ConstantImageSourceType::Pointer         m_ConstantProjectionStackSource;\n  typename DivideFilterType::Pointer                m_DivideFilter;\n  typename RayBoxIntersectionFilterType::Pointer    m_RayBoxFilter;\n\n  bool   m_EnforcePositivity;\n  double m_TruncationCorrection;\n  double m_HannCutFrequency;\n  double m_HannCutFrequencyY;\n  double m_ProjectionSubsetSize;\n  bool   m_DisableDisplacedDetectorFilter;\n\nprivate:\n  /** Geometry object */\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n\n  /** Number of iterations */\n  unsigned int m_NumberOfIterations;\n\n  /** Convergence factor. Default 0.3 */\n  double m_Lambda;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkIterativeFDKConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkIterativeFDKConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkIterativeFDKConeBeamReconstructionFilter_hxx\n#define rtkIterativeFDKConeBeamReconstructionFilter_hxx\n\n\n#include <algorithm>\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nIterativeFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::\n  IterativeFDKConeBeamReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set default parameters\n  m_EnforcePositivity = false;\n  m_NumberOfIterations = 3;\n  m_Lambda = 0.3;\n  m_TruncationCorrection = 0.0;\n  m_HannCutFrequency = 0.0;\n  m_HannCutFrequencyY = 0.0;\n  m_ProjectionSubsetSize = 16;\n\n  // Create each filter of the composite filter\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n  m_ParkerFilter = ParkerFilterType::New();\n  m_FDKFilter = FDKFilterType::New();\n  m_ThresholdFilter = ThresholdFilterType::New();\n  m_SubtractFilter = SubtractFilterType::New();\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_ConstantProjectionStackSource = ConstantImageSourceType::New();\n  m_RayBoxFilter = RayBoxIntersectionFilterType::New();\n  m_DivideFilter = DivideFilterType::New();\n\n  // Filter parameters\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(true);\n  m_DisableDisplacedDetectorFilter = false;\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nIterativeFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nIterativeFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput());\n\n  if (!inputPtr)\n    return;\n\n  m_FDKFilter->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  m_FDKFilter->GetOutput()->PropagateRequestedRegion();\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nIterativeFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateOutputInformation()\n{\n  // Set forward projection filter\n  m_ForwardProjectionFilter = this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n\n  // Set FDK parameters\n  m_FDKFilter->GetRampFilter()->SetTruncationCorrection(m_TruncationCorrection);\n  m_FDKFilter->GetRampFilter()->SetHannCutFrequency(m_HannCutFrequency);\n  m_FDKFilter->GetRampFilter()->SetHannCutFrequencyY(m_HannCutFrequencyY);\n  m_FDKFilter->SetProjectionSubsetSize(m_ProjectionSubsetSize);\n\n  // Source\n  m_ConstantProjectionStackSource->SetInformationFromImage(const_cast<TInputImage *>(this->GetInput(1)));\n  m_ConstantProjectionStackSource->SetConstant(0);\n\n  // Set box for the m_RayBoxFiltersectionImageFilter\n  itk::Vector<double, 3> Corner1, Corner2;\n  Corner1[0] = this->GetInput(0)->GetOrigin()[0];\n  Corner1[1] = this->GetInput(0)->GetOrigin()[1];\n  Corner1[2] = this->GetInput(0)->GetOrigin()[2];\n  Corner2[0] = this->GetInput(0)->GetOrigin()[0] +\n               this->GetInput(0)->GetLargestPossibleRegion().GetSize()[0] * this->GetInput(0)->GetSpacing()[0];\n  Corner2[1] = this->GetInput(0)->GetOrigin()[1] +\n               this->GetInput(0)->GetLargestPossibleRegion().GetSize()[1] * this->GetInput(0)->GetSpacing()[1];\n  Corner2[2] = this->GetInput(0)->GetOrigin()[2] +\n               this->GetInput(0)->GetLargestPossibleRegion().GetSize()[2] * this->GetInput(0)->GetSpacing()[2];\n  m_RayBoxFilter->SetBoxMin(Corner1);\n  m_RayBoxFilter->SetBoxMax(Corner2);\n\n  // Initial internal connections\n  m_DisplacedDetectorFilter->SetInput(this->GetInput(1));\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n\n  m_ParkerFilter->SetInput(m_DisplacedDetectorFilter->GetOutput());\n\n  m_FDKFilter->SetInput(0, this->GetInput(0));\n  m_FDKFilter->SetInput(1, m_ParkerFilter->GetOutput());\n\n  m_ForwardProjectionFilter->SetInput(0, m_ConstantProjectionStackSource->GetOutput());\n  m_ForwardProjectionFilter->SetInput(1, m_FDKFilter->GetOutput());\n\n  m_SubtractFilter->SetInput1(this->GetInput(1));\n  m_SubtractFilter->SetInput2(m_ForwardProjectionFilter->GetOutput());\n\n  m_RayBoxFilter->SetInput(m_ConstantProjectionStackSource->GetOutput());\n\n  m_MultiplyFilter->SetInput1(m_SubtractFilter->GetOutput());\n  m_MultiplyFilter->SetConstant2(m_Lambda);\n\n  m_DivideFilter->SetInput1(m_MultiplyFilter->GetOutput());\n  m_DivideFilter->SetInput2(m_RayBoxFilter->GetOutput());\n\n  m_DisplacedDetectorFilter->SetGeometry(m_Geometry);\n  m_ParkerFilter->SetGeometry(m_Geometry);\n  m_FDKFilter->SetGeometry(m_Geometry);\n  m_ForwardProjectionFilter->SetGeometry(m_Geometry);\n  m_RayBoxFilter->SetGeometry(m_Geometry.GetPointer());\n\n  // Slightly modify the pipeline if positivity enforcement is requested\n  if (m_EnforcePositivity)\n  {\n    m_ThresholdFilter->SetOutsideValue(0);\n    m_ThresholdFilter->ThresholdBelow(0);\n    m_ThresholdFilter->SetInput(m_FDKFilter->GetOutput());\n    m_ForwardProjectionFilter->SetInput(1, m_ThresholdFilter->GetOutput());\n  }\n\n  // Update output information on the last filter of the pipeline\n  m_DivideFilter->UpdateOutputInformation();\n\n  // Copy the information from the filter that will actually return the output\n  if (m_EnforcePositivity)\n    this->GetOutput()->CopyInformation(m_ThresholdFilter->GetOutput());\n  else\n    this->GetOutput()->CopyInformation(m_FDKFilter->GetOutput());\n\n  // Set memory management flags\n  // TODO\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nIterativeFDKConeBeamReconstructionFilter<TInputImage, TOutputImage, TFFTPrecision>::GenerateData()\n{\n  // Declare the image pointers used in the main loop\n  typename TInputImage::Pointer p_projs;\n  typename TInputImage::Pointer p_vol;\n\n  itk::IterationReporter iterationReporter(this, 0, 1);\n\n  // Run the first reconstruction\n  if (m_EnforcePositivity)\n    m_ThresholdFilter->Update();\n  else\n    m_FDKFilter->Update();\n\n  // first iteration is performed out of the loop\n  iterationReporter.CompletedStep();\n\n  // For each iteration over 1, go over each projection\n  for (unsigned int iter = 1; iter < m_NumberOfIterations; iter++)\n  {\n    m_DivideFilter->Update();\n\n    // Use previous iteration's result as input volume in next iteration\n    if (m_EnforcePositivity)\n      p_vol = m_ThresholdFilter->GetOutput();\n    else\n      p_vol = m_FDKFilter->GetOutput();\n    p_vol->DisconnectPipeline();\n    m_FDKFilter->SetInput(0, p_vol);\n\n    // Recreate broken link\n    if (m_EnforcePositivity)\n      m_ForwardProjectionFilter->SetInput(1, m_ThresholdFilter->GetOutput());\n    else\n      m_ForwardProjectionFilter->SetInput(1, m_FDKFilter->GetOutput());\n\n    // Use correction projections as input projections in next iteration\n    // No broken link to re-create\n    p_projs = m_DivideFilter->GetOutput();\n    p_projs->DisconnectPipeline();\n    m_DisplacedDetectorFilter->SetInput(p_projs);\n\n    // Run the next reconstruction\n    if (m_EnforcePositivity)\n    {\n      m_ThresholdFilter->Update();\n      this->GraftOutput(m_ThresholdFilter->GetOutput());\n    }\n    else\n    {\n      m_FDKFilter->Update();\n      this->GraftOutput(m_FDKFilter->GetOutput());\n    }\n\n    iterationReporter.CompletedStep();\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkIterativeFDKConeBeamReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkJosephBackAttenuatedProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkJosephBackAttenuatedProjectionImageFilter_h\n#define rtkJosephBackAttenuatedProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n#include \"rtkJosephBackProjectionImageFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\nnamespace Functor\n{\n/** \\class InterpolationWeightMultiplicationAttenuatedBackProjection\n * \\brief Function to multiply the interpolation weights with the projected\n * volume values and attenuation map.\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TCoordinateType, class TOutput = TInput>\nclass ITK_TEMPLATE_EXPORT InterpolationWeightMultiplicationAttenuatedBackProjection\n{\npublic:\n  InterpolationWeightMultiplicationAttenuatedBackProjection() { m_AttenuationPixel = 0; }\n\n  ~InterpolationWeightMultiplicationAttenuatedBackProjection() = default;\n  bool\n  operator!=(const InterpolationWeightMultiplicationAttenuatedBackProjection &) const\n  {\n    return false;\n  }\n\n  bool\n  operator==(const InterpolationWeightMultiplicationAttenuatedBackProjection & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline TOutput\n  operator()(const double stepLengthInVoxel, const TCoordinateType weight, const TInput * p, const int i)\n  {\n    const double w = weight * stepLengthInVoxel;\n\n    m_AttenuationPixel += w * (p + m_AttenuationMinusEmissionMapsPtrDiff)[i];\n    return w * (p + m_AttenuationMinusEmissionMapsPtrDiff)[i];\n  }\n\n  void\n  SetAttenuationMinusEmissionMapsPtrDiff(std::ptrdiff_t pd)\n  {\n    m_AttenuationMinusEmissionMapsPtrDiff = pd;\n  }\n  TOutput *\n  GetAttenuationPixel()\n  {\n    return &m_AttenuationPixel;\n  }\n\nprivate:\n  std::ptrdiff_t m_AttenuationMinusEmissionMapsPtrDiff;\n  TInput         m_AttenuationPixel;\n};\n\n/** \\class ComputeAttenuationCorrectionBackProjection\n * \\brief Function to compute the attenuation correction on the projection.\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT ComputeAttenuationCorrectionBackProjection\n{\npublic:\n  using VectorType = itk::Vector<double, 3>;\n\n  ComputeAttenuationCorrectionBackProjection() { m_Ex1 = 1; }\n\n  ~ComputeAttenuationCorrectionBackProjection() = default;\n  bool\n  operator!=(const ComputeAttenuationCorrectionBackProjection &) const\n  {\n    return false;\n  }\n\n  bool\n  operator==(const ComputeAttenuationCorrectionBackProjection & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline TOutput\n  operator()(const TInput rayValue, const TInput attenuationRay, const VectorType & stepInMM, bool & isNewRay)\n  {\n    if (isNewRay)\n    {\n      m_Ex1 = 1;\n      isNewRay = false;\n    }\n    TInput ex2 = exp(-attenuationRay * stepInMM.GetNorm());\n    TInput wf;\n    if (*m_AttenuationPixel > 0)\n    {\n      wf = (m_Ex1 - ex2) / *m_AttenuationPixel;\n    }\n    else\n    {\n      wf = m_Ex1 * stepInMM.GetNorm();\n    }\n\n    m_Ex1 = ex2;\n    *m_AttenuationPixel = 0;\n    return wf * rayValue;\n  }\n\n  void\n  SetAttenuationPixel(TInput * attenuationPixel)\n  {\n    m_AttenuationPixel = attenuationPixel;\n  }\n\nprivate:\n  TInput   m_Ex1;\n  TInput * m_AttenuationPixel;\n};\n\n/** \\class SplatWeightMultiplicationAttenuated\n * \\brief Function to multiply the interpolation weights with the projection\n * values.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TCoordinateType, class TOutput = TCoordinateType>\nclass ITK_TEMPLATE_EXPORT SplatWeightMultiplicationAttenuated\n{\npublic:\n  SplatWeightMultiplicationAttenuated() = default;\n  ~SplatWeightMultiplicationAttenuated() = default;\n  bool\n  operator!=(const SplatWeightMultiplicationAttenuated &) const\n  {\n    return false;\n  }\n\n  bool\n  operator==(const SplatWeightMultiplicationAttenuated & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const TInput &        rayValue,\n             TOutput &             output,\n             const double          stepLengthInVoxel,\n             const double          itkNotUsed(voxelSize),\n             const TCoordinateType weight) const\n  {\n    output += rayValue * weight * stepLengthInVoxel;\n  }\n};\n} // end namespace Functor\n\n/** \\class JosephBackAttenuatedProjectionImageFilter\n * \\brief Attenuated Joseph back projection.\n *\n * Performs a attenuated back projection, i.e. smearing of ray value along its path,\n * using [Joseph, IEEE TMI, 1982] and [Gullberg, Phys. Med. Biol., 1985]. The back projector is the adjoint operator of\n * the forward attenuated projector\n *\n * \\test rtkbackprojectiontest.cxx\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Projector\n */\n\ntemplate <\n  class TInputImage,\n  class TOutputImage,\n  class TInterpolationWeightMultiplication = Functor::InterpolationWeightMultiplicationAttenuatedBackProjection<\n    typename TInputImage::PixelType,\n    typename itk::PixelTraits<typename TInputImage::PixelType>::ValueType>,\n  class TSplatWeightMultiplication = Functor::\n    SplatWeightMultiplicationAttenuated<typename TInputImage::PixelType, double, typename TOutputImage::PixelType>,\n  class TSumAlongRay = Functor::ComputeAttenuationCorrectionBackProjection<typename TInputImage::PixelType,\n                                                                           typename TOutputImage::PixelType>>\nclass ITK_TEMPLATE_EXPORT JosephBackAttenuatedProjectionImageFilter\n  : public JosephBackProjectionImageFilter<TInputImage,\n                                           TOutputImage,\n                                           TInterpolationWeightMultiplication,\n                                           TSplatWeightMultiplication,\n                                           TSumAlongRay>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(JosephBackAttenuatedProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = JosephBackAttenuatedProjectionImageFilter;\n  using Superclass = JosephBackProjectionImageFilter<TInputImage,\n                                                     TOutputImage,\n                                                     TInterpolationWeightMultiplication,\n                                                     TSplatWeightMultiplication,\n                                                     TSumAlongRay>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using InputPixelType = typename TInputImage::PixelType;\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using CoordinateType = double;\n  using VectorType = itk::Vector<CoordinateType, TInputImage::ImageDimension>;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryPointer = typename GeometryType::Pointer;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(JosephBackAttenuatedProjectionImageFilter);\n\nprotected:\n  JosephBackAttenuatedProjectionImageFilter();\n  ~JosephBackAttenuatedProjectionImageFilter() override = default;\n\n  /** Apply changes to the input image requested region. */\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Only the last two inputs should be in the same space so we need\n   * to overwrite the method. */\n  void\n  VerifyInputInformation() const override;\n\n  void\n  GenerateData() override;\n\n  void\n  Init();\n};\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkJosephBackAttenuatedProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkJosephBackAttenuatedProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkJosephBackAttenuatedProjectionImageFilter_hxx\n#define rtkJosephBackAttenuatedProjectionImageFilter_hxx\n\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkBoxShape.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkInputDataObjectConstIterator.h>\n\nnamespace rtk\n{\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nJosephBackAttenuatedProjectionImageFilter<TInputImage,\n                                          TOutputImage,\n                                          TInterpolationWeightMultiplication,\n                                          TSplatWeightMultiplication,\n                                          TSumAlongRay>::JosephBackAttenuatedProjectionImageFilter()\n{\n  this->m_InferiorClip = 0.;\n  this->m_SuperiorClip = 1.;\n  this->SetNumberOfRequiredInputs(3);\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nvoid\nJosephBackAttenuatedProjectionImageFilter<TInputImage,\n                                          TOutputImage,\n                                          TInterpolationWeightMultiplication,\n                                          TSplatWeightMultiplication,\n                                          TSumAlongRay>::GenerateInputRequestedRegion()\n{\n  // Input 2 is the attenuation map relative to the volume\n  typename Superclass::InputImagePointer inputPtr2 = const_cast<TInputImage *>(this->GetInput(2));\n  if (!inputPtr2)\n    return;\n  Superclass::GenerateInputRequestedRegion();\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nvoid\nJosephBackAttenuatedProjectionImageFilter<TInputImage,\n                                          TOutputImage,\n                                          TInterpolationWeightMultiplication,\n                                          TSplatWeightMultiplication,\n                                          TSumAlongRay>::VerifyInputInformation() const\n{\n  using ImageBaseType = const itk::ImageBase<InputImageDimension>;\n\n  ImageBaseType * inputPtr1 = nullptr;\n\n  itk::InputDataObjectConstIterator it(this);\n  for (; !it.IsAtEnd(); ++it)\n  {\n    // Check whether the output is an image of the appropriate\n    // dimension (use ProcessObject's version of the GetInput()\n    // method since it returns the input as a pointer to a\n    // DataObject as opposed to the subclass version which\n    // static_casts the input to an TInputImage).\n    if (it.GetName() != \"_1\")\n    {\n      inputPtr1 = dynamic_cast<ImageBaseType *>(it.GetInput());\n    }\n    if (inputPtr1)\n    {\n      break;\n    }\n  }\n\n  for (; !it.IsAtEnd(); ++it)\n  {\n    if (it.GetName() != \"_1\")\n    {\n      auto * inputPtrN = dynamic_cast<ImageBaseType *>(it.GetInput());\n      // Physical space computation only matters if we're using two\n      // images, and not an image and a constant.\n      if (inputPtrN)\n      {\n        // check that the image occupy the same physical space, and that\n        // each index is at the same physical location\n\n        // tolerance for origin and spacing depends on the size of pixel\n        // tolerance for directions a fraction of the unit cube.\n        const double coordinateTol = itk::Math::abs(Self::GetGlobalDefaultCoordinateTolerance() *\n                                                    inputPtr1->GetSpacing()[0]); // use first dimension spacing\n\n        if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n              inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n        {\n          std::ostringstream originString, spacingString, directionString;\n          if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol))\n          {\n            originString.setf(std::ios::scientific);\n            originString.precision(7);\n            originString << \"InputImage Origin: \" << inputPtr1->GetOrigin() << \", InputImage\" << it.GetName()\n                         << \" Origin: \" << inputPtrN->GetOrigin() << std::endl;\n            originString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol))\n          {\n            spacingString.setf(std::ios::scientific);\n            spacingString.precision(7);\n            spacingString << \"InputImage Spacing: \" << inputPtr1->GetSpacing() << \", InputImage\" << it.GetName()\n                          << \" Spacing: \" << inputPtrN->GetSpacing() << std::endl;\n            spacingString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n                inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n          {\n            directionString.setf(std::ios::scientific);\n            directionString.precision(7);\n            directionString << \"InputImage Direction: \" << inputPtr1->GetDirection() << \", InputImage\" << it.GetName()\n                            << \" Direction: \" << inputPtrN->GetDirection() << std::endl;\n            directionString << \"\\tTolerance: \" << Self::GetGlobalDefaultDirectionTolerance() << std::endl;\n          }\n          itkExceptionMacro(<< \"Inputs do not occupy the same physical space! \" << std::endl\n                            << originString.str() << spacingString.str() << directionString.str());\n        }\n      }\n    }\n  }\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nvoid\nJosephBackAttenuatedProjectionImageFilter<TInputImage,\n                                          TOutputImage,\n                                          TInterpolationWeightMultiplication,\n                                          TSplatWeightMultiplication,\n                                          TSumAlongRay>::Init()\n{\n  this->m_InterpolationWeightMultiplication.SetAttenuationMinusEmissionMapsPtrDiff(\n    this->GetInput(2)->GetBufferPointer() - this->GetInput(0)->GetBufferPointer());\n  this->m_SumAlongRay.SetAttenuationPixel(this->m_InterpolationWeightMultiplication.GetAttenuationPixel());\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nvoid\nJosephBackAttenuatedProjectionImageFilter<TInputImage,\n                                          TOutputImage,\n                                          TInterpolationWeightMultiplication,\n                                          TSplatWeightMultiplication,\n                                          TSumAlongRay>::GenerateData()\n{\n  Init();\n  Superclass::GenerateData();\n}\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkJosephBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkJosephBackProjectionImageFilter_h\n#define rtkJosephBackProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\n#include <itkVectorImage.h>\n\nnamespace rtk\n{\nnamespace Functor\n{\n/** \\class InterpolationWeightMultiplicationBackProjection\n * \\brief Function to multiply the interpolation weights with the projected\n * volume values.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TCoordinateType, class TOutput = TInput>\nclass ITK_TEMPLATE_EXPORT InterpolationWeightMultiplicationBackProjection\n{\npublic:\n  InterpolationWeightMultiplicationBackProjection() = default;\n  ~InterpolationWeightMultiplicationBackProjection() = default;\n  bool\n  operator!=(const InterpolationWeightMultiplicationBackProjection &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const InterpolationWeightMultiplicationBackProjection & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline TOutput\n  operator()(const double          itkNotUsed(stepLengthInVoxel),\n             const TCoordinateType itkNotUsed(weight),\n             const TInput *        itkNotUsed(p),\n             const int             itkNotUsed(i)) const\n  {\n    return {};\n  }\n};\n\n/** \\class SumAlongRay\n * \\brief Function to compute the attenuation correction on the projection.\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT ValueAlongRay\n{\npublic:\n  using VectorType = itk::Vector<double, 3>;\n\n  ValueAlongRay() = default;\n  ~ValueAlongRay() = default;\n  bool\n  operator!=(const ValueAlongRay &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const ValueAlongRay & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline const TOutput &\n  operator()(const TInput &     rayValue,\n             const TInput       itkNotUsed(attenuationRay),\n             const VectorType & itkNotUsed(stepInMM),\n             bool               itkNotUsed(isEndRay)) const\n  {\n    return rayValue;\n  }\n};\n/** \\class SplatWeightMultiplication\n * \\brief Function to multiply the interpolation weights with the projection\n * values.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TCoordinateType, class TOutput = TCoordinateType>\nclass ITK_TEMPLATE_EXPORT SplatWeightMultiplication\n{\npublic:\n  SplatWeightMultiplication() = default;\n  ~SplatWeightMultiplication() = default;\n  bool\n  operator!=(const SplatWeightMultiplication &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const SplatWeightMultiplication & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const TInput &        rayValue,\n             TOutput &             output,\n             const double          stepLengthInVoxel,\n             const double          voxelSize,\n             const TCoordinateType weight) const\n  {\n    output += rayValue * weight * voxelSize * stepLengthInVoxel;\n  }\n};\n\n} // end namespace Functor\n\n\n/** \\class JosephBackProjectionImageFilter\n * \\brief Joseph back projection.\n *\n * Performs a back projection, i.e. smearing of ray value along its path,\n * using [Joseph, IEEE TMI, 1982]. The back projector is the adjoint operator of the\n * forward projector\n *\n * \\test rtkbackprojectiontest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK Projector\n */\n\ntemplate <\n  class TInputImage,\n  class TOutputImage,\n  class TInterpolationWeightMultiplication = Functor::InterpolationWeightMultiplicationBackProjection<\n    typename TInputImage::PixelType,\n    typename itk::PixelTraits<typename TInputImage::PixelType>::ValueType>,\n  class TSplatWeightMultiplication =\n    Functor::SplatWeightMultiplication<typename TInputImage::PixelType, double, typename TOutputImage::PixelType>,\n  class TSumAlongRay = Functor::ValueAlongRay<typename TInputImage::PixelType, typename TOutputImage::PixelType>>\nclass ITK_TEMPLATE_EXPORT JosephBackProjectionImageFilter : public BackProjectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(JosephBackProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = JosephBackProjectionImageFilter;\n  using Superclass = BackProjectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using InputPixelType = typename TInputImage::PixelType;\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using CoordinateType = double;\n  using VectorType = itk::Vector<CoordinateType, TInputImage::ImageDimension>;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryPointer = typename GeometryType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(JosephBackProjectionImageFilter);\n\n  /** Get/Set the functor that is used to multiply each interpolation value with a volume value */\n  TInterpolationWeightMultiplication &\n  GetInterpolationWeightMultiplication()\n  {\n    return m_InterpolationWeightMultiplication;\n  }\n  const TInterpolationWeightMultiplication &\n  GetInterpolationWeightMultiplication() const\n  {\n    return m_InterpolationWeightMultiplication;\n  }\n  void\n  SetInterpolationWeightMultiplication(const TInterpolationWeightMultiplication & _arg)\n  {\n    if (m_InterpolationWeightMultiplication != _arg)\n    {\n      m_InterpolationWeightMultiplication = _arg;\n      this->Modified();\n    }\n  }\n\n  /** Get/Set the functor that is used to multiply each interpolation value with a volume value */\n  TSplatWeightMultiplication &\n  GetSplatWeightMultiplication()\n  {\n    return m_SplatWeightMultiplication;\n  }\n  const TSplatWeightMultiplication &\n  GetSplatWeightMultiplication() const\n  {\n    return m_SplatWeightMultiplication;\n  }\n  void\n  SetSplatWeightMultiplication(const TSplatWeightMultiplication & _arg)\n  {\n    if (m_SplatWeightMultiplication != _arg)\n    {\n      m_SplatWeightMultiplication = _arg;\n      this->Modified();\n    }\n  }\n\n  /** Get/Set the functor that is used to compute the sum along the ray*/\n  TSumAlongRay &\n  GetSumAlongRay()\n  {\n    return m_SumAlongRay;\n  }\n  const TSumAlongRay &\n  GetSumAlongRay() const\n  {\n    return m_SumAlongRay;\n  }\n  void\n  SetSumAlongRay(const TSumAlongRay & _arg)\n  {\n    if (m_SumAlongRay != _arg)\n    {\n      m_SumAlongRay = _arg;\n      this->Modified();\n    }\n  }\n\n  /** Each ray is clipped from source+m_InferiorClip*(pixel-source) to\n  ** source+m_SuperiorClip*(pixel-source) with m_InferiorClip and\n  ** m_SuperiorClip equal 0 and 1 by default. */\n  itkGetMacro(InferiorClip, double);\n  itkSetMacro(InferiorClip, double);\n  itkGetMacro(SuperiorClip, double);\n  itkSetMacro(SuperiorClip, double);\n\nprotected:\n  JosephBackProjectionImageFilter();\n  ~JosephBackProjectionImageFilter() override = default;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  inline void\n  BilinearSplat(const InputPixelType & rayValue,\n                const double           stepLengthInVoxel,\n                const double           voxelSize,\n                OutputPixelType *      pxiyi,\n                OutputPixelType *      pxsyi,\n                OutputPixelType *      pxiys,\n                OutputPixelType *      pxsys,\n                const double           x,\n                const double           y,\n                const int              ox,\n                const int              oy);\n\n  inline void\n  BilinearSplatOnBorders(const InputPixelType & rayValue,\n                         const double           stepLengthInVoxel,\n                         const double           voxelSize,\n                         OutputPixelType *      pxiyi,\n                         OutputPixelType *      pxsyi,\n                         OutputPixelType *      pxiys,\n                         OutputPixelType *      pxsys,\n                         const double           x,\n                         const double           y,\n                         const int              ox,\n                         const int              oy,\n                         const CoordinateType   minx,\n                         const CoordinateType   miny,\n                         const CoordinateType   maxx,\n                         const CoordinateType   maxy);\n\n  inline OutputPixelType\n  BilinearInterpolation(const double           stepLengthInVoxel,\n                        const InputPixelType * pxiyi,\n                        const InputPixelType * pxsyi,\n                        const InputPixelType * pxiys,\n                        const InputPixelType * pxsys,\n                        const double           x,\n                        const double           y,\n                        const int              ox,\n                        const int              oy);\n\n  inline OutputPixelType\n  BilinearInterpolationOnBorders(const double           stepLengthInVoxel,\n                                 const InputPixelType * pxiyi,\n                                 const InputPixelType * pxsyi,\n                                 const InputPixelType * pxiys,\n                                 const InputPixelType * pxsys,\n                                 const double           x,\n                                 const double           y,\n                                 const int              ox,\n                                 const int              oy,\n                                 const double           minx,\n                                 const double           miny,\n                                 const double           maxx,\n                                 const double           maxy);\n\n  /** Functor */\n  TSplatWeightMultiplication         m_SplatWeightMultiplication;\n  TInterpolationWeightMultiplication m_InterpolationWeightMultiplication;\n  TSumAlongRay                       m_SumAlongRay;\n  double                             m_InferiorClip{ 0. };\n  double                             m_SuperiorClip{ 1. };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkJosephBackProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkJosephBackProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkJosephBackProjectionImageFilter_hxx\n#define rtkJosephBackProjectionImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkBoxShape.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkIdentityTransform.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nJosephBackProjectionImageFilter<TInputImage,\n                                TOutputImage,\n                                TInterpolationWeightMultiplication,\n                                TSplatWeightMultiplication,\n                                TSumAlongRay>::JosephBackProjectionImageFilter() = default;\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nvoid\nJosephBackProjectionImageFilter<TInputImage,\n                                TOutputImage,\n                                TInterpolationWeightMultiplication,\n                                TSplatWeightMultiplication,\n                                TSumAlongRay>::GenerateData()\n{\n  // Allocate the output image\n  this->AllocateOutputs();\n\n  const unsigned int               Dimension = TInputImage::ImageDimension;\n  typename TInputImage::RegionType buffReg = this->GetInput(1)->GetBufferedRegion();\n  int                              offsets[3];\n  offsets[0] = 1;\n  offsets[1] = this->GetInput(0)->GetBufferedRegion().GetSize()[0];\n  offsets[2] =\n    this->GetInput(0)->GetBufferedRegion().GetSize()[0] * this->GetInput(0)->GetBufferedRegion().GetSize()[1];\n\n  const auto * geometry = dynamic_cast<const GeometryType *>(this->GetGeometry());\n  if (!geometry)\n  {\n    itkGenericExceptionMacro(<< \"Error, ThreeDCircularProjectionGeometry expected\");\n  }\n\n  // beginBuffer is pointing at point with index (0,0,0) in memory, even if\n  // it is not in the allocated memory\n  typename TOutputImage::PixelType * beginBuffer = this->GetOutput()->GetBufferPointer() -\n                                                   offsets[0] * this->GetOutput()->GetBufferedRegion().GetIndex()[0] -\n                                                   offsets[1] * this->GetOutput()->GetBufferedRegion().GetIndex()[1] -\n                                                   offsets[2] * this->GetOutput()->GetBufferedRegion().GetIndex()[2];\n\n  // volPPToIndex maps the physical 3D coordinates of a point (in mm) to the\n  // corresponding 3D volume index\n  typename GeometryType::ThreeDHomogeneousMatrixType volPPToIndex;\n  volPPToIndex = GetPhysicalPointToIndexMatrix(this->GetInput(0));\n\n  // Initialize output region with input region in case the filter is not in\n  // place\n  if (this->GetInput() != this->GetOutput())\n  {\n    // Iterators on volume input and output\n    using InputRegionIterator = itk::ImageRegionConstIterator<TInputImage>;\n    InputRegionIterator itVolIn(this->GetInput(0), this->GetInput()->GetBufferedRegion());\n\n    itk::ImageRegionIteratorWithIndex<TOutputImage> itVolOut(this->GetOutput(), this->GetInput()->GetBufferedRegion());\n\n    while (!itVolIn.IsAtEnd())\n    {\n      itVolOut.Set(itVolIn.Get());\n      ++itVolIn;\n      ++itVolOut;\n    }\n  }\n\n  // Iterators on projections input\n  using InputRegionIterator = ProjectionsRegionConstIteratorRayBased<TInputImage>;\n  InputRegionIterator * itIn = nullptr;\n  itIn = InputRegionIterator::New(this->GetInput(1), buffReg, geometry, volPPToIndex);\n\n  // Create intersection functions, one for each possible main direction\n  auto                          box = BoxShape::New();\n  typename BoxShape::VectorType boxMin, boxMax;\n  for (unsigned int i = 0; i < Dimension; i++)\n  {\n    boxMin[i] = this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n    boxMax[i] =\n      this->GetOutput()->GetRequestedRegion().GetIndex()[i] + this->GetOutput()->GetRequestedRegion().GetSize()[i] - 1;\n    boxMax[i] *= 1. - itk::NumericTraits<BoxShape::ScalarType>::epsilon();\n  }\n  box->SetBoxMin(boxMin);\n  box->SetBoxMax(boxMax);\n\n  // m_InferiorClip and m_SuperiorClip are understood in the sense of a\n  // source-to-pixel vector. Since we go from pixel-to-source, we invert them.\n  double inferiorClip = 1. - m_SuperiorClip;\n  double superiorClip = 1. - m_InferiorClip;\n\n  // Go over each pixel of the projection\n  typename BoxShape::VectorType stepMM, np, fp;\n  for (unsigned int pix = 0; pix < buffReg.GetNumberOfPixels(); pix++, itIn->Next())\n  {\n    typename InputRegionIterator::PointType pixelPosition = itIn->GetPixelPosition();\n    typename InputRegionIterator::PointType dirVox = -itIn->GetSourceToPixel();\n\n    // Select main direction\n    unsigned int         mainDir = 0;\n    BoxShape::VectorType dirVoxAbs;\n    for (unsigned int i = 0; i < Dimension; i++)\n    {\n      dirVoxAbs[i] = itk::Math::abs(dirVox[i]);\n      if (dirVoxAbs[i] > dirVoxAbs[mainDir])\n        mainDir = i;\n    }\n\n    // Test if there is an intersection\n    BoxShape::ScalarType nearDist = NAN, farDist = NAN;\n    if (box->IsIntersectedByRay(pixelPosition, dirVox, nearDist, farDist) &&\n        farDist >= 0. && // check if detector after the source\n        nearDist <= 1.)  // check if detector after or in the volume\n    {\n      // Clip the casting between source and pixel of the detector\n      nearDist = std::max(nearDist, inferiorClip);\n      farDist = std::min(farDist, superiorClip);\n\n      // Compute and sort intersections: (n)earest and (f)arthest (p)points\n      np = pixelPosition + nearDist * dirVox;\n      fp = pixelPosition + farDist * dirVox;\n\n      // Compute main nearest and farthest slice indices\n      const int ns = itk::Math::rnd(np[mainDir]);\n      const int fs = itk::Math::rnd(fp[mainDir]);\n\n      // Determine the other two directions\n      unsigned int notMainDirInf = (mainDir + 1) % Dimension;\n      unsigned int notMainDirSup = (mainDir + 2) % Dimension;\n      if (notMainDirInf > notMainDirSup)\n        std::swap(notMainDirInf, notMainDirSup);\n\n      const CoordinateType minx = box->GetBoxMin()[notMainDirInf];\n      const CoordinateType miny = box->GetBoxMin()[notMainDirSup];\n      const CoordinateType maxx = box->GetBoxMax()[notMainDirInf];\n      const CoordinateType maxy = box->GetBoxMax()[notMainDirSup];\n\n      // Init data pointers to first pixel of slice ns (i)nferior and (s)uperior (x|y) corner\n      const int offsetx = offsets[notMainDirInf];\n      const int offsety = offsets[notMainDirSup];\n      int       offsetz = offsets[mainDir];\n\n      OutputPixelType * pxiyi = beginBuffer + ns * offsetz;\n      OutputPixelType * pxsyi = pxiyi + offsetx;\n      OutputPixelType * pxiys = pxiyi + offsety;\n      OutputPixelType * pxsys = pxsyi + offsety;\n\n      // Compute step size and go to first voxel\n      CoordinateType       residualB = ns - np[mainDir];\n      CoordinateType       residualE = fp[mainDir] - fs;\n      const CoordinateType norm = itk::NumericTraits<CoordinateType>::One / dirVox[mainDir];\n      CoordinateType       stepx = dirVox[notMainDirInf] * norm;\n      CoordinateType       stepy = dirVox[notMainDirSup] * norm;\n      if (np[mainDir] > fp[mainDir])\n      {\n        residualB *= -1;\n        residualE *= -1;\n        offsetz *= -1;\n        stepx *= -1;\n        stepy *= -1;\n      }\n      CoordinateType currentx = np[notMainDirInf] + residualB * stepx;\n      CoordinateType currenty = np[notMainDirSup] + residualB * stepy;\n\n      // Compute voxel to millimeters conversion\n      stepMM[notMainDirInf] = this->GetInput(0)->GetSpacing()[notMainDirInf] * stepx;\n      stepMM[notMainDirSup] = this->GetInput(0)->GetSpacing()[notMainDirSup] * stepy;\n      stepMM[mainDir] = this->GetInput(0)->GetSpacing()[mainDir];\n\n      typename TOutputImage::PixelType attenuationRay =\n        itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue();\n      bool isNewRay = true;\n      if (fs == ns) // If the voxel is a corner, we can skip most steps\n      {\n        attenuationRay += BilinearInterpolationOnBorders(itk::Math::abs(fp[mainDir] - np[mainDir]),\n                                                         pxiyi,\n                                                         pxsyi,\n                                                         pxiys,\n                                                         pxsys,\n                                                         currentx,\n                                                         currenty,\n                                                         offsetx,\n                                                         offsety,\n                                                         minx,\n                                                         miny,\n                                                         maxx,\n                                                         maxy);\n        const typename TInputImage::PixelType & rayValue =\n          m_SumAlongRay(itIn->Value(), attenuationRay, stepMM, isNewRay);\n        BilinearSplatOnBorders(rayValue,\n                               itk::Math::abs(fp[mainDir] - np[mainDir]),\n                               stepMM.GetNorm(),\n                               pxiyi,\n                               pxsyi,\n                               pxiys,\n                               pxsys,\n                               currentx,\n                               currenty,\n                               offsetx,\n                               offsety,\n                               minx,\n                               miny,\n                               maxx,\n                               maxy);\n      }\n      else\n      {\n        // First step\n        attenuationRay += BilinearInterpolationOnBorders(\n          residualB + 0.5, pxiyi, pxsyi, pxiys, pxsys, currentx, currenty, offsetx, offsety, minx, miny, maxx, maxy);\n\n        const typename TInputImage::PixelType & rayValueF =\n          m_SumAlongRay(itIn->Value(), attenuationRay, stepMM, isNewRay);\n\n        BilinearSplatOnBorders(rayValueF,\n                               residualB + 0.5,\n                               stepMM.GetNorm(),\n                               pxiyi,\n                               pxsyi,\n                               pxiys,\n                               pxsys,\n                               currentx,\n                               currenty,\n                               offsetx,\n                               offsety,\n                               minx,\n                               miny,\n                               maxx,\n                               maxy);\n\n        // Move to next main direction slice\n        pxiyi += offsetz;\n        pxsyi += offsetz;\n        pxiys += offsetz;\n        pxsys += offsetz;\n        currentx += stepx;\n        currenty += stepy;\n\n        // Middle steps\n        for (int i{ 0 }; i < itk::Math::abs(fs - ns) - 1; ++i)\n        {\n          attenuationRay += BilinearInterpolation(1., pxiyi, pxsyi, pxiys, pxsys, currentx, currenty, offsetx, offsety);\n\n          const typename TInputImage::PixelType & rayValueM =\n            m_SumAlongRay(itIn->Value(), attenuationRay, stepMM, isNewRay);\n\n          BilinearSplat(\n            rayValueM, 1.0, stepMM.GetNorm(), pxiyi, pxsyi, pxiys, pxsys, currentx, currenty, offsetx, offsety);\n\n          // Move to next main direction slice\n          pxiyi += offsetz;\n          pxsyi += offsetz;\n          pxiys += offsetz;\n          pxsys += offsetz;\n          currentx += stepx;\n          currenty += stepy;\n        }\n\n        // Last step\n        attenuationRay += BilinearInterpolationOnBorders(\n          residualE + 0.5, pxiyi, pxsyi, pxiys, pxsys, currentx, currenty, offsetx, offsety, minx, miny, maxx, maxy);\n\n        const typename TInputImage::PixelType & rayValueE =\n          m_SumAlongRay(itIn->Value(), attenuationRay, stepMM, isNewRay);\n\n        BilinearSplatOnBorders(rayValueE,\n                               residualE + 0.5,\n                               stepMM.GetNorm(),\n                               pxiyi,\n                               pxsyi,\n                               pxiys,\n                               pxsys,\n                               currentx,\n                               currenty,\n                               offsetx,\n                               offsety,\n                               minx,\n                               miny,\n                               maxx,\n                               maxy);\n      }\n    }\n  }\n  delete itIn;\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nvoid\nJosephBackProjectionImageFilter<TInputImage,\n                                TOutputImage,\n                                TInterpolationWeightMultiplication,\n                                TSplatWeightMultiplication,\n                                TSumAlongRay>::BilinearSplat(const InputPixelType & rayValue,\n                                                             const double           stepLengthInVoxel,\n                                                             const double           voxelSize,\n                                                             OutputPixelType *      pxiyi,\n                                                             OutputPixelType *      pxsyi,\n                                                             OutputPixelType *      pxiys,\n                                                             OutputPixelType *      pxsys,\n                                                             const double           x,\n                                                             const double           y,\n                                                             const int              ox,\n                                                             const int              oy)\n{\n  int            ix = itk::Math::floor(x);\n  int            iy = itk::Math::floor(y);\n  int            idx = ix * ox + iy * oy;\n  CoordinateType lx = x - ix;\n  CoordinateType ly = y - iy;\n  CoordinateType lxc = 1. - lx;\n  CoordinateType lyc = 1. - ly;\n\n  m_SplatWeightMultiplication(rayValue, pxiyi[idx], stepLengthInVoxel, voxelSize, lxc * lyc);\n  m_SplatWeightMultiplication(rayValue, pxsyi[idx], stepLengthInVoxel, voxelSize, lx * lyc);\n  m_SplatWeightMultiplication(rayValue, pxiys[idx], stepLengthInVoxel, voxelSize, lxc * ly);\n  m_SplatWeightMultiplication(rayValue, pxsys[idx], stepLengthInVoxel, voxelSize, lx * ly);\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\nvoid\nJosephBackProjectionImageFilter<TInputImage,\n                                TOutputImage,\n                                TInterpolationWeightMultiplication,\n                                TSplatWeightMultiplication,\n                                TSumAlongRay>::BilinearSplatOnBorders(const InputPixelType & rayValue,\n                                                                      const double           stepLengthInVoxel,\n                                                                      const double           voxelSize,\n                                                                      OutputPixelType *      pxiyi,\n                                                                      OutputPixelType *      pxsyi,\n                                                                      OutputPixelType *      pxiys,\n                                                                      OutputPixelType *      pxsys,\n                                                                      const double           x,\n                                                                      const double           y,\n                                                                      const int              ox,\n                                                                      const int              oy,\n                                                                      const CoordinateType   minx,\n                                                                      const CoordinateType   miny,\n                                                                      const CoordinateType   maxx,\n                                                                      const CoordinateType   maxy)\n{\n  int            ix = itk::Math::floor(x);\n  int            iy = itk::Math::floor(y);\n  int            idx = ix * ox + iy * oy;\n  CoordinateType lx = x - ix;\n  CoordinateType ly = y - iy;\n  CoordinateType lxc = 1. - lx;\n  CoordinateType lyc = 1. - ly;\n\n  int offset_xi = 0;\n  int offset_yi = 0;\n  int offset_xs = 0;\n  int offset_ys = 0;\n\n  if (ix < minx)\n    offset_xi = ox;\n  if (iy < miny)\n    offset_yi = oy;\n  if (ix >= maxx)\n    offset_xs = -ox;\n  if (iy >= maxy)\n    offset_ys = -oy;\n\n  m_SplatWeightMultiplication(rayValue, pxiyi[idx + offset_xi + offset_yi], stepLengthInVoxel, voxelSize, lxc * lyc);\n  m_SplatWeightMultiplication(rayValue, pxiys[idx + offset_xi + offset_ys], stepLengthInVoxel, voxelSize, lxc * ly);\n  m_SplatWeightMultiplication(rayValue, pxsyi[idx + offset_xs + offset_yi], stepLengthInVoxel, voxelSize, lx * lyc);\n  m_SplatWeightMultiplication(rayValue, pxsys[idx + offset_xs + offset_ys], stepLengthInVoxel, voxelSize, lx * ly);\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\ntypename JosephBackProjectionImageFilter<TInputImage,\n                                         TOutputImage,\n                                         TInterpolationWeightMultiplication,\n                                         TSplatWeightMultiplication,\n                                         TSumAlongRay>::OutputPixelType\nJosephBackProjectionImageFilter<TInputImage,\n                                TOutputImage,\n                                TInterpolationWeightMultiplication,\n                                TSplatWeightMultiplication,\n                                TSumAlongRay>::BilinearInterpolation(const double           stepLengthInVoxel,\n                                                                     const InputPixelType * pxiyi,\n                                                                     const InputPixelType * pxsyi,\n                                                                     const InputPixelType * pxiys,\n                                                                     const InputPixelType * pxsys,\n                                                                     const CoordinateType   x,\n                                                                     const CoordinateType   y,\n                                                                     const int              ox,\n                                                                     const int              oy)\n{\n  int            ix = itk::Math::floor(x);\n  int            iy = itk::Math::floor(y);\n  int            idx = ix * ox + iy * oy;\n  CoordinateType lx = x - ix;\n  CoordinateType ly = y - iy;\n  CoordinateType lxc = 1. - lx;\n  CoordinateType lyc = 1. - ly;\n  return (m_InterpolationWeightMultiplication(stepLengthInVoxel, lxc * lyc, pxiyi, idx) +\n          m_InterpolationWeightMultiplication(stepLengthInVoxel, lx * lyc, pxsyi, idx) +\n          m_InterpolationWeightMultiplication(stepLengthInVoxel, lxc * ly, pxiys, idx) +\n          m_InterpolationWeightMultiplication(stepLengthInVoxel, lx * ly, pxsys, idx));\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TSplatWeightMultiplication,\n          class TSumAlongRay>\ntypename JosephBackProjectionImageFilter<TInputImage,\n                                         TOutputImage,\n                                         TInterpolationWeightMultiplication,\n                                         TSplatWeightMultiplication,\n                                         TSumAlongRay>::OutputPixelType\nJosephBackProjectionImageFilter<TInputImage,\n                                TOutputImage,\n                                TInterpolationWeightMultiplication,\n                                TSplatWeightMultiplication,\n                                TSumAlongRay>::BilinearInterpolationOnBorders(const double           stepLengthInVoxel,\n                                                                              const InputPixelType * pxiyi,\n                                                                              const InputPixelType * pxsyi,\n                                                                              const InputPixelType * pxiys,\n                                                                              const InputPixelType * pxsys,\n                                                                              const CoordinateType   x,\n                                                                              const CoordinateType   y,\n                                                                              const int              ox,\n                                                                              const int              oy,\n                                                                              const CoordinateType   minx,\n                                                                              const CoordinateType   miny,\n                                                                              const CoordinateType   maxx,\n                                                                              const CoordinateType   maxy)\n{\n  int            ix = itk::Math::floor(x);\n  int            iy = itk::Math::floor(y);\n  int            idx = ix * ox + iy * oy;\n  CoordinateType lx = x - ix;\n  CoordinateType ly = y - iy;\n  CoordinateType lxc = 1. - lx;\n  CoordinateType lyc = 1. - ly;\n\n  int offset_xi = 0;\n  int offset_yi = 0;\n  int offset_xs = 0;\n  int offset_ys = 0;\n\n  OutputPixelType result = itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue();\n  if (ix < minx)\n    offset_xi = ox;\n  if (iy < miny)\n    offset_yi = oy;\n  if (ix >= maxx)\n    offset_xs = -ox;\n  if (iy >= maxy)\n    offset_ys = -oy;\n\n  result += m_InterpolationWeightMultiplication(stepLengthInVoxel, lxc * lyc, pxiyi, idx + offset_xi + offset_yi);\n  result += m_InterpolationWeightMultiplication(stepLengthInVoxel, lxc * ly, pxiys, idx + offset_xi + offset_ys);\n  result += m_InterpolationWeightMultiplication(stepLengthInVoxel, lx * lyc, pxsyi, idx + offset_xs + offset_yi);\n  result += m_InterpolationWeightMultiplication(stepLengthInVoxel, lx * ly, pxsys, idx + offset_xs + offset_ys);\n\n  return (result);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkJosephForwardAttenuatedProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkJosephForwardAttenuatedProjectionImageFilter_h\n#define rtkJosephForwardAttenuatedProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n#include \"rtkMacro.h\"\n#include <itkPixelTraits.h>\n#include <cmath>\n#include <vector>\n\nnamespace rtk\n{\nnamespace Functor\n{\n/** \\class InterpolationWeightMultiplicationAttenuated\n * \\brief Function to multiply the interpolation weights with the projected\n * volume values and attenuation map.\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TCoordinateType, class TOutput = TInput>\nclass ITK_TEMPLATE_EXPORT InterpolationWeightMultiplicationAttenuated\n{\npublic:\n  InterpolationWeightMultiplicationAttenuated()\n  {\n    for (std::size_t i = 0; i < itk::ITK_MAX_THREADS; i++)\n    {\n      m_AttenuationRay[i] = 0;\n      m_AttenuationPixel[i] = 0;\n      m_Ex1[i] = 1;\n    }\n  }\n\n  ~InterpolationWeightMultiplicationAttenuated() = default;\n  bool\n  operator!=(const InterpolationWeightMultiplicationAttenuated &) const\n  {\n    return false;\n  }\n\n  bool\n  operator==(const InterpolationWeightMultiplicationAttenuated & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline TOutput\n  operator()(const ThreadIdType    threadId,\n             const double          stepLengthInVoxel,\n             const TCoordinateType weight,\n             const TInput *        p,\n             const int             i)\n  {\n    const double w = weight * stepLengthInVoxel;\n\n    m_AttenuationRay[threadId] += w * (p + m_AttenuationMinusEmissionMapsPtrDiff)[i];\n    m_AttenuationPixel[threadId] += w * (p + m_AttenuationMinusEmissionMapsPtrDiff)[i];\n    return weight * p[i];\n  }\n\n  void\n  SetAttenuationMinusEmissionMapsPtrDiff(std::ptrdiff_t pd)\n  {\n    m_AttenuationMinusEmissionMapsPtrDiff = pd;\n  }\n  TOutput *\n  GetAttenuationRay()\n  {\n    return m_AttenuationRay;\n  }\n  TOutput *\n  GetAttenuationPixel()\n  {\n    return m_AttenuationPixel;\n  }\n  TOutput *\n  GetEx1()\n  {\n    return m_Ex1;\n  }\n\nprivate:\n  std::ptrdiff_t m_AttenuationMinusEmissionMapsPtrDiff;\n  TInput         m_AttenuationRay[itk::ITK_MAX_THREADS];\n  TInput         m_AttenuationPixel[itk::ITK_MAX_THREADS];\n  TInput         m_Ex1[itk::ITK_MAX_THREADS];\n};\n\n/** \\class ComputeAttenuationCorrection\n * \\brief Function to compute the attenuation correction on the projection.\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT ComputeAttenuationCorrection\n{\npublic:\n  using VectorType = itk::Vector<double, 3>;\n\n  ComputeAttenuationCorrection() = default;\n  ~ComputeAttenuationCorrection() = default;\n  bool\n  operator!=(const ComputeAttenuationCorrection &) const\n  {\n    return false;\n  }\n\n  bool\n  operator==(const ComputeAttenuationCorrection & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const ThreadIdType threadId, TOutput & sumValue, const TInput volumeValue, const VectorType & stepInMM)\n  {\n    TInput ex2 = exp(-m_AttenuationRay[threadId] * stepInMM.GetNorm());\n    TInput wf;\n\n    if (m_AttenuationPixel[threadId] > 0)\n    {\n      wf = (m_Ex1[threadId] - ex2) / m_AttenuationPixel[threadId];\n    }\n    else\n    {\n      wf = m_Ex1[threadId] * stepInMM.GetNorm();\n    }\n\n    m_Ex1[threadId] = ex2;\n    m_AttenuationPixel[threadId] = 0;\n    sumValue += wf * volumeValue;\n  }\n\n  void\n  SetAttenuationRayVector(TInput * attenuationRayVector)\n  {\n    m_AttenuationRay = attenuationRayVector;\n  }\n  void\n  SetAttenuationPixelVector(TInput * attenuationPixelVector)\n  {\n    m_AttenuationPixel = attenuationPixelVector;\n  }\n  void\n  SetEx1(TInput * ex1)\n  {\n    m_Ex1 = ex1;\n  }\n\nprivate:\n  TInput * m_AttenuationRay;\n  TInput * m_AttenuationPixel;\n  TInput * m_Ex1;\n};\n\n/** \\class ProjectedValueAccumulationAttenuated\n * \\brief Function to accumulate the ray casting on the projection.\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT ProjectedValueAccumulationAttenuated\n{\npublic:\n  using VectorType = itk::Vector<double, 3>;\n\n  ProjectedValueAccumulationAttenuated() = default;\n  ~ProjectedValueAccumulationAttenuated() = default;\n  bool\n  operator!=(const ProjectedValueAccumulationAttenuated &) const\n  {\n    return false;\n  }\n\n  bool\n  operator==(const ProjectedValueAccumulationAttenuated & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const ThreadIdType threadId,\n             const TInput &     input,\n             TOutput &          output,\n             const TOutput &    rayCastValue,\n             const VectorType & /*stepInMM*/,\n             const VectorType & itkNotUsed(source),\n             const VectorType & itkNotUsed(sourceToPixel),\n             const VectorType & itkNotUsed(nearestPoint),\n             const VectorType & itkNotUsed(farthestPoint))\n  {\n    output = input + rayCastValue;\n    m_Attenuation[threadId] = 0;\n    m_Ex1[threadId] = 1;\n  }\n\n  void\n  SetAttenuationVector(TInput * attenuationVector)\n  {\n    m_Attenuation = attenuationVector;\n  }\n  void\n  SetEx1(TInput * ex1)\n  {\n    m_Ex1 = ex1;\n  }\n\nprivate:\n  TInput * m_Attenuation;\n  TInput * m_Ex1;\n};\n} // end namespace Functor\n\n/** \\class JosephForwardAttenuatedProjectionImageFilter\n * \\brief Joseph forward projection.\n *\n * Performs a attenuated Joseph forward projection, i.e. accumulation along x-ray lines,\n * using [Joseph, IEEE TMI, 1982] and [Gullberg, Phys. Med. Biol., 1985]. The forward projector tests if the  detector\n * has been placed after the source and the volume. If the detector is in the volume\n * the ray tracing is performed only until that point.\n *\n * \\test rtkforwardattenuatedprojectiontest.cxx\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Projector\n */\n\ntemplate <\n  class TInputImage,\n  class TOutputImage,\n  class TInterpolationWeightMultiplication = Functor::InterpolationWeightMultiplicationAttenuated<\n    typename TInputImage::PixelType,\n    typename itk::PixelTraits<typename TInputImage::PixelType>::ValueType>,\n  class TProjectedValueAccumulation =\n    Functor::ProjectedValueAccumulationAttenuated<typename TInputImage::PixelType, typename TOutputImage::PixelType>,\n  class TSumAlongRay =\n    Functor::ComputeAttenuationCorrection<typename TInputImage::PixelType, typename TOutputImage::PixelType>>\nclass ITK_TEMPLATE_EXPORT JosephForwardAttenuatedProjectionImageFilter\n  : public JosephForwardProjectionImageFilter<TInputImage,\n                                              TOutputImage,\n                                              TInterpolationWeightMultiplication,\n                                              TProjectedValueAccumulation,\n                                              TSumAlongRay>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(JosephForwardAttenuatedProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = JosephForwardAttenuatedProjectionImageFilter;\n  using Superclass = JosephForwardProjectionImageFilter<TInputImage,\n                                                        TOutputImage,\n                                                        TInterpolationWeightMultiplication,\n                                                        TProjectedValueAccumulation,\n                                                        TSumAlongRay>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using InputPixelType = typename TInputImage::PixelType;\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using CoordinateType = double;\n  using VectorType = itk::Vector<CoordinateType, TInputImage::ImageDimension>;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(JosephForwardAttenuatedProjectionImageFilter);\n\nprotected:\n  JosephForwardAttenuatedProjectionImageFilter();\n  ~JosephForwardAttenuatedProjectionImageFilter() override = default;\n\n  /** Apply changes to the input image requested region. */\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  /** Only the last two inputs should be in the same space so we need\n   * to overwrite the method. */\n  void\n  VerifyInputInformation() const override;\n};\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkJosephForwardAttenuatedProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkJosephForwardAttenuatedProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkJosephForwardAttenuatedProjectionImageFilter_hxx\n#define rtkJosephForwardAttenuatedProjectionImageFilter_hxx\n\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkBoxShape.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkIdentityTransform.h>\n#include <itkInputDataObjectConstIterator.h>\n\nnamespace rtk\n{\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TComputeAttenuationCorrection>\nJosephForwardAttenuatedProjectionImageFilter<\n  TInputImage,\n  TOutputImage,\n  TInterpolationWeightMultiplication,\n  TProjectedValueAccumulation,\n  TComputeAttenuationCorrection>::JosephForwardAttenuatedProjectionImageFilter()\n{\n  this->SetNumberOfRequiredInputs(3);\n  this->DynamicMultiThreadingOff();\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TComputeAttenuationCorrection>\nvoid\nJosephForwardAttenuatedProjectionImageFilter<TInputImage,\n                                             TOutputImage,\n                                             TInterpolationWeightMultiplication,\n                                             TProjectedValueAccumulation,\n                                             TComputeAttenuationCorrection>::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n  // Input 2 is the attenuation map relative to the volume\n  typename Superclass::InputImagePointer inputPtr2 = const_cast<TInputImage *>(this->GetInput(2));\n  if (!inputPtr2)\n    return;\n\n  typename TInputImage::RegionType reqRegion2 = inputPtr2->GetLargestPossibleRegion();\n  inputPtr2->SetRequestedRegion(reqRegion2);\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TComputeAttenuationCorrection>\nvoid\nJosephForwardAttenuatedProjectionImageFilter<TInputImage,\n                                             TOutputImage,\n                                             TInterpolationWeightMultiplication,\n                                             TProjectedValueAccumulation,\n                                             TComputeAttenuationCorrection>::VerifyInputInformation() const\n{\n  Superclass::VerifyInputInformation();\n  using ImageBaseType = const itk::ImageBase<InputImageDimension>;\n\n  ImageBaseType * inputPtr1 = nullptr;\n\n  itk::InputDataObjectConstIterator it(this);\n  for (; !it.IsAtEnd(); ++it)\n  {\n    // Check whether the output is an image of the appropriate\n    // dimension (use ProcessObject's version of the GetInput()\n    // method since it returns the input as a pointer to a\n    // DataObject as opposed to the subclass version which\n    // static_casts the input to an TInputImage).\n    if (it.GetName() == \"_1\")\n    {\n      inputPtr1 = dynamic_cast<ImageBaseType *>(it.GetInput());\n    }\n    if (inputPtr1)\n    {\n      break;\n    }\n  }\n\n  for (; !it.IsAtEnd(); ++it)\n  {\n    if (it.GetName() == \"_2\")\n    {\n      auto * inputPtrN = dynamic_cast<ImageBaseType *>(it.GetInput());\n      // Physical space computation only matters if we're using two\n      // images, and not an image and a constant.\n      if (inputPtrN)\n      {\n        // check that the image occupy the same physical space, and that\n        // each index is at the same physical location\n\n        // tolerance for origin and spacing depends on the size of pixel\n        // tolerance for directions a fraction of the unit cube.\n        const double coordinateTol = itk::Math::abs(Self::GetGlobalDefaultCoordinateTolerance() *\n                                                    inputPtr1->GetSpacing()[0]); // use first dimension spacing\n\n        if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n              inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n        {\n          std::ostringstream originString, spacingString, directionString;\n          if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol))\n          {\n            originString.setf(std::ios::scientific);\n            originString.precision(7);\n            originString << \"InputImage Origin: \" << inputPtr1->GetOrigin() << \", InputImage\" << it.GetName()\n                         << \" Origin: \" << inputPtrN->GetOrigin() << std::endl;\n            originString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol))\n          {\n            spacingString.setf(std::ios::scientific);\n            spacingString.precision(7);\n            spacingString << \"InputImage Spacing: \" << inputPtr1->GetSpacing() << \", InputImage\" << it.GetName()\n                          << \" Spacing: \" << inputPtrN->GetSpacing() << std::endl;\n            spacingString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n                inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n          {\n            directionString.setf(std::ios::scientific);\n            directionString.precision(7);\n            directionString << \"InputImage Direction: \" << inputPtr1->GetDirection() << \", InputImage\" << it.GetName()\n                            << \" Direction: \" << inputPtrN->GetDirection() << std::endl;\n            directionString << \"\\tTolerance: \" << Self::GetGlobalDefaultDirectionTolerance() << std::endl;\n          }\n          itkExceptionMacro(<< \"Inputs do not occupy the same physical space! \" << std::endl\n                            << originString.str() << spacingString.str() << directionString.str());\n        }\n      }\n    }\n  }\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TComputeAttenuationCorrection>\nvoid\nJosephForwardAttenuatedProjectionImageFilter<TInputImage,\n                                             TOutputImage,\n                                             TInterpolationWeightMultiplication,\n                                             TProjectedValueAccumulation,\n                                             TComputeAttenuationCorrection>::BeforeThreadedGenerateData()\n{\n  this->GetInterpolationWeightMultiplication().SetAttenuationMinusEmissionMapsPtrDiff(\n    this->GetInput(2)->GetBufferPointer() - this->GetInput(1)->GetBufferPointer());\n  this->GetProjectedValueAccumulation().SetAttenuationVector(\n    this->GetInterpolationWeightMultiplication().GetAttenuationRay());\n  this->GetSumAlongRay().SetAttenuationRayVector(this->GetInterpolationWeightMultiplication().GetAttenuationRay());\n  this->GetSumAlongRay().SetAttenuationPixelVector(this->GetInterpolationWeightMultiplication().GetAttenuationPixel());\n  this->GetProjectedValueAccumulation().SetEx1(this->GetInterpolationWeightMultiplication().GetEx1());\n  this->GetSumAlongRay().SetEx1(this->GetInterpolationWeightMultiplication().GetEx1());\n}\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkJosephForwardProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkJosephForwardProjectionImageFilter_h\n#define rtkJosephForwardProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkMacro.h\"\n#include <itkPixelTraits.h>\n\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\n#include <itkVectorImage.h>\nnamespace rtk\n{\nnamespace Functor\n{\n/** \\class InterpolationWeightMultiplication\n * \\brief Function to multiply the interpolation weights with the projected\n * volume values.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TCoordinateType, class TOutput = TInput>\nclass ITK_TEMPLATE_EXPORT InterpolationWeightMultiplication\n{\npublic:\n  InterpolationWeightMultiplication() = default;\n  ~InterpolationWeightMultiplication() = default;\n  bool\n  operator!=(const InterpolationWeightMultiplication &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const InterpolationWeightMultiplication & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline TOutput\n  operator()(const ThreadIdType    itkNotUsed(threadId),\n             const double          itkNotUsed(stepLengthInVoxel),\n             const TCoordinateType weight,\n             const TInput *        p,\n             const int             i) const\n  {\n    return weight * p[i];\n  }\n};\n\n/** \\class SumAlongRay\n * \\brief Function to compute the attenuation correction on the projection.\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT SumAlongRay\n{\npublic:\n  using VectorType = itk::Vector<double, 3>;\n\n  SumAlongRay() = default;\n  ~SumAlongRay() = default;\n  bool\n  operator!=(const SumAlongRay &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const SumAlongRay & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const ThreadIdType itkNotUsed(threadId),\n             TOutput &          sumValue,\n             const TInput       volumeValue,\n             const VectorType & itkNotUsed(stepInMM))\n  {\n    sumValue += static_cast<TOutput>(volumeValue);\n  }\n};\n\n/** \\class ProjectedValueAccumulation\n * \\brief Function to accumulate the ray casting on the projection.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT ProjectedValueAccumulation\n{\npublic:\n  using VectorType = itk::Vector<double, 3>;\n\n  ProjectedValueAccumulation() = default;\n  ~ProjectedValueAccumulation() = default;\n  bool\n  operator!=(const ProjectedValueAccumulation &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const ProjectedValueAccumulation & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const ThreadIdType itkNotUsed(threadId),\n             const TInput &     input,\n             TOutput &          output,\n             const TOutput &    rayCastValue,\n             const VectorType & stepInMM,\n             const VectorType & itkNotUsed(source),\n             const VectorType & itkNotUsed(sourceToPixel),\n             const VectorType & itkNotUsed(nearestPoint),\n             const VectorType & itkNotUsed(farthestPoint)) const\n  {\n    output = input + rayCastValue * stepInMM.GetNorm();\n  }\n};\n\n} // end namespace Functor\n\n\n/** \\class JosephForwardProjectionImageFilter\n * \\brief Joseph forward projection.\n *\n * Performs a forward projection, i.e. accumulation along x-ray lines,\n * using [Joseph, IEEE TMI, 1982]. The forward projector tests if the  detector\n * has been placed after the source and the volume. If the detector is in the volume\n * the ray tracing is performed only until that point.\n *\n * \\test rtkforwardprojectiontest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Projector\n */\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication = Functor::InterpolationWeightMultiplication<\n            typename TInputImage::PixelType,\n            typename itk::PixelTraits<typename TInputImage::PixelType>::ValueType>,\n          class TProjectedValueAccumulation =\n            Functor::ProjectedValueAccumulation<typename TInputImage::PixelType, typename TOutputImage::PixelType>,\n          class TSumAlongRay = Functor::SumAlongRay<typename TInputImage::PixelType, typename TOutputImage::PixelType>>\nclass ITK_TEMPLATE_EXPORT JosephForwardProjectionImageFilter\n  : public ForwardProjectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(JosephForwardProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = JosephForwardProjectionImageFilter;\n  using Superclass = ForwardProjectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using InputPixelType = typename TInputImage::PixelType;\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using CoordinateType = double;\n  using VectorType = itk::Vector<CoordinateType, TInputImage::ImageDimension>;\n  using TClipImageType = itk::Image<double, TOutputImage::ImageDimension>;\n  using TClipImagePointer = typename TClipImageType::Pointer;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(JosephForwardProjectionImageFilter);\n\n  /** Get/Set the functor that is used to multiply each interpolation value with a volume value */\n  TInterpolationWeightMultiplication &\n  GetInterpolationWeightMultiplication()\n  {\n    return m_InterpolationWeightMultiplication;\n  }\n  const TInterpolationWeightMultiplication &\n  GetInterpolationWeightMultiplication() const\n  {\n    return m_InterpolationWeightMultiplication;\n  }\n  void\n  SetInterpolationWeightMultiplication(const TInterpolationWeightMultiplication & _arg)\n  {\n    if (m_InterpolationWeightMultiplication != _arg)\n    {\n      m_InterpolationWeightMultiplication = _arg;\n      this->Modified();\n    }\n  }\n\n  /** Get/Set the functor that is used to accumulate values in the projection image after the ray\n   * casting has been performed. */\n  TProjectedValueAccumulation &\n  GetProjectedValueAccumulation()\n  {\n    return m_ProjectedValueAccumulation;\n  }\n  const TProjectedValueAccumulation &\n  GetProjectedValueAccumulation() const\n  {\n    return m_ProjectedValueAccumulation;\n  }\n  void\n  SetProjectedValueAccumulation(const TProjectedValueAccumulation & _arg)\n  {\n    if (m_ProjectedValueAccumulation != _arg)\n    {\n      m_ProjectedValueAccumulation = _arg;\n      this->Modified();\n    }\n  }\n\n  /** Get/Set the functor that is used to compute the sum along the ray*/\n  TSumAlongRay &\n  GetSumAlongRay()\n  {\n    return m_SumAlongRay;\n  }\n  const TSumAlongRay &\n  GetSumAlongRay() const\n  {\n    return m_SumAlongRay;\n  }\n  void\n  SetSumAlongRay(const TSumAlongRay & _arg)\n  {\n    if (m_SumAlongRay != _arg)\n    {\n      m_SumAlongRay = _arg;\n      this->Modified();\n    }\n  }\n\n  /** Set/Get the inferior clip image. Each pixel of the image\n   ** corresponds to the value of the inferior clip of the ray\n   ** emitted from that pixel. */\n  void\n  SetInferiorClipImage(const TClipImageType * inferiorClipImage)\n  {\n    // Process object is not const-correct so the const casting is required.\n    this->SetInput(\"InferiorClipImage\", const_cast<TClipImageType *>(inferiorClipImage));\n  }\n  typename TClipImageType::ConstPointer\n  GetInferiorClipImage()\n  {\n    return static_cast<const TClipImageType *>(this->itk::ProcessObject::GetInput(\"InferiorClipImage\"));\n  }\n\n  /** Set/Get the superior clip image. Each pixel of the image\n   ** corresponds to the value of the superior clip of the ray\n   ** emitted from that pixel. */\n  void\n  SetSuperiorClipImage(const TClipImageType * superiorClipImage)\n  {\n    // Process object is not const-correct so the const casting is required.\n    this->SetInput(\"SuperiorClipImage\", const_cast<TClipImageType *>(superiorClipImage));\n  }\n  typename TClipImageType::ConstPointer\n  GetSuperiorClipImage()\n  {\n    return static_cast<const TClipImageType *>(this->itk::ProcessObject::GetInput(\"SuperiorClipImage\"));\n  }\n\n  /** Each ray is clipped from source+m_InferiorClip*(pixel-source) to\n  ** source+m_SuperiorClip*(pixel-source) with m_InferiorClip and\n  ** m_SuperiorClip equal 0 and 1 by default. */\n  itkGetMacro(InferiorClip, double);\n  itkSetMacro(InferiorClip, double);\n  itkGetMacro(SuperiorClip, double);\n  itkSetMacro(SuperiorClip, double);\n\nprotected:\n  JosephForwardProjectionImageFilter();\n  ~JosephForwardProjectionImageFilter() override = default;\n\n  /** Apply changes to the input image requested region. */\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, ThreadIdType threadId) override;\n\n  /** If a third input is given, it should be in the same physical space\n   * as the first one. */\n  void\n  VerifyInputInformation() const override;\n\n  inline OutputPixelType\n  BilinearInterpolation(const ThreadIdType     threadId,\n                        const double           stepLengthInVoxel,\n                        const InputPixelType * pxiyi,\n                        const InputPixelType * pxsyi,\n                        const InputPixelType * pxiys,\n                        const InputPixelType * pxsys,\n                        const double           x,\n                        const double           y,\n                        const int              ox,\n                        const int              oy);\n\n  inline OutputPixelType\n  BilinearInterpolationOnBorders(const ThreadIdType     threadId,\n                                 const double           stepLengthInVoxel,\n                                 const InputPixelType * pxiyi,\n                                 const InputPixelType * pxsyi,\n                                 const InputPixelType * pxiys,\n                                 const InputPixelType * pxsys,\n                                 const double           x,\n                                 const double           y,\n                                 const int              ox,\n                                 const int              oy,\n                                 const double           minx,\n                                 const double           miny,\n                                 const double           maxx,\n                                 const double           maxy);\n\nprivate:\n  // Functors\n  TInterpolationWeightMultiplication m_InterpolationWeightMultiplication;\n  TProjectedValueAccumulation        m_ProjectedValueAccumulation;\n  TSumAlongRay                       m_SumAlongRay;\n  double                             m_InferiorClip{ 0. };\n  double                             m_SuperiorClip{ 1. };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkJosephForwardProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkJosephForwardProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkJosephForwardProjectionImageFilter_hxx\n#define rtkJosephForwardProjectionImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkBoxShape.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\n#include <itkImageRegionIteratorWithIndex.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TSumAlongRay>\nJosephForwardProjectionImageFilter<TInputImage,\n                                   TOutputImage,\n                                   TInterpolationWeightMultiplication,\n                                   TProjectedValueAccumulation,\n                                   TSumAlongRay>::JosephForwardProjectionImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n}\n\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TSumAlongRay>\nvoid\nJosephForwardProjectionImageFilter<TInputImage,\n                                   TOutputImage,\n                                   TInterpolationWeightMultiplication,\n                                   TProjectedValueAccumulation,\n                                   TSumAlongRay>::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n\n  if (this->GetInferiorClipImage().IsNotNull())\n  {\n    TClipImagePointer inputInferiorClipImage = const_cast<TClipImageType *>(this->GetInferiorClipImage().GetPointer());\n    if (!inputInferiorClipImage)\n      return;\n    inputInferiorClipImage->SetRequestedRegion(inputInferiorClipImage->GetRequestedRegion());\n  }\n\n  if (this->GetSuperiorClipImage().IsNotNull())\n  {\n    TClipImagePointer inputSuperiorClipImage = const_cast<TClipImageType *>(this->GetSuperiorClipImage().GetPointer());\n    if (!inputSuperiorClipImage)\n      return;\n    inputSuperiorClipImage->SetRequestedRegion(inputSuperiorClipImage->GetRequestedRegion());\n  }\n}\n\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TSumAlongRay>\nvoid\nJosephForwardProjectionImageFilter<TInputImage,\n                                   TOutputImage,\n                                   TInterpolationWeightMultiplication,\n                                   TProjectedValueAccumulation,\n                                   TSumAlongRay>::VerifyInputInformation() const\n{\n  using ImageBaseType = const itk::ImageBase<TInputImage::ImageDimension>;\n\n  ImageBaseType * inputPtr1 = nullptr;\n\n  itk::InputDataObjectConstIterator it(this);\n  for (; !it.IsAtEnd(); ++it)\n  {\n    // Check whether the output is an image of the appropriate\n    // dimension (use ProcessObject's version of the GetInput()\n    // method since it returns the input as a pointer to a\n    // DataObject as opposed to the subclass version which\n    // static_casts the input to an TInputImage).\n    if (it.GetName() == \"Primary\")\n    {\n      inputPtr1 = dynamic_cast<ImageBaseType *>(it.GetInput());\n    }\n    if (inputPtr1)\n    {\n      break;\n    }\n  }\n\n  for (; !it.IsAtEnd(); ++it)\n  {\n    if (it.GetName() == \"InferiorClipImage\" || it.GetName() == \"SuperiorClipImage\")\n    {\n      auto * inputPtrN = dynamic_cast<ImageBaseType *>(it.GetInput());\n      // Physical space computation only matters if we're using two\n      // images, and not an image and a constant.\n      if (inputPtrN)\n      {\n        // check that the image occupy the same physical space, and that\n        // each index is at the same physical location\n\n        // tolerance for origin and spacing depends on the size of pixel\n        // tolerance for directions a fraction of the unit cube.\n        const double coordinateTol = itk::Math::abs(Self::GetGlobalDefaultCoordinateTolerance() *\n                                                    inputPtr1->GetSpacing()[0]); // use first dimension spacing\n\n        if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n              inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n        {\n          std::ostringstream originString, spacingString, directionString;\n          if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol))\n          {\n            originString.setf(std::ios::scientific);\n            originString.precision(7);\n            originString << \"InputImage Origin: \" << inputPtr1->GetOrigin() << \", InputImage\" << it.GetName()\n                         << \" Origin: \" << inputPtrN->GetOrigin() << std::endl;\n            originString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol))\n          {\n            spacingString.setf(std::ios::scientific);\n            spacingString.precision(7);\n            spacingString << \"InputImage Spacing: \" << inputPtr1->GetSpacing() << \", InputImage\" << it.GetName()\n                          << \" Spacing: \" << inputPtrN->GetSpacing() << std::endl;\n            spacingString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n                inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n          {\n            directionString.setf(std::ios::scientific);\n            directionString.precision(7);\n            directionString << \"InputImage Direction: \" << inputPtr1->GetDirection() << \", InputImage\" << it.GetName()\n                            << \" Direction: \" << inputPtrN->GetDirection() << std::endl;\n            directionString << \"\\tTolerance: \" << Self::GetGlobalDefaultDirectionTolerance() << std::endl;\n          }\n          itkExceptionMacro(<< \"Inputs do not occupy the same physical space! \" << std::endl\n                            << originString.str() << spacingString.str() << directionString.str());\n        }\n      }\n    }\n  }\n}\n\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TSumAlongRay>\nvoid\nJosephForwardProjectionImageFilter<TInputImage,\n                                   TOutputImage,\n                                   TInterpolationWeightMultiplication,\n                                   TProjectedValueAccumulation,\n                                   TSumAlongRay>::ThreadedGenerateData(const OutputImageRegionType &\n                                                                                    outputRegionForThread,\n                                                                       ThreadIdType threadId)\n{\n  const unsigned int Dimension = TInputImage::ImageDimension;\n  int                offsets[3];\n  offsets[0] = 1;\n  offsets[1] = this->GetInput(1)->GetBufferedRegion().GetSize()[0];\n  offsets[2] =\n    this->GetInput(1)->GetBufferedRegion().GetSize()[0] * this->GetInput(1)->GetBufferedRegion().GetSize()[1];\n  const typename Superclass::GeometryType::ConstPointer geometry = this->GetGeometry();\n\n  // beginBuffer is pointing at point with index (0,0,0) in memory, even if\n  // it is not in the allocated memory\n  const typename TInputImage::PixelType * beginBuffer =\n    this->GetInput(1)->GetBufferPointer() - offsets[0] * this->GetInput(1)->GetBufferedRegion().GetIndex()[0] -\n    offsets[1] * this->GetInput(1)->GetBufferedRegion().GetIndex()[1] -\n    offsets[2] * this->GetInput(1)->GetBufferedRegion().GetIndex()[2];\n\n  // volPPToIndex maps the physical 3D coordinates of a point (in mm) to the\n  // corresponding 3D volume index\n  typename Superclass::GeometryType::ThreeDHomogeneousMatrixType volPPToIndex;\n  volPPToIndex = GetPhysicalPointToIndexMatrix(this->GetInput(1));\n\n  // Iterators on input and output projections\n  using InputRegionIterator = ProjectionsRegionConstIteratorRayBased<TInputImage>;\n  InputRegionIterator * itIn = nullptr;\n  itIn = InputRegionIterator::New(this->GetInput(), outputRegionForThread, geometry, volPPToIndex);\n  itk::ImageRegionIteratorWithIndex<TOutputImage> itOut(this->GetOutput(), outputRegionForThread);\n  using ClipImageIterator = itk::ImageRegionConstIterator<TClipImageType>;\n  ClipImageIterator * itInferiorImage = nullptr;\n  ClipImageIterator * itSuperiorImage = nullptr;\n  if (this->GetInferiorClipImage().IsNotNull())\n  {\n    itInferiorImage = new ClipImageIterator(this->GetInferiorClipImage(), outputRegionForThread);\n  }\n  if (this->GetSuperiorClipImage().IsNotNull())\n  {\n    itSuperiorImage = new ClipImageIterator(this->GetSuperiorClipImage(), outputRegionForThread);\n  }\n\n  // Create intersection functions, one for each possible main direction\n  auto                          box = BoxShape::New();\n  typename BoxShape::VectorType boxMin, boxMax;\n  for (unsigned int i = 0; i < Dimension; i++)\n  {\n    boxMin[i] = this->GetInput(1)->GetBufferedRegion().GetIndex()[i];\n    boxMax[i] =\n      this->GetInput(1)->GetBufferedRegion().GetIndex()[i] + this->GetInput(1)->GetBufferedRegion().GetSize()[i] - 1;\n    boxMax[i] *= 1. - itk::NumericTraits<BoxShape::ScalarType>::epsilon();\n  }\n  box->SetBoxMin(boxMin);\n  box->SetBoxMax(boxMax);\n\n  // m_InferiorClip and m_SuperiorClip are understood in the sense of a\n  // source-to-pixel vector. Since we go from pixel-to-source, we invert them.\n  double inferiorClip = 1. - m_SuperiorClip;\n  double superiorClip = 1. - m_InferiorClip;\n\n  // Go over each pixel of the projection\n  typename BoxShape::VectorType stepMM, np, fp;\n  for (unsigned int pix = 0; pix < outputRegionForThread.GetNumberOfPixels(); pix++, itIn->Next(), ++itOut)\n  {\n    typename InputRegionIterator::PointType pixelPosition = itIn->GetPixelPosition();\n    typename InputRegionIterator::PointType dirVox = -itIn->GetSourceToPixel();\n\n    // Select main direction\n    unsigned int                  mainDir = 0;\n    typename BoxShape::VectorType dirVoxAbs;\n    for (unsigned int i = 0; i < Dimension; i++)\n    {\n      dirVoxAbs[i] = itk::Math::abs(dirVox[i]);\n      if (dirVoxAbs[i] > dirVoxAbs[mainDir])\n        mainDir = i;\n    }\n\n    if (this->GetInferiorClipImage().IsNotNull())\n    {\n      double superiorClipImage = 1 - itInferiorImage->Get();\n      superiorClip = std::min(1. - m_InferiorClip, superiorClipImage);\n      ++(*itInferiorImage);\n    }\n    if (this->GetSuperiorClipImage().IsNotNull())\n    {\n      double inferiorClipImage = 1 - itSuperiorImage->Get();\n      inferiorClip = std::max(1. - m_SuperiorClip, inferiorClipImage);\n      ++(*itSuperiorImage);\n    }\n\n    // Test if there is an intersection\n    BoxShape::ScalarType nearDist = NAN, farDist = NAN;\n    bool                 isIntersectByRay = box->IsIntersectedByRay(pixelPosition, dirVox, nearDist, farDist);\n    // Clip the casting between source and pixel of the detector\n    nearDist = std::max(nearDist, inferiorClip);\n    farDist = std::min(farDist, superiorClip);\n\n    if (isIntersectByRay && farDist > 0. && // check if detector after the source\n        nearDist <= 1. &&                   // check if detector after or in the volume\n        farDist > nearDist)\n    {\n      // Compute and sort intersections: (n)earest and (f)arthest (p)points\n      np = pixelPosition + nearDist * dirVox;\n      fp = pixelPosition + farDist * dirVox;\n\n      // Compute main nearest and farthest slice indices\n      const int ns = itk::Math::rnd(np[mainDir]);\n      const int fs = itk::Math::rnd(fp[mainDir]);\n\n      // Determine the other two directions\n      unsigned int notMainDirInf = (mainDir + 1) % Dimension;\n      unsigned int notMainDirSup = (mainDir + 2) % Dimension;\n      if (notMainDirInf > notMainDirSup)\n        std::swap(notMainDirInf, notMainDirSup);\n\n      const CoordinateType minx = box->GetBoxMin()[notMainDirInf];\n      const CoordinateType miny = box->GetBoxMin()[notMainDirSup];\n      const CoordinateType maxx = box->GetBoxMax()[notMainDirInf];\n      const CoordinateType maxy = box->GetBoxMax()[notMainDirSup];\n\n      // Init data pointers to first pixel of slice ns (i)nferior and (s)uperior (x|y) corner\n      const int offsetx = offsets[notMainDirInf];\n      const int offsety = offsets[notMainDirSup];\n      int       offsetz = offsets[mainDir];\n\n      const typename TInputImage::PixelType * pxiyi = beginBuffer + ns * offsetz;\n      const typename TInputImage::PixelType * pxsyi = pxiyi + offsetx;\n      const typename TInputImage::PixelType * pxiys = pxiyi + offsety;\n      const typename TInputImage::PixelType * pxsys = pxsyi + offsety;\n\n      // Compute step size and go to first voxel\n      CoordinateType       residualB = ns - np[mainDir];\n      CoordinateType       residualE = fp[mainDir] - fs;\n      const CoordinateType norm = itk::NumericTraits<CoordinateType>::One / dirVox[mainDir];\n      CoordinateType       stepx = dirVox[notMainDirInf] * norm;\n      CoordinateType       stepy = dirVox[notMainDirSup] * norm;\n      if (np[mainDir] > fp[mainDir])\n      {\n        residualB *= -1;\n        residualE *= -1;\n        offsetz *= -1;\n        stepx *= -1;\n        stepy *= -1;\n      }\n      CoordinateType currentx = np[notMainDirInf] + residualB * stepx;\n      CoordinateType currenty = np[notMainDirSup] + residualB * stepy;\n\n      // Compute voxel to millimeters conversion\n      stepMM[notMainDirInf] = this->GetInput(1)->GetSpacing()[notMainDirInf] * stepx;\n      stepMM[notMainDirSup] = this->GetInput(1)->GetSpacing()[notMainDirSup] * stepy;\n      stepMM[mainDir] = this->GetInput(1)->GetSpacing()[mainDir];\n\n      // Initialize the accumulation\n      typename TOutputImage::PixelType sum = itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue();\n\n      typename TInputImage::PixelType volumeValue = itk::NumericTraits<typename TInputImage::PixelType>::ZeroValue();\n      if (fs == ns) // If the voxel is a corner, we can skip most steps\n      {\n        volumeValue = BilinearInterpolationOnBorders(threadId,\n                                                     itk::Math::abs(fp[mainDir] - np[mainDir]),\n                                                     pxiyi,\n                                                     pxsyi,\n                                                     pxiys,\n                                                     pxsys,\n                                                     currentx,\n                                                     currenty,\n                                                     offsetx,\n                                                     offsety,\n                                                     minx,\n                                                     miny,\n                                                     maxx,\n                                                     maxy);\n        m_SumAlongRay(threadId, sum, volumeValue, stepMM);\n      }\n      else\n      {\n        // First step\n        volumeValue = BilinearInterpolationOnBorders(threadId,\n                                                     residualB + 0.5,\n                                                     pxiyi,\n                                                     pxsyi,\n                                                     pxiys,\n                                                     pxsys,\n                                                     currentx,\n                                                     currenty,\n                                                     offsetx,\n                                                     offsety,\n                                                     minx,\n                                                     miny,\n                                                     maxx,\n                                                     maxy);\n        m_SumAlongRay(threadId, sum, volumeValue, stepMM);\n\n        // Move to next main direction slice\n        pxiyi += offsetz;\n        pxsyi += offsetz;\n        pxiys += offsetz;\n        pxsys += offsetz;\n        currentx += stepx;\n        currenty += stepy;\n\n        // Middle steps\n        for (int i{ 0 }; i < itk::Math::abs(fs - ns) - 1; ++i)\n        {\n          volumeValue =\n            BilinearInterpolation(threadId, 1., pxiyi, pxsyi, pxiys, pxsys, currentx, currenty, offsetx, offsety);\n          m_SumAlongRay(threadId, sum, volumeValue, stepMM);\n\n          // Move to next main direction slice\n          pxiyi += offsetz;\n          pxsyi += offsetz;\n          pxiys += offsetz;\n          pxsys += offsetz;\n          currentx += stepx;\n          currenty += stepy;\n        }\n\n        // Last step\n        volumeValue = BilinearInterpolationOnBorders(threadId,\n                                                     residualE + 0.5,\n                                                     pxiyi,\n                                                     pxsyi,\n                                                     pxiys,\n                                                     pxsys,\n                                                     currentx,\n                                                     currenty,\n                                                     offsetx,\n                                                     offsety,\n                                                     minx,\n                                                     miny,\n                                                     maxx,\n                                                     maxy);\n        m_SumAlongRay(threadId, sum, volumeValue, stepMM);\n      }\n      // Accumulate\n      m_ProjectedValueAccumulation(threadId, itIn->Get(), itOut.Value(), sum, stepMM, pixelPosition, dirVox, np, fp);\n    }\n    else\n      m_ProjectedValueAccumulation(\n        threadId, itIn->Get(), itOut.Value(), {}, pixelPosition, pixelPosition, dirVox, pixelPosition, pixelPosition);\n  }\n  delete itIn;\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TSumAlongRay>\ntypename JosephForwardProjectionImageFilter<TInputImage,\n                                            TOutputImage,\n                                            TInterpolationWeightMultiplication,\n                                            TProjectedValueAccumulation,\n                                            TSumAlongRay>::OutputPixelType\nJosephForwardProjectionImageFilter<TInputImage,\n                                   TOutputImage,\n                                   TInterpolationWeightMultiplication,\n                                   TProjectedValueAccumulation,\n                                   TSumAlongRay>::BilinearInterpolation(const ThreadIdType     threadId,\n                                                                        const double           stepLengthInVoxel,\n                                                                        const InputPixelType * pxiyi,\n                                                                        const InputPixelType * pxsyi,\n                                                                        const InputPixelType * pxiys,\n                                                                        const InputPixelType * pxsys,\n                                                                        const CoordinateType   x,\n                                                                        const CoordinateType   y,\n                                                                        const int              ox,\n                                                                        const int              oy)\n{\n  int            ix = itk::Math::floor(x);\n  int            iy = itk::Math::floor(y);\n  int            idx = ix * ox + iy * oy;\n  CoordinateType lx = x - ix;\n  CoordinateType ly = y - iy;\n  CoordinateType lxc = 1. - lx;\n  CoordinateType lyc = 1. - ly;\n  return (m_InterpolationWeightMultiplication(threadId, stepLengthInVoxel, lxc * lyc, pxiyi, idx) +\n          m_InterpolationWeightMultiplication(threadId, stepLengthInVoxel, lx * lyc, pxsyi, idx) +\n          m_InterpolationWeightMultiplication(threadId, stepLengthInVoxel, lxc * ly, pxiys, idx) +\n          m_InterpolationWeightMultiplication(threadId, stepLengthInVoxel, lx * ly, pxsys, idx));\n  /* Alternative slower solution\n  const unsigned int   ix = itk::Math::Floor(x);\n  const unsigned int   iy = itk::Math::Floor(y);\n  const unsigned int   idx = ix*ox + iy*oy;\n  const CoordinateType a = p1[idx];\n  const CoordinateType b = p2[idx] - a;\n  const CoordinateType c = p3[idx] - a;\n  const CoordinateType lx = x-ix;\n  const CoordinateType ly = y-iy;\n  const CoordinateType d = p4[idx] - a - b - c;\n  return a + b*lx + c*ly + d*lx*ly;\n*/\n}\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication,\n          class TProjectedValueAccumulation,\n          class TSumAlongRay>\ntypename JosephForwardProjectionImageFilter<TInputImage,\n                                            TOutputImage,\n                                            TInterpolationWeightMultiplication,\n                                            TProjectedValueAccumulation,\n                                            TSumAlongRay>::OutputPixelType\nJosephForwardProjectionImageFilter<TInputImage,\n                                   TOutputImage,\n                                   TInterpolationWeightMultiplication,\n                                   TProjectedValueAccumulation,\n                                   TSumAlongRay>::BilinearInterpolationOnBorders(const ThreadIdType threadId,\n                                                                                 const double       stepLengthInVoxel,\n                                                                                 const InputPixelType * pxiyi,\n                                                                                 const InputPixelType * pxsyi,\n                                                                                 const InputPixelType * pxiys,\n                                                                                 const InputPixelType * pxsys,\n                                                                                 const CoordinateType   x,\n                                                                                 const CoordinateType   y,\n                                                                                 const int              ox,\n                                                                                 const int              oy,\n                                                                                 const CoordinateType   minx,\n                                                                                 const CoordinateType   miny,\n                                                                                 const CoordinateType   maxx,\n                                                                                 const CoordinateType   maxy)\n{\n  int            ix = itk::Math::floor(x);\n  int            iy = itk::Math::floor(y);\n  int            idx = ix * ox + iy * oy;\n  CoordinateType lx = x - ix;\n  CoordinateType ly = y - iy;\n  CoordinateType lxc = 1. - lx;\n  CoordinateType lyc = 1. - ly;\n\n  int offset_xi = 0;\n  int offset_yi = 0;\n  int offset_xs = 0;\n  int offset_ys = 0;\n\n  OutputPixelType result = itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue();\n  if (ix < minx)\n    offset_xi = ox;\n  if (iy < miny)\n    offset_yi = oy;\n  if (ix >= maxx)\n    offset_xs = -ox;\n  if (iy >= maxy)\n    offset_ys = -oy;\n\n  result +=\n    m_InterpolationWeightMultiplication(threadId, stepLengthInVoxel, lxc * lyc, pxiyi, idx + offset_xi + offset_yi);\n  result +=\n    m_InterpolationWeightMultiplication(threadId, stepLengthInVoxel, lxc * ly, pxiys, idx + offset_xi + offset_ys);\n  result +=\n    m_InterpolationWeightMultiplication(threadId, stepLengthInVoxel, lx * lyc, pxsyi, idx + offset_xs + offset_yi);\n  result +=\n    m_InterpolationWeightMultiplication(threadId, stepLengthInVoxel, lx * ly, pxsys, idx + offset_xs + offset_ys);\n\n  result *= stepLengthInVoxel;\n\n  return (result);\n}\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkLUTbasedVariableI0RawToAttenuationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkLUTbasedVariableI0RawToAttenuationImageFilter_h\n#define rtkLUTbasedVariableI0RawToAttenuationImageFilter_h\n\n#include <itkNumericTraits.h>\n#include <itkSubtractImageFilter.h>\n#include <itkLogImageFilter.h>\n#include <itkThresholdImageFilter.h>\n\n#include \"rtkLookupTableImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class LUTbasedVariableI0RawToAttenuationImageFilter\n * \\brief Performs the conversion from raw data to attenuations\n *\n * Performs the conversion from raw data to attenuations using a lookup table\n * which is typically possible when the input type is 16-bit, e.g., unsigned\n * short. The I0 value (intensity when there is no attenuation) is assumed to\n * be constant and can be changed.\n *\n * If the input is of type I0EstimationProjectionFilter, then the member I0 is\n * not used but the estimated value is automatically retrieved.\n *\n * The lookup table is obtained using the following mini-pipeline:\n *\n * \\dot\n * digraph LookupTable {\n *\n *  Input1 [label=\"index\"]\n *  Input2 [label=\"log(max(1,m_I0-m_IDark))\"]\n *  Input3 [label=\"m_IDark\"]\n *  Output [label=\"LookupTable\", shape=Mdiamond];\n *\n *  node [shape=box];\n *  SubR [label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"]\n *  ThresR [label=\"itk::ThresholdImageFilter\" URL=\"\\ref itk::ThresholdImageFilter\"];\n *  Log [label=\"itk::LogImageFilter\" URL=\"\\ref itk::LogImageFilter\"]\n *  Sub [label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n *\n *  Input1 -> SubR\n *  Input3 -> SubR\n *  SubR -> ThresR\n *  ThresR -> Log\n *\n *\n *  Log -> Sub\n *  Input2 -> Sub\n *  Sub -> Output\n * }\n * \\enddot\n *\n * \\test rtklutbasedrawtoattenuationtest.cxx\n *\n * \\author S. Brousmiche, S. Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT LUTbasedVariableI0RawToAttenuationImageFilter\n  : public LookupTableImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(LUTbasedVariableI0RawToAttenuationImageFilter);\n\n  /** Standard class type alias. */\n  using Self = LUTbasedVariableI0RawToAttenuationImageFilter;\n  using Superclass = LookupTableImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using InputImagePixelType = typename TInputImage::PixelType;\n  using OutputImagePixelType = typename TOutputImage::PixelType;\n  using LookupTableType = typename Superclass::FunctorType::LookupTableType;\n  using SubtractLUTFilterType = typename itk::SubtractImageFilter<LookupTableType>;\n  using ThresholdLUTFilterType = typename itk::ThresholdImageFilter<LookupTableType>;\n  using LogLUTFilterType = typename itk::LogImageFilter<LookupTableType, LookupTableType>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(LUTbasedVariableI0RawToAttenuationImageFilter);\n\n  /** Air level I0\n   */\n  itkGetMacro(I0, double);\n  itkSetMacro(I0, double);\n\n  /** Intensity when there is no photons (beam off)\n   */\n  itkGetMacro(IDark, double);\n  itkSetMacro(IDark, double);\n\n  void\n  BeforeThreadedGenerateData() override;\n\nprotected:\n  LUTbasedVariableI0RawToAttenuationImageFilter();\n  ~LUTbasedVariableI0RawToAttenuationImageFilter() override = default;\n\nprivate:\n  double                                   m_I0;\n  double                                   m_IDark;\n  typename SubtractLUTFilterType::Pointer  m_SubtractRampFilter;\n  typename ThresholdLUTFilterType::Pointer m_ThresholdRampFilter;\n  typename LogLUTFilterType::Pointer       m_LogRampFilter;\n  typename SubtractLUTFilterType::Pointer  m_SubtractLUTFilter;\n};\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkLUTbasedVariableI0RawToAttenuationImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkLUTbasedVariableI0RawToAttenuationImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkLUTbasedVariableI0RawToAttenuationImageFilter_hxx\n#define rtkLUTbasedVariableI0RawToAttenuationImageFilter_hxx\n\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n#include \"rtkI0EstimationProjectionFilter.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nLUTbasedVariableI0RawToAttenuationImageFilter<TInputImage,\n                                              TOutputImage>::LUTbasedVariableI0RawToAttenuationImageFilter()\n{\n  // Create the lut\n  auto                               lut = LookupTableType::New();\n  typename LookupTableType::SizeType size;\n  size[0] =\n    itk::NumericTraits<InputImagePixelType>::max() - itk::NumericTraits<InputImagePixelType>::NonpositiveMin() + 1;\n  lut->SetRegions(size);\n  lut->Allocate();\n\n  // Iterate and set lut\n  itk::ImageRegionIteratorWithIndex<LookupTableType> it(lut, lut->GetBufferedRegion());\n  it.Set(0);\n  ++it;\n  while (!it.IsAtEnd())\n  {\n    it.Set(it.GetIndex()[0]);\n    ++it;\n  }\n\n  // Default value for I0 is the numerical max\n  m_I0 = size[0] - 1;\n  m_IDark = 0;\n\n  // Mini pipeline for creating the lut.\n  m_SubtractRampFilter = SubtractLUTFilterType::New();\n  m_SubtractLUTFilter = SubtractLUTFilterType::New();\n  m_ThresholdRampFilter = ThresholdLUTFilterType::New();\n  m_LogRampFilter = LogLUTFilterType::New();\n\n  m_SubtractRampFilter->SetInput1(lut);\n  m_SubtractRampFilter->SetConstant2(m_IDark);\n  m_SubtractRampFilter->InPlaceOff();\n  m_ThresholdRampFilter->SetInput(m_SubtractRampFilter->GetOutput());\n  m_ThresholdRampFilter->ThresholdBelow(1.);\n  m_ThresholdRampFilter->SetOutsideValue(1.);\n  m_LogRampFilter->SetInput(m_ThresholdRampFilter->GetOutput());\n\n  m_SubtractLUTFilter->SetConstant1((OutputImagePixelType)log(std::max(m_I0 - m_IDark, 1.)));\n  m_SubtractLUTFilter->SetInput2(m_LogRampFilter->GetOutput());\n\n  // Set the lut to member and functor\n  this->SetLookupTable(m_SubtractLUTFilter->GetOutput());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nLUTbasedVariableI0RawToAttenuationImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  auto * i0est =\n    dynamic_cast<rtk::I0EstimationProjectionFilter<TInputImage> *>(this->GetInput()->GetSource().GetPointer());\n  if (i0est)\n  {\n    m_SubtractLUTFilter->SetConstant1((OutputImagePixelType)log(std::max((double)i0est->GetI0() - m_IDark, 1.)));\n  }\n  else\n  {\n    m_SubtractLUTFilter->SetConstant1((OutputImagePixelType)log(std::max(m_I0 - m_IDark, 1.)));\n  }\n  m_SubtractRampFilter->SetInput2(m_IDark);\n\n  Superclass::BeforeThreadedGenerateData(); // Update the LUT\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkLagCorrectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkLagCorrectionImageFilter_h\n#define rtkLagCorrectionImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include <itkVector.h>\n#include <vector>\n\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class LagCorrectionImageFilter\n * \\brief Classical Linear Time Invariant Lag correction\n *\n * Recursive correction algorithm for detector decay characteristics.\n * Based on [Hsieh, Proceedings of SPIE, 2000]\n *\n * The IRF (Impulse Response Function) is given by:\n *    \\f$h(k)=b_0 \\delta(k) + \\sum_{n=1}^N b_n e^{-a_n k}\\f$\n * where \\f$k\\f$ is the discrete time, \\f$N\\f$ is the model order (number of exponentials),\n * \\f$\\delta(k)\\f$ is the impulse function and the \\f${a_n, b_n}_{n=1:N}\\f$ parameters are respectively the exponential\n * rates and lag coefficients to be provided. The sum of all $b_n$ must be normalized such that h(0) equals 1.\n *\n * The parameters are typically estimated from either RSRF (Rising Step RF) or FSRF (Falling Step RF) response\n * functions.\n *\n * \\test rtklagcorrectiontest.cxx\n *\n * \\author Sebastien Brousmiche\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <typename TImage, unsigned VModelOrder>\nclass ITK_TEMPLATE_EXPORT LagCorrectionImageFilter : public itk::InPlaceImageFilter<TImage, TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(LagCorrectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = LagCorrectionImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TImage, TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(LagCorrectionImageFilter);\n\n  using ImageRegionType = typename TImage::RegionType;\n  using ImageSizeType = typename TImage::SizeType;\n  using PixelType = typename TImage::PixelType;\n  using IndexType = typename TImage::IndexType;\n  using VectorType = typename itk::Vector<float, VModelOrder>;\n  using FloatVectorType = typename std::vector<float>;\n  using OutputImageRegionType = typename TImage::RegionType;\n\n  /** Get / Set the model parameters A and B*/\n  itkGetMacro(A, VectorType);\n  itkGetMacro(B, VectorType);\n  virtual void\n  SetCoefficients(const VectorType A, const VectorType B)\n  {\n    if ((this->m_A != A) && (this->m_B != B))\n    {\n      if ((A.Size() == VModelOrder) && (B.Size() == VModelOrder))\n      {\n      }\n      this->m_A = A;\n      this->m_B = B;\n      this->Modified();\n      m_NewParamJustReceived = true;\n    }\n  }\n\nprotected:\n  LagCorrectionImageFilter();\n  ~LagCorrectionImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  ThreadedGenerateData(const ImageRegionType & thRegion, itk::ThreadIdType threadId) override;\n\n  /** The correction is applied along the third (stack) dimension.\n      Therefore, we must avoid splitting along the stack.\n      The split is done along the second dimension. */\n  unsigned int\n  SplitRequestedRegion(unsigned int i, unsigned int num, OutputImageRegionType & splitRegion) override;\n  virtual int\n  SplitRequestedRegion(int i, int num, OutputImageRegionType & splitRegion);\n\n  VectorType m_A;     // a_n coefficients (lag rates)\n  VectorType m_B;     // b coefficients (lag coefficients)\n  VectorType m_ExpmA; // exp(-a)\n  float      m_SumB;  // normalization factor\n\nprotected:\n  FloatVectorType m_S; // State variable\n\nprivate:\n  bool      m_NewParamJustReceived; // For state/correction initialization\n  IndexType m_StartIdx;             // To account for cropping\n};\n\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkLagCorrectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkLagCorrectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkLagCorrectionImageFilter_hxx\n#define rtkLagCorrectionImageFilter_hxx\n\n\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n#include <iterator>\n\nnamespace rtk\n{\n\ntemplate <typename TImage, unsigned VModelOrder>\nLagCorrectionImageFilter<TImage, VModelOrder>::LagCorrectionImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n  this->SetNumberOfRequiredInputs(1);\n  m_A.Fill(0.0f);\n  m_B.Fill(0.0f);\n  m_ExpmA.Fill(0.0f);\n  m_NewParamJustReceived = false;\n}\n\ntemplate <typename TImage, unsigned VModelOrder>\nvoid\nLagCorrectionImageFilter<TImage, VModelOrder>::GenerateOutputInformation()\n{\n  // get pointers to the input and output\n  typename TImage::Pointer inputPtr = const_cast<TImage *>(this->GetInput());\n  typename TImage::Pointer outputPtr = this->GetOutput();\n\n  if (!outputPtr || !inputPtr)\n  {\n    return;\n  }\n\n  this->SetInPlace(false);\n\n  // Copy the meta data for this data type\n  outputPtr->SetSpacing(inputPtr->GetSpacing());\n  outputPtr->SetOrigin(inputPtr->GetOrigin());\n  outputPtr->SetDirection(inputPtr->GetDirection());\n  outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel());\n\n  typename TImage::RegionType outputLargestPossibleRegion;\n  outputLargestPossibleRegion = inputPtr->GetLargestPossibleRegion();\n\n  // Compute the X coordinates of the corners of the image (images offset incl. in origin?)\n  typename Superclass::InputImageType::PointType origin = inputPtr->GetOrigin();\n\n  outputPtr->SetOrigin(origin);\n  outputPtr->SetRegions(outputLargestPossibleRegion);\n  outputPtr->SetSpacing(inputPtr->GetSpacing());\n\n  // Initialization at first frame\n  if (m_NewParamJustReceived && (m_B[0] != 0.f))\n  {\n    m_SumB = 1.f;\n    for (unsigned int n = 0; n < VModelOrder; n++)\n    {\n      m_ExpmA[n] = expf(-m_A[n]);\n      m_SumB += m_B[n];\n    }\n\n    m_StartIdx = this->GetInput()->GetLargestPossibleRegion().GetIndex();\n    ImageSizeType SizeInput = this->GetInput()->GetLargestPossibleRegion().GetSize();\n    m_S.assign(SizeInput[0] * SizeInput[1] * VModelOrder, 0.f);\n    m_NewParamJustReceived = false;\n  }\n}\n\ntemplate <typename TImage, unsigned VModelOrder>\nvoid\nLagCorrectionImageFilter<TImage, VModelOrder>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer  inputPtr = const_cast<TImage *>(this->GetInput());\n  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n    return;\n\n  typename TImage::RegionType inputRequestedRegion = outputPtr->GetRequestedRegion();\n  inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()); // Because Largest region has been updated\n  inputPtr->SetRequestedRegion(inputRequestedRegion);\n}\n\ntemplate <typename TImage, unsigned VModelOrder>\nvoid\nLagCorrectionImageFilter<TImage, VModelOrder>::ThreadedGenerateData(const ImageRegionType & thRegion,\n                                                                    itk::ThreadIdType       itkNotUsed(threadId))\n{\n  // Input / ouput iterators\n  itk::ImageRegionConstIterator<TImage> itIn(this->GetInput(), thRegion);\n  itk::ImageRegionIterator<TImage>      itOut(this->GetOutput(), thRegion);\n\n  itIn.GoToBegin();\n  itOut.GoToBegin();\n\n  if (m_B[0] == 0.f)\n  {\n    while (!itIn.IsAtEnd())\n    {\n      itOut.Set(itIn.Get());\n      ++itIn;\n      ++itOut;\n    }\n    return;\n  }\n\n  ImageSizeType SizeInput = this->GetInput()->GetLargestPossibleRegion().GetSize();\n\n  for (unsigned int k = 0; k < thRegion.GetSize(2); ++k)\n  {\n    unsigned int jj = (thRegion.GetIndex()[1] - m_StartIdx[1]) * SizeInput[0];\n    for (unsigned int j = 0; j < thRegion.GetSize(1); ++j)\n    {\n      unsigned int ii = thRegion.GetIndex()[0] - m_StartIdx[0];\n      for (unsigned int i = 0; i < thRegion.GetSize(0); ++i, ++ii)\n      {\n        unsigned idx_s = (jj + ii) * VModelOrder;\n\n        // Get measured pixel value y[k]\n        auto yk = static_cast<float>(itIn.Get());\n\n        // Computes correction\n        float      xk = yk; // Initial corrected pixel\n        VectorType Sa;      // Update of the state\n        for (unsigned int n = 0; n < VModelOrder; n++)\n        {\n          // Compute the update of internal state for nth exponential\n          Sa[n] = m_ExpmA[n] * m_S[idx_s + n];\n\n          // Update x[k] by removing contribution of the nth exponential\n          xk -= m_B[n] * Sa[n];\n        }\n\n        // Apply normalization factor\n        xk = xk / m_SumB;\n\n        // Update internal state Snk\n        for (unsigned int n = 0; n < VModelOrder; n++)\n        {\n          m_S[idx_s + n] = xk + Sa[n];\n        }\n\n        // Avoid negative values\n        xk = (xk < 0.0f) ? 0.f : xk;\n\n        itOut.Set(static_cast<PixelType>(xk));\n\n        ++itIn;\n        ++itOut;\n      }\n      jj += SizeInput[0];\n    }\n  }\n}\n\ntemplate <typename TImage, unsigned VModelOrder>\nunsigned int\nLagCorrectionImageFilter<TImage, VModelOrder>::SplitRequestedRegion(unsigned int            i,\n                                                                    unsigned int            num,\n                                                                    OutputImageRegionType & splitRegion)\n{\n  return SplitRequestedRegion((int)i, (int)num, splitRegion);\n}\n\ntemplate <typename TImage, unsigned VModelOrder>\nint\nLagCorrectionImageFilter<TImage, VModelOrder>::SplitRequestedRegion(int i, int num, OutputImageRegionType & splitRegion)\n{\n  // Split along the \"second\" direction\n\n  // Get the output pointer\n  TImage *                          outputPtr = this->GetOutput();\n  const typename TImage::SizeType & requestedRegionSize = outputPtr->GetRequestedRegion().GetSize();\n\n  int                        splitAxis = 0;\n  typename TImage::IndexType splitIndex;\n  typename TImage::SizeType  splitSize;\n\n  // Initialize the splitRegion to the output requested region\n  splitRegion = outputPtr->GetRequestedRegion();\n  splitIndex = splitRegion.GetIndex();\n  splitSize = splitRegion.GetSize();\n\n  // split on the outermost dimension available\n  splitAxis = 1;\n  if (requestedRegionSize[splitAxis] == 1)\n  {\n    splitAxis = 0;\n  }\n\n  // determine the actual number of pieces that will be generated\n  typename TImage::SizeType::SizeValueType range = requestedRegionSize[splitAxis];\n  int                                      valuesPerThread = itk::Math::Ceil<int>(range / (double)num);\n  int                                      maxThreadIdUsed = itk::Math::Ceil<int>(range / (double)valuesPerThread) - 1;\n\n  // Split the region\n  if (i < maxThreadIdUsed)\n  {\n    splitIndex[splitAxis] += i * valuesPerThread;\n    splitSize[splitAxis] = valuesPerThread;\n  }\n  if (i == maxThreadIdUsed)\n  {\n    splitIndex[splitAxis] += i * valuesPerThread;\n    // last thread needs to process the \"rest\" dimension being split\n    splitSize[splitAxis] = splitSize[splitAxis] - i * valuesPerThread;\n  }\n\n  // set the split region ivars\n  splitRegion.SetIndex(splitIndex);\n  splitRegion.SetSize(splitSize);\n\n  return maxThreadIdUsed + 1;\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkLaplacianImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkLaplacianImageFilter_h\n#define rtkLaplacianImageFilter_h\n\n#include \"rtkForwardDifferenceGradientImageFilter.h\"\n#include \"rtkBackwardDifferenceDivergenceImageFilter.h\"\n#include \"itkMultiplyImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include <itkCudaImage.h>\n#endif\n\nnamespace rtk\n{\n\n/** \\class LaplacianImageFilter\n * \\brief Computes the laplacian of the input image\n *\n * Computes the gradient of the input image, then the divergence of\n * this gradient. The exact definition of the gradient and divergence filters can\n * be found in Chambolle, Antonin. \"An Algorithm for Total\n * Variation Minimization and Applications.\" J. Math. Imaging Vis. 20,\n * no. 1-2 (January 2004): 89-97. The border conditions are described there.\n *\n * \\ingroup RTK IntensityImageFilters\n */\n\ntemplate <typename TOutputImage>\nclass ITK_TEMPLATE_EXPORT LaplacianImageFilter : public itk::ImageToImageFilter<TOutputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(LaplacianImageFilter);\n\n  /** Standard class type alias. */\n  using Self = LaplacianImageFilter;\n  using Superclass = itk::ImageToImageFilter<TOutputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using OutputImagePointer = typename TOutputImage::Pointer;\n  using CPUImageType = itk::Image<typename TOutputImage::PixelType, TOutputImage::ImageDimension>;\n  using VectorPixelType = itk::CovariantVector<typename TOutputImage::ValueType, TOutputImage::ImageDimension>;\n\n#ifdef RTK_USE_CUDA\n  typedef\n    typename std::conditional<std::is_same<TOutputImage, CPUImageType>::value,\n                              itk::Image<VectorPixelType, TOutputImage::ImageDimension>,\n                              itk::CudaImage<VectorPixelType, TOutputImage::ImageDimension>>::type GradientImageType;\n#else\n  using GradientImageType = itk::Image<VectorPixelType, TOutputImage::ImageDimension>;\n#endif\n  using GradientFilterType = rtk::ForwardDifferenceGradientImageFilter<TOutputImage,\n                                                                       typename TOutputImage::ValueType,\n                                                                       typename TOutputImage::ValueType,\n                                                                       GradientImageType>;\n  using DivergenceFilterType = rtk::BackwardDifferenceDivergenceImageFilter<GradientImageType, TOutputImage>;\n  using MultiplyImageFilterType = itk::MultiplyImageFilter<GradientImageType, TOutputImage>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(LaplacianImageFilter);\n\n  void\n  SetWeights(const TOutputImage * weights);\n  typename TOutputImage::ConstPointer\n  GetWeights();\n\nprotected:\n  LaplacianImageFilter();\n  ~LaplacianImageFilter() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Handle regions */\n  void\n  GenerateOutputInformation() override;\n\n  typename GradientFilterType::Pointer      m_Gradient;\n  typename DivergenceFilterType::Pointer    m_Divergence;\n  typename MultiplyImageFilterType::Pointer m_Multiply;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkLaplacianImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkLaplacianImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkLaplacianImageFilter_hxx\n#define rtkLaplacianImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage>\nLaplacianImageFilter<TOutputImage>::LaplacianImageFilter()\n{\n  // Create the filters\n  m_Gradient = GradientFilterType::New();\n  m_Divergence = DivergenceFilterType::New();\n\n  // Set memory management parameters\n  m_Gradient->ReleaseDataFlagOn();\n}\n\ntemplate <typename TOutputImage>\nvoid\nLaplacianImageFilter<TOutputImage>::GenerateOutputInformation()\n{\n  Superclass::GenerateOutputInformation();\n\n  // Set runtime connections\n  m_Gradient->SetInput(this->GetInput());\n\n  // Set internal connection between filter\n  if (this->GetWeights().IsNotNull())\n  {\n    m_Multiply = MultiplyImageFilterType::New();\n    m_Multiply->SetInput1(m_Gradient->GetOutput());\n    m_Multiply->SetInput2(this->GetWeights());\n    m_Divergence->SetInput(m_Multiply->GetOutput());\n  }\n  else\n    m_Divergence->SetInput(m_Gradient->GetOutput());\n\n  // Update the last filter\n  m_Divergence->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_Divergence->GetOutput());\n}\n\ntemplate <typename TOutputImage>\nvoid\nLaplacianImageFilter<TOutputImage>::GenerateData()\n{\n  // Update the last filter\n  m_Divergence->Update();\n\n  // Graft its output to the composite filter's output\n  this->GraftOutput(m_Divergence->GetOutput());\n}\n\ntemplate <typename TOutputImage>\nvoid\nLaplacianImageFilter<TOutputImage>::SetWeights(const TOutputImage * weights)\n{\n  this->SetInput(\"Weights\", const_cast<TOutputImage *>(weights));\n}\n\ntemplate <typename TOutputImage>\ntypename TOutputImage::ConstPointer\nLaplacianImageFilter<TOutputImage>::GetWeights()\n{\n  return static_cast<const TOutputImage *>(this->itk::ProcessObject::GetInput(\"Weights\"));\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkLastDimensionL0GradientDenoisingImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkLastDimensionL0GradientDenoisingImageFilter_h\n#define rtkLastDimensionL0GradientDenoisingImageFilter_h\n\n#include \"itkInPlaceImageFilter.h\"\n\n#include <itkImageRegionSplitterDirection.h>\n\nnamespace rtk\n{\n/** \\class LastDimensionL0GradientDenoisingImageFilter\n * \\brief Denoises along the last dimension, reducing the L0 norm of the gradient\n *\n * This filter implements the \"Fast and Effective L0 Gradient Minimization by Region Fusion\"\n * method, developped by Nguyen and Brown. Their method is computationally demanding, but its\n * restriction to 1D can be implemented efficiently. This is what this filter does.\n *\n * \\test rtkl0gradientnormtest\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <class TInputImage>\n\nclass ITK_TEMPLATE_EXPORT LastDimensionL0GradientDenoisingImageFilter\n  : public itk::InPlaceImageFilter<TInputImage, TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(LastDimensionL0GradientDenoisingImageFilter);\n\n  /** Standard class type alias. */\n  using Self = LastDimensionL0GradientDenoisingImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using InputPixelType = typename TInputImage::PixelType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(LastDimensionL0GradientDenoisingImageFilter);\n\n  /** Get / Set the threshold. Default is 0.001 */\n  itkGetMacro(Lambda, double);\n  itkSetMacro(Lambda, double);\n\n  /** Get / Set the number of iterations. Default is 10 */\n  itkGetMacro(NumberOfIterations, unsigned int);\n  itkSetMacro(NumberOfIterations, unsigned int);\n\nprotected:\n  LastDimensionL0GradientDenoisingImageFilter();\n  ~LastDimensionL0GradientDenoisingImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  ThreadedGenerateData(const typename TInputImage::RegionType & outputRegionForThread,\n                       itk::ThreadIdType                        itkNotUsed(threadId)) override;\n\n  /** Splits the OutputRequestedRegion along the first direction, not the last */\n  const itk::ImageRegionSplitterBase *\n                                             GetImageRegionSplitter() const override;\n  itk::ImageRegionSplitterDirection::Pointer m_Splitter;\n\n  virtual void\n  OneDimensionMinimizeL0NormOfGradient(InputPixelType * input,\n                                       unsigned int     length,\n                                       double           lambda,\n                                       unsigned int     nbIters);\n\n  double       m_Lambda;\n  unsigned int m_NumberOfIterations;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkLastDimensionL0GradientDenoisingImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkLastDimensionL0GradientDenoisingImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkLastDimensionL0GradientDenoisingImageFilter_hxx\n#define rtkLastDimensionL0GradientDenoisingImageFilter_hxx\n\n#include \"itkImageRegionIteratorWithIndex.h\"\n#include \"itkImageRegionIterator.h\"\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <class TInputImage>\nLastDimensionL0GradientDenoisingImageFilter<TInputImage>::LastDimensionL0GradientDenoisingImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n\n  // Set the direction along which the output requested region should NOT be split\n  m_Splitter = itk::ImageRegionSplitterDirection::New();\n  m_Splitter->SetDirection(TInputImage::ImageDimension - 1);\n\n  // Default parameters\n  m_NumberOfIterations = 5;\n  m_Lambda = 0.;\n}\n\ntemplate <class TInputImage>\nconst itk::ImageRegionSplitterBase *\nLastDimensionL0GradientDenoisingImageFilter<TInputImage>::GetImageRegionSplitter() const\n{\n  return m_Splitter;\n}\n\ntemplate <class TInputImage>\nvoid\nLastDimensionL0GradientDenoisingImageFilter<TInputImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Initialize the input requested region to the output requested region, then extend it along the last dimension\n  typename TInputImage::RegionType inputRequested = this->GetOutput()->GetRequestedRegion();\n  inputRequested.SetSize(TInputImage::ImageDimension - 1,\n                         this->GetInput(0)->GetLargestPossibleRegion().GetSize(TInputImage::ImageDimension - 1));\n  inputRequested.SetIndex(TInputImage::ImageDimension - 1,\n                          this->GetInput(0)->GetLargestPossibleRegion().GetIndex(TInputImage::ImageDimension - 1));\n\n  // Get pointers to the input and ROI\n  typename TInputImage::Pointer inputPtr = const_cast<TInputImage *>(this->GetInput());\n  inputPtr->SetRequestedRegion(inputRequested);\n}\n\ntemplate <class TInputImage>\nvoid\nLastDimensionL0GradientDenoisingImageFilter<TInputImage>::OneDimensionMinimizeL0NormOfGradient(InputPixelType * input,\n                                                                                               unsigned int     length,\n                                                                                               double           lambda,\n                                                                                               unsigned int     nbIters)\n{\n  // Initialize\n  float                       beta = 0;\n  std::vector<unsigned int>   firsts(length);\n  std::vector<float>          weights(length);\n  std::vector<InputPixelType> values(length);\n  unsigned int                nbGroups = length;\n\n  // Fill in the arrays\n  for (unsigned int i = 0; i < length; i++)\n  {\n    firsts[i] = i;\n    weights[i] = 1.0;\n    values[i] = input[i];\n  }\n\n  // Main loop\n  for (unsigned int iter = 0; iter < nbIters; iter++)\n  {\n    // Set the threshold for the current iteration (beta increases over time towards lambda)\n    beta = (float)iter / (float)nbIters * lambda;\n\n    // Run through all groups\n    unsigned int i = 0;\n    while (i < nbGroups - 1)\n    {\n      // Check the right neighbour of the current group\n      unsigned int j = (i + 1) % nbGroups;\n\n      // Decide whether or not to merge the current group with its right neighbour\n      if (weights[i] * weights[j] * (values[i] - values[j]) * (values[i] - values[j]) <=\n          beta * (weights[i] + weights[j]))\n      {\n        // Perform the fusion\n\n        // The merged group's value is the weighted mean between the values of both groups\n        values[i] = (weights[i] * values[i] + weights[j] * values[j]) / (weights[i] + weights[j]);\n\n        // The merged group's weight is the sum of the weights of both groups\n        weights[i] = weights[i] + weights[j];\n\n        // Remove j-th element by shifting everything after it\n        for (unsigned int k = j + 1; k < length; k++)\n        {\n          firsts[k - 1] = firsts[k];\n          values[k - 1] = values[k];\n          weights[k - 1] = weights[k];\n        }\n        firsts[length - 1] = 0;\n        values[length - 1] = 0;\n        weights[length - 1] = 0;\n\n        // Decrement the total number of groups\n        nbGroups--;\n      }\n\n      // Move to next group\n      i++;\n    }\n  }\n\n  // Assemble the pieces to create the denoised output (overwriting the input)\n  for (unsigned int i = 0; i < nbGroups; i++)\n  {\n    for (unsigned int j = firsts[i]; j < firsts[i] + weights[i]; j++)\n    {\n      input[j % length] = values[i];\n    }\n  }\n}\n\ntemplate <class TInputImage>\nvoid\nLastDimensionL0GradientDenoisingImageFilter<TInputImage>::ThreadedGenerateData(\n  const typename TInputImage::RegionType & outputRegionForThread,\n  itk::ThreadIdType                        itkNotUsed(threadId))\n{\n  // Walks the first frame of the outputRegionForThread\n  // For each voxel, creates an input iterator that walks\n  // the last dimension and computes the average, and\n  // a similar output iterator that replaces the output\n  // by their average along last dimension if ROI=1\n\n  // Create a region containing only the first frame of outputRegionForThread\n  typename TInputImage::RegionType FirstFrameRegion = outputRegionForThread;\n  FirstFrameRegion.SetSize(TInputImage::ImageDimension - 1, 1);\n\n  // Iterate on this region\n  itk::ImageRegionIteratorWithIndex<TInputImage> FakeIterator(this->GetOutput(), FirstFrameRegion);\n\n  // Create a single-voxel region traversing last dimension\n  typename TInputImage::RegionType SingleVoxelRegion = outputRegionForThread;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension - 1; dim++)\n  {\n    SingleVoxelRegion.SetSize(dim, 1);\n    SingleVoxelRegion.SetIndex(dim, 0);\n  }\n\n  while (!FakeIterator.IsAtEnd())\n  {\n    // Configure the SingleVoxelRegion correctly to follow the FakeIterator\n    // It is the only purpose of this FakeIterator\n    SingleVoxelRegion.SetIndex(FakeIterator.GetIndex());\n\n    // Walk the input along last dimension for this voxel, filling an array with the values read\n    itk::ImageRegionConstIterator<TInputImage> inputIterator(this->GetInput(), SingleVoxelRegion);\n    auto * toBeRegularized = new InputPixelType[outputRegionForThread.GetSize(TInputImage::ImageDimension - 1)];\n\n    unsigned int i = 0;\n    while (!inputIterator.IsAtEnd())\n    {\n      toBeRegularized[i] = inputIterator.Get();\n      i++;\n      ++inputIterator;\n    }\n\n    // Perform regularization (in place) on this array\n    OneDimensionMinimizeL0NormOfGradient(toBeRegularized,\n                                         outputRegionForThread.GetSize(TInputImage::ImageDimension - 1),\n                                         this->GetLambda(),\n                                         this->GetNumberOfIterations());\n\n    // Walk the output along last dimension for this voxel,\n    // replacing voxel with their regularized value\n    itk::ImageRegionIterator<TInputImage> outputIterator(this->GetOutput(), SingleVoxelRegion);\n    i = 0;\n    while (!outputIterator.IsAtEnd())\n    {\n      outputIterator.Set(toBeRegularized[i]);\n      i++;\n      ++outputIterator;\n    }\n\n    delete[] toBeRegularized;\n\n    ++FakeIterator;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkLookupTableImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkLookupTableImageFilter_h\n#define rtkLookupTableImageFilter_h\n\n#include <itkUnaryFunctorImageFilter.h>\n#include <itkLinearInterpolateImageFunction.h>\n\nnamespace rtk\n{\n\n/** \\class LookupTableImageFilter\n * \\brief Function to do the lookup operation.\n *\n * The lookup table is a 1D image. Two cases:\n * - if the pixel type is float or double, the meta information of the image\n * (spacing and origin) is used to select the pixel position and interpolate\n * linearly at this position.\n * - otherwise, it reads the value at the integer position, without\n * interpolation.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Functions\n */\n\nnamespace Functor\n{\n\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT LUT\n{\npublic:\n  using LookupTableType = itk::Image<TOutput, 1>;\n  using LookupTablePointer = typename LookupTableType::Pointer;\n  using LookupTableDataPointer = typename LookupTableType::PixelType *;\n  using InterpolatorType = typename itk::LinearInterpolateImageFunction<LookupTableType, double>;\n  using InterpolatorPointer = typename InterpolatorType::Pointer;\n\n  LUT()\n    : m_LookupTableDataPointer(nullptr)\n    , m_Interpolator(InterpolatorType::New()) {};\n  ~LUT() = default;\n\n  /** Get/Set the lookup table. */\n  LookupTablePointer\n  GetLookupTable()\n  {\n    return m_LookupTablePointer;\n  }\n  void\n  SetLookupTable(LookupTableType * lut)\n  {\n    m_LookupTablePointer = lut;\n    m_LookupTableDataPointer = lut->GetBufferPointer();\n    m_InverseLUTSpacing = 1. / m_LookupTablePointer->GetSpacing()[0];\n    m_Interpolator->SetInputImage(lut);\n  }\n\n  LookupTableDataPointer\n  GetLookupTable() const\n  {\n    return m_LookupTableDataPointer;\n  }\n\n  bool\n  operator!=(const LUT & lut) const\n  {\n    return m_LookupTableDataPointer != lut.GetLookupTable();\n  }\n  bool\n  operator==(const LUT & lut) const\n  {\n    return m_LookupTableDataPointer == lut.GetLookupTable();\n  }\n\n  inline TOutput\n  operator()(const TInput & val) const;\n\nprivate:\n  LookupTablePointer     m_LookupTablePointer;\n  LookupTableDataPointer m_LookupTableDataPointer;\n  InterpolatorPointer    m_Interpolator;\n  double                 m_InverseLUTSpacing;\n};\n\ntemplate <class TInput, class TOutput>\nTOutput\nLUT<TInput, TOutput>::operator()(const TInput & val) const\n{\n  return m_LookupTableDataPointer[val];\n}\n\ntemplate <>\ninline float\nLUT<float, float>::operator()(const float & val) const\n{\n  InterpolatorType::ContinuousIndexType index;\n  index[0] = m_InverseLUTSpacing * (val - m_LookupTablePointer->GetOrigin()[0]);\n  return float(m_Interpolator->EvaluateAtContinuousIndex(index));\n}\n\ntemplate <>\ninline double\nLUT<double, double>::operator()(const double & val) const\n{\n  InterpolatorType::ContinuousIndexType index;\n  index[0] = m_InverseLUTSpacing * (val - m_LookupTablePointer->GetOrigin()[0]);\n  return double(m_Interpolator->EvaluateAtContinuousIndex(index));\n}\n\n} // end namespace Functor\n\n/** \\class LookupTableImageFilter\n * \\brief Converts values of an input image using lookup table.\n *\n * The lookup table is passed via a functor of type Functor::LUT. If the image\n * is of type integer, it directly reads the corresponding value in the lookup\n * table. If the lookup table is of type double or float, it uses the meta-\n * information of the lookup table (origin and spacing) to locate a continuous\n * index and interpolate at the corresponding location.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT LookupTableImageFilter\n  : public itk::UnaryFunctorImageFilter<TInputImage,\n                                        TOutputImage,\n                                        Functor::LUT<typename TInputImage::PixelType, typename TOutputImage::PixelType>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(LookupTableImageFilter);\n\n  /** Lookup table type definition. */\n  using FunctorType = Functor::LUT<typename TInputImage::PixelType, typename TOutputImage::PixelType>;\n  using LookupTableType = typename FunctorType::LookupTableType;\n\n  /** Standard class type alias. */\n  using Self = LookupTableImageFilter;\n  using Superclass = itk::UnaryFunctorImageFilter<TInputImage, TOutputImage, FunctorType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(LookupTableImageFilter);\n\n  /** Set lookup table. */\n  virtual void\n  SetLookupTable(LookupTableType * _arg)\n  {\n    // Idem as itkSetObjectMacro + call to functor SetLookupTableDataPointer\n    itkDebugMacro(\"setting \" << \"LookupTable\"\n                                \" to \"\n                             << _arg);\n    if (this->m_LookupTable != _arg || (_arg && _arg->GetTimeStamp() > this->GetTimeStamp()))\n    {\n      this->m_LookupTable = _arg;\n      this->Modified();\n      this->GetFunctor().SetLookupTable(_arg);\n    }\n  }\n\n  /** Get lookup table. */\n  itkGetModifiableObjectMacro(LookupTable, LookupTableType);\n\n  /** Update the LUT before using it to process the data in case it is the\n   * result of a pipeline. */\n  void\n  BeforeThreadedGenerateData() override;\n\nprotected:\n  LookupTableImageFilter() = default;\n  ~LookupTableImageFilter() override = default;\n  typename LookupTableType::Pointer m_LookupTable;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkLookupTableImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkLookupTableImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkLookupTableImageFilter_hxx\n#define rtkLookupTableImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nLookupTableImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  // In case the lut is the result of a pipeline\n  this->m_LookupTable->Update();\n  this->SetLookupTable(m_LookupTable);\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkMacro.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMacro_h\n#define rtkMacro_h\n\n#include <iostream>\n#include <itkMacro.h>\n#include <itkImageBase.h>\n#include \"rtkGgoArgsInfoManager.h\"\n#include \"rtkIterationCommands.h\"\n\n//--------------------------------------------------------------------\n#ifndef CLANG_PRAGMA_PUSH\n#  define ITK_PRAGMA(x) _Pragma(#x)\n#  if defined(__clang__) && defined(__has_warning)\n#    define CLANG_PRAGMA_PUSH ITK_PRAGMA(clang diagnostic push)\n#    define CLANG_PRAGMA_POP ITK_PRAGMA(clang diagnostic pop)\n#    if __has_warning(\"-Wfloat-equal\")\n#      define CLANG_SUPPRESS_Wfloat_equal ITK_PRAGMA(clang diagnostic ignored \"-Wfloat-equal\")\n#    endif\n#  else\n#    define CLANG_PRAGMA_PUSH\n#    define CLANG_PRAGMA_POP\n#    define CLANG_SUPPRESS_Wfloat_equal\n#  endif\n#endif\n//--------------------------------------------------------------------\n\n//--------------------------------------------------------------------\n/** \\brief Debugging macro, displays name and content of a variable\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\n#ifndef DD\n#  define DD(a) std::cout << #a \" = [ \" << a << \" ]\" << std::endl;\n#endif\n//--------------------------------------------------------------------\n\n//--------------------------------------------------------------------\n/** \\brief Process gengetopt\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\n#define GGO(ggo_filename, args_info)                                                  \\\n  args_info_##ggo_filename               args_info;                                   \\\n  cmdline_parser_##ggo_filename##_params args_params;                                 \\\n  cmdline_parser_##ggo_filename##_params_init(&args_params);                          \\\n  args_params.print_errors = 1;                                                       \\\n  args_params.check_required = 0;                                                     \\\n  args_params.override = 1;                                                           \\\n  args_params.initialize = 1;                                                         \\\n  if (0 != cmdline_parser_##ggo_filename##_ext(argc, argv, &args_info, &args_params)) \\\n  {                                                                                   \\\n    std::cerr << \"Error in cmdline_parser_\" #ggo_filename \"_ext\" << std::endl;        \\\n    exit(1);                                                                          \\\n  }                                                                                   \\\n  args_params.check_required = 1;                                                     \\\n  if (0 != cmdline_parser_##ggo_filename##_ext(argc, argv, &args_info, &args_params)) \\\n  {                                                                                   \\\n    std::cerr << \"Error in cmdline_parser_\" #ggo_filename \"_ext\" << std::endl;        \\\n    exit(1);                                                                          \\\n  }                                                                                   \\\n  rtk::args_info_manager<args_info_##ggo_filename> manager_object(args_info, cmdline_parser_##ggo_filename##_free);\n//--------------------------------------------------------------------\n\n//--------------------------------------------------------------------\n/** \\brief Update a filter and catching/displaying exceptions\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\n#define TRY_AND_EXIT_ON_ITK_EXCEPTION(execFunc)                                                              \\\n  try                                                                                                        \\\n  {                                                                                                          \\\n    execFunc;                                                                                                \\\n  }                                                                                                          \\\n  catch (itk::ExceptionObject & err)                                                                         \\\n  {                                                                                                          \\\n    std::cerr << \"ExceptionObject caught with \" #execFunc << \" in file \" << __FILE__ << \" line \" << __LINE__ \\\n              << std::endl;                                                                                  \\\n    std::cerr << err << std::endl;                                                                           \\\n    itk::InvalidRequestedRegionError * rInv;                                                                 \\\n    rInv = dynamic_cast<itk::InvalidRequestedRegionError *>(&err);                                           \\\n    if (rInv)                                                                                                \\\n    {                                                                                                        \\\n      if (rInv->GetDataObject()->GetSource())                                                                \\\n      {                                                                                                      \\\n        std::cerr << \"Invalid requested region error triggered by \"                                          \\\n                  << rInv->GetDataObject()->GetSource()->GetNameOfClass() << std::endl;                      \\\n      }                                                                                                      \\\n      const itk::ImageBase<3> * img = dynamic_cast<const itk::ImageBase<3> *>(rInv->GetDataObject());        \\\n      if (img)                                                                                               \\\n      {                                                                                                      \\\n        DD(img->GetRequestedRegion())                                                                        \\\n        DD(img->GetLargestPossibleRegion())                                                                  \\\n      }                                                                                                      \\\n    }                                                                                                        \\\n    exit(EXIT_FAILURE);                                                                                      \\\n  }\n//--------------------------------------------------------------------\n\n//--------------------------------------------------------------------\n/** \\brief Redefine ITK's New macros in order to add a watcher to\n * each new filter created\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\n#ifdef RTK_PROBE_EACH_FILTER\n#  undef itkSimpleNewMacro\n#  define itkSimpleNewMacro(x)                                                          \\\n    static Pointer New(void)                                                            \\\n    {                                                                                   \\\n      Pointer smartPtr = ::itk::ObjectFactory<x>::Create();                             \\\n      if (smartPtr.GetPointer() == nullptr)                                             \\\n      {                                                                                 \\\n        smartPtr = new x;                                                               \\\n      }                                                                                 \\\n      smartPtr->UnRegister();                                                           \\\n      /* If smartPtr is a ProcessObject, watch it */                                    \\\n      itk::ProcessObject * processObjectPointer = nullptr;                              \\\n      processObjectPointer = dynamic_cast<itk::ProcessObject *>(smartPtr.GetPointer()); \\\n      if (processObjectPointer != nullptr)                                              \\\n      {                                                                                 \\\n        rtk::GlobalResourceProbe::GetInstance()->Watch(processObjectPointer);           \\\n      }                                                                                 \\\n      return smartPtr;                                                                  \\\n    }\n\n#  undef itkCreateAnotherMacro\n#  define itkCreateAnotherMacro(x)                                         \\\n    virtual ::itk::LightObject::Pointer CreateAnother(void) const override \\\n    {                                                                      \\\n      ::itk::LightObject::Pointer smartPtr;                                \\\n      smartPtr = x::New().GetPointer();                                    \\\n      return smartPtr;                                                     \\\n    }\n\n#  undef itkFactorylessNewMacro\n#  define itkFactorylessNewMacro(x)                                                     \\\n    static Pointer New(void)                                                            \\\n    {                                                                                   \\\n      Pointer smartPtr;                                                                 \\\n      x *     rawPtr = new x;                                                           \\\n      smartPtr = rawPtr;                                                                \\\n      rawPtr->UnRegister();                                                             \\\n      /* If smartPtr is a ProcessObject, watch it */                                    \\\n      itk::ProcessObject * processObjectPointer = nullptr;                              \\\n      processObjectPointer = dynamic_cast<itk::ProcessObject *>(smartPtr.GetPointer()); \\\n      if (processObjectPointer != nullptr)                                              \\\n      {                                                                                 \\\n        rtk::GlobalResourceProbe::GetInstance()->Watch(processObjectPointer);           \\\n      }                                                                                 \\\n      return smartPtr;                                                                  \\\n    }                                                                                   \\\n    virtual ::itk::LightObject::Pointer CreateAnother(void) const override              \\\n    {                                                                                   \\\n      ::itk::LightObject::Pointer smartPtr;                                             \\\n      smartPtr = x::New().GetPointer();                                                 \\\n      return smartPtr;                                                                  \\\n    }\n#endif // RTK_PROBE_EACH_FILTER\n//--------------------------------------------------------------------\n\n//--------------------------------------------------------------------\n/** \\brief Manage iteration reporting for filters supporting it.\n *\n * If verbose flag is set, outputs a string noticing iteration completion.\n * If output-every argument is provided, save intermediate output in a file.\n * If iteration-file-name is provided, the intermediate output is saved in a file\n * having custom name and location.\n *\n * \\author Aurélien Coussat\n *\n * \\ingroup RTK\n */\n#define REPORT_ITERATIONS(filter, filter_type, output_image_type)                               \\\n  if (args_info.verbose_flag)                                                                   \\\n  {                                                                                             \\\n    using VerboseIterationCommandType = rtk::VerboseIterationCommand<filter_type>;              \\\n    auto verboseIterationCommand = VerboseIterationCommandType::New();                          \\\n    filter->AddObserver(itk::AnyEvent(), verboseIterationCommand);                              \\\n  }                                                                                             \\\n  if (args_info.output_every_given)                                                             \\\n  {                                                                                             \\\n    typedef rtk::OutputIterationCommand<filter_type, output_image_type> OutputIterationCommand; \\\n    auto outputIterationCommand = OutputIterationCommand::New();                                \\\n    outputIterationCommand->SetTriggerEvery(args_info.output_every_arg);                        \\\n    if (args_info.iteration_file_name_given)                                                    \\\n    {                                                                                           \\\n      outputIterationCommand->SetFileFormat(args_info.iteration_file_name_arg);                 \\\n    }                                                                                           \\\n    else                                                                                        \\\n    {                                                                                           \\\n      outputIterationCommand->SetFileFormat(\"iter%d.mha\");                                      \\\n    }                                                                                           \\\n    filter->AddObserver(itk::IterationEvent(), outputIterationCommand);                         \\\n  }\n//--------------------------------------------------------------------\n\n#endif\n"
  },
  {
    "path": "include/rtkMagnitudeThresholdImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMagnitudeThresholdImageFilter_h\n#define rtkMagnitudeThresholdImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include <itkVector.h>\n\nnamespace rtk\n{\n/** \\class MagnitudeThresholdImageFilter\n *\n * \\brief Performs thresholding on the norm of each vector-valued input pixel\n *\n * If the norm of a vector is higher than the threshold, divides the\n * components of the vector by norm / threshold. Mathematically, it amounts\n * to projecting onto the L_2 ball of radius m_Threshold\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <typename TInputImage, typename TRealType = float, typename TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT MagnitudeThresholdImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(MagnitudeThresholdImageFilter);\n\n  /** Standard class type alias. */\n  using Self = MagnitudeThresholdImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods) */\n  itkOverrideGetNameOfClassMacro(MagnitudeThresholdImageFilter);\n\n  /** Extract some information from the image types.  Dimensionality\n   * of the two images is assumed to be the same. */\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using InputPixelType = typename TInputImage::PixelType;\n\n  /** Image type alias support */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n\n  /** The dimensionality of the input and output images. */\n  static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;\n\n  /** Length of the vector pixel type of the input image. */\n  static constexpr unsigned int VectorDimension = InputPixelType::Dimension;\n\n  /** Define the data type and the vector of data type used in calculations. */\n  using RealType = TRealType;\n  using RealVectorType = itk::Vector<TRealType, InputPixelType::Dimension>;\n  using RealVectorImageType = itk::Image<RealVectorType, TInputImage::ImageDimension>;\n\n  /** Superclass type alias. */\n  using OutputImageRegionType = typename Superclass::OutputImageRegionType;\n\n  /** Begin concept checking */\n  itkConceptMacro(InputHasNumericTraitsCheck, (itk::Concept::HasNumericTraits<typename InputPixelType::ValueType>));\n  itkConceptMacro(RealTypeHasNumericTraitsCheck, (itk::Concept::HasNumericTraits<RealType>));\n  /** End concept checking */\n\n  itkGetMacro(Threshold, TRealType);\n  itkSetMacro(Threshold, TRealType);\n\nprotected:\n  MagnitudeThresholdImageFilter();\n  ~MagnitudeThresholdImageFilter() override = default;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  TRealType m_Threshold;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkMagnitudeThresholdImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkMagnitudeThresholdImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMagnitudeThresholdImageFilter_hxx\n#define rtkMagnitudeThresholdImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkProgressReporter.h>\n\nnamespace rtk\n{\n\ntemplate <typename TInputImage, typename TRealType, typename TOutputImage>\nMagnitudeThresholdImageFilter<TInputImage, TRealType, TOutputImage>::MagnitudeThresholdImageFilter()\n{\n  m_Threshold = 0;\n}\n\ntemplate <typename TInputImage, typename TRealType, typename TOutputImage>\nvoid\nMagnitudeThresholdImageFilter<TInputImage, TRealType, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  itk::ImageRegionConstIterator<TInputImage> InputIt;\n  itk::ImageRegionIterator<TOutputImage>     OutputIt;\n\n  InputIt = itk::ImageRegionConstIterator<TInputImage>(this->GetInput(), outputRegionForThread);\n  OutputIt = itk::ImageRegionIterator<TOutputImage>(this->GetOutput(), outputRegionForThread);\n\n  double norm = NAN;\n  while (!InputIt.IsAtEnd())\n  {\n    norm = InputIt.Get().GetNorm();\n\n    if (norm > m_Threshold)\n      OutputIt.Set(m_Threshold * InputIt.Get() / norm);\n\n    ++InputIt;\n    ++OutputIt;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkMaskCollimationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMaskCollimationImageFilter_h\n#define rtkMaskCollimationImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkConfiguration.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class MaskCollimationImageFilter\n * \\brief Mask out everything behind the jaws (typically in Ora file format,\n * i.e., the medPhoton scanner)\n *\n * \\test rtkoratest\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT MaskCollimationImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(MaskCollimationImageFilter);\n\n  /** Standard class type alias. */\n  using Self = MaskCollimationImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryPointer = typename GeometryType::Pointer;\n  using FileNamesContainer = std::vector<std::string>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(MaskCollimationImageFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, GeometryType);\n  itkSetObjectMacro(Geometry, GeometryType);\n\n  /** Set the index of the rotation axis. The rotation axis is assumed to be one of the vector of the basis of the\n   * coordinate system. The default is the y vector (index 1). */\n  itkSetMacro(RotationAxisIndex, unsigned int);\n\nprotected:\n  MaskCollimationImageFilter();\n  ~MaskCollimationImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  /** Apply changes to the input image requested region. */\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  // Set default parameters\n  unsigned int m_RotationAxisIndex = 1; // y-axis\n\nprivate:\n  /** RTK geometry object */\n  GeometryPointer m_Geometry;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkMaskCollimationImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkMaskCollimationImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMaskCollimationImageFilter_hxx\n#define rtkMaskCollimationImageFilter_hxx\n\n\n#include <itkImageRegionIteratorWithIndex.h>\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nMaskCollimationImageFilter<TInputImage, TOutputImage>::MaskCollimationImageFilter()\n  : m_Geometry(nullptr)\n{}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nMaskCollimationImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nMaskCollimationImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->GetGeometry()->GetGantryAngles().size() != this->GetOutput()->GetLargestPossibleRegion().GetSize()[2])\n    itkExceptionMacro(<< \"Number of projections in the input stack and the geometry object differ.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nMaskCollimationImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Iterators on input and output\n  using InputRegionIterator = ProjectionsRegionConstIteratorRayBased<TInputImage>;\n  InputRegionIterator * itIn = nullptr;\n  itIn = InputRegionIterator::New(this->GetInput(), outputRegionForThread, m_Geometry);\n  itk::ImageRegionIteratorWithIndex<TOutputImage> itOut(this->GetOutput(), outputRegionForThread);\n\n  // Go over each projection\n  unsigned int npixperslice = 0;\n  npixperslice = outputRegionForThread.GetSize(0) * outputRegionForThread.GetSize(1);\n  for (typename OutputImageRegionType::SizeValueType iProj = outputRegionForThread.GetIndex(2);\n       iProj < outputRegionForThread.GetIndex(2) + outputRegionForThread.GetSize(2);\n       iProj++)\n  {\n    for (unsigned int pix = 0; pix < npixperslice; pix++, itIn->Next(), ++itOut)\n    {\n      using PointType = typename InputRegionIterator::PointType;\n      PointType source = itIn->GetSourcePosition();\n      double    sourceNorm = source.GetNorm();\n      PointType pixel = itIn->GetPixelPosition();\n\n      PointType pixelToSource(source - pixel);\n      PointType sourceDir = source / sourceNorm;\n\n      // Get the 3D position of the ray and the main plane\n      // (at 0,0,0 and orthogonal to source to center)\n      const double mag = sourceNorm / (pixelToSource * sourceDir);\n      PointType    intersection = source - mag * pixelToSource;\n\n      // The first coordinate on the plane is measured along the detector\n      // orthogonal to the plane defined by the detector source direction\n      // and the secon detector vector\n      PointType v;\n      v[0] = this->GetGeometry()->GetRotationMatrix(iProj)[m_RotationAxisIndex][0];\n      v[1] = this->GetGeometry()->GetRotationMatrix(iProj)[m_RotationAxisIndex][1];\n      v[2] = this->GetGeometry()->GetRotationMatrix(iProj)[m_RotationAxisIndex][2];\n      PointType u = CrossProduct(v, sourceDir);\n      u /= u.GetNorm();\n      double ucoord = u * intersection;\n\n      // The second coordinate is measured along the orthogonal\n      v = CrossProduct(sourceDir, u);\n      double vcoord = v * intersection;\n\n      if (ucoord > -1. * this->GetGeometry()->GetCollimationUInf()[iProj] &&\n          ucoord < this->GetGeometry()->GetCollimationUSup()[iProj] &&\n          vcoord > -1. * this->GetGeometry()->GetCollimationVInf()[iProj] &&\n          vcoord < this->GetGeometry()->GetCollimationVSup()[iProj])\n      {\n        itOut.Set(itIn->Get());\n      }\n      else\n      {\n        itOut.Set(0.);\n      }\n    }\n  }\n\n  delete itIn;\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkMaximumIntensityProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMaximumIntensityProjectionImageFilter_h\n#define rtkMaximumIntensityProjectionImageFilter_h\n\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n\nnamespace rtk\n{\nnamespace Functor\n{\n\n/** \\class MaximumIntensityAlongRay\n * \\brief Function to compute the maximum intensity (MIP) value along the ray projection.\n *\n * \\author Mikhail Polkovnikov\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT MaximumIntensityAlongRay\n{\npublic:\n  using VectorType = itk::Vector<double, 3>;\n\n  MaximumIntensityAlongRay() = default;\n  ~MaximumIntensityAlongRay() = default;\n  bool\n  operator!=(const MaximumIntensityAlongRay &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const MaximumIntensityAlongRay & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const ThreadIdType itkNotUsed(threadId),\n             TOutput &          mipValue,\n             const TInput       volumeValue,\n             const VectorType & itkNotUsed(stepInMM))\n  {\n    TOutput tmp = static_cast<TOutput>(volumeValue);\n    if (tmp > mipValue)\n    {\n      mipValue = tmp;\n    }\n  }\n};\n\n/** \\class MaximumIntensityProjectedValueAccumulation\n * \\brief Function to calculate maximum intensity step along the ray projection.\n *\n * \\author Mikhail Polkovnikov\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT MaximumIntensityProjectedValueAccumulation\n{\npublic:\n  using VectorType = itk::Vector<double, 3>;\n\n  bool\n  operator!=(const MaximumIntensityProjectedValueAccumulation &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const MaximumIntensityProjectedValueAccumulation & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline void\n  operator()(const ThreadIdType itkNotUsed(threadId),\n             const TInput &     input,\n             TOutput &          output,\n             const TOutput &    rayCastValue,\n             const VectorType & stepInMM,\n             const VectorType & itkNotUsed(source),\n             const VectorType & itkNotUsed(sourceToPixel),\n             const VectorType & itkNotUsed(nearestPoint),\n             const VectorType & itkNotUsed(farthestPoint)) const\n  {\n    TOutput tmp = static_cast<TOutput>(input);\n    if (tmp < rayCastValue)\n    {\n      tmp = rayCastValue;\n    }\n    output = tmp * stepInMM.GetNorm();\n  }\n};\n\n} // end namespace Functor\n\n\n/** \\class MaximumIntensityProjectionImageFilter\n * \\brief MIP filter.\n *\n * Performs a MIP forward projection, i.e. calculation of a maximum intensity\n * step along the x-ray line.\n *\n * \\author Mikhail Polkovnikov\n *\n * \\ingroup RTK Projector\n */\n\ntemplate <class TInputImage,\n          class TOutputImage,\n          class TInterpolationWeightMultiplication = Functor::InterpolationWeightMultiplication<\n            typename TInputImage::PixelType,\n            typename itk::PixelTraits<typename TInputImage::PixelType>::ValueType>,\n          class TProjectedValueAccumulation =\n            Functor::MaximumIntensityProjectedValueAccumulation<typename TInputImage::PixelType,\n                                                                typename TOutputImage::PixelType>,\n          class TSumAlongRay =\n            Functor::MaximumIntensityAlongRay<typename TInputImage::PixelType, typename TOutputImage::PixelType>>\nclass ITK_TEMPLATE_EXPORT MaximumIntensityProjectionImageFilter\n  : public JosephForwardProjectionImageFilter<TInputImage,\n                                              TOutputImage,\n                                              TInterpolationWeightMultiplication,\n                                              TProjectedValueAccumulation,\n                                              TSumAlongRay>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(MaximumIntensityProjectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = MaximumIntensityProjectionImageFilter;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(MaximumIntensityProjectionImageFilter);\n\nprotected:\n  MaximumIntensityProjectionImageFilter() = default;\n  ~MaximumIntensityProjectionImageFilter() override = default;\n};\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkMechlemOneStepSpectralReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMechlemOneStepSpectralReconstructionFilter_h\n#define rtkMechlemOneStepSpectralReconstructionFilter_h\n\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkWeidingerForwardModelImageFilter.h\"\n#include \"rtkGetNewtonUpdateImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkNesterovUpdateImageFilter.h\"\n#include \"rtkSeparableQuadraticSurrogateRegularizationImageFilter.h\"\n#include \"rtkAddMatrixAndDiagonalImageFilter.h\"\n#include \"rtkReorderProjectionsImageFilter.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkAddImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n\n#include <itkCastImageFilter.h>\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaWeidingerForwardModelImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class MechlemOneStepSpectralReconstructionFilter\n * \\brief Implements the one-step spectral CT inversion method described by Mechlem et al.\n *\n * This filter implements one-step spectral CT inversion method described by Mechlem et al.\n * in their paper \"Joint statistical iterative material image reconstruction\n * for spectral computed tomography using a semi-empirical forward model\", IEEE TMI 2017\n * It reconstructs a vector-valued volume (each component is a material) from vector-valued\n * projections (each component is the count of photons in an energy bin of the spectral detector).\n * It requires knowledge of the incident spectrum, of the detector's energy distribution and\n * of the materials' matrix of mass-attenuation coefficients as a function of the incident energy.\n *\n * \\dot\n * digraph MechlemOneStepSpectralReconstructionFilter {\n *\n * Input0 [ label=\"Input 0 (Material volumes)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Photon counts)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (Incident spectrum)\"];\n * Input2 [shape=Mdiamond];\n * Input3 [label=\"Input 3 (Support mask)\"];\n * Input3 [shape=Mdiamond];\n * Input4 [label=\"Input 4 (Spatial Regularization Weights)\"];\n * Input4 [shape=Mdiamond];\n * Input5 [label=\"Input 5 (Projection Weights)\"];\n * Input5 [shape=Mdiamond];\n * Output [label=\"Output (Material volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * Extract [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n * VolumeSource [ label=\"rtk::ConstantImageSource (1 component volume, full of ones)\"\n *                URL=\"\\ref rtk::ConstantImageSource\"];\n * SingleComponentProjectionsSource [ label=\"rtk::ConstantImageSource (1 component projections, full of zeros)\"\n *                                    URL=\"\\ref rtk::ConstantImageSource\"];\n * VolumeSourceGradients [ label=\"rtk::ConstantImageSource (m components)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * VolumeSourceHessians [ label=\"rtk::ConstantImageSource (m x m components)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ProjectionsSource [ label=\"rtk::ConstantImageSource (m components)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ForwardProjection [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * SingleComponentForwardProjection [ label=\"rtk::ForwardProjectionImageFilter (1 component)\"\n *                                    URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * BackProjectionGradients [ label=\"rtk::BackProjectionImageFilter (gradients)\"\n *                           URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * BackProjectionHessians [ label=\"rtk::BackProjectionImageFilter (hessians)\"\n *                          URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * Weidinger [ label=\"rtk::WeidingerForwardModelImageFilter\" URL=\"\\ref rtk::WeidingerForwardModelImageFilter\"];\n * SQSRegul [ label=\"rtk::SeparableQuadraticSurrogateRegularizationImageFilter\"\n *            URL=\"\\ref rtk::SeparableQuadraticSurrogateRegularizationImageFilter\"];\n * MultiplyRegulGradient [ label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\" style=dashed];\n * MultiplyRegulHessian [ label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\" style=dashed];\n * MultiplyGradientToBeBackProjected [ label=\"itk::MultiplyImageFilter\"\n *                                     URL=\"\\ref itk::MultiplyImageFilter\" style=dashed];\n * AddGradients [ label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n * AddHessians [ label=\"rtk::AddMatrixAndDiagonalImageFilter\" URL=\"\\ref rtk::AddMatrixAndDiagonalImageFilter\"];\n * Newton [ label=\"rtk::GetNewtonUpdateImageFilter\" URL=\"\\ref rtk::GetNewtonUpdateImageFilter\"];\n * Nesterov [ label=\"rtk::NesterovUpdateImageFilter\" URL=\"\\ref rtk::NesterovUpdateImageFilter\"];\n * MultiplySupport [ label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\" style=dashed];\n * Alphak [ label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * NextAlphak [ label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * ReorderProjections [label=\"rtk::ReorderProjectionsImageFilter (Photon Counts)\"\n *                       URL=\"\\ref ReorderProjectionsImageFilter\" style=dashed];\n * ReorderProjectionsWeights [label=\"rtk::ReorderProjectionsImageFilter (Projection Weights)\"\n *                            URL=\"\\ref ReorderProjectionsImageFilter\" style=dashed];\n *\n * Input0 -> Alphak [arrowhead=none];\n * Alphak -> ForwardProjection;\n * Alphak -> SQSRegul;\n * ProjectionsSource -> ForwardProjection;\n * Input1 -> ReorderProjections;\n * ReorderProjections -> Extract;\n * Extract -> Weidinger;\n * Input2 -> Weidinger;\n * ForwardProjection -> Weidinger;\n * VolumeSourceGradients -> BackProjectionGradients;\n * VolumeSourceHessians -> BackProjectionHessians;\n * VolumeSource -> SingleComponentForwardProjection;\n * SingleComponentProjectionsSource -> SingleComponentForwardProjection;\n * SingleComponentForwardProjection -> Weidinger;\n * Weidinger -> BackProjectionGradients;\n * Weidinger -> BackProjectionHessians;\n * Input4 -> MultiplyRegulGradient;\n * SQSRegul -> MultiplyRegulGradient;\n * MultiplyRegulGradient -> AddGradients;\n * Input5 -> ReorderProjectionsWeights;\n * ReorderProjectionsWeights-> MultiplyGradientToBeBackProjected;\n * Weidinger -> MultiplyGradientToBeBackProjected\n * MultiplyGradientToBeBackProjected -> AddGradients;\n * AddGradients -> Newton;\n * Input4 -> MultiplyRegulHessian;\n * SQSRegul -> MultiplyRegulHessian;\n * MultiplyRegulHessian -> AddHessians;\n * BackProjectionHessians -> AddHessians;\n * AddHessians -> Newton;\n * Newton -> Nesterov;\n * Alphak -> Nesterov;\n * Nesterov -> MultiplySupport;\n * Input3 -> MultiplySupport;\n * MultiplySupport -> NextAlphak [arrowhead=none];\n * NextAlphak -> Output;\n * NextAlphak -> Alphak [style=dashed, constraint=false];\n * }\n * \\enddot\n *\n * \\test rtkmechlemtest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TOutputImage, typename TMeasuredProjections, typename TIncidentSpectrum>\nclass ITK_TEMPLATE_EXPORT MechlemOneStepSpectralReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<TOutputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(MechlemOneStepSpectralReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = MechlemOneStepSpectralReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<TOutputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(MechlemOneStepSpectralReconstructionFilter);\n\n  /** Internal type alias and parameters */\n  static constexpr unsigned int nBins = TMeasuredProjections::PixelType::Dimension;\n  static constexpr unsigned int nMaterials = TOutputImage::PixelType::Dimension;\n  using dataType = typename TOutputImage::PixelType::ValueType;\n\n  /** Alternative type for the input materials volume and the input photon counts **/\n  using VectorImageType = typename itk::VectorImage<dataType, TOutputImage::ImageDimension>;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUOutputImageType = typename itk::Image<typename TOutputImage::PixelType, TOutputImage::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using HessiansImageType = typename std::conditional_t<\n    std::is_same_v<TOutputImage, CPUOutputImageType>,\n    itk::Image<itk::Vector<dataType, nMaterials * nMaterials>, TOutputImage::ImageDimension>,\n    itk::CudaImage<itk::Vector<dataType, nMaterials * nMaterials>, TOutputImage::ImageDimension>>;\n  using SingleComponentImageType = typename std::conditional_t<std::is_same_v<TOutputImage, CPUOutputImageType>,\n                                                               itk::Image<dataType, TOutputImage::ImageDimension>,\n                                                               itk::CudaImage<dataType, TOutputImage::ImageDimension>>;\n#else\n  using HessiansImageType =\n    typename itk::Image<itk::Vector<dataType, nMaterials * nMaterials>, TOutputImage::ImageDimension>;\n  using SingleComponentImageType = typename itk::Image<dataType, TOutputImage::ImageDimension>;\n#endif\n\n#if !defined(ITK_WRAPPING_PARSER)\n#  ifdef RTK_USE_CUDA\n  using WeidingerForwardModelType = typename std::conditional_t<\n    std::is_same_v<TOutputImage, CPUOutputImageType>,\n    WeidingerForwardModelImageFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>,\n    CudaWeidingerForwardModelImageFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>>;\n  using CudaSingleComponentForwardProjectionImageFilterType =\n    typename std::conditional_t<std::is_same_v<TOutputImage, CPUOutputImageType>,\n                                JosephForwardProjectionImageFilter<SingleComponentImageType, SingleComponentImageType>,\n                                CudaForwardProjectionImageFilter<SingleComponentImageType, SingleComponentImageType>>;\n  using CudaHessiansBackProjectionImageFilterType =\n    typename std::conditional_t<std::is_same_v<TOutputImage, CPUOutputImageType>,\n                                BackProjectionImageFilter<HessiansImageType, HessiansImageType>,\n                                CudaBackProjectionImageFilter<HessiansImageType>>;\n#  else\n  using WeidingerForwardModelType =\n    WeidingerForwardModelImageFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>;\n  using CudaSingleComponentForwardProjectionImageFilterType =\n    JosephForwardProjectionImageFilter<SingleComponentImageType, SingleComponentImageType>;\n  using CudaHessiansBackProjectionImageFilterType = BackProjectionImageFilter<HessiansImageType, HessiansImageType>;\n#  endif\n  using GradientsImageType = TOutputImage;\n#endif\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n#if !defined(ITK_WRAPPING_PARSER)\n  /** Filter type alias */\n  using CastMaterialVolumesFilterType = itk::CastImageFilter<VectorImageType, TOutputImage>;\n  using CastMeasuredProjectionsFilterType = itk::CastImageFilter<VectorImageType, TMeasuredProjections>;\n  using ExtractMeasuredProjectionsFilterType = itk::ExtractImageFilter<TMeasuredProjections, TMeasuredProjections>;\n  using AddFilterType = itk::AddImageFilter<GradientsImageType>;\n  using SingleComponentForwardProjectionFilterType =\n    rtk::ForwardProjectionImageFilter<SingleComponentImageType, SingleComponentImageType>;\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<TOutputImage, TOutputImage>;\n  using GradientsBackProjectionFilterType = rtk::BackProjectionImageFilter<GradientsImageType, GradientsImageType>;\n  using HessiansBackProjectionFilterType = rtk::BackProjectionImageFilter<HessiansImageType, HessiansImageType>;\n  using NesterovFilterType = rtk::NesterovUpdateImageFilter<TOutputImage>;\n  using SingleComponentImageSourceType = rtk::ConstantImageSource<SingleComponentImageType>;\n  using MaterialProjectionsSourceType = rtk::ConstantImageSource<TOutputImage>;\n  using GradientsSourceType = rtk::ConstantImageSource<GradientsImageType>;\n  using HessiansSourceType = rtk::ConstantImageSource<HessiansImageType>;\n  using SQSRegularizationType = rtk::SeparableQuadraticSurrogateRegularizationImageFilter<GradientsImageType>;\n  using AddMatrixAndDiagonalFilterType = rtk::AddMatrixAndDiagonalImageFilter<GradientsImageType, HessiansImageType>;\n  using NewtonFilterType = rtk::GetNewtonUpdateImageFilter<GradientsImageType, HessiansImageType>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<TOutputImage, SingleComponentImageType>;\n  using MultiplyGradientFilterType = itk::MultiplyImageFilter<GradientsImageType, SingleComponentImageType>;\n  using ReorderMeasuredProjectionsFilterType = rtk::ReorderProjectionsImageFilter<TMeasuredProjections>;\n  using ReorderProjectionsWeightsFilterType = rtk::ReorderProjectionsImageFilter<SingleComponentImageType>;\n#endif\n\n  /** Pass the geometry to all filters needing it */\n  itkSetConstObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  itkSetMacro(NumberOfIterations, int);\n  itkGetMacro(NumberOfIterations, int);\n\n  /** Number of subsets per iteration. */\n  itkSetMacro(NumberOfSubsets, int);\n  itkGetMacro(NumberOfSubsets, int);\n\n  /** Parameter to trigger Nesterov's reset. The value is a number of subsets\n  ** which can be larger than the number of subsets per iteration. 1 means no\n  ** Nesterov acceleration. */\n  itkSetMacro(ResetNesterovEvery, int);\n  itkGetMacro(ResetNesterovEvery, int);\n\n  /** Set methods for all inputs, since they have different types */\n  void\n  SetInputMaterialVolumes(const TOutputImage * materialVolumes);\n  void\n  SetInputMaterialVolumes(const VectorImageType * materialVolumes);\n  void\n  SetInputMeasuredProjections(const TMeasuredProjections * measuredProjections);\n  void\n  SetInputMeasuredProjections(const VectorImageType * measuredProjections);\n  void\n  SetInputIncidentSpectrum(const TIncidentSpectrum * incidentSpectrum);\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  void\n  SetInputPhotonCounts(const TMeasuredProjections * measuredProjections);\n  void\n  SetInputSpectrum(const TIncidentSpectrum * incidentSpectrum);\n#endif\n  void\n  SetSupportMask(const SingleComponentImageType * support);\n  void\n  SetSpatialRegularizationWeights(const SingleComponentImageType * regweights);\n  void\n  SetProjectionWeights(const SingleComponentImageType * weiprojections);\n\n  /** Set/Get for the regularization weights */\n  itkSetMacro(RegularizationWeights, typename TOutputImage::PixelType);\n  itkGetMacro(RegularizationWeights, typename TOutputImage::PixelType);\n\n  /** Set/Get for the radius */\n  itkSetMacro(RegularizationRadius, typename TOutputImage::RegionType::SizeType);\n  itkGetMacro(RegularizationRadius, typename TOutputImage::RegionType::SizeType);\n\n  /** Set methods forwarding the detector response and material attenuation\n   * matrices to the internal WeidingerForwardModel filter */\n  using BinnedDetectorResponseType = vnl_matrix<dataType>;\n  using MaterialAttenuationsType = vnl_matrix<dataType>;\n  virtual void\n  SetBinnedDetectorResponse(const BinnedDetectorResponseType & detResp);\n  virtual void\n  SetMaterialAttenuations(const MaterialAttenuationsType & matAtt);\n\nprotected:\n  MechlemOneStepSpectralReconstructionFilter();\n  ~MechlemOneStepSpectralReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n#if !defined(ITK_WRAPPING_PARSER)\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename CastMaterialVolumesFilterType::Pointer              m_CastMaterialVolumesFilter;\n  typename CastMeasuredProjectionsFilterType::Pointer          m_CastMeasuredProjectionsFilter;\n  typename ExtractMeasuredProjectionsFilterType::Pointer       m_ExtractMeasuredProjectionsFilter;\n  typename AddFilterType::Pointer                              m_AddGradients;\n  typename SingleComponentForwardProjectionFilterType::Pointer m_SingleComponentForwardProjectionFilter;\n  typename MaterialProjectionsSourceType::Pointer              m_ProjectionsSource;\n  typename SingleComponentImageSourceType::Pointer             m_SingleComponentProjectionsSource;\n  typename SingleComponentImageSourceType::Pointer             m_SingleComponentVolumeSource;\n  typename GradientsSourceType::Pointer                        m_GradientsSource;\n  typename HessiansSourceType::Pointer                         m_HessiansSource;\n  typename WeidingerForwardModelType::Pointer                  m_WeidingerForward;\n  typename SQSRegularizationType::Pointer                      m_SQSRegul;\n  typename AddMatrixAndDiagonalFilterType::Pointer             m_AddHessians;\n  typename NewtonFilterType::Pointer                           m_NewtonFilter;\n  typename NesterovFilterType::Pointer                         m_NesterovFilter;\n  typename ForwardProjectionFilterType::Pointer                m_ForwardProjectionFilter;\n  typename GradientsBackProjectionFilterType::Pointer          m_GradientsBackProjectionFilter;\n  typename HessiansBackProjectionFilterType::Pointer           m_HessiansBackProjectionFilter;\n  typename MultiplyFilterType::Pointer                         m_MultiplySupportFilter;\n  typename MultiplyGradientFilterType::Pointer                 m_MultiplyRegulGradientsFilter;\n  typename MultiplyGradientFilterType::Pointer                 m_MultiplyRegulHessiansFilter;\n  typename MultiplyGradientFilterType::Pointer                 m_MultiplyGradientToBeBackprojectedFilter;\n  typename ReorderMeasuredProjectionsFilterType::Pointer       m_ReorderMeasuredProjectionsFilter;\n  typename ReorderProjectionsWeightsFilterType::Pointer        m_ReorderProjectionsWeightsFilter;\n#endif\n\n  /** The inputs of this filter have the same type but not the same meaning\n   * It is normal that they do not occupy the same physical space. Therefore this check\n   * must be removed */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n\n  /** Getters for the inputs */\n  typename TOutputImage::ConstPointer\n  GetInputMaterialVolumes();\n  typename TMeasuredProjections::ConstPointer\n  GetInputMeasuredProjections();\n  typename TIncidentSpectrum::ConstPointer\n  GetInputIncidentSpectrum();\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  typename TMeasuredProjections::ConstPointer\n  GetInputPhotonCounts();\n  typename TIncidentSpectrum::ConstPointer\n  GetInputSpectrum();\n#endif\n  typename SingleComponentImageType::ConstPointer\n  GetSupportMask();\n  typename SingleComponentImageType::ConstPointer\n  GetSpatialRegularizationWeights();\n  typename SingleComponentImageType::ConstPointer\n  GetProjectionWeights();\n\n#if !defined(ITK_WRAPPING_PARSER)\n  /** Functions to instantiate forward and back projection filters with a different\n   * number of components than the ones provided by the IterativeConeBeamReconstructionFilter class */\n  typename SingleComponentForwardProjectionFilterType::Pointer\n  InstantiateSingleComponentForwardProjectionFilter(int fwtype);\n  typename HessiansBackProjectionFilterType::Pointer\n  InstantiateHessiansBackProjectionFilter(int bptype);\n#endif\n\n  ThreeDCircularProjectionGeometry::ConstPointer m_Geometry;\n\n  int              m_NumberOfIterations;\n  int              m_NumberOfProjectionsPerSubset;\n  int              m_NumberOfSubsets;\n  std::vector<int> m_NumberOfProjectionsInSubset;\n  int              m_NumberOfProjections;\n  int              m_ResetNesterovEvery;\n\n  typename TOutputImage::PixelType            m_RegularizationWeights;\n  typename TOutputImage::RegionType::SizeType m_RegularizationRadius;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkMechlemOneStepSpectralReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkMechlemOneStepSpectralReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMechlemOneStepSpectralReconstructionFilter_hxx\n#define rtkMechlemOneStepSpectralReconstructionFilter_hxx\n\n\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  MechlemOneStepSpectralReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(3);\n\n  // Set the default values of member parameters\n  m_NumberOfIterations = 3;\n  m_NumberOfProjectionsPerSubset = 0;\n  m_NumberOfSubsets = 1;\n  m_ResetNesterovEvery = itk::NumericTraits<int>::max();\n  m_NumberOfProjections = 0;\n  m_RegularizationWeights.Fill(0);\n  m_RegularizationRadius.Fill(0);\n\n  // Create the filters\n  m_CastMaterialVolumesFilter = CastMaterialVolumesFilterType::New();\n  m_CastMeasuredProjectionsFilter = CastMeasuredProjectionsFilterType::New();\n  m_ExtractMeasuredProjectionsFilter = ExtractMeasuredProjectionsFilterType::New();\n  m_AddGradients = AddFilterType::New();\n  m_AddHessians = AddMatrixAndDiagonalFilterType::New();\n  m_ProjectionsSource = MaterialProjectionsSourceType::New();\n  m_SingleComponentProjectionsSource = SingleComponentImageSourceType::New();\n  m_SingleComponentVolumeSource = SingleComponentImageSourceType::New();\n  m_GradientsSource = GradientsSourceType::New();\n  m_HessiansSource = HessiansSourceType::New();\n  m_SQSRegul = SQSRegularizationType::New();\n  m_MultiplyRegulGradientsFilter = MultiplyGradientFilterType::New();\n  m_MultiplyRegulHessiansFilter = MultiplyGradientFilterType::New();\n  m_MultiplyGradientToBeBackprojectedFilter = MultiplyGradientFilterType::New();\n  m_WeidingerForward = WeidingerForwardModelType::New();\n  m_NewtonFilter = NewtonFilterType::New();\n  m_NesterovFilter = NesterovFilterType::New();\n  m_MultiplySupportFilter = MultiplyFilterType::New();\n  m_ReorderMeasuredProjectionsFilter = ReorderMeasuredProjectionsFilterType::New();\n  m_ReorderProjectionsWeightsFilter = ReorderProjectionsWeightsFilterType::New();\n\n  // Set permanent parameters\n  m_ProjectionsSource->SetConstant(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_SingleComponentProjectionsSource->SetConstant(\n    itk::NumericTraits<typename TOutputImage::PixelType::ValueType>::ZeroValue());\n  m_SingleComponentVolumeSource->SetConstant(itk::NumericTraits<typename TOutputImage::PixelType::ValueType>::One);\n  m_GradientsSource->SetConstant(\n    itk::NumericTraits<\n      typename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n        GradientsImageType::PixelType>::ZeroValue());\n  m_HessiansSource->SetConstant(\n    itk::NumericTraits<\n      typename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n        HessiansImageType::PixelType>::ZeroValue());\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SetInputMaterialVolumes(const TOutputImage * materialVolumes)\n{\n  this->SetNthInput(0, const_cast<TOutputImage *>(materialVolumes));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SetInputMaterialVolumes(const VectorImageType * variableLengthVectorMaterialVolumes)\n{\n  m_CastMaterialVolumesFilter->SetInput(variableLengthVectorMaterialVolumes);\n  this->SetNthInput(0, const_cast<TOutputImage *>(m_CastMaterialVolumesFilter->GetOutput()));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SetInputMeasuredProjections(const TMeasuredProjections * measuredProjections)\n{\n  this->SetNthInput(1, const_cast<TMeasuredProjections *>(measuredProjections));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SetInputMeasuredProjections(const VectorImageType * variableLengthVectorMeasuredProjections)\n{\n  m_CastMeasuredProjectionsFilter->SetInput(variableLengthVectorMeasuredProjections);\n  this->SetNthInput(1, const_cast<TMeasuredProjections *>(m_CastMeasuredProjectionsFilter->GetOutput()));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SetInputIncidentSpectrum(const TIncidentSpectrum * incidentSpectrum)\n{\n  this->SetNthInput(2, const_cast<TIncidentSpectrum *>(incidentSpectrum));\n}\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::SetInputPhotonCounts(\n  const TMeasuredProjections * measuredProjections)\n{\n  this->SetInputMeasuredProjections(measuredProjections);\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::SetInputSpectrum(\n  const TIncidentSpectrum * incidentSpectrum)\n{\n  this->SetInputIncidentSpectrum(incidentSpectrum);\n}\n#endif\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::SetSupportMask(\n  const SingleComponentImageType * support)\n{\n  this->SetNthInput(3, const_cast<SingleComponentImageType *>(support));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SetSpatialRegularizationWeights(const SingleComponentImageType * regweights)\n{\n  this->SetNthInput(4, const_cast<SingleComponentImageType *>(regweights));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::SetProjectionWeights(\n  const SingleComponentImageType * weiprojections)\n{\n  this->SetNthInput(5, const_cast<SingleComponentImageType *>(weiprojections));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename TOutputImage::ConstPointer\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  GetInputMaterialVolumes()\n{\n  return static_cast<const TOutputImage *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename TMeasuredProjections::ConstPointer\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  GetInputMeasuredProjections()\n{\n  return static_cast<const TMeasuredProjections *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename TIncidentSpectrum::ConstPointer\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  GetInputIncidentSpectrum()\n{\n  return static_cast<const TIncidentSpectrum *>(this->itk::ProcessObject::GetInput(2));\n}\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename TMeasuredProjections::ConstPointer\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  GetInputPhotonCounts()\n{\n  return this->GetInputMeasuredProjections();\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename TIncidentSpectrum::ConstPointer\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::GetInputSpectrum()\n{\n  return this->GetInputIncidentSpectrum();\n}\n#endif\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SingleComponentImageType::ConstPointer\n  MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::GetSupportMask()\n{\n  return static_cast<const SingleComponentImageType *>(this->itk::ProcessObject::GetInput(3));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SingleComponentImageType::ConstPointer\n  MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n    GetSpatialRegularizationWeights()\n{\n  return static_cast<const SingleComponentImageType *>(this->itk::ProcessObject::GetInput(4));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SingleComponentImageType::ConstPointer\n  MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n    GetProjectionWeights()\n{\n  return static_cast<const SingleComponentImageType *>(this->itk::ProcessObject::GetInput(5));\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SingleComponentForwardProjectionFilterType::Pointer\n  MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n    InstantiateSingleComponentForwardProjectionFilter(int fwtype)\n{\n  // Define the type of image to be back projected\n  using TSingleComponent =\n    typename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n      SingleComponentImageType;\n\n  // Declare the pointer\n  typename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n    SingleComponentForwardProjectionFilterType::Pointer fw;\n\n  // Instantiate it\n  switch (fwtype)\n  {\n    case (MechlemOneStepSpectralReconstructionFilter::FP_JOSEPH):\n      fw = rtk::JosephForwardProjectionImageFilter<TSingleComponent, TSingleComponent>::New();\n      break;\n    case (MechlemOneStepSpectralReconstructionFilter::FP_CUDARAYCAST):\n      fw = CudaSingleComponentForwardProjectionImageFilterType::New();\n      if (std::is_same_v<TOutputImage, CPUOutputImageType>)\n        itkGenericExceptionMacro(<< \"The program has not been compiled with cuda option\");\n      break;\n\n    default:\n      itkGenericExceptionMacro(<< \"Unhandled --fp value.\");\n  }\n  return fw;\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\ntypename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  HessiansBackProjectionFilterType::Pointer\n  MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n    InstantiateHessiansBackProjectionFilter(int bptype)\n{\n  // Define the type of image to be back projected\n  using THessians = typename MechlemOneStepSpectralReconstructionFilter<TOutputImage,\n                                                                        TMeasuredProjections,\n                                                                        TIncidentSpectrum>::HessiansImageType;\n\n  // Declare the pointer\n  typename MechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n    HessiansBackProjectionFilterType::Pointer bp;\n\n  // Instantiate it\n  switch (bptype)\n  {\n    case (MechlemOneStepSpectralReconstructionFilter::BP_VOXELBASED):\n      bp = rtk::BackProjectionImageFilter<THessians, THessians>::New();\n      break;\n    case (MechlemOneStepSpectralReconstructionFilter::BP_JOSEPH):\n      bp = rtk::JosephBackProjectionImageFilter<THessians, THessians>::New();\n      break;\n    case (MechlemOneStepSpectralReconstructionFilter::BP_CUDAVOXELBASED):\n      bp = CudaHessiansBackProjectionImageFilterType::New();\n      if (std::is_same_v<TOutputImage, CPUOutputImageType>)\n        itkGenericExceptionMacro(<< \"The program has not been compiled with cuda option\");\n      break;\n    case (MechlemOneStepSpectralReconstructionFilter::BP_CUDARAYCAST):\n      itkGenericExceptionMacro(<< \"The CUDA ray cast back projector can currently not handle vector images\");\n      break;\n    default:\n      itkGenericExceptionMacro(<< \"Unhandled --bp value.\");\n  }\n  return bp;\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SetMaterialAttenuations(const MaterialAttenuationsType & matAtt)\n{\n  m_WeidingerForward->SetMaterialAttenuations(matAtt);\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  SetBinnedDetectorResponse(const BinnedDetectorResponseType & detResp)\n{\n  m_WeidingerForward->SetBinnedDetectorResponse(detResp);\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::VerifyPreconditions()\n  const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  GenerateInputRequestedRegion()\n{\n  // Input 0 is the material volumes we update\n  typename TOutputImage::Pointer inputPtr0 = const_cast<TOutputImage *>(this->GetInputMaterialVolumes().GetPointer());\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the photon counts\n  typename TMeasuredProjections::Pointer inputPtr1 =\n    const_cast<TMeasuredProjections *>(this->GetInputMeasuredProjections().GetPointer());\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n\n  // Input 2 is the incident spectrum\n  typename TIncidentSpectrum::Pointer inputPtr2 =\n    const_cast<TIncidentSpectrum *>(this->GetInputIncidentSpectrum().GetPointer());\n  if (!inputPtr2)\n    return;\n  inputPtr2->SetRequestedRegion(inputPtr2->GetLargestPossibleRegion());\n\n  // Input 3 is the support (optional)\n  typename SingleComponentImageType::Pointer inputPtr3 =\n    const_cast<SingleComponentImageType *>(this->GetSupportMask().GetPointer());\n  if (inputPtr3)\n    inputPtr3->SetRequestedRegion(inputPtr0->GetRequestedRegion());\n\n  // Input 4 is the image of weights for the regularization (optional)\n  typename SingleComponentImageType::Pointer inputPtr4 =\n    const_cast<SingleComponentImageType *>(this->GetSpatialRegularizationWeights().GetPointer());\n  if (inputPtr4)\n    inputPtr4->SetRequestedRegion(inputPtr0->GetRequestedRegion());\n\n  // Input 5 is the image of weights for the gradient to be backprojected (optional)\n  typename SingleComponentImageType::Pointer inputPtr5 =\n    const_cast<SingleComponentImageType *>(this->GetProjectionWeights().GetPointer());\n  if (inputPtr5)\n    inputPtr5->SetRequestedRegion(inputPtr1->GetRequestedRegion());\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::\n  GenerateOutputInformation()\n{\n  typename TMeasuredProjections::RegionType largest = this->GetInputMeasuredProjections()->GetLargestPossibleRegion();\n  m_NumberOfProjections = largest.GetSize()[TMeasuredProjections::ImageDimension - 1];\n\n  // Set forward projection filter\n  m_ForwardProjectionFilter =\n    this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration); // The multi-component one\n  m_SingleComponentForwardProjectionFilter = InstantiateSingleComponentForwardProjectionFilter(\n    this->m_CurrentForwardProjectionConfiguration); // The single-component one\n\n  // Set back projection filter\n  m_GradientsBackProjectionFilter = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  m_HessiansBackProjectionFilter =\n    this->InstantiateHessiansBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n\n  // Pre-compute the number of projections in each subset\n  m_NumberOfProjectionsInSubset.clear();\n  m_NumberOfProjectionsPerSubset = itk::Math::ceil((float)m_NumberOfProjections / (float)m_NumberOfSubsets);\n  for (int s = 0; s < m_NumberOfSubsets; s++)\n    m_NumberOfProjectionsInSubset.push_back(\n      std::min(m_NumberOfProjectionsPerSubset, m_NumberOfProjections - s * m_NumberOfProjectionsPerSubset));\n\n  // Compute the extract filter's initial extract region\n  typename TMeasuredProjections::RegionType extractionRegion = largest;\n  extractionRegion.SetSize(TMeasuredProjections::ImageDimension - 1, m_NumberOfProjectionsInSubset[0]);\n  extractionRegion.SetIndex(TMeasuredProjections::ImageDimension - 1, 0);\n\n  // Set runtime connections. Links with the forward and back projection filters should be set here,\n  // since those filters are not instantiated by the constructor, but by\n  // a call to SetForwardProjectionFilter() and SetBackProjectionFilter()\n  if (m_NumberOfSubsets != 1)\n  {\n    m_ReorderMeasuredProjectionsFilter->SetInput(this->GetInputMeasuredProjections());\n    m_ReorderMeasuredProjectionsFilter->SetInputGeometry(this->m_Geometry);\n    m_ReorderMeasuredProjectionsFilter->SetPermutation(ReorderMeasuredProjectionsFilterType::SHUFFLE);\n    m_ExtractMeasuredProjectionsFilter->SetInput(m_ReorderMeasuredProjectionsFilter->GetOutput());\n\n    m_ForwardProjectionFilter->SetGeometry(m_ReorderMeasuredProjectionsFilter->GetOutputGeometry());\n    m_SingleComponentForwardProjectionFilter->SetGeometry(m_ReorderMeasuredProjectionsFilter->GetOutputGeometry());\n    m_GradientsBackProjectionFilter->SetGeometry(m_ReorderMeasuredProjectionsFilter->GetOutputGeometry());\n    m_HessiansBackProjectionFilter->SetGeometry(m_ReorderMeasuredProjectionsFilter->GetOutputGeometry());\n  }\n  else\n  {\n    m_ExtractMeasuredProjectionsFilter->SetInput(this->GetInputMeasuredProjections());\n\n    m_ForwardProjectionFilter->SetGeometry(this->m_Geometry);\n    m_SingleComponentForwardProjectionFilter->SetGeometry(this->m_Geometry);\n    m_GradientsBackProjectionFilter->SetGeometry(this->m_Geometry.GetPointer());\n    m_HessiansBackProjectionFilter->SetGeometry(this->m_Geometry.GetPointer());\n  }\n\n  m_ForwardProjectionFilter->SetInput(0, m_ProjectionsSource->GetOutput());\n  m_ForwardProjectionFilter->SetInput(1, this->GetInputMaterialVolumes());\n\n  m_SingleComponentForwardProjectionFilter->SetInput(0, m_SingleComponentProjectionsSource->GetOutput());\n  m_SingleComponentForwardProjectionFilter->SetInput(1, m_SingleComponentVolumeSource->GetOutput());\n\n  m_WeidingerForward->SetInputDecomposedProjections(m_ForwardProjectionFilter->GetOutput());\n  m_WeidingerForward->SetInputMeasuredProjections(m_ExtractMeasuredProjectionsFilter->GetOutput());\n  m_WeidingerForward->SetInputIncidentSpectrum(this->GetInputIncidentSpectrum());\n  m_WeidingerForward->SetInputProjectionsOfOnes(m_SingleComponentForwardProjectionFilter->GetOutput());\n\n  m_GradientsBackProjectionFilter->SetInput(0, m_GradientsSource->GetOutput());\n  if (this->GetProjectionWeights().GetPointer() != nullptr)\n  {\n    m_MultiplyGradientToBeBackprojectedFilter->SetInput1(m_WeidingerForward->GetOutput1());\n    if (m_NumberOfSubsets != 1)\n    {\n      m_ReorderProjectionsWeightsFilter->SetInput(this->GetProjectionWeights());\n      m_ReorderProjectionsWeightsFilter->SetInputGeometry(this->m_Geometry);\n      m_ReorderProjectionsWeightsFilter->SetPermutation(ReorderProjectionsWeightsFilterType::SHUFFLE);\n      m_MultiplyGradientToBeBackprojectedFilter->SetInput2(m_ReorderProjectionsWeightsFilter->GetOutput());\n    }\n    else\n    {\n      m_MultiplyGradientToBeBackprojectedFilter->SetInput2(this->GetProjectionWeights());\n    }\n    m_GradientsBackProjectionFilter->SetInput(1, m_MultiplyGradientToBeBackprojectedFilter->GetOutput());\n  }\n  else\n  {\n    m_GradientsBackProjectionFilter->SetInput(1, m_WeidingerForward->GetOutput1());\n  }\n\n  m_HessiansBackProjectionFilter->SetInput(0, m_HessiansSource->GetOutput());\n  m_HessiansBackProjectionFilter->SetInput(1, m_WeidingerForward->GetOutput2());\n\n  m_SQSRegul->SetInput(this->GetInputMaterialVolumes());\n\n  if (this->GetSpatialRegularizationWeights().GetPointer() != nullptr)\n  {\n    m_MultiplyRegulGradientsFilter->SetInput1(m_SQSRegul->GetOutput(0));\n    m_MultiplyRegulGradientsFilter->SetInput2(this->GetSpatialRegularizationWeights());\n    m_MultiplyRegulHessiansFilter->SetInput1(m_SQSRegul->GetOutput(1));\n    m_MultiplyRegulHessiansFilter->SetInput2(this->GetSpatialRegularizationWeights());\n    m_AddGradients->SetInput1(m_MultiplyRegulGradientsFilter->GetOutput());\n    m_AddHessians->SetInputDiagonal(m_MultiplyRegulHessiansFilter->GetOutput());\n  }\n  else\n  {\n    m_AddGradients->SetInput1(m_SQSRegul->GetOutput(0));\n    m_AddHessians->SetInputDiagonal(m_SQSRegul->GetOutput(1));\n  }\n\n  m_AddGradients->SetInput2(m_GradientsBackProjectionFilter->GetOutput());\n  m_AddHessians->SetInputMatrix(m_HessiansBackProjectionFilter->GetOutput());\n\n  m_NewtonFilter->SetInputGradient(m_AddGradients->GetOutput());\n  m_NewtonFilter->SetInputHessian(m_AddHessians->GetOutput());\n\n  m_NesterovFilter->SetInput(0, this->GetInputMaterialVolumes());\n  m_NesterovFilter->SetInput(1, m_NewtonFilter->GetOutput());\n\n  typename TOutputImage::Pointer lastOutput = m_NesterovFilter->GetOutput();\n  if (this->GetSupportMask().GetPointer() != nullptr)\n  {\n    m_MultiplySupportFilter->SetInput1(m_NesterovFilter->GetOutput());\n    m_MultiplySupportFilter->SetInput2(this->GetSupportMask());\n    lastOutput = m_MultiplySupportFilter->GetOutput();\n  }\n\n  // Set information for the extract filter and the sources\n  m_ExtractMeasuredProjectionsFilter->SetExtractionRegion(extractionRegion);\n  m_ExtractMeasuredProjectionsFilter->UpdateOutputInformation();\n  m_SingleComponentProjectionsSource->SetInformationFromImage(m_ExtractMeasuredProjectionsFilter->GetOutput());\n  m_ProjectionsSource->SetInformationFromImage(m_ExtractMeasuredProjectionsFilter->GetOutput());\n  m_SingleComponentVolumeSource->SetInformationFromImage(this->GetInputMaterialVolumes());\n  m_GradientsSource->SetInformationFromImage(this->GetInputMaterialVolumes());\n  m_HessiansSource->SetInformationFromImage(this->GetInputMaterialVolumes());\n\n  // Set regularization parameters\n  m_SQSRegul->SetRegularizationWeights(m_RegularizationWeights);\n  m_SQSRegul->SetRadius(m_RegularizationRadius);\n\n  // Have the last filter calculate its output information\n  lastOutput->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(lastOutput);\n}\n\ntemplate <class TOutputImage, class TMeasuredProjections, class TIncidentSpectrum>\nvoid\nMechlemOneStepSpectralReconstructionFilter<TOutputImage, TMeasuredProjections, TIncidentSpectrum>::GenerateData()\n{\n  itk::IterationReporter iterationReporter(this, 0, 1);\n\n  // Run the iteration loop\n  typename TOutputImage::Pointer Next_Zk;\n  for (int iter = 0; iter < m_NumberOfIterations; iter++)\n  {\n    for (int subset = 0; subset < m_NumberOfSubsets; subset++)\n    {\n      // Initialize Nesterov filter\n      int k = iter * m_NumberOfSubsets + subset;\n      if (k % m_ResetNesterovEvery == 0)\n      {\n        int r = m_NumberOfIterations * m_NumberOfSubsets - k;\n        m_NesterovFilter->SetNumberOfIterations(std::min(m_ResetNesterovEvery, r));\n      }\n\n      // Starting from the second subset, or the second iteration\n      // if there is only one subset, plug the output\n      // of Nesterov back as input of the forward projection\n      // The Nesterov filter itself doesn't need its output\n      // plugged back as input, since it stores intermediate\n      // images that contain all the required data. It only\n      // needs the new update from rtkGetNewtonUpdateImageFilter\n      if ((iter + subset) > 0)\n      {\n        Next_Zk->DisconnectPipeline();\n        m_ForwardProjectionFilter->SetInput(1, Next_Zk);\n        m_SQSRegul->SetInput(Next_Zk);\n        m_NesterovFilter->SetInput(Next_Zk);\n\n        m_GradientsBackProjectionFilter->SetInput(0, m_GradientsSource->GetOutput());\n        m_HessiansBackProjectionFilter->SetInput(0, m_HessiansSource->GetOutput());\n      }\n#ifdef RTK_USE_CUDA\n      constexpr int NProjPerExtract = SLAB_SIZE;\n#else\n      constexpr int NProjPerExtract = 16;\n#endif\n      for (int i = 0; i < m_NumberOfProjectionsInSubset[subset]; i += NProjPerExtract)\n      {\n        // Set the extract filter's region\n        typename TMeasuredProjections::RegionType extractionRegion =\n          this->GetInputMeasuredProjections()->GetLargestPossibleRegion();\n        extractionRegion.SetSize(TMeasuredProjections::ImageDimension - 1,\n                                 std::min(NProjPerExtract, m_NumberOfProjectionsInSubset[subset] - i));\n        extractionRegion.SetIndex(TMeasuredProjections::ImageDimension - 1,\n                                  subset * m_NumberOfProjectionsPerSubset + i);\n        m_ExtractMeasuredProjectionsFilter->SetExtractionRegion(extractionRegion);\n        m_ExtractMeasuredProjectionsFilter->UpdateOutputInformation();\n\n        // Set the projection sources accordingly\n        m_SingleComponentProjectionsSource->SetInformationFromImage(m_ExtractMeasuredProjectionsFilter->GetOutput());\n        m_ProjectionsSource->SetInformationFromImage(m_ExtractMeasuredProjectionsFilter->GetOutput());\n\n        if (i < m_NumberOfProjectionsInSubset[subset] - NProjPerExtract)\n        {\n          // Backproject gradient and hessian of that projection\n          m_GradientsBackProjectionFilter->Update();\n          m_HessiansBackProjectionFilter->Update();\n          typename GradientsImageType::Pointer gBP = m_GradientsBackProjectionFilter->GetOutput();\n          typename HessiansImageType::Pointer  hBP = m_HessiansBackProjectionFilter->GetOutput();\n          gBP->DisconnectPipeline();\n          hBP->DisconnectPipeline();\n          m_GradientsBackProjectionFilter->SetInput(gBP);\n          m_HessiansBackProjectionFilter->SetInput(hBP);\n        }\n        else\n        {\n          // Restore original pipeline\n          m_AddGradients->SetInput2(m_GradientsBackProjectionFilter->GetOutput());\n          m_AddHessians->SetInputMatrix(m_HessiansBackProjectionFilter->GetOutput());\n        }\n      }\n\n      // Update the most downstream filter\n      if (this->GetSupportMask().GetPointer() != nullptr)\n      {\n        m_MultiplySupportFilter->Update();\n        Next_Zk = m_MultiplySupportFilter->GetOutput();\n      }\n      else\n      {\n        m_NesterovFilter->Update();\n        Next_Zk = m_NesterovFilter->GetOutput();\n      }\n      this->GraftOutput(Next_Zk);\n      iterationReporter.CompletedStep();\n    }\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter_h\n#define rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter_h\n\n#include \"rtkFourDConjugateGradientConeBeamReconstructionFilter.h\"\n#include \"rtkMotionCompensatedFourDReconstructionConjugateGradientOperator.h\"\n#include \"rtkWarpProjectionStackToFourDImageFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaWarpForwardProjectionImageFilter.h\"\n#  include \"rtkCudaWarpBackProjectionImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter\n * \\brief Implements motion compensated 4D reconstruction by conjugate gradient\n *\n * \\dot\n * digraph MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter {\n *\n * Input0 [label=\"Input 0 (Input: 4D sequence of volumes)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (4D Sequence of DVFs)\"];\n * Input2 [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction: 4D sequence of volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * AfterInput0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * ConjugateGradient [ label=\"rtk::ConjugateGradientImageFilter\" URL=\"\\ref rtk::ConjugateGradientImageFilter\"];\n * PSTFD [ label=\"rtk::WarpProjectionStackToFourDImageFilter\" URL=\"\\ref rtk::WarpProjectionStackToFourDImageFilter\"];\n *\n * Input0 -> AfterInput0 [arrowhead=none];\n * AfterInput0 -> ConjugateGradient;\n * Input0 -> PSTFD;\n * Input1 -> PSTFD;\n * Input1 -> PSTFD;\n * PSTFD -> ConjugateGradient;\n * ConjugateGradient -> Output;\n * }\n * \\enddot\n *\n * \\test rtkmotioncompensatedfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter\n  : public rtk::FourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter;\n  using Superclass = FourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = VolumeSeriesType;\n  using OutputImageType = VolumeSeriesType;\n  using VolumeType = ProjectionStackType;\n  using VectorForDVF = itk::CovariantVector<typename VolumeSeriesType::ValueType, VolumeSeriesType::ImageDimension - 1>;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUVolumeSeriesType =\n    typename itk::Image<typename VolumeSeriesType::PixelType, VolumeSeriesType::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using DVFSequenceImageType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension>,\n                                itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension>>;\n  using DVFImageType = typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                                   itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension - 1>,\n                                                   itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension - 1>>;\n#else\n  using DVFSequenceImageType = itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension - 1>;\n#endif\n\n  /** Typedefs of each subfilter of this composite filter */\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter);\n\n  /** Neither the Forward nor the Back projection filters can be set by the user */\n  void\n  SetForwardProjectionFilter(ForwardProjectionType itkNotUsed(_arg)) override\n  {\n    itkExceptionMacro(<< \"ForwardProjection cannot be changed\");\n  }\n  void\n  SetBackProjectionFilter(BackProjectionType itkNotUsed(_arg)) override\n  {\n    itkExceptionMacro(<< \"BackProjection cannot be changed\");\n  }\n\n  /** The ND + time motion vector field */\n  void\n  SetDisplacementField(const DVFSequenceImageType * DisplacementField);\n  void\n  SetInverseDisplacementField(const DVFSequenceImageType * InverseDisplacementField);\n  typename DVFSequenceImageType::ConstPointer\n  GetDisplacementField();\n  typename DVFSequenceImageType::ConstPointer\n  GetInverseDisplacementField();\n\n  /** Set the vector containing the signal in the sub-filters */\n  void\n  SetSignal(const std::vector<double> signal) override;\n\n  // Sub filters type alias\n  using MCProjStackToFourDType = rtk::WarpProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>;\n  using MCCGOperatorType =\n    rtk::MotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>;\n\n  /** Set and Get for the UseCudaCyclicDeformation variable */\n  itkSetMacro(UseCudaCyclicDeformation, bool);\n  itkGetMacro(UseCudaCyclicDeformation, bool);\n\nprotected:\n  MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter();\n  ~MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n\n  bool m_UseCudaCyclicDeformation;\n\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter_hxx\n#define rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::\n  MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(3);\n  this->m_ProjStackToFourDFilter = MCProjStackToFourDType::New();\n  this->m_CGOperator = MCCGOperatorType::New();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::\n  SetDisplacementField(const DVFSequenceImageType * DisplacementField)\n{\n  this->SetNthInput(2, const_cast<DVFSequenceImageType *>(DisplacementField));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::\n  SetInverseDisplacementField(const DVFSequenceImageType * InverseDisplacementField)\n{\n  this->SetNthInput(3, const_cast<DVFSequenceImageType *>(InverseDisplacementField));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::\n  DVFSequenceImageType::ConstPointer\n  MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType,\n                                                                      ProjectionStackType>::GetDisplacementField()\n{\n  return static_cast<const DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(2));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<\n  VolumeSeriesType,\n  ProjectionStackType>::DVFSequenceImageType::ConstPointer\nMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType,\n                                                                    ProjectionStackType>::GetInverseDisplacementField()\n{\n  return static_cast<const DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(3));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n#ifdef RTK_USE_CUDA\n  dynamic_cast<MCProjStackToFourDType *>(this->m_ProjStackToFourDFilter.GetPointer())->SetSignal(signal);\n  dynamic_cast<MCCGOperatorType *>(this->m_CGOperator.GetPointer())->SetSignal(signal);\n#else\n  (void)signal;\n#endif\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType,\n                                                                    ProjectionStackType>::GenerateOutputInformation()\n{\n#ifdef RTK_USE_CUDA\n  dynamic_cast<MCCGOperatorType *>(this->m_CGOperator.GetPointer())->SetDisplacementField(this->GetDisplacementField());\n  dynamic_cast<MCCGOperatorType *>(this->m_CGOperator.GetPointer())\n    ->SetInverseDisplacementField(this->GetInverseDisplacementField());\n  dynamic_cast<MCCGOperatorType *>(this->m_CGOperator.GetPointer())\n    ->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n  dynamic_cast<MCProjStackToFourDType *>(this->m_ProjStackToFourDFilter.GetPointer())\n    ->SetDisplacementField(this->GetDisplacementField());\n  dynamic_cast<MCProjStackToFourDType *>(this->m_ProjStackToFourDFilter.GetPointer())\n    ->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n#endif\n\n  Superclass::GenerateOutputInformation();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType,\n                                                                    ProjectionStackType>::GenerateInputRequestedRegion()\n{\n  this->m_CGOperator->PropagateRequestedRegion(this->m_CGOperator->GetOutput());\n}\n\n} // end namespace rtk\n\n#endif // rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkMotionCompensatedFourDROOSTERConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkMotionCompensatedFourDROOSTERConeBeamReconstructionFilter_h\n#define rtkMotionCompensatedFourDROOSTERConeBeamReconstructionFilter_h\n\n#include \"rtkFourDROOSTERConeBeamReconstructionFilter.h\"\n#include \"rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter.h\"\n\nnamespace rtk\n{\n/** \\class MotionCompensatedFourDROOSTERConeBeamReconstructionFilter\n * \\brief Implements Motion Compensated 4D RecOnstructiOn using Spatial and TEmporal\n * Regularization (short MC-ROOSTER)\n *\n * See the reference paper: \"Cardiac C-arm computed tomography using\n * a 3D + time ROI reconstruction method with spatial and temporal regularization\"\n * by Mory et al.\n *\n * MC ROOSTER reconstruction consists in performing Motion-Compensated 4D Conjugate\n * Gradient reconstruction, then applying several regularization steps :\n * - Replacing all negative values by zero\n * - Averaging along time where no movement is expected\n * - Applying total variation denoising in space\n * - Applying wavelets denoising in space\n * - Applying total variation denoising in time\n * - Applying gradient's L0 norm denoising in timeWarpSequenceFilterType\n * and starting over as many times as the number of main loop iterations desired.\n *\n * \\dot\n * digraph MotionCompensatedFourDROOSTERConeBeamReconstructionFilter {\n *\n * PrimaryInput [label=\"Primary input (4D sequence of volumes)\"];\n * PrimaryInput [shape=Mdiamond];\n * InputProjectionStack [label=\"Input projection stack\"];\n * InputProjectionStack [shape=Mdiamond];\n * InputMotionMask [label=\"Input motion mask\"];\n * InputMotionMask [shape=Mdiamond];\n * InputDisplacementField [label=\"Input displacement field\"];\n * InputDisplacementField [shape=Mdiamond];\n * InputInverseDisplacementField [group=invwarp, label=\"Input inverse displacement field\"];\n * InputInverseDisplacementField [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction: 4D sequence of volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * FourDCG [ label=\"rtk::FourDConjugateGradientConeBeamReconstructionFilter\"\n *           URL=\"\\ref rtk::FourDConjugateGradientConeBeamReconstructionFilter\"];\n * Positivity [group=regul, label=\"itk::ThresholdImageFilter (positivity)\" URL=\"\\ref itk::ThresholdImageFilter\"];\n * Resample [group=regul, label=\"itk::ResampleImageFilter\" URL=\"\\ref itk::ResampleImageFilter\"];\n * MotionMask [group=regul, label=\"rtk::AverageOutOfROIImageFilter\" URL=\"\\ref rtk::AverageOutOfROIImageFilter\"];\n * TVSpace [group=regul, label=\"rtk::TotalVariationDenoisingBPDQImageFilter (in space)\"\n *          URL=\"\\ref rtk::TotalVariationDenoisingBPDQImageFilter\"];\n * Wavelets [group=regul, label=\"rtk::DaubechiesWaveletsDenoiseSequenceImageFilter (in space)\"\n *           URL=\"\\ref rtk::DaubechiesWaveletsDenoiseSequenceImageFilter\"];\n * TVTime [group=regul, label=\"rtk::TotalVariationDenoisingBPDQImageFilter (along time)\"\n *         URL=\"\\ref rtk::TotalVariationDenoisingBPDQImageFilter\"];\n * L0Time [group=regul, label=\"rtk::LastDimensionL0GradientDenoisingImageFilter (along time)\"\n *         URL=\"\\ref rtk::LastDimensionL0GradientDenoisingImageFilter\"];\n * Unwarp [group=regul, label=\"rtk::UnwarpSequenceImageFilter\" URL=\"\\ref rtk::UnwarpSequenceImageFilter\"];\n * Subtract [group=invwarp, label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * Add [group=invwarp, label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n *\n * AfterPrimaryInput [group=invisible, label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterFourDCG [group=invisible, label=\"m_PerformPositivity ?\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterPositivity [group=invisible, label=\"m_PerformMotionMask ?\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterMotionMask [group=invisible, label=\"m_PerformTVSpatialDenoising ?\",\n *                  fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterTVSpace [group=invisible, label=\"m_PerformWaveletsSpatialDenoising ?\",\n *               fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterWavelets [group=invisible, label=\"m_PerformWarping ?\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterTVTime [group=invisible, label=\"m_PerformL0TemporalDenoising ?\",\n *              fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterL0Time [group=invisible, label=\"m_ComputeInverseWarpingByConjugateGradient ?\",\n *              fixedsize=\"false\", width=0, height=0, shape=none];\n * InputDisplacementField -> FourDCG;\n * InputInverseDisplacementField -> FourDCG;\n *\n * PrimaryInput -> AfterPrimaryInput [arrowhead=none];\n * AfterPrimaryInput -> FourDCG;\n * InputProjectionStack -> FourDCG;\n * FourDCG -> AfterFourDCG;\n * AfterFourDCG -> Positivity [label=\"true\"];\n * Positivity -> AfterPositivity;\n * AfterPositivity -> MotionMask [label=\"true\"];\n * MotionMask -> AfterMotionMask;\n * InputMotionMask -> Resample;\n * Resample -> MotionMask;\n * AfterMotionMask -> TVSpace [label=\"true\"];\n * TVSpace -> AfterTVSpace;FourDROOSTERConeBeamReconstructionFilter\n * AfterTVSpace -> Wavelets [label=\"true\"];\n * Wavelets -> AfterWavelets;\n * AfterWavelets -> TVTime [label=\"true\"];\n * TVTime -> AfterTVTime [arrowhead=none];\n * AfterTVTime -> L0Time [label=\"true\"];\n * L0Time -> AfterL0Time;\n * AfterL0Time -> Output;\n * AfterL0Time -> AfterPrimaryInput [style=dashed];\n *\n * AfterFourDCG -> AfterPositivity  [label=\"false\"];\n * AfterPositivity -> AfterMotionMask [label=\"false\"];\n * AfterMotionMask -> AfterTVSpace [label=\"false\"];\n * AfterTVSpace -> AfterWavelets [label=\"false\"];\n * AfterWavelets -> AfterTVTime [label=\"false\"];\n * AfterTVTime -> AfterL0Time [label=\"false\"];\n *\n * // Invisible edges between the regularization filters\n * edge[style=invis];\n * Positivity -> MotionMask;\n * MotionMask -> TVSpace;\n * TVSpace -> Wavelets;\n * Wavelets -> TVTime;\n * TVTime -> L0Time;\n *\n * }\n * \\enddot\n *\n * \\test rtkmotioncompensatedfourdroostertest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT MotionCompensatedFourDROOSTERConeBeamReconstructionFilter\n  : public rtk::FourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(MotionCompensatedFourDROOSTERConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = MotionCompensatedFourDROOSTERConeBeamReconstructionFilter;\n  using Superclass = rtk::FourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using VolumeType = ProjectionStackType;\n  using CovariantVectorForSpatialGradient =\n    itk::CovariantVector<typename VolumeSeriesType::ValueType, VolumeSeriesType::ImageDimension - 1>;\n  using CovariantVectorForTemporalGradient = itk::CovariantVector<typename VolumeSeriesType::ValueType, 1>;\n  using DVFVectorType = CovariantVectorForSpatialGradient;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n#ifdef RTK_USE_CUDA\n  using SpatialGradientImageType = itk::CudaImage<CovariantVectorForSpatialGradient, VolumeSeriesType::ImageDimension>;\n  using TemporalGradientImageType =\n    itk::CudaImage<CovariantVectorForTemporalGradient, VolumeSeriesType::ImageDimension>;\n  using DVFSequenceImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension - 1>;\n#else\n  using SpatialGradientImageType = itk::Image<CovariantVectorForSpatialGradient, VolumeSeriesType::ImageDimension>;\n  using TemporalGradientImageType = itk::Image<CovariantVectorForTemporalGradient, VolumeSeriesType::ImageDimension>;\n  using DVFSequenceImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension - 1>;\n#endif\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(MotionCompensatedFourDROOSTERConeBeamReconstructionFilter);\n\n  using MotionCompensatedFourDCGFilterType =\n    rtk::MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n\n  /** Neither the forward nor the back projection filter can be set by the user */\n  void\n  SetForwardProjectionFilter(ForwardProjectionType itkNotUsed(fwtype)) override\n  {\n    itkExceptionMacro(<< \"ForwardProjection cannot be changed\");\n  }\n  void\n  SetBackProjectionFilter(BackProjectionType itkNotUsed(bptype)) override\n  {\n    itkExceptionMacro(<< \"BackProjection cannot be changed\");\n  }\n\n  /** Set the vector containing the signal in the sub-filters */\n  void\n  SetSignal(const std::vector<double> signal) override;\n\nprotected:\n  MotionCompensatedFourDROOSTERConeBeamReconstructionFilter();\n  ~MotionCompensatedFourDROOSTERConeBeamReconstructionFilter() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkMotionCompensatedFourDROOSTERConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkMotionCompensatedFourDROOSTERConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkMotionCompensatedFourDROOSTERConeBeamReconstructionFilter_hxx\n#define rtkMotionCompensatedFourDROOSTERConeBeamReconstructionFilter_hxx\n\n#include <itkImageFileWriter.h>\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nMotionCompensatedFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::\n  MotionCompensatedFourDROOSTERConeBeamReconstructionFilter()\n{\n  // Create the filters\n#ifdef RTK_USE_CUDA\n  this->m_FourDCGFilter = MotionCompensatedFourDCGFilterType::New();\n#endif\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n  this->m_FourDCGFilter->SetSignal(signal);\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType,\n                                                          ProjectionStackType>::GenerateInputRequestedRegion()\n{\n  // Set variables so that the superclass' implementation\n  // generates the correct input requested regions\n  this->m_PerformWarping = true;\n  this->m_ComputeInverseWarpingByConjugateGradient = false;\n\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType,\n                                                          ProjectionStackType>::GenerateOutputInformation()\n{\n  // Set m_PerformWarping to false so as not\n  // to plug any of the warping filters into the pipeline\n  // (DVFs are taken into account in the motion compensated 4D conjugate gradient filter)\n  this->m_PerformWarping = false;\n\n  // Set the 4D conjugate gradient filter\n  dynamic_cast<MotionCompensatedFourDCGFilterType *>(this->m_FourDCGFilter.GetPointer())\n    ->SetDisplacementField(this->GetDisplacementField());\n  dynamic_cast<MotionCompensatedFourDCGFilterType *>(this->m_FourDCGFilter.GetPointer())\n    ->SetInverseDisplacementField(this->GetInverseDisplacementField());\n  dynamic_cast<MotionCompensatedFourDCGFilterType *>(this->m_FourDCGFilter.GetPointer())\n    ->SetUseCudaCyclicDeformation(this->m_UseCudaCyclicDeformation);\n\n  // Call the superclass implementation\n  Superclass::GenerateOutputInformation();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>::GenerateData()\n{\n  // Set the variables so that the superclass implementation updates the right filters\n  this->m_PerformWarping = false;\n\n  // Call the superclass implementation\n  Superclass::GenerateData();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkMotionCompensatedFourDReconstructionConjugateGradientOperator.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkMotionCompensatedFourDReconstructionConjugateGradientOperator_h\n#define rtkMotionCompensatedFourDReconstructionConjugateGradientOperator_h\n\n#include \"rtkFourDReconstructionConjugateGradientOperator.h\"\n#include \"rtkCyclicDeformationImageFilter.h\"\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaWarpForwardProjectionImageFilter.h\"\n#  include \"rtkCudaWarpBackProjectionImageFilter.h\"\n#  include \"rtkCudaCyclicDeformationImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class MotionCompensatedFourDReconstructionConjugateGradientOperator\n * \\brief Like FourDReconstructionConjugateGradientOperator, but motion-compensated\n *\n * \\dot\n * digraph MotionCompensatedFourDReconstructionConjugateGradientOperator {\n *\n * Input0 [ label=\"Input 0 (Input: 4D sequence of volumes)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (Projection weights)\"];\n * Input2 [shape=Mdiamond];\n * Input3 [label=\"Input 3 (4D Sequence of DVFs)\"];\n * Input3 [shape=Mdiamond];\n * Input4 [label=\"Input 4 (4D Sequence of inverse DVFs)\"];\n * Input4 [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction: 4D sequence of volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * SourceVol [ label=\"rtk::ConstantImageSource (volume)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * SourceVol2 [ label=\"rtk::ConstantImageSource (volume)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * SourceProj [ label=\"rtk::ConstantImageSource (projections)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * Source4D [ label=\"rtk::ConstantImageSource (4D)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * CyclicDeformation [label=\"rtk::CyclicDeformationImageFilter (for DVFs)\"\n *                    URL=\"\\ref rtk::CyclicDeformationImageFilter\"];\n * CyclicDeformationInv [label=\"rtk::CyclicDeformationImageFilter (for inverse DVFs)\"\n *                       URL=\"\\ref rtk::CyclicDeformationImageFilter\"];\n * ForwardProj [ label=\"rtk::CudaWarpForwardProjectionImageFilter\"\n *               URL=\"\\ref rtk::CudaWarpForwardProjectionImageFilter\"];\n * Interpolation [ label=\"InterpolatorWithKnownWeightsImageFilter\"\n *                 URL=\"\\ref rtk::InterpolatorWithKnownWeightsImageFilter\"];\n * BackProj [ label=\"rtk::CudaWarpBackProjectionImageFilter\" URL=\"\\ref rtk::CudaWarpBackProjectionImageFilter\"];\n * Splat [ label=\"rtk::SplatWithKnownWeightsImageFilter\" URL=\"\\ref rtk::SplatWithKnownWeightsImageFilter\"];\n * AfterSplat [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterInput0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterSource4D [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * Input3 -> CyclicDeformation;\n * Input4 -> CyclicDeformationInv;\n * CyclicDeformationInv -> ForwardProj;\n * CyclicDeformation -> BackProj;\n * Input0 -> Interpolation;\n * SourceVol -> Interpolation;\n * Interpolation -> ForwardProj;\n * SourceVol2 -> BackProj;\n * ForwardProj -> Multiply;\n * Input2 -> Multiply;\n * Multiply -> BackProj;\n * BackProj -> Splat;\n * Splat -> AfterSplat[arrowhead=none];\n * AfterSplat -> Output;\n * AfterSplat -> AfterSource4D[style=dashed, constraint=false];\n * Source4D -> AfterSource4D[arrowhead=none];\n * AfterSource4D -> Splat;\n * SourceProj -> ForwardProj;\n * }\n * \\enddot\n *\n * \\test rtkfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT MotionCompensatedFourDReconstructionConjugateGradientOperator\n  : public FourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(MotionCompensatedFourDReconstructionConjugateGradientOperator);\n\n  /** Standard class type alias. */\n  using Self = MotionCompensatedFourDReconstructionConjugateGradientOperator;\n  using Superclass = FourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using VolumeType = ProjectionStackType;\n  using VectorForDVF = itk::CovariantVector<typename VolumeSeriesType::ValueType, VolumeSeriesType::ImageDimension - 1>;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUVolumeSeriesType =\n    typename itk::Image<typename VolumeSeriesType::PixelType, VolumeSeriesType::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using DVFSequenceImageType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension>,\n                                itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension>>;\n  using DVFImageType = typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                                   itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension - 1>,\n                                                   itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension - 1>>;\n  using WarpForwardProjectionImageFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                JosephForwardProjectionImageFilter<ProjectionStackType, ProjectionStackType>,\n                                CudaWarpForwardProjectionImageFilter>;\n  using WarpBackProjectionImageFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                BackProjectionImageFilter<VolumeType, VolumeType>,\n                                CudaWarpBackProjectionImageFilter>;\n#else\n  using DVFSequenceImageType = itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension - 1>;\n  using WarpForwardProjectionImageFilterType =\n    JosephForwardProjectionImageFilter<ProjectionStackType, ProjectionStackType>;\n  using WarpBackProjectionImageFilterType = BackProjectionImageFilter<VolumeType, VolumeType>;\n#endif\n  using CPUDVFInterpolatorType = CyclicDeformationImageFilter<DVFSequenceImageType, DVFImageType>;\n#ifdef RTK_USE_CUDA\n  using CudaCyclicDeformationImageFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                CPUDVFInterpolatorType,\n                                CudaCyclicDeformationImageFilter>;\n#else\n  using CudaCyclicDeformationImageFilterType = CPUDVFInterpolatorType;\n#endif\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(MotionCompensatedFourDReconstructionConjugateGradientOperator);\n\n  /** The forward and back projection filters cannot be set by the user */\n  void\n  SetForwardProjectionFilter(typename Superclass::ForwardProjectionFilterType * itkNotUsed(_arg))\n  {\n    itkExceptionMacro(<< \"ForwardProjection cannot be changed\");\n  }\n  void\n  SetBackProjectionFilter(typename Superclass::BackProjectionFilterType * itkNotUsed(_arg))\n  {\n    itkExceptionMacro(<< \"BackProjection cannot be changed\");\n  }\n\n  /** The ND + time motion vector field */\n  void\n  SetDisplacementField(const DVFSequenceImageType * DisplacementField);\n  void\n  SetInverseDisplacementField(const DVFSequenceImageType * InverseDisplacementField);\n  typename DVFSequenceImageType::ConstPointer\n  GetInverseDisplacementField();\n  typename DVFSequenceImageType::ConstPointer\n  GetDisplacementField();\n\n  /** Set the vector containing the signal in the sub-filters */\n  void\n  SetSignal(const std::vector<double> signal) override;\n\n  /** Set and Get for the UseCudaCyclicDeformation variable */\n  itkSetMacro(UseCudaCyclicDeformation, bool);\n  itkGetMacro(UseCudaCyclicDeformation, bool);\n\nprotected:\n  MotionCompensatedFourDReconstructionConjugateGradientOperator();\n  ~MotionCompensatedFourDReconstructionConjugateGradientOperator() override = default;\n\n  /** Builds the pipeline and computes output information */\n  void\n  GenerateOutputInformation() override;\n\n  /** The inputs should not be in the same space so there is nothing to verify */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename CPUDVFInterpolatorType::Pointer m_DVFInterpolatorFilter;\n  typename CPUDVFInterpolatorType::Pointer m_InverseDVFInterpolatorFilter;\n  std::vector<double>                      m_Signal;\n  bool                                     m_UseCudaCyclicDeformation;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkMotionCompensatedFourDReconstructionConjugateGradientOperator.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkMotionCompensatedFourDReconstructionConjugateGradientOperator.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkMotionCompensatedFourDReconstructionConjugateGradientOperator_hxx\n#define rtkMotionCompensatedFourDReconstructionConjugateGradientOperator_hxx\n\n\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nMotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::\n  MotionCompensatedFourDReconstructionConjugateGradientOperator()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  m_UseCudaCyclicDeformation = false;\n\n  this->m_ForwardProjectionFilter = WarpForwardProjectionImageFilterType::New();\n  this->m_BackProjectionFilter = WarpBackProjectionImageFilterType::New();\n  if (std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n    itkWarningMacro(\"The warp forward and back project image filters exist only\"\n                    << \" in CUDA. Ignoring the displacement vector field and using CPU\"\n                    << \"Joseph forward projection and CPU voxel-based back projection\");\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::\n  SetDisplacementField(const DVFSequenceImageType * DisplacementField)\n{\n  this->SetNthInput(2, const_cast<DVFSequenceImageType *>(DisplacementField));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::\n  SetInverseDisplacementField(const DVFSequenceImageType * InverseDisplacementField)\n{\n  this->SetNthInput(3, const_cast<DVFSequenceImageType *>(InverseDisplacementField));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename MotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::\n  DVFSequenceImageType::ConstPointer\n  MotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType,\n                                                                ProjectionStackType>::GetDisplacementField()\n{\n  return static_cast<const DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(2));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename MotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::\n  DVFSequenceImageType::ConstPointer\n  MotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType,\n                                                                ProjectionStackType>::GetInverseDisplacementField()\n{\n  return static_cast<const DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(3));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n  this->m_Signal = signal;\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType,\n                                                              ProjectionStackType>::GenerateOutputInformation()\n{\n  m_DVFInterpolatorFilter = CPUDVFInterpolatorType::New();\n  m_InverseDVFInterpolatorFilter = CPUDVFInterpolatorType::New();\n  if (m_UseCudaCyclicDeformation)\n  {\n    if (std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n      itkGenericExceptionMacro(<< \"UseCudaCyclicDeformation option only available with itk::CudaImage.\");\n    m_DVFInterpolatorFilter = CudaCyclicDeformationImageFilterType::New();\n    m_InverseDVFInterpolatorFilter = CudaCyclicDeformationImageFilterType::New();\n  }\n\n  m_DVFInterpolatorFilter->SetSignalVector(this->m_Signal);\n  m_DVFInterpolatorFilter->SetInput(this->GetDisplacementField());\n  m_DVFInterpolatorFilter->SetFrame(0);\n\n  m_InverseDVFInterpolatorFilter->SetSignalVector(this->m_Signal);\n  m_InverseDVFInterpolatorFilter->SetInput(this->GetInverseDisplacementField());\n  m_InverseDVFInterpolatorFilter->SetFrame(0);\n\n#ifdef RTK_USE_CUDA\n  CudaWarpForwardProjectionImageFilter * wfp;\n  wfp = dynamic_cast<CudaWarpForwardProjectionImageFilter *>(this->m_ForwardProjectionFilter.GetPointer());\n  using CudaDVFImageType = itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension - 1>;\n  CudaDVFImageType * cudvf;\n  cudvf = dynamic_cast<CudaDVFImageType *>(m_InverseDVFInterpolatorFilter->GetOutput());\n  wfp->SetDisplacementField(cudvf);\n  CudaWarpBackProjectionImageFilter * wbp;\n  wbp = dynamic_cast<CudaWarpBackProjectionImageFilter *>(this->m_BackProjectionFilter.GetPointer());\n  cudvf = dynamic_cast<CudaDVFImageType *>(m_DVFInterpolatorFilter->GetOutput());\n  wbp->SetDisplacementField(cudvf);\n#endif\n\n  Superclass::GenerateOutputInformation();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nMotionCompensatedFourDReconstructionConjugateGradientOperator<VolumeSeriesType, ProjectionStackType>::GenerateData()\n{\n  int Dimension = ProjectionStackType::ImageDimension;\n\n  // Prepare the index for the constant projection stack source and the extract filter\n  typename ProjectionStackType::RegionType sourceRegion = this->GetInputProjectionStack()->GetLargestPossibleRegion();\n  typename ProjectionStackType::SizeType   sourceSize = sourceRegion.GetSize();\n  typename ProjectionStackType::IndexType  sourceIndex = sourceRegion.GetIndex();\n\n  int NumberProjs = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  int FirstProj = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n\n  // Divide the stack of projections into slabs of projections of identical phase\n  std::vector<int>          firstProjectionInSlabs;\n  std::vector<unsigned int> sizeOfSlabs;\n  firstProjectionInSlabs.push_back(FirstProj);\n  if (NumberProjs == 1)\n    sizeOfSlabs.push_back(1);\n  else\n  {\n    for (int proj = FirstProj + 1; proj < FirstProj + NumberProjs; proj++)\n    {\n      if (itk::Math::abs(m_Signal[proj] - m_Signal[proj - 1]) > 1e-4)\n      {\n        // Compute the number of projections in the current slab\n        sizeOfSlabs.push_back(proj - firstProjectionInSlabs[firstProjectionInSlabs.size() - 1]);\n\n        // Update the index of the first projection in the next slab\n        firstProjectionInSlabs.push_back(proj);\n      }\n    }\n    sizeOfSlabs.push_back(NumberProjs - firstProjectionInSlabs[firstProjectionInSlabs.size() - 1]);\n  }\n\n  bool                               firstSlabProcessed = false;\n  typename VolumeSeriesType::Pointer pimg;\n\n  // Process the projections in order\n  for (unsigned int slab = 0; slab < firstProjectionInSlabs.size(); slab++)\n  {\n    // Set the projection stack source\n    sourceIndex[Dimension - 1] = firstProjectionInSlabs[slab];\n    sourceSize[Dimension - 1] = sizeOfSlabs[slab];\n    this->m_ConstantProjectionStackSource->SetIndex(sourceIndex);\n    this->m_ConstantProjectionStackSource->SetSize(sourceSize);\n\n    // Set the interpolation filters, including those for the DVFs\n    this->m_InterpolationFilter->SetProjectionNumber(firstProjectionInSlabs[slab]);\n    this->m_SplatFilter->SetProjectionNumber(firstProjectionInSlabs[slab]);\n    m_DVFInterpolatorFilter->SetFrame(firstProjectionInSlabs[slab]);\n    m_InverseDVFInterpolatorFilter->SetFrame(firstProjectionInSlabs[slab]);\n\n    // After the first update, we need to use the output as input.\n    if (firstSlabProcessed)\n    {\n      pimg = this->m_SplatFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      this->m_SplatFilter->SetInputVolumeSeries(pimg);\n    }\n\n    // Update the last filter\n    this->m_SplatFilter->Update();\n\n    // Update condition\n    firstSlabProcessed = true;\n  }\n\n  // Graft its output\n  this->GraftOutput(this->m_SplatFilter->GetOutput());\n\n  // Release the data in internal filters\n  pimg->ReleaseData();\n  this->m_ConstantVolumeSource1->GetOutput()->ReleaseData();\n  this->m_ConstantVolumeSource2->GetOutput()->ReleaseData();\n  this->m_ConstantVolumeSeriesSource->GetOutput()->ReleaseData();\n  this->m_ConstantProjectionStackSource->GetOutput()->ReleaseData();\n  this->m_DisplacedDetectorFilter->GetOutput()->ReleaseData();\n  this->m_InterpolationFilter->GetOutput()->ReleaseData();\n  this->m_BackProjectionFilter->GetOutput()->ReleaseData();\n  this->m_ForwardProjectionFilter->GetOutput()->ReleaseData();\n  m_DVFInterpolatorFilter->GetOutput()->ReleaseData();\n  m_InverseDVFInterpolatorFilter->GetOutput()->ReleaseData();\n\n  // Send the input back onto the CPU\n  this->GetInputVolumeSeries()->GetBufferPointer();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkMultiplyByVectorImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkMultiplyByVectorImageFilter_h\n#define rtkMultiplyByVectorImageFilter_h\n\n#include <itkImageToImageFilter.h>\n\nnamespace rtk\n{\n/** \\class MultiplyByVectorImageFilter\n * \\brief Multiplies each (n-1) dimension image by the corresponding\n * element in a vector\n *\n * This filter takes in input a n-D image and a vector. It multiplies\n * each (n-1) dimension image by the corresponding\n * element in the vector. The image's size along the last dimension\n * must be equal to vector's size.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <class TInputImage>\nclass ITK_TEMPLATE_EXPORT MultiplyByVectorImageFilter : public itk::ImageToImageFilter<TInputImage, TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(MultiplyByVectorImageFilter);\n\n  /** Standard class type alias. */\n  using Self = MultiplyByVectorImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(MultiplyByVectorImageFilter);\n\n  /** The image containing the weights applied to the temporal components */\n  void\n  SetVector(std::vector<float> vect);\n\nprotected:\n  MultiplyByVectorImageFilter();\n  ~MultiplyByVectorImageFilter() override = default;\n\n  /** Does the real work. */\n  void\n  DynamicThreadedGenerateData(const typename TInputImage::RegionType & outputRegionForThread) override;\n\nprivate:\n  std::vector<float> m_Vector;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkMultiplyByVectorImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkMultiplyByVectorImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkMultiplyByVectorImageFilter_hxx\n#define rtkMultiplyByVectorImageFilter_hxx\n\n#include \"itkImageRegionIterator.h\"\n\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <class TInputImage>\nMultiplyByVectorImageFilter<TInputImage>::MultiplyByVectorImageFilter() = default;\n\ntemplate <class TInputImage>\nvoid\nMultiplyByVectorImageFilter<TInputImage>::SetVector(std::vector<float> vect)\n{\n  m_Vector = vect;\n  this->Modified();\n}\n\ntemplate <class TInputImage>\nvoid\nMultiplyByVectorImageFilter<TInputImage>::DynamicThreadedGenerateData(\n  const typename TInputImage::RegionType & outputRegionForThread)\n{\n  int Dimension = this->GetInput()->GetImageDimension();\n\n  for (unsigned int i = outputRegionForThread.GetIndex()[Dimension - 1];\n       i < outputRegionForThread.GetSize()[Dimension - 1] + outputRegionForThread.GetIndex()[Dimension - 1];\n       i++)\n  {\n    typename TInputImage::RegionType SubRegion;\n    SubRegion = outputRegionForThread;\n    SubRegion.SetSize(Dimension - 1, 1);\n    SubRegion.SetIndex(Dimension - 1, i);\n\n    itk::ImageRegionIterator<TInputImage>      outputIterator(this->GetOutput(), SubRegion);\n    itk::ImageRegionConstIterator<TInputImage> inputIterator(this->GetInput(), SubRegion);\n\n    while (!inputIterator.IsAtEnd())\n    {\n      outputIterator.Set(inputIterator.Get() * m_Vector[i]);\n      ++outputIterator;\n      ++inputIterator;\n    }\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkNesterovUpdateImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkNesterovUpdateImageFilter_h\n#define rtkNesterovUpdateImageFilter_h\n\n#include \"itkInPlaceImageFilter.h\"\n#include \"itkPixelTraits.h\"\n\nnamespace rtk\n{\n\n/** \\class NesterovUpdateImageFilter\n * \\brief Applies Nesterov's momentum technique\n *\n * NesterovUpdateImageFilter implements Nesterov's momentum technique in order\n * to accelerate the convergence rate of Newton's method, or other optimization\n * algorithms. The implementation is based on the description of [Mechlem et\n * al, 10.1109/TMI.2017.2726687, 2018], based on [Kim et al,\n * 10.1109/TMI.2014.2350962, 2015] implementing [Nesterov,\n * 10.1007/s10107-004-0552-5, 2005] for ordered-subset tomographic\n * reconstruction. The first input is the current iterate, the second input is\n * the opposite of the next step, e.g., the product of the inverse hessian\n * matrix by the gradient vector for an update of Newton's algorithm before\n * applying a minus sign.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT NesterovUpdateImageFilter : public itk::InPlaceImageFilter<TImage, TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(NesterovUpdateImageFilter);\n\n  /** Standard class type alias. */\n  using Self = NesterovUpdateImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TImage, TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using OutputImageRegionType = typename Superclass::OutputImageType::RegionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(NesterovUpdateImageFilter);\n\n  /** Get and Set macro*/\n  itkGetMacro(NumberOfIterations, int);\n  itkSetMacro(NumberOfIterations, int);\n\nprotected:\n  NesterovUpdateImageFilter();\n  ~NesterovUpdateImageFilter() override;\n\n  /** Does the real work. */\n  void\n  BeforeThreadedGenerateData() override;\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n  void\n  AfterThreadedGenerateData() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  int                                                              m_NumberOfIterations;\n  int                                                              m_CurrentIteration;\n  bool                                                             m_MustInitializeIntermediateImages;\n  typename itk::PixelTraits<typename TImage::PixelType>::ValueType m_TCoeff;\n  typename itk::PixelTraits<typename TImage::PixelType>::ValueType m_TCoeffNext;\n  typename itk::PixelTraits<typename TImage::PixelType>::ValueType m_Sum;\n  typename itk::PixelTraits<typename TImage::PixelType>::ValueType m_Ratio;\n\n  // Internal images\n  typename TImage::Pointer m_Vk;\n  typename TImage::Pointer m_Alphak;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkNesterovUpdateImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkNesterovUpdateImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkNesterovUpdateImageFilter_hxx\n#define rtkNesterovUpdateImageFilter_hxx\n\n#include \"itkImageRegionIterator.h\"\n\nnamespace rtk\n{\n\ntemplate <typename TImage>\nNesterovUpdateImageFilter<TImage>::NesterovUpdateImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n  m_Vk = TImage::New();\n  m_Alphak = TImage::New();\n\n  m_NumberOfIterations = 100;\n  m_MustInitializeIntermediateImages = true;\n}\n\ntemplate <typename TImage>\nNesterovUpdateImageFilter<TImage>::~NesterovUpdateImageFilter() = default;\n\ntemplate <typename TImage>\nvoid\nNesterovUpdateImageFilter<TImage>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the image to update\n  typename Superclass::InputImagePointer inputPtr0 = const_cast<TImage *>(this->GetInput(0));\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the update computed by Newton's method\n  typename Superclass::InputImagePointer inputPtr1 = const_cast<TImage *>(this->GetInput(1));\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n}\n\ntemplate <typename TImage>\nvoid\nNesterovUpdateImageFilter<TImage>::BeforeThreadedGenerateData()\n{\n  if (m_MustInitializeIntermediateImages)\n  {\n    // Allocate the intermediate images\n    m_Vk->CopyInformation(this->GetInput(0));\n    m_Vk->SetRegions(m_Vk->GetLargestPossibleRegion());\n    m_Vk->Allocate();\n    m_Alphak->CopyInformation(this->GetInput(0));\n    m_Alphak->SetRegions(m_Alphak->GetLargestPossibleRegion());\n    m_Alphak->Allocate();\n\n    // Nesterov's coefficients change at every iteration,\n    // and this filter only performs one iteration. It needs\n    // to keep track of the iteration number\n    m_CurrentIteration = 0;\n\n    m_TCoeff = 1.;\n    m_Sum = 0.;\n    m_Ratio = 0.;\n  }\n  else\n    m_TCoeff = m_TCoeffNext;\n  m_TCoeffNext = 0.5 * (1. + sqrt(1. + 4. * m_TCoeff * m_TCoeff));\n  m_Sum += m_TCoeffNext;\n  m_Ratio = m_TCoeffNext / m_Sum;\n}\n\ntemplate <typename TImage>\nvoid\nNesterovUpdateImageFilter<TImage>::DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread)\n{\n  if (m_MustInitializeIntermediateImages)\n  {\n    // Copy the input 0 into them\n    itk::ImageRegionConstIterator<TImage> inIt(this->GetInput(0), outputRegionForThread);\n    itk::ImageRegionIterator<TImage>      vIt(m_Vk, outputRegionForThread);\n    itk::ImageRegionIterator<TImage>      alphaIt(m_Alphak, outputRegionForThread);\n\n    while (!inIt.IsAtEnd())\n    {\n      vIt.Set(inIt.Get());\n      alphaIt.Set(inIt.Get());\n\n      ++inIt;\n      ++vIt;\n      ++alphaIt;\n    }\n  }\n\n  // Create iterators for all inputs and outputs\n  itk::ImageRegionIterator<TImage>      v_k_It(m_Vk, outputRegionForThread);\n  itk::ImageRegionConstIterator<TImage> z_k_ItIn(this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<TImage>      z_k_ItOut(this->GetOutput(), outputRegionForThread);\n  itk::ImageRegionConstIterator<TImage> g_k_It(this->GetInput(1), outputRegionForThread);\n\n  // Perform computations\n  if (m_CurrentIteration == m_NumberOfIterations - 1)\n  {\n    // Last iteration, no need to update v_k and z_k. Return alpha_k, the current iterate.\n    itk::ImageRegionIterator<TImage> alpha_k_It(this->GetOutput(), outputRegionForThread);\n    while (!alpha_k_It.IsAtEnd())\n    {\n      alpha_k_It.Set(z_k_ItIn.Get() - g_k_It.Get());\n      ++alpha_k_It;\n      ++z_k_ItIn;\n      ++g_k_It;\n    }\n  }\n  else\n  {\n    itk::ImageRegionIterator<TImage> alpha_k_It(m_Alphak, outputRegionForThread);\n    while (!alpha_k_It.IsAtEnd())\n    {\n      alpha_k_It.Set(z_k_ItIn.Get() - g_k_It.Get());\n      v_k_It.Set(v_k_It.Get() - m_TCoeff * g_k_It.Get());\n      z_k_ItOut.Set(alpha_k_It.Get() + m_Ratio * (v_k_It.Get() - alpha_k_It.Get()));\n\n      ++alpha_k_It;\n      ++v_k_It;\n      ++z_k_ItIn;\n      ++z_k_ItOut;\n      ++g_k_It;\n    }\n  }\n}\n\ntemplate <typename TImage>\nvoid\nNesterovUpdateImageFilter<TImage>::AfterThreadedGenerateData()\n{\n  m_CurrentIteration++;\n  if (m_CurrentIteration == m_NumberOfIterations)\n    m_MustInitializeIntermediateImages = true;\n  else\n    m_MustInitializeIntermediateImages = false;\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkOSEMConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOSEMConeBeamReconstructionFilter_h\n#define rtkOSEMConeBeamReconstructionFilter_h\n\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkDePierroRegularizationImageFilter.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n#include <itkAddImageAdaptor.h>\n#include <itkDivideImageFilter.h>\n#include <itkDivideOrZeroOutImageFilter.h>\n\n#include \"rtkConstantImageSource.h\"\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class OSEMConeBeamReconstructionFilter\n * \\brief Implements the Ordered-Subset Expectation-Maximization algorithm.\n *\n * OSEMConeBeamReconstructionFilter is a composite filter which combines\n * the different steps of the OSEM cone-beam reconstruction, mainly:\n * - ExtractFilterType to create the subsets.\n * - ForwardProjectionImageFilter,\n * - DivideImageFilter,\n * - BackProjectionImageFilter.\n * The input stack of projections is processed piece by piece (the size is\n * controlled with ProjectionSubsetSize) via the use of itk::ExtractImageFilter\n * to extract sub-stacks.\n *\n * One weighting steps must be applied when processing a given subset:\n * - each voxel of the back projection must be divided by the value it would take if\n * a projection filled with ones was being reprojected.\n *\n * By default the quadratic penalization described in [De Pierro, IEEE TMI, 1995] is applied\n * during the iterative process. The hyperparameter for the regularization can be changed\n * using the SetBetaRegularization method. If the hyperparameter is set to 0 the\n * filter behaves like the classic MLEM/OSEM algorithm.\n *\n * \\dot\n * digraph OSEMConeBeamReconstructionFilter {\n *\n *  Input0 [ label=\"Input 0 (Volume)\"];\n *  Input0 [shape=Mdiamond];\n *  Input1 [label=\"Input 1 (Projections)\"];\n *  Input1 [shape=Mdiamond];\n *  Output [label=\"Output (Reconstruction)\"];\n *  Output [shape=Mdiamond];\n *\n *  node [shape=box];\n *  ForwardProject [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n *  Extract [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n *  Divide1 [ label=\"itk::DivideImageFilter\" URL=\"\\ref itk::DivideImageFilter\"];\n *  Divide [ label=\"itk::DivideImageFilter\" URL=\"\\ref itk::DivideImageFilter\"];\n *  ProjectionZero [ label=\"rtk::ConstantImageSource (full of zero)\" URL=\"\\ref rtk::ConstantImageSource\"];\n *  ConstantVolume2[ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n *  ConstantVolume [ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n *  ConstantProjectionStack [ label=\"rtk::ConstantImageSource (full of one)\" URL=\"\\ref rtk::ConstantImageSource\"];\n *  BackProjection [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n *  BackProjection2 [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n *  Multiply [ label=\"itk::MultiplyImageFilter \" URL=\"\\ref itk::MultiplyImageFilter\"];\n *  OutofInput0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *  OutofMultiply [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *  OutofBP [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *  BeforeBP [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *  BeforeMultiply [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *  Input0 -> OutofInput0 [arrowhead=none];\n *  OutofInput0 -> ForwardProject;\n *  OutofInput0 -> BeforeMultiply [arrowhead=none];\n *  BeforeMultiply -> Multiply;\n *  Extract -> Divide1;\n *  ProjectionZero -> ForwardProject;\n *  Input1 -> Extract;\n *  ForwardProject -> Divide1;\n *  Divide1 -> BackProjection;\n *  ConstantVolume -> BeforeBP [arrowhead=none];\n *  BeforeBP -> BackProjection;\n *  ConstantProjectionStack -> BackProjection2;\n *  ConstantVolume2 -> BackProjection2;\n *  BackProjection2 -> Divide;\n *  BackProjection -> OutofBP [arrowhead=none];\n *  Divide -> Multiply\n *  OutofBP-> Divide;\n *  OutofBP -> BeforeBP [style=dashed, constraint=false];\n *  Multiply -> OutofMultiply;\n *  OutofMultiply -> OutofInput0 [headport=\"se\", style=dashed];\n *  OutofMultiply -> Output;\n *  }\n * \\enddot\n *\n * \\test rtkosemtest.cxx\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <class TVolumeImage, class TProjectionImage = TVolumeImage>\nclass ITK_TEMPLATE_EXPORT OSEMConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(OSEMConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = OSEMConeBeamReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using VolumeType = TVolumeImage;\n  using ProjectionType = TProjectionImage;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using ExtractFilterType = itk::ExtractImageFilter<ProjectionType, ProjectionType>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<VolumeType, VolumeType, VolumeType>;\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<ProjectionType, VolumeType>;\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<VolumeType, ProjectionType>;\n  using DivideProjectionFilterType = itk::DivideOrZeroOutImageFilter<ProjectionType, ProjectionType, ProjectionType>;\n  using DivideVolumeFilterType = itk::DivideOrZeroOutImageFilter<VolumeType, VolumeType, VolumeType>;\n  using ConstantVolumeSourceType = rtk::ConstantImageSource<VolumeType>;\n  using ConstantProjectionSourceType = rtk::ConstantImageSource<ProjectionType>;\n  using DePierroRegularizationFilterType = rtk::DePierroRegularizationImageFilter<VolumeType, VolumeType>;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(OSEMConeBeamReconstructionFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Get / Set the number of iterations. Default is 3. */\n  itkGetMacro(NumberOfIterations, unsigned int);\n  itkSetMacro(NumberOfIterations, unsigned int);\n\n  /** Get / Set the number of projections per subset. Default is 1. */\n  itkGetMacro(NumberOfProjectionsPerSubset, unsigned int);\n  itkSetMacro(NumberOfProjectionsPerSubset, unsigned int);\n\n  /** Get / Set the hyperparameter for the regularization. Default is 0.01 */\n  itkGetMacro(BetaRegularization, double);\n  itkSetMacro(BetaRegularization, double);\n\n  /** Get / Set StoreNormalizationImages. If true, the normalizations images\n   * are only computed once during the first iteration and stored to be reused\n   * for the next iterations. This speed up the computation time but it is\n   * more memory consuming than if the normalizations images were computed at\n   * each iteration (false). Default is true */\n  itkGetMacro(StoreNormalizationImages, bool);\n  itkSetMacro(StoreNormalizationImages, bool);\n\nprotected:\n  OSEMConeBeamReconstructionFilter();\n  ~OSEMConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Pointers to each subfilter of this composite filter */\n  typename ExtractFilterType::Pointer                m_ExtractFilter;\n  typename ForwardProjectionFilterType::Pointer      m_ForwardProjectionFilter;\n  typename MultiplyFilterType::Pointer               m_MultiplyFilter;\n  typename BackProjectionFilterType::Pointer         m_BackProjectionFilter;\n  typename BackProjectionFilterType::Pointer         m_BackProjectionNormalizationFilter;\n  typename DivideProjectionFilterType::Pointer       m_DivideProjectionFilter;\n  typename DivideVolumeFilterType::Pointer           m_DivideVolumeFilter;\n  typename ConstantProjectionSourceType::Pointer     m_ZeroConstantProjectionStackSource;\n  typename ConstantProjectionSourceType::Pointer     m_OneConstantProjectionStackSource;\n  typename ConstantVolumeSourceType::Pointer         m_ConstantVolumeSource;\n  typename DePierroRegularizationFilterType::Pointer m_DePierroRegularizationFilter;\n\nprivate:\n  /** Number of projections processed before the volume is updated (several for OS-EM) */\n  unsigned int m_NumberOfProjectionsPerSubset{ 1 };\n\n  /** Geometry object */\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n\n  /** Number of iterations */\n  unsigned int m_NumberOfIterations{ 3 };\n\n  /** Hyperparameter for the regularization */\n  double m_BetaRegularization{ 0. };\n\n  bool m_StoreNormalizationImages{ true };\n\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkOSEMConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkOSEMConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOSEMConeBeamReconstructionFilter_hxx\n#define rtkOSEMConeBeamReconstructionFilter_hxx\n\n#include \"rtkGeneralPurposeFunctions.h\"\n\n#include <algorithm>\n#include <itkTimeProbe.h>\n\n#include <itkImageFileWriter.h>\n\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\ntemplate <class TVolumeImage, class TProjectionImage>\nOSEMConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::OSEMConeBeamReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Create each filter of the composite filter\n  m_ExtractFilter = ExtractFilterType::New();\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_ConstantVolumeSource = ConstantVolumeSourceType::New();\n  m_ZeroConstantProjectionStackSource = ConstantProjectionSourceType::New();\n  m_DivideProjectionFilter = DivideProjectionFilterType::New();\n  m_DePierroRegularizationFilter = DePierroRegularizationFilterType::New();\n\n  // Create the filters required for the normalization of the\n  // backprojection\n  m_OneConstantProjectionStackSource = ConstantProjectionSourceType::New();\n  m_DivideVolumeFilter = DivideVolumeFilterType::New();\n\n  // Permanent internal connections\n  m_DivideProjectionFilter->SetInput1(m_ExtractFilter->GetOutput());\n  m_DivideVolumeFilter->SetInput1(m_MultiplyFilter->GetOutput());\n\n  // Default parameters\n  m_ExtractFilter->SetDirectionCollapseToSubmatrix();\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nOSEMConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nOSEMConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<TVolumeImage *>(this->GetInput());\n\n  if (!inputPtr)\n    return;\n\n  m_BackProjectionFilter->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  m_BackProjectionFilter->GetOutput()->PropagateRequestedRegion();\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nOSEMConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::GenerateOutputInformation()\n{\n\n  // We only set the first sub-stack at that point, the rest will be\n  // requested in the GenerateData function\n  typename ExtractFilterType::InputImageRegionType projRegion;\n\n  // Set forward projection filter\n  m_ForwardProjectionFilter = this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n\n  // Set back projection filter\n  m_BackProjectionFilter = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  m_BackProjectionNormalizationFilter =\n    this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n\n  projRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  m_ExtractFilter->SetExtractionRegion(projRegion);\n\n  m_ExtractFilter->SetInput(this->GetInput(1));\n  m_ExtractFilter->UpdateOutputInformation();\n\n  // Links with the forward and back projection filters should be set here\n  // and not in the constructor, as these filters are set at runtime\n  m_ConstantVolumeSource->SetInformationFromImage(const_cast<TVolumeImage *>(this->GetInput(0)));\n  m_ConstantVolumeSource->SetConstant(0);\n\n  m_OneConstantProjectionStackSource->SetInformationFromImage(\n    const_cast<TProjectionImage *>(m_ExtractFilter->GetOutput()));\n  m_OneConstantProjectionStackSource->SetConstant(1);\n\n  m_ZeroConstantProjectionStackSource->SetInformationFromImage(\n    const_cast<TProjectionImage *>(m_ExtractFilter->GetOutput()));\n  m_ZeroConstantProjectionStackSource->SetConstant(0);\n\n  m_BackProjectionFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_DivideProjectionFilter->GetOutput());\n  m_BackProjectionFilter->SetTranspose(false);\n\n  m_BackProjectionNormalizationFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n  m_BackProjectionNormalizationFilter->SetInput(1, m_OneConstantProjectionStackSource->GetOutput());\n  m_BackProjectionNormalizationFilter->SetTranspose(false);\n\n  m_MultiplyFilter->SetInput1(m_BackProjectionFilter->GetOutput());\n  m_MultiplyFilter->SetInput2(this->GetInput(0));\n\n  m_DePierroRegularizationFilter->SetInput(0, this->GetInput(0));\n  m_DePierroRegularizationFilter->SetInput(1, m_MultiplyFilter->GetOutput());\n  m_DePierroRegularizationFilter->SetInput(2, m_BackProjectionNormalizationFilter->GetOutput());\n  m_DePierroRegularizationFilter->SetBeta(m_BetaRegularization);\n  m_DivideVolumeFilter->SetInput2(m_DePierroRegularizationFilter->GetOutput());\n  m_DivideVolumeFilter->SetConstant(0);\n\n  m_ForwardProjectionFilter->SetInput(0, m_ZeroConstantProjectionStackSource->GetOutput());\n  m_ForwardProjectionFilter->SetInput(1, this->GetInput(0));\n\n  m_DivideProjectionFilter->SetInput2(m_ForwardProjectionFilter->GetOutput());\n  m_DivideProjectionFilter->SetConstant(1);\n\n  m_ForwardProjectionFilter->SetGeometry(this->m_Geometry);\n  m_BackProjectionFilter->SetGeometry(this->m_Geometry);\n  m_BackProjectionNormalizationFilter->SetGeometry(this->m_Geometry);\n\n  // Update output information\n  m_DivideVolumeFilter->UpdateOutputInformation();\n  this->GetOutput()->SetOrigin(m_DivideVolumeFilter->GetOutput()->GetOrigin());\n  this->GetOutput()->SetSpacing(m_DivideVolumeFilter->GetOutput()->GetSpacing());\n  this->GetOutput()->SetDirection(m_DivideVolumeFilter->GetOutput()->GetDirection());\n  this->GetOutput()->SetLargestPossibleRegion(m_DivideVolumeFilter->GetOutput()->GetLargestPossibleRegion());\n\n  // Set memory management flags\n  m_ForwardProjectionFilter->ReleaseDataFlagOn();\n  m_DivideProjectionFilter->ReleaseDataFlagOn();\n  m_MultiplyFilter->ReleaseDataFlagOn();\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nOSEMConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::GenerateData()\n{\n  const unsigned int Dimension = this->InputImageDimension;\n\n  // The backprojection works on one projection at a time\n  typename ExtractFilterType::InputImageRegionType subsetRegion;\n  subsetRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  unsigned int nProj = subsetRegion.GetSize(Dimension - 1);\n  subsetRegion.SetSize(Dimension - 1, 1);\n\n  // Fill and shuffle randomly the projection order.\n  // Should be tunable with other solutions.\n  std::vector<unsigned int> projOrder(nProj);\n\n  // If m_StoreNormalizationImages is true, the backprojection of\n  // ones will be only computed once during the first iteration.\n  // The result will be stored in an vector and reused for the next iterations.\n  std::vector<typename TVolumeImage::Pointer> vectorNorm;\n\n  for (unsigned int i = 0; i < nProj; i++)\n    projOrder[i] = i;\n  std::shuffle(projOrder.begin(), projOrder.end(), Superclass::m_DefaultRandomEngine);\n\n  // Declare the image used in the main loop\n  typename TVolumeImage::Pointer pimg;\n  typename TVolumeImage::Pointer norm;\n\n  itk::IterationReporter iterationReporter(this, 0, 1);\n\n  // For each iteration, go over each projection\n  for (unsigned int iter = 0; iter < m_NumberOfIterations; iter++)\n  {\n    unsigned int projectionsProcessedInSubset = 0;\n    unsigned int currentSubset = 0;\n    for (unsigned int i = 0; i < nProj; i++)\n    {\n      // Change projection subset\n      subsetRegion.SetIndex(Dimension - 1, projOrder[i]);\n      m_ExtractFilter->SetExtractionRegion(subsetRegion);\n      m_ExtractFilter->UpdateOutputInformation();\n\n      m_ZeroConstantProjectionStackSource->SetInformationFromImage(\n        const_cast<TProjectionImage *>(m_ExtractFilter->GetOutput()));\n\n      // This is required to reset the full pipeline\n      m_BackProjectionFilter->GetOutput()->UpdateOutputInformation();\n      m_BackProjectionFilter->GetOutput()->PropagateRequestedRegion();\n\n      m_BackProjectionFilter->Update();\n      if (iter == 0 || !m_StoreNormalizationImages)\n      {\n        m_OneConstantProjectionStackSource->SetInformationFromImage(\n          const_cast<TProjectionImage *>(m_ExtractFilter->GetOutput()));\n        m_BackProjectionNormalizationFilter->GetOutput()->UpdateOutputInformation();\n        m_BackProjectionNormalizationFilter->GetOutput()->PropagateRequestedRegion();\n        m_BackProjectionNormalizationFilter->Update();\n      }\n\n      projectionsProcessedInSubset++;\n      if ((projectionsProcessedInSubset == m_NumberOfProjectionsPerSubset) || (i == nProj - 1))\n      {\n        if (iter == 0 && m_StoreNormalizationImages)\n        {\n          vectorNorm.push_back(m_BackProjectionNormalizationFilter->GetOutput());\n          vectorNorm.back()->DisconnectPipeline();\n        }\n        m_MultiplyFilter->SetInput1(m_BackProjectionFilter->GetOutput());\n\n        m_DivideVolumeFilter->SetInput1(m_MultiplyFilter->GetOutput());\n        m_DePierroRegularizationFilter->SetInput(1, m_MultiplyFilter->GetOutput());\n        if (m_StoreNormalizationImages)\n          m_DePierroRegularizationFilter->SetInput(2, vectorNorm[currentSubset]);\n        else\n          m_DePierroRegularizationFilter->SetInput(2, m_BackProjectionNormalizationFilter->GetOutput());\n        m_DePierroRegularizationFilter->Update();\n\n        m_DivideVolumeFilter->SetInput2(m_DePierroRegularizationFilter->GetOutput());\n        m_DivideVolumeFilter->Update();\n\n        // To start a new subset:\n        // - plug the output of the pipeline back into the Forward projection filter\n        // - set the input of the Back projection filter to zero\n        pimg = m_DivideVolumeFilter->GetOutput();\n        pimg->DisconnectPipeline();\n\n        m_ForwardProjectionFilter->SetInput(1, pimg);\n        m_DePierroRegularizationFilter->SetInput(0, pimg);\n        m_MultiplyFilter->SetInput2(pimg);\n        m_BackProjectionFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n        m_BackProjectionNormalizationFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n\n        currentSubset++;\n        projectionsProcessedInSubset = 0;\n      }\n      // Backproject in the same image otherwise.\n      else\n      {\n        pimg = m_BackProjectionFilter->GetOutput();\n        pimg->DisconnectPipeline();\n        m_BackProjectionFilter->SetInput(0, pimg);\n        if (iter == 0 || !m_StoreNormalizationImages)\n        {\n          norm = m_BackProjectionNormalizationFilter->GetOutput();\n          norm->DisconnectPipeline();\n          m_BackProjectionNormalizationFilter->SetInput(0, norm);\n        }\n      }\n    }\n    this->GraftOutput(pimg);\n    iterationReporter.CompletedStep();\n  }\n  vectorNorm.clear();\n}\n\n} // end namespace rtk\n\n#endif // rtkOSEMConeBeamReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkOraGeometryReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOraGeometryReader_h\n#define rtkOraGeometryReader_h\n\n#include <itkLightProcessObject.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class OraGeometryReader\n *\n * Creates a 3D circular geometry from an ora (medPhoton) dataset.\n *\n * \\test rtkoratest\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT OraGeometryReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(OraGeometryReader);\n\n  /** Standard type alias */\n  using Self = OraGeometryReader;\n  using Superclass = itk::LightProcessObject;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using PointType = GeometryType::PointType;\n  using Matrix3x3Type = GeometryType::Matrix3x3Type;\n  using VectorType = GeometryType::VectorType;\n  using MarginVectorType = itk::Vector<double, 4>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(OraGeometryReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Get the pointer to the generated geometry object. */\n  itkGetModifiableObjectMacro(Geometry, GeometryType);\n\n  /** Some convenient type alias. */\n  using FileNamesContainer = std::vector<std::string>;\n\n  /** Set the vector of strings that contains the projection file names. Files\n   * are processed in sequential order. */\n  void\n  SetProjectionsFileNames(const FileNamesContainer & name)\n  {\n    if (m_ProjectionsFileNames != name)\n    {\n      m_ProjectionsFileNames = name;\n      this->Modified();\n    }\n  }\n  const FileNamesContainer &\n  GetProjectionsFileNames() const\n  {\n    return m_ProjectionsFileNames;\n  }\n\n  /** Collimation margin: adds a small margin to the collimation edge to remove\n   * collimator shadow. A positive value means less collimation. Default is 0.\n   * The order is uinf, usup, vinf, vsup.\n   * */\n  itkGetMacro(CollimationMargin, MarginVectorType);\n  itkSetMacro(CollimationMargin, MarginVectorType);\n\n  /** Selected OptiTrack object ID. Default is -1, i.e., do not use the\n   * OptiTrack object ID. * */\n  itkGetMacro(OptiTrackObjectID, int);\n  itkSetMacro(OptiTrackObjectID, int);\n\n\nprotected:\n  OraGeometryReader()\n    : m_Geometry(nullptr)\n    , m_CollimationMargin(0.) {};\n\n  ~OraGeometryReader() override = default;\n\nprivate:\n  void\n  GenerateData() override;\n\n  GeometryType::Pointer m_Geometry;\n  FileNamesContainer    m_ProjectionsFileNames;\n  MarginVectorType      m_CollimationMargin;\n  int                   m_OptiTrackObjectID{ -1 };\n};\n\n} // namespace rtk\n\n#endif // rtkOraGeometryReader_h\n"
  },
  {
    "path": "include/rtkOraImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOraImageIO_h\n#define rtkOraImageIO_h\n\n// This is done to avoid any interference with zlib\n#ifdef OF\n#  undef OF\n#endif\n\n#include <itkMetaImageIO.h>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class OraImageIO\n * \\brief Class for reading Ora Image file format\n *\n * The ora image file format is used by medPhoton, extension of the header file\n * is ora.xml which points to a mhd and a raw files.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT OraImageIO : public itk::MetaImageIO\n{\npublic:\n  /** Standard class type alias. */\n  using Self = OraImageIO;\n  using Superclass = itk::MetaImageIO;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(OraImageIO);\n\n  /*-------- This part of the interface deals with reading data. ------ */\n\n  /** Determine the file type. Returns true if this ImageIO can read the\n   * file specified. */\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n\n  /** Set the spacing and dimension information for the set filename. */\n  void\n  ReadImageInformation() override;\n\n  /** Reads the data from disk into the memory buffer provided. */\n  void\n  Read(void * buffer) override;\n\n  bool\n  CanWriteFile(const char * filename) override;\n\nprotected:\n  std::string m_MetaFileName;\n}; // end class OraImageIO\n} // namespace rtk\n\n#endif /* end #define rtkOraImageIO_h */\n"
  },
  {
    "path": "include/rtkOraImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOraImageIOFactory_h\n#define rtkOraImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkOraImageIO.h\"\n\n// itk include\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class OraImageIOFactory\n * \\brief ITK factory for Ora file I/O.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT OraImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(OraImageIOFactory);\n\n  /** Standard class type alias. */\n  using Self = OraImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"Ora ImageIO Factory, allows the loading of Ora images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(OraImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\nprotected:\n  OraImageIOFactory();\n  ~OraImageIOFactory() override = default;\n  using myProductType = OraImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif /* end #define rtkOraImageIOFactory_h */\n"
  },
  {
    "path": "include/rtkOraLookupTableImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOraLookupTableImageFilter_h\n#define rtkOraLookupTableImageFilter_h\n\n#include \"rtkLookupTableImageFilter.h\"\n#include <itkNumericTraits.h>\n\nnamespace rtk\n{\n\n/** \\class OraLookupTableImageFilter\n * \\brief Lookup table for Ora data.\n *\n * The lookup table uses the slope and intercept from the meta information to\n * create a linear lookup table. The log is taken depending on the flag\n * ComputeLineIntegral.\n *\n * \\test rtkoratest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TOutputImage>\nclass ITK_TEMPLATE_EXPORT OraLookupTableImageFilter\n  : public LookupTableImageFilter<itk::Image<unsigned short, TOutputImage::ImageDimension>, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(OraLookupTableImageFilter);\n\n  /** Standard class type alias. */\n  using Self = OraLookupTableImageFilter;\n  using Superclass = LookupTableImageFilter<itk::Image<unsigned short, TOutputImage::ImageDimension>, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using InputImagePixelType = unsigned short;\n  using OutputImagePixelType = typename TOutputImage::PixelType;\n  using LookupTableType = typename Superclass::FunctorType::LookupTableType;\n  using FileNamesContainer = std::vector<std::string>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(OraLookupTableImageFilter);\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  /** Convert the projection data to line integrals after pre-processing.\n  ** Default is on. */\n  itkSetMacro(ComputeLineIntegral, bool);\n  itkGetConstMacro(ComputeLineIntegral, bool);\n  itkBooleanMacro(ComputeLineIntegral);\n\n  /** Set the vector of strings that contains the file names. Files\n   * are processed in sequential order. */\n  void\n  SetFileNames(const FileNamesContainer & name)\n  {\n    if (m_FileNames != name)\n    {\n      m_FileNames = name;\n      this->Modified();\n    }\n  }\n  const FileNamesContainer &\n  GetFileNames() const\n  {\n    return m_FileNames;\n  }\n\nprotected:\n  OraLookupTableImageFilter() = default;\n  ~OraLookupTableImageFilter() override = default;\n\nprivate:\n  bool m_ComputeLineIntegral{ true };\n\n  /** A list of filenames to be processed. */\n  FileNamesContainer m_FileNames;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkOraLookupTableImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkOraLookupTableImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOraLookupTableImageFilter_hxx\n#define rtkOraLookupTableImageFilter_hxx\n\n\n#include <itkImageIOBase.h>\n#include <itkImageIOFactory.h>\n#include <itkMetaDataObject.h>\n\nnamespace rtk\n{\n\ntemplate <class TOutputImage>\nvoid\nOraLookupTableImageFilter<TOutputImage>::BeforeThreadedGenerateData()\n{\n  // Create the lut\n  auto                               lut = LookupTableType::New();\n  typename LookupTableType::SizeType size;\n  size[0] = itk::NumericTraits<InputImagePixelType>::max() - itk::NumericTraits<InputImagePixelType>::min() + 1;\n  lut->SetRegions(size);\n  lut->Allocate();\n\n  // Read meta data dictionary from file\n  int                       fileIdx = this->GetOutput()->GetRequestedRegion().GetIndex()[2];\n  itk::ImageIOBase::Pointer reader;\n  reader =\n    itk::ImageIOFactory::CreateImageIO(m_FileNames[fileIdx].c_str(), itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n  if (!reader)\n  {\n    itkExceptionMacro(\"Error reading file \" << m_FileNames[fileIdx]);\n  }\n  reader->SetFileName(m_FileNames[fileIdx].c_str());\n  reader->ReadImageInformation();\n  const itk::MetaDataDictionary & dic = reader->GetMetaDataDictionary();\n\n  // Retrieve and set slope / intercept\n  double slope = 1.;\n  using MetaDataDoubleType = itk::MetaDataObject<double>;\n  const MetaDataDoubleType * slopeMeta = dynamic_cast<const MetaDataDoubleType *>(dic[\"rescale_slope\"]);\n  if (slopeMeta != nullptr)\n  {\n    slope = slopeMeta->GetMetaDataObjectValue();\n  }\n\n  double                     intercept = 0.;\n  const MetaDataDoubleType * interceptMeta = dynamic_cast<const MetaDataDoubleType *>(dic[\"rescale_intercept\"]);\n  if (interceptMeta != nullptr)\n  {\n    intercept = interceptMeta->GetMetaDataObjectValue();\n  }\n\n  // Iterate and set lut\n  itk::ImageRegionIteratorWithIndex<LookupTableType> it(lut, lut->GetBufferedRegion());\n  it.GoToBegin();\n  if (m_ComputeLineIntegral)\n  {\n    int    negidx = itk::Math::Floor<int, double>(itk::Math::floor(-intercept / slope));\n    double negval = -1. * std::log(slope * (negidx + 1) + intercept);\n    while (!it.IsAtEnd() && (int)it.GetIndex()[0] <= negidx)\n    {\n      it.Set(negval);\n      ++it;\n    }\n    while (!it.IsAtEnd())\n    {\n      it.Set(-1. * std::log(slope * it.GetIndex()[0] + intercept));\n      ++it;\n    }\n  }\n  else\n  {\n    while (!it.IsAtEnd())\n    {\n      it.Set(slope * it.GetIndex()[0] + intercept);\n      ++it;\n    }\n  }\n  this->SetLookupTable(lut);\n  Superclass::BeforeThreadedGenerateData(); // Update the LUT\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkOraXMLFileReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOraXMLFileReader_h\n#define rtkOraXMLFileReader_h\n\n#include <itkXMLFile.h>\n#include <itkMetaDataDictionary.h>\n#include <itkMetaDataObject.h>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class OraXMLFileReader\n *\n * Reads the XML-format file written by a medPhoton scanner\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT OraXMLFileReader : public itk::XMLReader<itk::MetaDataDictionary>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(OraXMLFileReader);\n\n  /** Standard type alias */\n  using Self = OraXMLFileReader;\n  using Superclass = itk::XMLReader<itk::MetaDataDictionary>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(OraXMLFileReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Determine if a file can be read */\n  int\n  CanReadFile(const char * name) override;\n\nprotected:\n  OraXMLFileReader();\n  ~OraXMLFileReader() override = default;\n\n  void\n  StartElement(const char * name, const char ** atts) override;\n\n  void\n  EndElement(const char * name) override;\n\n  void\n  CharacterDataHandler(const char * inData, int inLength) override;\n\n  void\n  EncapsulatePoint(const char * metaName, const char * name);\n  void\n  EncapsulateMatrix3x3(const char * metaName, const char * name);\n  void\n  EncapsulateDouble(const char * metaName, const char * name);\n  template <typename TValue>\n  void\n  EncapsulateVector(const char * metaName, const char * name);\n  void\n  EncapsulateString(const char * metaName, const char * name);\n\nprivate:\n  itk::MetaDataDictionary m_Dictionary;\n  std::string             m_CurCharacterData;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkParkerShortScanImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkParkerShortScanImageFilter_h\n#define rtkParkerShortScanImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class ParkerShortScanImageFilter\n *\n * Weighting of image projections to handle short-scans\n * in tomography reconstruction. Based on [Parker, Med Phys, 1982].\n * Class implements a fix to typo in equation (12) of Parker as seen\n * in book \"Principles of computerized tomographic imaging\" by Kak and Slaney\n *\n * \\test rtkshortscantest.cxx, rtkshortscancompcudatest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT ParkerShortScanImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ParkerShortScanImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ParkerShortScanImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n  using WeightImageType = itk::Image<typename TOutputImage::PixelType, 1>;\n\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using GeometryPointer = GeometryType::Pointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(ParkerShortScanImageFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, GeometryType);\n  itkSetObjectMacro(Geometry, GeometryType);\n\n  /** Get / Set the angular gap threshold above which a short scan is detected. */\n  itkGetMacro(AngularGapThreshold, double);\n  itkSetMacro(AngularGapThreshold, double);\n\nprotected:\n  ParkerShortScanImageFilter() = default;\n  ~ParkerShortScanImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  /** Actual angular gap in the projections */\n  double m_Delta;\n\n  /** First angle of the short scan */\n  double m_FirstAngle;\n\n  /** Internal variable indicating whether this scan is short */\n  bool m_IsShortScan{ false };\n\nprivate:\n  /** RTK geometry object */\n  GeometryPointer m_Geometry;\n\n  /** Superior and inferior position of the detector along the weighting direction, i.e. x.\n   * The computed value account for the x projection offset of the geometry.\n   */\n  double m_InferiorCorner;\n  double m_SuperiorCorner;\n\n  /** Minimum angular gap to automatically detect a short scan. Defaults is pi/9 radians. */\n  double m_AngularGapThreshold{ itk::Math::pi / 9 };\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkParkerShortScanImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkParkerShortScanImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkParkerShortScanImageFilter_hxx\n#define rtkParkerShortScanImageFilter_hxx\n\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkMacro.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nParkerShortScanImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nParkerShortScanImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get angular gaps and max gap\n  std::vector<double> angularGaps = m_Geometry->GetAngularGapsWithNext(m_Geometry->GetGantryAngles());\n  int                 nProj = angularGaps.size();\n  int                 maxAngularGapPos = 0;\n  for (int iProj = 1; iProj < nProj; iProj++)\n    if (angularGaps[iProj] > angularGaps[maxAngularGapPos])\n      maxAngularGapPos = iProj;\n\n  // Not a short scan if less than m_AngularGapThreshold degrees max gap, => nothing to do\n  // FIXME: do nothing in parallel geometry, currently handled with a trick in the geometry object\n  if (m_Geometry->GetSourceToDetectorDistances()[0] == 0. || angularGaps[maxAngularGapPos] < m_AngularGapThreshold)\n  {\n    m_IsShortScan = false;\n    return;\n  }\n  m_IsShortScan = true;\n\n  const std::vector<double>            rotationAngles = m_Geometry->GetGantryAngles();\n  const std::map<double, unsigned int> sortedAngles = m_Geometry->GetUniqueSortedAngles(m_Geometry->GetGantryAngles());\n\n  // Compute delta between first and last angle where there is weighting required\n  std::map<double, unsigned int>::const_iterator itLastAngle;\n  itLastAngle = sortedAngles.find(rotationAngles[maxAngularGapPos]);\n  auto itFirstAngle = itLastAngle;\n  itFirstAngle = (++itFirstAngle == sortedAngles.end()) ? sortedAngles.begin() : itFirstAngle;\n  m_FirstAngle = itFirstAngle->first;\n  double lastAngle = itLastAngle->first;\n  if (lastAngle < m_FirstAngle)\n  {\n    lastAngle += 2 * itk::Math::pi;\n  }\n  // Delta\n  m_Delta = 0.5 * (lastAngle - m_FirstAngle - itk::Math::pi);\n  m_Delta = m_Delta - 2 * itk::Math::pi * floor(m_Delta / (2 * itk::Math::pi)); // between -2*PI and 2*PI\n\n  // Pre-compute the two corners of the projection images\n  typename TInputImage::IndexType id = this->GetInput()->GetLargestPossibleRegion().GetIndex();\n  typename TInputImage::SizeType  sz = this->GetInput()->GetLargestPossibleRegion().GetSize();\n  typename TInputImage::SizeType  ones;\n  ones.Fill(1);\n  typename TInputImage::PointType corner1, corner2;\n  this->GetInput()->TransformIndexToPhysicalPoint(id, corner1);\n  this->GetInput()->TransformIndexToPhysicalPoint(id - ones + sz, corner2);\n\n  // Go over projection images\n  auto lpr = this->GetOutput()->GetLargestPossibleRegion();\n  for (unsigned int k = 0; k < lpr.GetSize(2); k++)\n  {\n    double sox = m_Geometry->GetSourceOffsetsX()[k];\n    double sid = m_Geometry->GetSourceToIsocenterDistances()[k];\n    double invsid = 1. / sqrt(sid * sid + sox * sox);\n\n    // Check that Parker weighting is relevant for this projection\n    double halfDetectorWidth1 = itk::Math::abs(m_Geometry->ToUntiltedCoordinateAtIsocenter(k, corner1[0]));\n    double halfDetectorWidth2 = itk::Math::abs(m_Geometry->ToUntiltedCoordinateAtIsocenter(k, corner2[0]));\n    double halfDetectorWidth = std::min(halfDetectorWidth1, halfDetectorWidth2);\n    if (m_Delta < atan(halfDetectorWidth * invsid))\n    {\n      itkWarningMacro(<< \"You do not have enough data for proper Parker weighting (short scan)\"\n                      << \" according to projection #\" << k << \". Delta is \" << m_Delta * 180. / itk::Math::pi\n                      << \" degrees and should be more than half the beam angle, i.e. \"\n                      << atan(halfDetectorWidth * invsid) * 180. / itk::Math::pi << \" degrees.\");\n      return;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nParkerShortScanImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Input / ouput iterators\n  itk::ImageRegionConstIterator<InputImageType> itIn(this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<OutputImageType>     itOut(this->GetOutput(), outputRegionForThread);\n  itIn.GoToBegin();\n  itOut.GoToBegin();\n\n  // Not a short scan if less than m_AngularGapThreshold degrees max gap, => nothing to do\n  // FIXME: do nothing in parallel geometry, currently handled with a trick in the geometry object\n  if (!m_IsShortScan)\n  {\n    if (this->GetInput() != this->GetOutput()) // If not in place, copy is\n                                               // required\n    {\n      while (!itIn.IsAtEnd())\n      {\n        itOut.Set(itIn.Get());\n        ++itIn;\n        ++itOut;\n      }\n    }\n    return;\n  }\n\n  // Weight image parameters\n  typename WeightImageType::RegionType  region;\n  typename WeightImageType::SpacingType spacing;\n  typename WeightImageType::PointType   origin;\n  region.SetSize(0, outputRegionForThread.GetSize(0));\n  region.SetIndex(0, outputRegionForThread.GetIndex(0));\n  spacing[0] = this->GetInput()->GetSpacing()[0];\n  origin[0] = this->GetInput()->GetOrigin()[0];\n\n  // Create one line of weights\n  auto weights = WeightImageType::New();\n  weights->SetSpacing(spacing);\n  weights->SetOrigin(origin);\n  weights->SetRegions(region);\n  weights->Allocate();\n  typename itk::ImageRegionIteratorWithIndex<WeightImageType> itWeights(weights, weights->GetLargestPossibleRegion());\n\n  const std::vector<double> rotationAngles = m_Geometry->GetGantryAngles();\n\n  // Go over projection images\n  for (unsigned int k = 0; k < outputRegionForThread.GetSize(2); k++)\n  {\n    double sox = m_Geometry->GetSourceOffsetsX()[itIn.GetIndex()[2]];\n    double sid = m_Geometry->GetSourceToIsocenterDistances()[itIn.GetIndex()[2]];\n    double invsid = 1. / sqrt(sid * sid + sox * sox);\n\n    // Prepare weights for current slice (depends on ProjectionOffsetsX)\n    typename WeightImageType::PointType point;\n    weights->TransformIndexToPhysicalPoint(itWeights.GetIndex(), point);\n\n    // Parker's article assumes that the scan starts at 0, convert projection\n    // angle accordingly\n    double beta = rotationAngles[itIn.GetIndex()[2]];\n    beta = beta - m_FirstAngle;\n    if (beta < 0)\n      beta += 2 * itk::Math::pi;\n\n    itWeights.GoToBegin();\n    while (!itWeights.IsAtEnd())\n    {\n      const double l = m_Geometry->ToUntiltedCoordinateAtIsocenter(itIn.GetIndex()[2], point[0]);\n      double       alpha = atan(-1 * l * invsid);\n      const double pi = itk::Math::pi;\n      if (beta <= 2 * m_Delta - 2 * alpha)\n        itWeights.Set(2. * pow(sin((pi * beta) / (4 * (m_Delta - alpha))), 2.));\n      else if (beta <= pi - 2 * alpha)\n        itWeights.Set(2.);\n      else if (beta <= pi + 2 * m_Delta)\n        // Denominator fix to a typo in equation (12) of Parker's article.\n        itWeights.Set(2. * pow(sin((pi * (pi + 2 * m_Delta - beta)) / (4 * (m_Delta + alpha))), 2.));\n      else\n        itWeights.Set(0.);\n\n      ++itWeights;\n      point[0] += spacing[0];\n    }\n\n    // Multiply each line of the current slice\n    for (unsigned int j = 0; j < outputRegionForThread.GetSize(1); j++)\n    {\n      itWeights.GoToBegin();\n      while (!itWeights.IsAtEnd())\n      {\n        itOut.Set(itIn.Get() * itWeights.Get());\n        ++itWeights;\n        ++itIn;\n        ++itOut;\n      }\n    }\n  }\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkPhaseGatingImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkPhaseGatingImageFilter_h\n#define rtkPhaseGatingImageFilter_h\n\n#include \"rtkSubSelectImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkPhaseReader.h\"\n\nnamespace rtk\n{\n/** \\class PhaseGatingImageFilter\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT PhaseGatingImageFilter : public SubSelectImageFilter<ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(PhaseGatingImageFilter);\n\n  /** Standard class type alias. */\n  using Self = PhaseGatingImageFilter;\n  using Superclass = SubSelectImageFilter<ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(PhaseGatingImageFilter);\n\n  itkSetMacro(PhasesFileName, std::string);\n  itkGetMacro(PhasesFileName, std::string);\n\n  itkSetMacro(GatingWindowWidth, float);\n  itkGetMacro(GatingWindowWidth, float);\n\n  itkSetMacro(GatingWindowCenter, float);\n  itkGetMacro(GatingWindowCenter, float);\n\n  itkSetMacro(GatingWindowShape, int);\n  itkGetMacro(GatingWindowShape, int);\n\n  std::vector<float>\n  GetGatingWeights();\n  std::vector<float>\n  GetGatingWeightsOnSelectedProjections();\n\nprotected:\n  PhaseGatingImageFilter();\n  ~PhaseGatingImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  SelectProjections();\n\n  void\n  ComputeWeights();\n\n  void\n  SetPhases(std::vector<float> phases);\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  rtk::PhaseReader::Pointer m_PhaseReader;\n\n  /** Member variables */\n  std::vector<float> m_GatingWeights;\n  std::vector<float> m_GatingWeightsOnSelectedProjections;\n  std::vector<float> m_Phases;\n  float              m_GatingWindowWidth;\n  float              m_GatingWindowCenter;\n  int                m_GatingWindowShape;\n  std::string        m_PhasesFileName;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkPhaseGatingImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkPhaseGatingImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkPhaseGatingImageFilter_hxx\n#define rtkPhaseGatingImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n\n#include \"math.h\"\n\nnamespace rtk\n{\n\ntemplate <typename ProjectionStackType>\nPhaseGatingImageFilter<ProjectionStackType>::PhaseGatingImageFilter()\n{\n  m_PhaseReader = PhaseReader::New();\n\n  // Set default parameters\n  m_GatingWindowWidth = 1;\n  m_GatingWindowShape = 0;\n  m_GatingWindowCenter = 0.5;\n}\n\ntemplate <typename ProjectionStackType>\nvoid\nPhaseGatingImageFilter<ProjectionStackType>::ComputeWeights()\n{\n  m_GatingWeights.clear();\n  float distance = NAN;\n\n  // Compute the gating weights\n  for (float m_Phase : m_Phases)\n  {\n    distance =\n      std::min(itk::Math::abs(m_GatingWindowCenter - 1 - m_Phase), itk::Math::abs(m_GatingWindowCenter - m_Phase));\n    distance = std::min(distance, itk::Math::abs(m_GatingWindowCenter + 1.f - m_Phase));\n\n    switch (m_GatingWindowShape)\n    {\n      case (0): // Rectangular\n        if (2 * distance <= m_GatingWindowWidth)\n          m_GatingWeights.push_back(1);\n        else\n          m_GatingWeights.push_back(0);\n        break;\n      case (1): // Triangular\n        m_GatingWeights.push_back(std::max(1.f - 2.f * distance / m_GatingWindowWidth, 0.f));\n        break;\n      default:\n        std::cerr << \"Unhandled gating window shape value.\" << std::endl;\n    }\n  }\n}\n\ntemplate <typename ProjectionStackType>\nvoid\nPhaseGatingImageFilter<ProjectionStackType>::GenerateOutputInformation()\n{\n  m_PhaseReader->SetFileName(m_PhasesFileName);\n  m_PhaseReader->SetFieldDelimiterCharacter(';');\n  m_PhaseReader->HasRowHeadersOff();\n  m_PhaseReader->HasColumnHeadersOff();\n  m_PhaseReader->Update();\n  SetPhases(m_PhaseReader->GetOutput());\n  ComputeWeights();\n  SelectProjections();\n\n  Superclass::GenerateOutputInformation();\n}\n\ntemplate <typename ProjectionStackType>\nvoid\nPhaseGatingImageFilter<ProjectionStackType>::SetPhases(std::vector<float> phases)\n{\n  m_Phases = phases;\n}\n\ntemplate <typename ProjectionStackType>\nstd::vector<float>\nPhaseGatingImageFilter<ProjectionStackType>::GetGatingWeights()\n{\n  return m_GatingWeights;\n}\n\ntemplate <typename ProjectionStackType>\nstd::vector<float>\nPhaseGatingImageFilter<ProjectionStackType>::GetGatingWeightsOnSelectedProjections()\n{\n  return m_GatingWeightsOnSelectedProjections;\n}\n\ntemplate <typename ProjectionStackType>\nvoid\nPhaseGatingImageFilter<ProjectionStackType>::SelectProjections()\n{\n  float eps = 0.0001;\n  this->m_SelectedProjections.resize(m_GatingWeights.size(), false);\n  this->m_NbSelectedProjs = 0;\n  m_GatingWeightsOnSelectedProjections.clear();\n\n  // Select only those projections that have non-zero weights to speed up computing\n  for (unsigned int i = 0; i < m_GatingWeights.size(); i++)\n  {\n    if (m_GatingWeights[i] > eps)\n    {\n      this->m_SelectedProjections[i] = true;\n      this->m_NbSelectedProjs++;\n      m_GatingWeightsOnSelectedProjections.push_back(m_GatingWeights[i]);\n    }\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkPhaseReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkPhaseReader_h\n#define rtkPhaseReader_h\n\n#include \"RTKExport.h\"\n#include <itkCSVFileReaderBase.h>\n\nnamespace rtk\n{\n\n/** \\class PhaseReader\n *\n * \\brief Parses csv file containing the cardiac or respiratory phases of each projection.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT PhaseReader : public itk::CSVFileReaderBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(PhaseReader);\n\n  /** Standard class type alias */\n  using Self = PhaseReader;\n  using Superclass = CSVFileReaderBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods) */\n  itkOverrideGetNameOfClassMacro(PhaseReader);\n\n  /** The value type of the dataset. */\n  using ValueType = float;\n\n  /** Parses the data from the file. Gets the phases of the projections\n   * into a vector, then generate an Array2D object containing the interpolation weights  */\n  void\n  Parse() override;\n\n  /** Aliased to the Parse() method to be consistent with the rest of the\n   * pipeline. */\n  virtual void\n  Update();\n\n  /** Aliased to the GetDataFrameObject() method to be consistent with the\n   *  rest of the pipeline */\n  virtual std::vector<float>\n  GetOutput();\n\nprotected:\n  PhaseReader();\n  ~PhaseReader() override = default;\n\n  /** Print the reader. */\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\nprivate:\n  std::vector<float> m_Phases;\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkPhasesToInterpolationWeights.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkPhasesToInterpolationWeights_h\n#define rtkPhasesToInterpolationWeights_h\n\n#include \"RTKExport.h\"\n#include \"itkCSVFileReaderBase.h\"\n#include \"itkArray2D.h\"\n\nnamespace rtk\n{\n\n/** \\class PhasesToInterpolationWeights\n * \\brief Parses csv file containing the cardiac or respiratory phases of each projection, and generates interpolation\n * weights for 4D reconstruction.\n *\n * Useful for 4D reconstruction of beating heart or breathing thorax\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\nclass RTK_EXPORT PhasesToInterpolationWeights : public itk::CSVFileReaderBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(PhasesToInterpolationWeights);\n\n  /** Standard class type alias */\n  using Self = PhasesToInterpolationWeights;\n  using Superclass = CSVFileReaderBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods) */\n  itkOverrideGetNameOfClassMacro(PhasesToInterpolationWeights);\n\n  /** DataFrame Object types */\n  using Array2DType = itk::Array2D<float>;\n\n  /** The value type of the dataset. */\n  using ValueType = float;\n\n  //  /** This method can be used to get the data frame object once the data from\n  //  * the file has been parsed. */\n  //  itkGetModifiableObjectMacro(Array2D,Array2DType);\n\n  /** Parses the data from the file. Gets the phases of the projections\n   * into a vector, then generate an Array2D object containing the interpolation weights  */\n  void\n  Parse() override;\n\n  /** Aliased to the Parse() method to be consistent with the rest of the\n   * pipeline. */\n  virtual void\n  Update();\n\n  /** Aliased to the GetDataFrameObject() method to be consistent with the\n   *  rest of the pipeline */\n  virtual Array2DType\n  GetOutput();\n\n  /** Configure the filter to use uneven temporal spacing (finer temporal resolution during systole) */\n  itkSetMacro(UnevenTemporalSpacing, bool);\n  itkGetMacro(UnevenTemporalSpacing, bool);\n\n  /** Configure the filter to use uneven temporal spacing (finer temporal resolution during systole) */\n  itkSetMacro(NumberOfReconstructedFrames, int);\n  itkGetMacro(NumberOfReconstructedFrames, int);\n\n  /** Set/Get for a list of booleans indicating whether or not each projection must be selected */\n  void\n  SetSelectedProjections(std::vector<bool> sprojs);\n  itkGetMacro(SelectedProjections, std::vector<bool>);\n\nprotected:\n  PhasesToInterpolationWeights();\n  ~PhasesToInterpolationWeights() override = default;\n\n  /** Print the reader. */\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\nprivate:\n  Array2DType       m_Array2D;\n  int               m_NumberOfReconstructedFrames;\n  bool              m_UnevenTemporalSpacing;\n  std::vector<bool> m_SelectedProjections;\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkPolynomialGainCorrectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkPolynomialGainCorrectionImageFilter_h\n#define rtkPolynomialGainCorrectionImageFilter_h\n\n#include <itkImageToImageFilter.h>\n\n#include <vector>\n\n#include \"rtkMacro.h\"\n\n/** \\class PolynomialGainCorrection\n * \\brief Pixel-wize polynomial gain calibration\n *\n * Based on 'An improved method for flat-field correction of flat panel x-ray detector'\n *          Kwan, Med. Phys 33 (2), 2006\n * Only allow unsigned short as input format\n *\n * \\author Sebastien Brousmiche\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT PolynomialGainCorrectionImageFilter\n  : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(PolynomialGainCorrectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = PolynomialGainCorrectionImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n  using InputImageRegionType = typename InputImageType::RegionType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using VectorType = typename std::vector<float>;\n  using OutputSizeType = typename OutputImageType::SizeType;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(PolynomialGainCorrectionImageFilter);\n\n  /** Dark image, 2D same size of one input projection */\n  void\n  SetDarkImage(InputImageType * darkImage);\n\n  /** Weights, matrix A from reference paper\n   *  3D image: 2D x order. */\n  void\n  SetGainCoefficients(OutputImageType * gain);\n\n  /* if K==0, the filter is bypassed */\n  itkSetMacro(K, float);\n  itkGetMacro(K, float);\n\nprotected:\n  PolynomialGainCorrectionImageFilter();\n  ~PolynomialGainCorrectionImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  bool               m_MapsLoaded{ false }; // True if gain maps loaded\n  int                m_VModelOrder{ 1 };    // Polynomial correction order\n  float              m_K{ 1.0f };           // Scaling constant, a 0 means no correction\n  VectorType         m_PowerLut;            // Vector containing I^n\n  InputImagePointer  m_DarkImage;           // Dark image\n  OutputImagePointer m_GainImage;           // Gain coefficients (A matrix)\n  OutputSizeType     m_GainSize;            // Gain map size\n}; // end of class\n\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkPolynomialGainCorrectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkPolynomialGainCorrectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkPolynomialGainCorrectionImageFilter_hxx\n#define rtkPolynomialGainCorrectionImageFilter_hxx\n\n\n#include <itkImageFileReader.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nPolynomialGainCorrectionImageFilter<TInputImage, TOutputImage>::PolynomialGainCorrectionImageFilter() = default;\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nPolynomialGainCorrectionImageFilter<TInputImage, TOutputImage>::SetDarkImage(InputImageType * darkImage)\n{\n  m_DarkImage = darkImage;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nPolynomialGainCorrectionImageFilter<TInputImage, TOutputImage>::SetGainCoefficients(OutputImageType * gain)\n{\n  m_GainImage = gain;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nPolynomialGainCorrectionImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  // get pointers to the input and output\n  InputImagePointer  inputPtr = const_cast<InputImageType *>(this->GetInput());\n  OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!outputPtr || !inputPtr)\n  {\n    return;\n  }\n\n  // Copy the meta data for this data type\n  outputPtr->SetSpacing(inputPtr->GetSpacing());\n  outputPtr->SetOrigin(inputPtr->GetOrigin());\n  outputPtr->SetDirection(inputPtr->GetDirection());\n  outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel());\n\n  InputImageRegionType outputLargestPossibleRegion;\n  outputLargestPossibleRegion = inputPtr->GetLargestPossibleRegion();\n  outputPtr->SetRegions(outputLargestPossibleRegion);\n\n  // TODO: Do something if input not unsigned 16-bits\n  // if (TInputImage::PixelType != USHORT)\n  //{\n  //    itkWarningMacro(<<\"Polynomial gain calibration only allow unsigned short pixel format as input\" );\n  //    m_K = 0.0; // To disable processing\n  //}\n\n  // TInputImage::PixelType\n  if (!m_MapsLoaded && m_K != 0.0)\n  {\n    m_GainSize = m_GainImage->GetLargestPossibleRegion().GetSize();\n\n    m_VModelOrder = m_GainSize[2];\n    m_MapsLoaded = true;\n\n    // Create power LUT: the values for the different orders for the same pixel value are close to each other\n    int npixValues = 65536; // Input values are 16-bit unsigned\n    for (int pid = 0; pid < npixValues; ++pid)\n    {\n      auto value = static_cast<float>(pid);\n      for (int order = 0; order < m_VModelOrder; ++order)\n      {\n        m_PowerLut.push_back(value);\n        value = value * value;\n      }\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nPolynomialGainCorrectionImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer  inputPtr = const_cast<InputImageType *>(this->GetInput());\n  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n    return;\n\n  InputImageRegionType inputRequestedRegion = outputPtr->GetLargestPossibleRegion();\n  inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()); // Because Largest region has been updated\n  inputPtr->SetRegions(inputRequestedRegion);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nPolynomialGainCorrectionImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  itk::ImageRegionConstIterator<InputImageType> itIn(this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<OutputImageType>     itOut(this->GetOutput(), outputRegionForThread);\n  itIn.GoToBegin();\n  itOut.GoToBegin();\n\n  // K==0 = no weighting requested\n  if (m_K == 0.)\n  {\n    while (!itIn.IsAtEnd())\n    {\n      itOut.Set(static_cast<typename TOutputImage::PixelType>(itIn.Get()));\n      ++itIn;\n      ++itOut;\n    }\n    return;\n  }\n\n  InputImageRegionType darkRegion = outputRegionForThread;\n  darkRegion.SetSize(2, 1);\n  darkRegion.SetIndex(2, 0);\n  itk::ImageRegionConstIterator<InputImageType> itDark(m_DarkImage, darkRegion);\n\n  // Get gain map buffer\n  const typename OutputImageType::PixelType * gainBuffer = m_GainImage->GetBufferPointer();\n\n  int startk = static_cast<int>(outputRegionForThread.GetIndex(2));\n  for (int k = startk; k < startk + static_cast<int>(outputRegionForThread.GetSize(2)); k++)\n  {\n    itDark.GoToBegin();\n\n    int startj = outputRegionForThread.GetIndex(1);\n    for (int j = startj; j < startj + static_cast<int>(outputRegionForThread.GetSize(1)); j++)\n    {\n      int starti = outputRegionForThread.GetIndex(0);\n      for (int i = starti; i < starti + static_cast<int>(outputRegionForThread.GetSize(0)); i++)\n      {\n        int darkx = static_cast<int>(itDark.Get());\n        int px = static_cast<int>(itIn.Get()) - darkx;\n        px = (px >= 0) ? px : 0;\n\n        float correctedValue = 0.f;\n        int   lutidx = px * m_VModelOrder;\n        for (int m = 0; m < m_VModelOrder; ++m)\n        {\n          int   gainidx = m * m_GainSize[1] * m_GainSize[0] + j * m_GainSize[0] + i;\n          float gainM = gainBuffer[gainidx];\n          correctedValue += gainM * m_PowerLut[lutidx + m];\n        }\n        correctedValue *= m_K;\n\n        itOut.Set(static_cast<typename TOutputImage::PixelType>(correctedValue));\n\n        ++itIn;\n        ++itOut;\n        ++itDark;\n      }\n    }\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkProgressCommands.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProgressCommands_h\n#define rtkProgressCommands_h\n\n#include <itkCommand.h>\n\nnamespace rtk\n{\n\n/** \\class ProgressCommand\n * \\brief Abstract superclass to all progress callbacks.\n * Derived classes must implement the Run() method.\n *\n * \\author Aurélien Coussat\n *\n * \\ingroup RTK\n *\n */\ntemplate <typename TCaller>\nclass ITK_TEMPLATE_EXPORT ProgressCommand : public itk::Command\n{\npublic:\n  /** Standard class typedefs. */\n  typedef ProgressCommand         Self;\n  typedef itk::Command            Superclass;\n  typedef itk::SmartPointer<Self> Pointer;\n\n  void\n  Execute(itk::Object * caller, const itk::EventObject & event) override\n  {\n    Execute((const itk::Object *)caller, event);\n  }\n\n  void\n  Execute(const itk::Object * caller, const itk::EventObject & event) override\n  {\n    const auto * cCaller = dynamic_cast<const TCaller *>(caller);\n    if (cCaller)\n    {\n      if (itk::EndEvent().CheckEvent(&event))\n      {\n        End(cCaller);\n        return;\n      }\n      if (itk::ProgressEvent().CheckEvent(&event))\n      {\n        Run(cCaller);\n      }\n    } // TODO fail when cast fails\n  }\n\n\nprotected:\n  /** Callback function to be redefined by derived classes. */\n  virtual void\n  Run(const TCaller * caller) = 0;\n\n  /** Callback function executed when filter concludes. */\n  virtual void\n  End(const TCaller * itkNotUsed(caller))\n  { /* Default implementation: do nothing */\n  }\n};\n\n/** \\class PercentageProgressCommand\n * \\brief Outputs every time a filter progresses by at least one percent.\n *\n * \\author Aurélien Coussat\n *\n * \\ingroup RTK\n *\n */\ntemplate <typename TCaller>\nclass ITK_TEMPLATE_EXPORT PercentageProgressCommand : public ProgressCommand<TCaller>\n{\npublic:\n  /** Standard class typedefs. */\n  typedef PercentageProgressCommand Self;\n  typedef ProgressCommand<TCaller>  Superclass;\n  typedef itk::SmartPointer<Self>   Pointer;\n  itkNewMacro(Self);\n\n  int percentage = -1;\n\nprotected:\n  void\n  Run(const TCaller * caller) override\n  {\n    int newPercentage = (int)(caller->GetProgress() * 100.);\n    if (newPercentage > percentage)\n    {\n      // TODO allow string personnalization?\n      std::cout << \"\\r\" << caller->GetNameOfClass() << \" \" << newPercentage << \"% completed.\" << std::flush;\n      percentage = newPercentage;\n    }\n  }\n\n  void\n  End(const TCaller * itkNotUsed(caller)) override\n  {\n    std::cout << std::endl; // new line when execution ends\n  }\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectGeometricPhantomImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectGeometricPhantomImageFilter_h\n#define rtkProjectGeometricPhantomImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include <itkAddImageFilter.h>\n#include \"rtkGeometricPhantom.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class ProjectGeometricPhantomImageFilter\n * \\brief Analytical projection a GeometricPhantom\n *\n * \\test rtkprojectgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT ProjectGeometricPhantomImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ProjectGeometricPhantomImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ProjectGeometricPhantomImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryConstPointer = typename GeometryType::ConstPointer;\n  using GeometricPhantomConstPointer = GeometricPhantom::ConstPointer;\n  using StringType = std::string;\n  using VectorType = ConvexShape::VectorType;\n  using RotationMatrixType = ConvexShape::RotationMatrixType;\n  using ScalarType = ConvexShape::ScalarType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ProjectGeometricPhantomImageFilter);\n\n  /** Get / Set the object pointer to the geometry. */\n  itkGetConstObjectMacro(GeometricPhantom, GeometricPhantom);\n  itkSetConstObjectMacro(GeometricPhantom, GeometricPhantom);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetConstObjectMacro(Geometry, GeometryType);\n  itkSetConstObjectMacro(Geometry, GeometryType);\n\n  /** Get/Set the phantom file path. */\n  itkSetMacro(ConfigFile, StringType);\n  itkGetMacro(ConfigFile, StringType);\n\n  /** Multiplicative scaling factor along each 3D component. */\n  itkSetMacro(PhantomScale, VectorType);\n  itkGetMacro(PhantomScale, VectorType);\n\n  /** Set isotropic scaling factor. */\n  virtual void\n  SetPhantomScale(const ScalarType _arg)\n  {\n    SetPhantomScale(VectorType(_arg));\n  }\n\n  /** Get / Set the spatial offset of the phantom relative to its center. The\n   * default value is (0, 0, 0). */\n  itkSetMacro(OriginOffset, VectorType);\n  itkGetMacro(OriginOffset, VectorType);\n\n  /** Get / Set a rotation matrix for the phantom. Default is identity. */\n  itkSetMacro(RotationMatrix, RotationMatrixType);\n  itkGetMacro(RotationMatrix, RotationMatrixType);\n\n  /** Add clipping plane to the object. The plane is defined by the equation\n   * dir * (x,y,z)' + pos = 0. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n  void\n  SetClipPlanes(const std::vector<VectorType> & dir, const std::vector<ScalarType> & pos);\n\nprotected:\n  ProjectGeometricPhantomImageFilter();\n  ~ProjectGeometricPhantomImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateData() override;\n\nprivate:\n  GeometricPhantomConstPointer m_GeometricPhantom;\n  GeometryConstPointer         m_Geometry;\n  StringType                   m_ConfigFile;\n  VectorType                   m_PhantomScale{ 1. };\n  VectorType                   m_OriginOffset{ 0. };\n  RotationMatrixType           m_RotationMatrix;\n  std::vector<VectorType>      m_PlaneDirections;\n  std::vector<ScalarType>      m_PlanePositions;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkProjectGeometricPhantomImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectGeometricPhantomImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectGeometricPhantomImageFilter_hxx\n#define rtkProjectGeometricPhantomImageFilter_hxx\n\n#include \"rtkForbildPhantomFileReader.h\"\n#include \"rtkRayConvexIntersectionImageFilter.h\"\n\n#include <iostream>\n#include <fstream>\n#include <sstream>\n#include <cstdio>\n#include <cstdlib>\n\nnamespace rtk\n{\ntemplate <class TInputImage, class TOutputImage>\nProjectGeometricPhantomImageFilter<TInputImage, TOutputImage>::ProjectGeometricPhantomImageFilter()\n{\n  m_RotationMatrix.SetIdentity();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nProjectGeometricPhantomImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nProjectGeometricPhantomImageFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  // Reading figure config file\n  if (!m_ConfigFile.empty())\n  {\n    auto reader = rtk::ForbildPhantomFileReader::New();\n    reader->SetFilename(m_ConfigFile);\n    reader->GenerateOutputInformation();\n    this->m_GeometricPhantom = reader->GetGeometricPhantom();\n  }\n\n  // Check that it's not empty\n  const GeometricPhantom::ConvexShapeVector & cov = m_GeometricPhantom->GetConvexShapes();\n  if (cov.empty())\n    itkExceptionMacro(<< \"Empty phantom\");\n\n  // Create one add filter per convex object\n  std::vector<typename itk::ImageSource<TOutputImage>::Pointer> projectors;\n  for (const auto & convexShape : cov)\n  {\n    ConvexShape::Pointer co = convexShape->Clone();\n    co->Rotate(m_RotationMatrix);\n    co->Translate(m_OriginOffset);\n    co->Rescale(m_PhantomScale);\n    for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n      co->AddClipPlane(m_PlaneDirections[i], m_PlanePositions[i]);\n\n    if (!projectors.empty())\n    {\n      using RCOIType = RayConvexIntersectionImageFilter<TOutputImage, TOutputImage>;\n      auto rcoi = RCOIType::New();\n      rcoi->SetInput(projectors.back()->GetOutput());\n      rcoi->SetGeometry(this->GetGeometry());\n      rcoi->SetConvexShape(co);\n      projectors.push_back(rcoi.GetPointer());\n    }\n    else\n    {\n      using RCOIType = RayConvexIntersectionImageFilter<TInputImage, TOutputImage>;\n      auto rcoi = RCOIType::New();\n      rcoi->SetInput(this->GetInput());\n      rcoi->SetGeometry(this->GetGeometry());\n      rcoi->SetConvexShape(co);\n      projectors.push_back(rcoi.GetPointer());\n    }\n  }\n\n  projectors.back()->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  projectors.back()->Update();\n  this->GraftOutput(projectors.back()->GetOutput());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nProjectGeometricPhantomImageFilter<TInputImage, TOutputImage>::AddClipPlane(const VectorType & dir,\n                                                                            const ScalarType & pos)\n{\n  for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n  {\n    if (dir == m_PlaneDirections[i] && pos == m_PlanePositions[i])\n      return;\n  }\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nProjectGeometricPhantomImageFilter<TInputImage, TOutputImage>::SetClipPlanes(const std::vector<VectorType> & dir,\n                                                                             const std::vector<ScalarType> & pos)\n{\n  m_PlaneDirections = dir;\n  m_PlanePositions = pos;\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionGeometry.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionGeometry_h\n#define rtkProjectionGeometry_h\n\n#include <itkImageBase.h>\n\n#include <vector>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class ProjectionGeometry\n * \\brief A templated class holding a vector of M x (M+1) matrices\n *\n * This class contains a vector of projection matrices.\n * Each matrix corresponds to a different position of a\n * projector, e.g. a detector and an x-ray source.\n * The class is meant to be specialized for specific geometries.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Geometry\n */\ntemplate <unsigned int TDimension = 3>\nclass ITK_TEMPLATE_EXPORT ProjectionGeometry : public itk::DataObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ProjectionGeometry);\n\n  using Self = ProjectionGeometry<TDimension>;\n  using Superclass = itk::DataObject;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Convenient type alias */\n  using SizeType = typename itk::ImageBase<TDimension>::SizeType;\n  using PointType = typename itk::ImageBase<TDimension>::PointType;\n  using SpacingType = typename itk::ImageBase<TDimension>::SpacingType;\n\n  using MatrixType = typename itk::Matrix<double, TDimension, TDimension + 1>;\n\n  /** Get the vector of projection matrices.\n   * A projection matrix is a M x (M+1) homogeneous matrix.\n   * The multiplication of a M-D point in physical coordinates\n   * with the i-th matrix provides the physical coordinate on\n   * the i-th projection.\n   */\n  const std::vector<MatrixType> &\n  GetMatrices() const\n  {\n    return this->m_Matrices;\n  }\n\n  /** Get the i-th projection matrix. */\n  MatrixType\n  GetMatrix(const unsigned int i) const\n  {\n    if (i >= this->m_Matrices.size())\n    {\n      itkExceptionMacro(<< \"Requested matrix index \" << i << \" is out of bound.\");\n    }\n    return this->m_Matrices[i];\n  }\n\n  /** Empty the geometry object. */\n  virtual void\n  Clear();\n\nprotected:\n  ProjectionGeometry() = default;\n  ~ProjectionGeometry() override = default;\n\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  /** Add projection matrix */\n  virtual void\n  AddMatrix(const MatrixType & m)\n  {\n    this->m_Matrices.push_back(m);\n    this->Modified();\n  }\n\nprivate:\n  /** Projection matrices */\n  std::vector<MatrixType> m_Matrices;\n};\n} // namespace rtk\n\n#include \"rtkProjectionGeometry.hxx\"\n\n#endif // rtkProjectionGeometry_h\n"
  },
  {
    "path": "include/rtkProjectionGeometry.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionGeometry_hxx\n#define rtkProjectionGeometry_hxx\n\n\nnamespace rtk\n{\n\ntemplate <unsigned int TDimension>\nvoid\nProjectionGeometry<TDimension>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  os << \"List of projection matrices:\" << std::endl;\n  for (unsigned int i = 0; i < m_Matrices.size(); i++)\n  {\n    os << indent << \"Matrix #\" << i << \": \" << m_Matrices[i] << std::endl;\n  }\n}\n\ntemplate <unsigned int TDimension>\nvoid\nProjectionGeometry<TDimension>::Clear()\n{\n  m_Matrices.clear();\n  this->Modified();\n}\n\n} // namespace rtk\n\n#endif // rtkProjectionGeometry_hxx\n"
  },
  {
    "path": "include/rtkProjectionStackToFourDImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkProjectionStackToFourDImageFilter_h\n#define rtkProjectionStackToFourDImageFilter_h\n\n#include <itkExtractImageFilter.h>\n#include <itkArray2D.h>\n\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkSplatWithKnownWeightsImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaSplatImageFilter.h\"\n#  include \"rtkCudaConstantVolumeSource.h\"\n#  include \"rtkCudaConstantVolumeSeriesSource.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class ProjectionStackToFourDImageFilter\n * \\brief Implements part of the 4D reconstruction by conjugate gradient\n *\n * See the reference paper: \"Cardiac C-arm computed tomography using\n * a 3D + time ROI reconstruction method with spatial and temporal regularization\"\n * by Mory et al.\n *\n * 4D conjugate gradient reconstruction consists in iteratively\n * minimizing the following cost function:\n *\n * Sum_over_theta || R_theta S_theta f - p_theta ||_2^2\n *\n * with\n * - f a 4D series of 3D volumes, each one being the reconstruction\n * at a given respiratory/cardiac phase\n * - p_theta is the projection measured at angle theta\n * - S_theta an interpolation operator which, from the 3D + time sequence f,\n * estimates the 3D volume through which projection p_theta has been acquired\n * - R_theta is the X-ray transform (the forward projection operator) for angle theta\n *\n * Computing the gradient of this cost function yields:\n *\n * S_theta^T R_theta^T R_theta S_theta f - S_theta^T R_theta^T p_theta\n *\n * where A^T means the adjoint of operator A.\n *\n * ProjectionStackToFourDImageFilter implements S_theta^T R_theta^T.\n *\n * \\dot\n * digraph ProjectionStackToFourDImageFilter {\n *\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Input0 [ label=\"Input 0 (Input: 4D sequence of volumes)\"];\n * Input0 [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction: 4D sequence of volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * Extract [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n * VolumeSeriesSource [ label=\"rtk::ConstantImageSource (4D)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * AfterSource4D [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Source [ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * Backproj [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * Splat [ label=\"rtk::SplatWithKnownWeightsImageFilter\" URL=\"\\ref rtk::SplatWithKnownWeightsImageFilter\"];\n * AfterSplat [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * Input1 -> Extract;\n * Input0 -> VolumeSeriesSource [style=invis];\n * VolumeSeriesSource -> AfterSource4D[arrowhead=none];\n * AfterSource4D -> Splat;\n * Extract -> Backproj;\n * Source -> Backproj;\n * Backproj -> Splat;\n * Splat -> AfterSplat[arrowhead=none];\n * AfterSplat -> Output;\n * AfterSplat -> AfterSource4D[style=dashed, constraint=none];\n * }\n * \\enddot\n *\n * \\test rtkfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision = double>\nclass ITK_TEMPLATE_EXPORT ProjectionStackToFourDImageFilter\n  : public itk::ImageToImageFilter<VolumeSeriesType, VolumeSeriesType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ProjectionStackToFourDImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ProjectionStackToFourDImageFilter;\n  using Superclass = itk::ImageToImageFilter<VolumeSeriesType, VolumeSeriesType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using VolumeType = ProjectionStackType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ProjectionStackToFourDImageFilter);\n\n  /** Set/Get the 4D image to be updated.*/\n  void\n  SetInputVolumeSeries(const VolumeSeriesType * VolumeSeries);\n  typename VolumeSeriesType::ConstPointer\n  GetInputVolumeSeries();\n\n  /** Set/Get the stack of projections */\n  void\n  SetInputProjectionStack(const ProjectionStackType * Projection);\n  typename ProjectionStackType::ConstPointer\n  GetInputProjectionStack();\n\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<VolumeType, VolumeType>;\n  using ExtractFilterType = itk::ExtractImageFilter<ProjectionStackType, ProjectionStackType>;\n  using ConstantVolumeSourceType = rtk::ConstantImageSource<VolumeType>;\n  using ConstantVolumeSeriesSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n  using SplatFilterType = rtk::SplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>;\n\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUVolumeSeriesType =\n    typename itk::Image<typename VolumeSeriesType::PixelType, VolumeSeriesType::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using CudaSplatImageFilterType = typename std::\n    conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>, SplatFilterType, CudaSplatImageFilter>;\n  using CudaConstantVolumeSourceType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                ConstantVolumeSourceType,\n                                CudaConstantVolumeSource>;\n  using CudaConstantVolumeSeriesSourceType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                ConstantVolumeSeriesSourceType,\n                                CudaConstantVolumeSeriesSource>;\n#else\n  using CudaSplatImageFilterType = SplatFilterType;\n  using CudaConstantVolumeSourceType = ConstantVolumeSourceType;\n  using CudaConstantVolumeSeriesSourceType = ConstantVolumeSeriesSourceType;\n#endif\n\n  /** Pass the backprojection filter to SingleProjectionToFourDFilter */\n  void\n  SetBackProjectionFilter(BackProjectionFilterType * _arg);\n\n  /** Pass the geometry to SingleProjectionToFourDFilter */\n  itkSetConstObjectMacro(Geometry, GeometryType);\n\n  /** Use CUDA splat / sources */\n  itkSetMacro(UseCudaSplat, bool);\n  itkGetMacro(UseCudaSplat, bool);\n  itkSetMacro(UseCudaSources, bool);\n  itkGetMacro(UseCudaSources, bool);\n\n  /** Macros that take care of implementing the Get and Set methods for Weights */\n  itkGetMacro(Weights, itk::Array2D<float>);\n  itkSetMacro(Weights, itk::Array2D<float>);\n\n  /** Store the phase signal in a member variable */\n  virtual void\n  SetSignal(const std::vector<double> signal);\n\nprotected:\n  ProjectionStackToFourDImageFilter();\n  ~ProjectionStackToFourDImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  InitializeConstantSource();\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename SplatFilterType::Pointer                m_SplatFilter;\n  typename BackProjectionFilterType::Pointer       m_BackProjectionFilter;\n  typename ExtractFilterType::Pointer              m_ExtractFilter;\n  typename ConstantVolumeSourceType::Pointer       m_ConstantVolumeSource;\n  typename ConstantVolumeSeriesSourceType::Pointer m_ConstantVolumeSeriesSource;\n\n  /** Other member variables */\n  itk::Array2D<float>        m_Weights;\n  GeometryType::ConstPointer m_Geometry;\n  bool                       m_UseCudaSplat;\n  bool                       m_UseCudaSources;\n  std::vector<double>        m_Signal;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkProjectionStackToFourDImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionStackToFourDImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkProjectionStackToFourDImageFilter_hxx\n#define rtkProjectionStackToFourDImageFilter_hxx\n\n#include \"rtkGeneralPurposeFunctions.h\"\n\n#include \"itkObjectFactory.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::\n  ProjectionStackToFourDImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  m_UseCudaSplat = false;\n  m_UseCudaSources = false;\n\n  // Create the filters\n  m_ExtractFilter = ExtractFilterType::New();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::SetInputVolumeSeries(\n  const VolumeSeriesType * VolumeSeries)\n{\n  this->SetNthInput(0, const_cast<VolumeSeriesType *>(VolumeSeries));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::SetInputProjectionStack(\n  const ProjectionStackType * Projection)\n{\n  this->SetNthInput(1, const_cast<ProjectionStackType *>(Projection));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\ntypename VolumeSeriesType::ConstPointer\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::GetInputVolumeSeries()\n{\n  return static_cast<const VolumeSeriesType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\ntypename ProjectionStackType::ConstPointer\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::GetInputProjectionStack()\n{\n  return static_cast<const ProjectionStackType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::SetBackProjectionFilter(\n  BackProjectionFilterType * _arg)\n{\n  m_BackProjectionFilter = _arg;\n  this->Modified();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::SetSignal(\n  const std::vector<double> signal)\n{\n  this->m_Signal = signal;\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::InitializeConstantSource()\n{\n  unsigned int Dimension = 3;\n\n  // Configure the constant volume sources\n  typename VolumeType::SizeType      ConstantVolumeSourceSize;\n  typename VolumeType::SpacingType   ConstantVolumeSourceSpacing;\n  typename VolumeType::PointType     ConstantVolumeSourceOrigin;\n  typename VolumeType::DirectionType ConstantVolumeSourceDirection;\n\n  ConstantVolumeSourceSize.Fill(0);\n  ConstantVolumeSourceSpacing.Fill(0);\n  ConstantVolumeSourceOrigin.Fill(0);\n\n  for (unsigned int i = 0; i < Dimension; i++)\n  {\n    ConstantVolumeSourceSize[i] = GetInputVolumeSeries()->GetLargestPossibleRegion().GetSize()[i];\n    ConstantVolumeSourceSpacing[i] = GetInputVolumeSeries()->GetSpacing()[i];\n    ConstantVolumeSourceOrigin[i] = GetInputVolumeSeries()->GetOrigin()[i];\n  }\n  ConstantVolumeSourceDirection.SetIdentity();\n\n  m_ConstantVolumeSource->SetOrigin(ConstantVolumeSourceOrigin);\n  m_ConstantVolumeSource->SetSpacing(ConstantVolumeSourceSpacing);\n  m_ConstantVolumeSource->SetDirection(ConstantVolumeSourceDirection);\n  m_ConstantVolumeSource->SetSize(ConstantVolumeSourceSize);\n  m_ConstantVolumeSource->SetConstant(0.);\n\n  // Configure the constant volume series source\n  m_ConstantVolumeSeriesSource->SetInformationFromImage(this->GetInputVolumeSeries());\n  m_ConstantVolumeSeriesSource->SetConstant(0.);\n  m_ConstantVolumeSeriesSource->ReleaseDataFlagOn();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::GenerateOutputInformation()\n{\n  // Create and set the splat filter\n  m_SplatFilter = SplatFilterType::New();\n  if (m_UseCudaSplat)\n  {\n    if (std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n      itkGenericExceptionMacro(<< \"UseCudaSplat option only available with itk::CudaImage.\");\n    m_SplatFilter = CudaSplatImageFilterType::New();\n  }\n\n  // Create the constant sources (first on CPU, and overwrite with the GPU version if CUDA requested)\n  m_ConstantVolumeSource = ConstantVolumeSourceType::New();\n  m_ConstantVolumeSeriesSource = ConstantVolumeSeriesSourceType::New();\n  if (m_UseCudaSources)\n  {\n    if (std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n      itkGenericExceptionMacro(<< \"UseCudaSources option only available with itk::CudaImage.\");\n    m_ConstantVolumeSource = CudaConstantVolumeSourceType::New();\n    m_ConstantVolumeSeriesSource = CudaConstantVolumeSeriesSourceType::New();\n  }\n\n  // Set runtime connections\n  m_ExtractFilter->SetInput(this->GetInputProjectionStack());\n\n  m_BackProjectionFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_ExtractFilter->GetOutput());\n  m_BackProjectionFilter->SetInPlace(false);\n\n  m_SplatFilter->SetInputVolumeSeries(m_ConstantVolumeSeriesSource->GetOutput());\n  m_SplatFilter->SetInputVolume(m_BackProjectionFilter->GetOutput());\n\n  // Prepare the extract filter\n  int Dimension = ProjectionStackType::ImageDimension; // Dimension=3\n  //  unsigned int NumberProjs = GetInputProjectionStack()->GetLargestPossibleRegion().GetSize(2);\n  //  if (NumberProjs != m_Weights.columns())\n  //    itkWarningMacro(\"Size of interpolation weights array does not match the number of projections\");\n\n  typename ExtractFilterType::InputImageRegionType subsetRegion;\n  subsetRegion = GetInputProjectionStack()->GetLargestPossibleRegion();\n  subsetRegion.SetSize(Dimension - 1, 1);\n  m_ExtractFilter->SetExtractionRegion(subsetRegion);\n\n  // Set runtime parameters\n  m_BackProjectionFilter->SetGeometry(m_Geometry.GetPointer());\n  m_SplatFilter->SetProjectionNumber(subsetRegion.GetIndex(Dimension - 1));\n  m_SplatFilter->SetWeights(m_Weights);\n\n  // Have the last filter calculate its output information\n  this->InitializeConstantSource();\n  m_SplatFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_SplatFilter->GetOutput());\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::GenerateInputRequestedRegion()\n{\n  // The 4D input volume need not be loaded in memory, is it only used to configure the\n  // m_ConstantVolumeSeriesSource with the correct information\n  // Leave its requested region unchanged (set by the other filters that need it)\n\n  // Calculation of the requested region on input 1 is left to the back projection filter\n  this->m_BackProjectionFilter->PropagateRequestedRegion(this->m_BackProjectionFilter->GetOutput());\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType, typename TFFTPrecision>\nvoid\nProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType, TFFTPrecision>::GenerateData()\n{\n  int Dimension = ProjectionStackType::ImageDimension;\n\n  // Prepare the index for the constant projection stack source and the extract filter\n  typename ProjectionStackType::RegionType extractRegion = this->GetInputProjectionStack()->GetLargestPossibleRegion();\n  typename ProjectionStackType::SizeType   extractSize = extractRegion.GetSize();\n  typename ProjectionStackType::IndexType  extractIndex = extractRegion.GetIndex();\n\n  int NumberProjs = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  int FirstProj = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n\n  std::vector<int>          firstProjectionInSlabs;\n  std::vector<unsigned int> sizeOfSlabs;\n  firstProjectionInSlabs.push_back(FirstProj);\n  if (NumberProjs == 1)\n    sizeOfSlabs.push_back(1);\n  else\n  {\n    for (int proj = FirstProj + 1; proj < FirstProj + NumberProjs; proj++)\n    {\n      if (itk::Math::abs(m_Signal[proj] - m_Signal[proj - 1]) > 1e-4)\n      {\n        // Compute the number of projections in the current slab\n        sizeOfSlabs.push_back(proj - firstProjectionInSlabs[firstProjectionInSlabs.size() - 1]);\n\n        // Update the index of the first projection in the next slab\n        firstProjectionInSlabs.push_back(proj);\n      }\n    }\n    sizeOfSlabs.push_back(NumberProjs - firstProjectionInSlabs[firstProjectionInSlabs.size() - 1]);\n  }\n  bool                               firstSlabProcessed = false;\n  typename VolumeSeriesType::Pointer pimg;\n\n  // Process the projections in order\n  for (unsigned int slab = 0; slab < firstProjectionInSlabs.size(); slab++)\n  {\n    // Set the projection stack source\n    extractIndex[Dimension - 1] = firstProjectionInSlabs[slab];\n    extractSize[Dimension - 1] = sizeOfSlabs[slab];\n    extractRegion.SetIndex(extractIndex);\n    extractRegion.SetSize(extractSize);\n    m_ExtractFilter->SetExtractionRegion(extractRegion);\n\n    m_SplatFilter->SetProjectionNumber(firstProjectionInSlabs[slab]);\n\n    // After the first update, we need to use the output as input.\n    if (firstSlabProcessed)\n    {\n      pimg = this->m_SplatFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      this->m_SplatFilter->SetInputVolumeSeries(pimg);\n    }\n\n    // Update the last filter\n    m_SplatFilter->Update();\n\n    // Update condition\n    firstSlabProcessed = true;\n  }\n\n  // Graft its output\n  this->GraftOutput(m_SplatFilter->GetOutput());\n\n  // Release the data in internal filters\n  if (pimg.IsNotNull())\n    pimg->ReleaseData();\n  m_BackProjectionFilter->GetOutput()->ReleaseData();\n  m_ExtractFilter->GetOutput()->ReleaseData();\n  m_ConstantVolumeSource->GetOutput()->ReleaseData();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsDecompositionNegativeLogLikelihood.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionsDecompositionNegativeLogLikelihood_h\n#define rtkProjectionsDecompositionNegativeLogLikelihood_h\n\n#include <itkSingleValuedCostFunction.h>\n#include <itkVectorImage.h>\n#include <itkVariableLengthVector.h>\n#include <itkVariableSizeMatrix.h>\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class rtkProjectionsDecompositionNegativeLogLikelihood\n * \\brief Base class for projections decomposition cost functions\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\n// We have to define the cost function first\nclass ProjectionsDecompositionNegativeLogLikelihood : public itk::SingleValuedCostFunction\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ProjectionsDecompositionNegativeLogLikelihood);\n\n  using Self = ProjectionsDecompositionNegativeLogLikelihood;\n  using Superclass = itk::SingleValuedCostFunction;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  itkNewMacro(Self);\n  itkOverrideGetNameOfClassMacro(ProjectionsDecompositionNegativeLogLikelihood);\n\n  //  enum { SpaceDimension=m_NumberOfMaterials };\n\n  using ParametersType = Superclass::ParametersType;\n  using DerivativeType = Superclass::DerivativeType;\n  using MeasureType = Superclass::MeasureType;\n\n  using DetectorResponseType = vnl_matrix<double>;\n  using MaterialAttenuationsType = vnl_matrix<double>;\n  using IncidentSpectrumType = vnl_matrix<float>;\n  using MeasuredDataType = itk::VariableLengthVector<double>;\n  using ThresholdsType = itk::VariableLengthVector<int>;\n  using MeanAttenuationInBinType = itk::VariableSizeMatrix<double>;\n\n  // Constructor\n  ProjectionsDecompositionNegativeLogLikelihood()\n  {\n    m_NumberOfEnergies = 0;\n    m_NumberOfMaterials = 0;\n    m_Initialized = false;\n  }\n\n  // Destructor\n  ~ProjectionsDecompositionNegativeLogLikelihood() override = default;\n\n  MeasureType\n  GetValue(const ParametersType & itkNotUsed(parameters)) const override\n  {\n    long double measure = 0;\n    return measure;\n  }\n  void\n  GetDerivative(const ParametersType & itkNotUsed(lineIntegrals),\n                DerivativeType &       itkNotUsed(derivatives)) const override\n  {\n    itkExceptionMacro(<< \"Not implemented\");\n  }\n  virtual void\n  Initialize()\n  {}\n\n  virtual itk::VariableLengthVector<float>\n  GetInverseCramerRaoLowerBound()\n  {\n    // Return the inverses of the diagonal components (i.e. the inverse variances, to be used directly in WLS\n    // reconstruction)\n    itk::VariableLengthVector<double> diag;\n    diag.SetSize(m_NumberOfMaterials);\n    diag.Fill(0);\n\n    for (unsigned int mat = 0; mat < m_NumberOfMaterials; mat++)\n      diag[mat] = 1. / m_Fischer.GetInverse()[mat][mat];\n    return diag;\n  }\n\n  virtual itk::VariableLengthVector<float>\n  GetCramerRaoLowerBound()\n  {\n    // Return the inverses of the diagonal components (i.e. the inverse variances, to be used directly in WLS\n    // reconstruction)\n    itk::VariableLengthVector<double> diag;\n    diag.SetSize(m_NumberOfMaterials);\n    diag.Fill(0);\n\n    for (unsigned int mat = 0; mat < m_NumberOfMaterials; mat++)\n      diag[mat] = m_Fischer.GetInverse()[mat][mat];\n    return diag;\n  }\n\n  virtual itk::VariableLengthVector<float>\n  GetFischerMatrix()\n  {\n    // Return the whole Fischer information matrix\n    itk::VariableLengthVector<double> fischer;\n    fischer.SetSize(m_NumberOfMaterials * m_NumberOfMaterials);\n    fischer.Fill(0);\n\n    for (unsigned int i = 0; i < m_NumberOfMaterials; i++)\n      for (unsigned int j = 0; j < m_NumberOfMaterials; j++)\n        fischer[i * m_NumberOfMaterials + j] = m_Fischer[i][j];\n    return fischer;\n  }\n\n  virtual void\n  ComputeFischerMatrix(const ParametersType & itkNotUsed(lineIntegrals))\n  {}\n\n  unsigned int\n  GetNumberOfParameters() const override\n  {\n    return m_NumberOfMaterials;\n  }\n\n  virtual vnl_vector<double>\n  ForwardModel(const ParametersType & lineIntegrals) const\n  {\n    vnl_vector<double> attenuationFactors;\n    attenuationFactors.set_size(m_NumberOfEnergies);\n    GetAttenuationFactors(lineIntegrals, attenuationFactors);\n\n    // Apply detector response, getting the lambdas\n    return (m_IncidentSpectrumAndDetectorResponseProduct * attenuationFactors);\n  }\n\n  void\n  GetAttenuationFactors(const ParametersType & lineIntegrals, vnl_vector<double> & attenuationFactors) const\n  {\n    // Apply attenuation at each energy\n    vnl_vector<double> vnlLineIntegrals;\n\n    // Initialize the line integrals vnl vector\n    vnlLineIntegrals.set_size(m_NumberOfMaterials);\n    for (unsigned int m = 0; m < m_NumberOfMaterials; m++)\n      vnlLineIntegrals[m] = lineIntegrals[m];\n\n    // Apply the material attenuations matrix\n    attenuationFactors = this->m_MaterialAttenuations * vnlLineIntegrals;\n\n    // Compute the negative exponential\n    for (unsigned int energy = 0; energy < m_NumberOfEnergies; energy++)\n    {\n      attenuationFactors[energy] = std::exp(-attenuationFactors[energy]);\n    }\n  }\n\n  itk::VariableLengthVector<double>\n  GuessInitialization() const\n  {\n    itk::VariableLengthVector<double> initialGuess;\n    initialGuess.SetSize(m_NumberOfMaterials);\n\n    // Compute the mean attenuation in each bin, weighted by the input spectrum\n    // Needs to be done for each pixel, since the input spectrum is variable\n    MeanAttenuationInBinType MeanAttenuationInBin;\n    MeanAttenuationInBin.SetSize(this->m_NumberOfMaterials, this->m_NumberOfSpectralBins);\n    MeanAttenuationInBin.Fill(0);\n\n    for (unsigned int mat = 0; mat < this->m_NumberOfMaterials; mat++)\n    {\n      for (unsigned int bin = 0; bin < m_NumberOfSpectralBins; bin++)\n      {\n        double accumulate = 0;\n        double accumulateWeights = 0;\n        for (int energy = m_Thresholds[bin] - 1;\n             (energy < m_Thresholds[bin + 1]) && (energy < (int)(this->m_MaterialAttenuations.rows()));\n             energy++)\n        {\n          accumulate += this->m_MaterialAttenuations[energy][mat] * this->m_IncidentSpectrum[0][energy];\n          accumulateWeights += this->m_IncidentSpectrum[0][energy];\n        }\n        MeanAttenuationInBin[mat][bin] = accumulate / accumulateWeights;\n      }\n    }\n\n    for (unsigned int mat = 0; mat < m_NumberOfMaterials; mat++)\n    {\n      // Initialise to a very high value\n      initialGuess[mat] = 1e10;\n      for (unsigned int bin = 0; bin < m_NumberOfSpectralBins; bin++)\n      {\n        // Compute the length of current material required to obtain the attenuation\n        // observed in current bin. Keep only the minimum among all bins\n        double requiredLength = this->BinwiseLogTransform()[bin] / MeanAttenuationInBin[mat][bin];\n        if (initialGuess[mat] > requiredLength)\n          initialGuess[mat] = requiredLength;\n      }\n    }\n\n    return initialGuess;\n  }\n\n  itk::VariableLengthVector<double>\n  BinwiseLogTransform() const\n  {\n    itk::VariableLengthVector<double> logTransforms;\n    logTransforms.SetSize(m_NumberOfSpectralBins);\n\n    vnl_vector<double> ones, nonAttenuated;\n    ones.set_size(m_NumberOfEnergies);\n    ones.fill(1.0);\n\n    // The way m_IncidentSpectrumAndDetectorResponseProduct works is\n    // it is mutliplied by the vector of attenuations factors (here\n    // filled with ones, since we want the non-attenuated signal)\n    nonAttenuated = m_IncidentSpectrumAndDetectorResponseProduct * ones;\n\n    for (unsigned int i = 0; i < m_MeasuredData.GetSize(); i++)\n    {\n      // Divide by the actually measured photon counts and apply log\n      if (m_MeasuredData[i] > 0)\n        logTransforms[i] = log(nonAttenuated[i] / m_MeasuredData[i]);\n    }\n\n    return logTransforms;\n  }\n\n  virtual vnl_vector<double>\n  GetVariances(const ParametersType & itkNotUsed(lineIntegrals)) const\n  {\n    vnl_vector<double> meaninglessResult;\n    meaninglessResult.set_size(m_NumberOfSpectralBins);\n    meaninglessResult.fill(0.);\n    return (meaninglessResult);\n  }\n\n  itkSetMacro(MeasuredData, MeasuredDataType);\n  itkGetMacro(MeasuredData, MeasuredDataType);\n\n  itkSetMacro(DetectorResponse, DetectorResponseType);\n  itkGetMacro(DetectorResponse, DetectorResponseType);\n\n  itkSetMacro(MaterialAttenuations, MaterialAttenuationsType);\n  itkGetMacro(MaterialAttenuations, MaterialAttenuationsType);\n\n  itkSetMacro(NumberOfEnergies, unsigned int);\n  itkGetMacro(NumberOfEnergies, unsigned int);\n\n  itkSetMacro(NumberOfMaterials, unsigned int);\n  itkGetMacro(NumberOfMaterials, unsigned int);\n\n  itkSetMacro(IncidentSpectrum, IncidentSpectrumType);\n  itkGetMacro(IncidentSpectrum, IncidentSpectrumType);\n\n  itkSetMacro(NumberOfSpectralBins, unsigned int);\n  itkGetMacro(NumberOfSpectralBins, unsigned int);\n\n  itkSetMacro(Thresholds, ThresholdsType);\n  itkGetMacro(Thresholds, ThresholdsType);\n\nprotected:\n  MaterialAttenuationsType       m_MaterialAttenuations;\n  DetectorResponseType           m_DetectorResponse;\n  MeasuredDataType               m_MeasuredData;\n  ThresholdsType                 m_Thresholds;\n  IncidentSpectrumType           m_IncidentSpectrum;\n  vnl_matrix<double>             m_IncidentSpectrumAndDetectorResponseProduct;\n  unsigned int                   m_NumberOfEnergies;\n  unsigned int                   m_NumberOfMaterials;\n  unsigned int                   m_NumberOfSpectralBins;\n  bool                           m_Initialized;\n  itk::VariableSizeMatrix<float> m_Fischer;\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionsReader_h\n#define rtkProjectionsReader_h\n\n// ITK\n#include <itkImageSource.h>\n#include <itkImageIOFactory.h>\n#include <itkStreamingImageFilter.h>\n\n// RTK\n#include \"rtkWaterPrecorrectionImageFilter.h\"\n#include \"rtkConditionalMedianImageFilter.h\"\n\n// Standard lib\n#include <vector>\n#include <string>\n\nnamespace rtk\n{\n\n/** \\class ProjectionsReader\n *\n * This is the universal projections reader of rtk (raw data converted to\n * attenuation). Currently handles his (Elekta Synergy), hnd (Varian OBI),\n * edf (ESRF), XRad. For all other ITK file formats (mha, tif, ...), it is\n * assumed that the attenuation is directly passed if the pixel type is not\n * unsigned short and there is no processing. Optionnally, one can activate\n * cropping, binning, scatter correction, etc. The details of the mini-\n * pipeline is provided below, note that dashed filters are shunt if they\n * are not required according to parameters.\n *\n * \\dot\n * digraph ProjectionsReader {\n *\n * Output [label=\"Output (Projections)\", shape=Mdiamond];\n *\n * node [shape=box];\n * Raw [label=\"itk::ImageSeriesReader\" URL=\"\\ref itk::ImageSeriesReader\"];\n * ElektaRaw [label=\"rtk::ElektaSynergyRawLookupTableImageFilter\"\n *            URL=\"\\ref rtk::ElektaSynergyRawLookupTableImageFilter\"];\n * ChangeInformation [label=\"itk::ChangeInformationImageFilter\"\n *                    URL=\"\\ref itk::ChangeInformationImageFilter\" style=dashed];\n * Crop [label=\"itk::CropImageFilter\" URL=\"\\ref itk::CropImageFilter\" style=dashed];\n * Binning [label=\"itk::BinShrinkImageFilter\" URL=\"\\ref itk::BinShrinkImageFilter\" style=dashed];\n * ConditionalMedian [label=\"rtk::ConditionalMedianImageFilter\"\n *                    URL=\"\\ref rtk::ConditionalMedianImageFilter\" style=dashed];\n * Scatter [label=\"rtk::BoellaardScatterCorrectionImageFilter\"\n *          URL=\"\\ref rtk::BoellaardScatterCorrectionImageFilter\" style=dashed];\n * I0est [label=\"rtk::I0EstimationProjectionFilter\" URL=\"\\ref rtk::I0EstimationProjectionFilter\" style=dashed];\n * BeforeLUT [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * LUT [label=\"rtk::LUTbasedVariableI0RawToAttenuationImageFilter\"\n *      URL=\"\\ref rtk::LUTbasedVariableI0RawToAttenuationImageFilter\"];\n * BeforeVarian [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Varian [label=\"rtk::VarianObiRawImageFilter\" URL=\"\\ref rtk::VarianObiRawImageFilter\"];\n * WPC [label=\"rtk::WaterPrecorrectionImageFilter\" URL=\"\\ref rtk::WaterPrecorrectionImageFilter\" style=dashed];\n * Streaming [label=\"itk::StreamingImageFilter\" URL=\"\\ref itk::StreamingImageFilter\"];\n * BeforeEDF [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * EDF [label=\"rtk::EdfRawToAttenuationImageFilter\"  URL=\"\\ref rtk::EdfRawToAttenuationImageFilter\"];\n * BeforeXRad [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * XRad [label=\"rtk::XRadRawToAttenuationImageFilter\"  URL=\"\\ref rtk::XRadRawToAttenuationImageFilter\"];\n * Cast [label=\"itk::CastImageFilter\"  URL=\"\\ref itk::CastImageFilter\"];\n * OraRaw [label=\"rtk::OraLookupTableImageFilter\" URL=\"\\ref rtk::OraLookupTableImageFilter\"];\n *\n * Raw->ChangeInformation [label=\"Default\"]\n * ChangeInformation->Crop\n * Crop->ElektaRaw [label=\"Elekta\"]\n * Binning->OraRaw [label=\"Ora && ushort\"]\n * OraRaw->WPC\n * ElektaRaw->ConditionalMedian\n * Crop->ConditionalMedian[label=\"Default\"]\n * ConditionalMedian->Binning\n * Binning->Scatter [label=\"Elekta, Varian, IBA, ushort\"]\n * Scatter->I0est [label=\"Default\"]\n * I0est->BeforeLUT\n * BeforeLUT->LUT [label=\"ComputeLineIntegral\\n(default)\"]\n * BeforeLUT->Cast\n * LUT->WPC\n * I0est->BeforeVarian [label=\"Varian\"]\n * BeforeVarian->Varian [label=\"ComputeLineIntegral\\n(default)\"]\n * BeforeVarian->Cast\n * Varian->WPC\n * EDF->WPC\n * ChangeInformation->BeforeEDF [label=\"edf short\"]\n * BeforeEDF->EDF [label=\"ComputeLineIntegral\\n(default)\"]\n * BeforeEDF->Cast\n * XRad->WPC\n * ChangeInformation->BeforeXRad [label=\"XRad\"]\n * BeforeXRad->XRad [label=\"ComputeLineIntegral\\n(default)\"]\n * BeforeXRad->Cast\n * Cast->WPC\n * WPC->Streaming\n * Streaming->Output\n *\n * Binning->WPC [label=\"Default\"]\n *\n * {rank=same; XRad EDF Varian LUT OraRaw}\n * }\n * \\enddot\n *\n * \\test rtkedftest.cxx, rtkelektatest.cxx, rtkimagxtest.cxx,\n * rtkdigisenstest.cxx, rtkxradtest.cxx, rtkvariantest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageSource\n */\ntemplate <class TOutputImage>\nclass ITK_TEMPLATE_EXPORT ProjectionsReader : public itk::ImageSource<TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ProjectionsReader);\n\n  /** Standard class type alias. */\n  using Self = ProjectionsReader;\n  using Superclass = itk::ImageSource<TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ProjectionsReader);\n\n  /** Some convenient type alias. */\n  using OutputImageType = TOutputImage;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n  using OutputImagePixelType = typename OutputImageType::PixelType;\n  using OutputImageDirectionType = typename OutputImageType::DirectionType;\n  using OutputImageSpacingType = typename OutputImageType::SpacingType;\n  using OutputImagePointType = typename OutputImageType::PointType;\n  using OutputImageSizeType = typename OutputImageType::SizeType;\n\n  using FileNamesContainer = std::vector<std::string>;\n  using ShrinkFactorsType = itk::FixedArray<unsigned int, TOutputImage::ImageDimension>;\n  using MedianRadiusType = typename rtk::ConditionalMedianImageFilter<TOutputImage>::MedianRadiusType;\n  using WaterPrecorrectionVectorType = std::vector<double>;\n\n  /** Typdefs of filters of the mini-pipeline that do not depend on the raw\n   * data type. */\n  using WaterPrecorrectionType = rtk::WaterPrecorrectionImageFilter<TOutputImage, TOutputImage>;\n  using StreamingType = itk::StreamingImageFilter<TOutputImage, TOutputImage>;\n\n  /** ImageDimension constant */\n  static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension;\n\n  /** Set the vector of strings that contains the file names. Files\n   * are processed in sequential order. */\n  void\n  SetFileNames(const FileNamesContainer & name)\n  {\n    if (m_FileNames != name)\n    {\n      m_FileNames = name;\n      this->Modified();\n    }\n  }\n  const FileNamesContainer &\n  GetFileNames() const\n  {\n    return m_FileNames;\n  }\n\n  /** Set/Get the new image information for the input projections before any pre-processing. */\n  itkSetMacro(Origin, OutputImagePointType);\n  itkGetConstMacro(Origin, OutputImagePointType);\n\n  itkSetMacro(Spacing, OutputImageSpacingType);\n  itkGetConstMacro(Spacing, OutputImageSpacingType);\n\n  itkSetMacro(Direction, OutputImageDirectionType);\n  itkGetConstMacro(Direction, OutputImageDirectionType);\n\n  /** Set/Get the cropping sizes for the upper and lower boundaries. */\n  itkSetMacro(UpperBoundaryCropSize, OutputImageSizeType);\n  itkGetConstMacro(UpperBoundaryCropSize, OutputImageSizeType);\n  itkSetMacro(LowerBoundaryCropSize, OutputImageSizeType);\n  itkGetConstMacro(LowerBoundaryCropSize, OutputImageSizeType);\n\n  /** Set/Get itk::BinShrinkImageFilter parameters */\n  itkSetMacro(ShrinkFactors, ShrinkFactorsType);\n  itkGetConstReferenceMacro(ShrinkFactors, ShrinkFactorsType);\n\n  /** Set/Get itk::ConditionalMedianImageFilter parameters */\n  itkSetMacro(MedianRadius, MedianRadiusType);\n  itkGetConstReferenceMacro(MedianRadius, MedianRadiusType);\n  itkGetMacro(ConditionalMedianThresholdMultiplier, double);\n  itkSetMacro(ConditionalMedianThresholdMultiplier, double);\n\n  /** Set/Get rtk::BoellaardScatterCorrectionImageFilter */\n  itkGetMacro(AirThreshold, double);\n  itkSetMacro(AirThreshold, double);\n\n  itkGetMacro(ScatterToPrimaryRatio, double);\n  itkSetMacro(ScatterToPrimaryRatio, double);\n\n  itkGetMacro(NonNegativityConstraintThreshold, double);\n  itkSetMacro(NonNegativityConstraintThreshold, double);\n\n  /** Set/Get rtk::LUTbasedVariableI0RawToAttenuationImageFilter. Default is\n   * used if not set which depends on the input image type max. If equals 0,\n   * automated estimation is activated using rtk::I0EstimationProjectionFilter.\n   */\n  itkGetMacro(I0, double);\n  itkSetMacro(I0, double);\n\n  /** Set/Get the intensity with no photons for\n   * rtk::LUTbasedVariableI0RawToAttenuationImageFilter.\n   */\n  itkGetMacro(IDark, double);\n  itkSetMacro(IDark, double);\n\n  /** Get / Set the water precorrection parameters. */\n  itkGetMacro(WaterPrecorrectionCoefficients, WaterPrecorrectionVectorType);\n  virtual void\n  SetWaterPrecorrectionCoefficients(const WaterPrecorrectionVectorType _arg)\n  {\n    if (this->m_WaterPrecorrectionCoefficients != _arg)\n    {\n      this->m_WaterPrecorrectionCoefficients = _arg;\n      this->Modified();\n    }\n  }\n\n  /** Convert the projection data to line integrals after pre-processing.\n  ** Default is on. */\n  itkSetMacro(ComputeLineIntegral, bool);\n  itkGetConstMacro(ComputeLineIntegral, bool);\n  itkBooleanMacro(ComputeLineIntegral);\n\n  /** Set/Get the index of the component to be extracted\n   * if the projection data contains vectors instead of scalars. */\n  itkGetMacro(VectorComponent, unsigned int);\n  itkSetMacro(VectorComponent, unsigned int);\n\n  /** Set/Get the ImageIO helper class. Often this is created via the object\n   * factory mechanism that determines whether a particular ImageIO can\n   * read a certain file. This method provides a way to get the ImageIO\n   * instance that is created. Or you can directly specify the ImageIO\n   * to use to read a particular file in case the factory mechanism will\n   * not work properly (e.g., unknown or unusual extension). */\n  itkSetObjectMacro(ImageIO, itk::ImageIOBase);\n  itkGetConstObjectMacro(ImageIO, itk::ImageIOBase);\n\n  /** Prepare the allocation of the output image during the first back\n   * propagation of the pipeline. */\n  void\n  GenerateOutputInformation() override;\n\nprotected:\n  ProjectionsReader();\n  ~ProjectionsReader() override = default;\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** A list of filenames to be processed. */\n  FileNamesContainer m_FileNames;\n\nprivate:\n  /** Function that checks and propagates the parameters of the class to the\n   * mini-pipeline. Due to concept checking, i0 propagation can only be done\n   * with unsigned shorts and is left apart without template. */\n  template <class TInputImage>\n  void\n  PropagateParametersToMiniPipeline();\n  void\n  ConnectElektaRawFilter(itk::ImageBase<OutputImageDimension> ** nextInputBase);\n  void\n  PropagateI0(itk::ImageBase<OutputImageDimension> ** nextInputBase);\n\n  /** The projections reader which template depends on the scanner.\n   * It is not typed because we want to keep the data as on disk.\n   * The pointer is stored to reference the filter and avoid its destruction. */\n  itk::ProcessObject::Pointer m_RawDataReader;\n\n  /** Pointers for pre-processing filters that are created only when required. */\n  itk::ProcessObject::Pointer m_VectorComponentSelectionFilter;\n  itk::ProcessObject::Pointer m_ChangeInformationFilter;\n  itk::ProcessObject::Pointer m_ElektaRawFilter;\n  itk::ProcessObject::Pointer m_CropFilter;\n  itk::ProcessObject::Pointer m_ConditionalMedianFilter;\n  itk::ProcessObject::Pointer m_BinningFilter;\n  itk::ProcessObject::Pointer m_ScatterFilter;\n  itk::ProcessObject::Pointer m_I0EstimationFilter;\n\n  /** Conversion from raw to attenuation. Depends on the input image type, set\n   * to binning filter output by default. */\n  typename itk::ImageSource<TOutputImage>::Pointer m_RawToAttenuationFilter;\n\n  /** When m_ComputeLineIntegral is off, one just casts the value instead of\n   * doing a line integral. */\n  typename itk::ImageSource<TOutputImage>::Pointer m_RawCastFilter;\n\n  /** Pointers for post-processing filters that are created only when required. */\n  typename WaterPrecorrectionType::Pointer m_WaterPrecorrectionFilter;\n  typename StreamingType::Pointer          m_StreamingFilter;\n\n  /** Image IO object which is stored to create the pipe only when required */\n  itk::ImageIOBase::Pointer m_ImageIO{ nullptr };\n\n  /** Copy of parameters for the mini-pipeline. Parameters are checked and\n   * propagated when required in the GenerateOutputInformation. Refer to the\n   * documentation of the corresponding filter for more information. */\n  OutputImagePointType         m_Origin;\n  OutputImageSpacingType       m_Spacing;\n  OutputImageDirectionType     m_Direction;\n  OutputImageSizeType          m_LowerBoundaryCropSize;\n  OutputImageSizeType          m_UpperBoundaryCropSize;\n  ShrinkFactorsType            m_ShrinkFactors;\n  MedianRadiusType             m_MedianRadius;\n  double                       m_AirThreshold{ 32000 };\n  double                       m_ScatterToPrimaryRatio{ 0. };\n  double                       m_NonNegativityConstraintThreshold{ itk::NumericTraits<double>::NonpositiveMin() };\n  double                       m_I0{ itk::NumericTraits<double>::NonpositiveMin() };\n  double                       m_IDark{ 0. };\n  double                       m_ConditionalMedianThresholdMultiplier{ 1. };\n  WaterPrecorrectionVectorType m_WaterPrecorrectionCoefficients;\n  bool                         m_ComputeLineIntegral{ true };\n  unsigned int                 m_VectorComponent{ 0 };\n};\n\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkProjectionsReader.hxx\"\n#endif\n\n#endif // rtkProjectionsReader_h\n"
  },
  {
    "path": "include/rtkProjectionsReader.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionsReader_hxx\n#define rtkProjectionsReader_hxx\n\n\n// ITK\n#include <itkConfigure.h>\n#include <itkImageSeriesReader.h>\n#include <itkCropImageFilter.h>\n#include <itkBinShrinkImageFilter.h>\n#include <itkNumericTraits.h>\n#include <itkChangeInformationImageFilter.h>\n#include <itkCastImageFilter.h>\n#include <itkVectorIndexSelectionCastImageFilter.h>\n\n// RTK\n#include \"rtkIOFactories.h\"\n#include \"rtkBoellaardScatterCorrectionImageFilter.h\"\n#include \"rtkLUTbasedVariableI0RawToAttenuationImageFilter.h\"\n#include \"rtkConditionalMedianImageFilter.h\"\n\n// Varian Obi includes\n#include \"rtkHndImageIOFactory.h\"\n#include \"rtkXimImageIOFactory.h\"\n#include \"rtkVarianObiRawImageFilter.h\"\n\n// Elekta Synergy includes\n#include \"rtkHisImageIOFactory.h\"\n#include \"rtkElektaSynergyRawLookupTableImageFilter.h\"\n#include \"rtkElektaSynergyLookupTableImageFilter.h\"\n\n// ImagX includes\n#include \"rtkImagXImageIOFactory.h\"\n\n// European Synchrotron Radiation Facility\n#include \"rtkEdfImageIOFactory.h\"\n#include \"rtkEdfRawToAttenuationImageFilter.h\"\n\n// Xrad small animal scanner\n#include \"rtkXRadImageIOFactory.h\"\n#include \"rtkXRadRawToAttenuationImageFilter.h\"\n\n// Ora (medPhoton) image files\n#include \"rtkOraLookupTableImageFilter.h\"\n\n// Macro to handle input images with vector pixel type in GenerateOutputInformation();\n#define SET_INPUT_IMAGE_VECTOR_TYPE(componentType, numberOfComponents)                                              \\\n  if (!strcmp(imageIO->GetComponentTypeAsString(imageIO->GetComponentType()).c_str(), #componentType) &&            \\\n      (imageIO->GetNumberOfComponents() == numberOfComponents))                                                     \\\n  {                                                                                                                 \\\n    using InputPixelType = itk::Vector<componentType, numberOfComponents>;                                          \\\n    using InputImageType = itk::Image<InputPixelType, OutputImageDimension>;                                        \\\n    using ReaderType = itk::ImageSeriesReader<InputImageType>;                                                      \\\n    auto reader = ReaderType::New();                                                                                \\\n    m_RawDataReader = reader;                                                                                       \\\n    using VectorComponentSelectionType = itk::VectorIndexSelectionCastImageFilter<InputImageType, OutputImageType>; \\\n    auto vectorComponentSelectionFilter = VectorComponentSelectionType::New();                                      \\\n    if (m_VectorComponent < numberOfComponents)                                                                     \\\n      vectorComponentSelectionFilter->SetIndex(m_VectorComponent);                                                  \\\n    else                                                                                                            \\\n      itkGenericExceptionMacro(<< \"Cannot extract \" << m_VectorComponent << \"-th component from vector of size \"    \\\n                               << numberOfComponents);                                                              \\\n    m_VectorComponentSelectionFilter = vectorComponentSelectionFilter;                                              \\\n  }\n\n// Macro to handle input images with vector pixel type in PropagateParametersToMiniPipeline();\n#define PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(componentType, numberOfComponents)                                        \\\n  if (!strcmp(m_ImageIO->GetComponentTypeAsString(m_ImageIO->GetComponentType()).c_str(), #componentType) &&        \\\n      (m_ImageIO->GetNumberOfComponents() == numberOfComponents))                                                   \\\n  {                                                                                                                 \\\n    using InputPixelType = itk::Vector<componentType, numberOfComponents>;                                          \\\n    using InputImageType = itk::Image<InputPixelType, OutputImageDimension>;                                        \\\n    using RawType = typename itk::ImageSeriesReader<InputImageType>;                                                \\\n    RawType * raw = dynamic_cast<RawType *>(m_RawDataReader.GetPointer());                                          \\\n    assert(raw != nullptr);                                                                                         \\\n    raw->SetFileNames(this->GetFileNames());                                                                        \\\n    raw->SetImageIO(m_ImageIO);                                                                                     \\\n    using VectorComponentSelectionType = itk::VectorIndexSelectionCastImageFilter<InputImageType, OutputImageType>; \\\n    VectorComponentSelectionType * vectorComponentSelectionFilter =                                                 \\\n      dynamic_cast<VectorComponentSelectionType *>(m_VectorComponentSelectionFilter.GetPointer());                  \\\n    assert(vectorComponentSelectionFilter != nullptr);                                                              \\\n    vectorComponentSelectionFilter->SetInput(raw->GetOutput());                                                     \\\n    output = vectorComponentSelectionFilter->GetOutput();                                                           \\\n  }\n\nnamespace rtk\n{\n\n//--------------------------------------------------------------------\ntemplate <class TOutputImage>\nProjectionsReader<TOutputImage>::ProjectionsReader()\n{\n  // Filters common to all input types and that do not depend on the input image type.\n  m_WaterPrecorrectionFilter = WaterPrecorrectionType::New();\n  m_StreamingFilter = StreamingType::New();\n\n  // Default values of parameters\n  m_Spacing.Fill(itk::NumericTraits<typename OutputImageType::SpacingValueType>::max());\n  m_Origin.Fill(itk::NumericTraits<typename OutputImageType::PointValueType>::max());\n  m_Direction.Fill(itk::NumericTraits<typename OutputImageType::PointValueType>::max());\n  m_LowerBoundaryCropSize.Fill(0);\n  m_UpperBoundaryCropSize.Fill(0);\n  m_ShrinkFactors.Fill(1);\n  m_MedianRadius.Fill(0);\n}\n\n//--------------------------------------------------------------------\ntemplate <class TOutputImage>\nvoid\nProjectionsReader<TOutputImage>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n\n  if (m_RawDataReader.GetPointer())\n    os << indent << \"RawDataReader: \" << m_RawDataReader->GetNameOfClass() << std::endl;\n  if (m_RawToAttenuationFilter.GetPointer())\n    os << indent << \"RawToProjectionsFilter: \" << m_RawToAttenuationFilter->GetNameOfClass() << std::endl;\n}\n\n//--------------------------------------------------------------------\ntemplate <class TOutputImage>\nvoid\nProjectionsReader<TOutputImage>::GenerateOutputInformation()\n{\n  if (m_FileNames.empty())\n    return;\n\n  static bool firstTime = true;\n  if (firstTime)\n    rtk::RegisterIOFactories();\n  firstTime = false;\n\n  itk::ImageIOBase::Pointer imageIO =\n    itk::ImageIOFactory::CreateImageIO(m_FileNames[0].c_str(), itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n\n  if (imageIO == nullptr)\n  {\n    if (m_ImageIO != nullptr)\n    {\n      // Can only occur if the image IO has been set manually\n      std::swap(m_ImageIO, imageIO);\n    }\n    else\n    {\n      itkGenericExceptionMacro(<< \"Cannot create ImageIOFactory for file \" << m_FileNames[0].c_str());\n    }\n  }\n\n  if (m_ImageIO != imageIO)\n  {\n    imageIO->SetFileName(m_FileNames[0].c_str());\n    imageIO->ReadImageInformation();\n\n    // In this block, we create the filters used depending on the input type\n\n    // Reset\n    m_RawDataReader = nullptr;\n    m_VectorComponentSelectionFilter = nullptr;\n    m_ChangeInformationFilter = nullptr;\n    m_ElektaRawFilter = nullptr;\n    m_CropFilter = nullptr;\n    m_ConditionalMedianFilter = nullptr;\n    m_BinningFilter = nullptr;\n    m_ScatterFilter = nullptr;\n    m_I0EstimationFilter = nullptr;\n    m_RawToAttenuationFilter = nullptr;\n    m_RawCastFilter = nullptr;\n\n    // Start creation\n    if ((!strcmp(imageIO->GetNameOfClass(), \"EdfImageIO\") &&\n         imageIO->GetComponentType() == itk::ImageIOBase::IOComponentEnum::USHORT) ||\n        !strcmp(imageIO->GetNameOfClass(), \"XRadImageIO\"))\n    {\n      using InputPixelType = unsigned short;\n      using InputImageType = itk::Image<InputPixelType, OutputImageDimension>;\n\n      // Reader\n      using ReaderType = itk::ImageSeriesReader<InputImageType>;\n      auto reader = ReaderType::New();\n      m_RawDataReader = reader;\n\n      // Change information\n      using ChangeInfoType = itk::ChangeInformationImageFilter<InputImageType>;\n      auto cif = ChangeInfoType::New();\n      m_ChangeInformationFilter = cif;\n\n      if (!strcmp(imageIO->GetNameOfClass(), \"EdfImageIO\"))\n      {\n        /////////// ESRF\n        // Convert raw to Projections\n        using RawFilterType = rtk::EdfRawToAttenuationImageFilter<InputImageType, OutputImageType>;\n        auto rawFilter = RawFilterType::New();\n        m_RawToAttenuationFilter = rawFilter;\n\n        // Or just cast to OutputImageType\n        using CastFilterType = itk::CastImageFilter<InputImageType, OutputImageType>;\n        auto castFilter = CastFilterType::New();\n        m_RawCastFilter = castFilter;\n      }\n      if (!strcmp(imageIO->GetNameOfClass(), \"XRadImageIO\"))\n      {\n        /////////// XRad\n        // Convert raw to Projections\n        auto rawFilterXRad = rtk::XRadRawToAttenuationImageFilter<InputImageType, OutputImageType>::New();\n        m_RawToAttenuationFilter = rawFilterXRad;\n\n        // Or just cast to OutputImageType\n        using CastFilterType = itk::CastImageFilter<InputImageType, OutputImageType>;\n        auto castFilter = CastFilterType::New();\n        m_RawCastFilter = castFilter;\n      }\n    }\n    else if (!strcmp(imageIO->GetNameOfClass(), \"HndImageIO\") || !strcmp(imageIO->GetNameOfClass(), \"XimImageIO\"))\n    {\n      /////////// Varian OBI\n      using InputPixelType = unsigned int;\n      using InputImageType = itk::Image<InputPixelType, OutputImageDimension>;\n\n      // Reader\n      using ReaderType = itk::ImageSeriesReader<InputImageType>;\n      auto reader = ReaderType::New();\n      m_RawDataReader = reader;\n\n      // Change information\n      using ChangeInfoType = itk::ChangeInformationImageFilter<InputImageType>;\n      auto cif = ChangeInfoType::New();\n      m_ChangeInformationFilter = cif;\n\n      // Crop\n      using CropType = itk::CropImageFilter<InputImageType, InputImageType>;\n      auto crop = CropType::New();\n      m_CropFilter = crop;\n\n      // Conditional median\n      using ConditionalMedianType = rtk::ConditionalMedianImageFilter<InputImageType>;\n      auto cond = ConditionalMedianType::New();\n      m_ConditionalMedianFilter = cond;\n\n      // Bin\n      using BinType = itk::BinShrinkImageFilter<InputImageType, InputImageType>;\n      auto bin = BinType::New();\n      m_BinningFilter = bin;\n\n      // Scatter correction\n      using ScatterFilterType = rtk::BoellaardScatterCorrectionImageFilter<InputImageType, InputImageType>;\n      auto scatter = ScatterFilterType::New();\n      m_ScatterFilter = scatter;\n\n      // I0 estimation filter (shunt from pipeline by default)\n      using I0EstimationFilterType = rtk::I0EstimationProjectionFilter<InputImageType, InputImageType>;\n      auto i0est = I0EstimationFilterType::New();\n      m_I0EstimationFilter = i0est;\n\n      // Convert raw to Projections\n      using RawFilterType = rtk::VarianObiRawImageFilter<InputImageType, OutputImageType>;\n      auto rawFilter = RawFilterType::New();\n      m_RawToAttenuationFilter = rawFilter;\n\n      // Or just cast to OutputImageType\n      using CastFilterType = itk::CastImageFilter<InputImageType, OutputImageType>;\n      auto castFilter = CastFilterType::New();\n      m_RawCastFilter = castFilter;\n    }\n    else if (imageIO->GetComponentType() == itk::ImageIOBase::IOComponentEnum::USHORT)\n    {\n      /////////// Ora, Elekta synergy, IBA / iMagX, unsigned short\n      using InputPixelType = unsigned short;\n      using InputImageType = itk::Image<InputPixelType, OutputImageDimension>;\n\n      // Reader\n      using ReaderType = itk::ImageSeriesReader<InputImageType>;\n      auto reader = ReaderType::New();\n      m_RawDataReader = reader;\n\n      // Change information\n      using ChangeInfoType = itk::ChangeInformationImageFilter<InputImageType>;\n      auto cif = ChangeInfoType::New();\n      m_ChangeInformationFilter = cif;\n\n      // Crop\n      using CropType = itk::CropImageFilter<InputImageType, InputImageType>;\n      auto crop = CropType::New();\n      m_CropFilter = crop;\n\n      // Elekta specific conversion of input raw data\n      if (!strcmp(imageIO->GetNameOfClass(), \"HisImageIO\"))\n      {\n        using ElektaRawType =\n          rtk::ElektaSynergyRawLookupTableImageFilter<itk::Image<unsigned short, OutputImageDimension>,\n                                                      itk::Image<unsigned short, OutputImageDimension>>;\n        auto elekta = ElektaRawType::New();\n        m_ElektaRawFilter = elekta;\n\n        // Backward compatibility for default Elekta parameters\n        OutputImageSizeType defaultCropSize;\n        defaultCropSize.Fill(0);\n        if (m_LowerBoundaryCropSize == defaultCropSize && m_UpperBoundaryCropSize == defaultCropSize)\n        {\n          m_LowerBoundaryCropSize.Fill(4);\n          m_LowerBoundaryCropSize[2] = 0;\n          m_UpperBoundaryCropSize.Fill(4);\n          m_UpperBoundaryCropSize[2] = 0;\n        }\n        if (m_I0 == itk::NumericTraits<double>::NonpositiveMin())\n          m_I0 = 65536;\n      }\n\n      // Conditional median\n      using ConditionalMedianType = rtk::ConditionalMedianImageFilter<InputImageType>;\n      auto cond = ConditionalMedianType::New();\n      m_ConditionalMedianFilter = cond;\n\n      // Bin\n      using BinType = itk::BinShrinkImageFilter<InputImageType, InputImageType>;\n      auto bin = BinType::New();\n      m_BinningFilter = bin;\n\n      // Ora & ushort specific conversion of input raw data\n      if (!strcmp(imageIO->GetNameOfClass(), \"OraImageIO\"))\n      {\n        using OraRawType = rtk::OraLookupTableImageFilter<OutputImageType>;\n        auto oraraw = OraRawType::New();\n        m_RawToAttenuationFilter = oraraw;\n      }\n      else\n      {\n        // Scatter correction\n        using ScatterFilterType = rtk::BoellaardScatterCorrectionImageFilter<InputImageType, InputImageType>;\n        auto scatter = ScatterFilterType::New();\n        m_ScatterFilter = scatter;\n\n        // I0 estimation filter (shunt from pipeline by default)\n        using I0EstimationFilterType = rtk::I0EstimationProjectionFilter<InputImageType, InputImageType>;\n        auto i0est = I0EstimationFilterType::New();\n        m_I0EstimationFilter = i0est;\n\n        // Convert raw to Projections\n        using RawFilterType = rtk::LUTbasedVariableI0RawToAttenuationImageFilter<InputImageType, OutputImageType>;\n        auto rawFilter = RawFilterType::New();\n        m_RawToAttenuationFilter = rawFilter;\n\n        // Or just casts to OutputImageType\n        using CastFilterType = itk::CastImageFilter<InputImageType, OutputImageType>;\n        auto castFilter = CastFilterType::New();\n        m_RawCastFilter = castFilter;\n      }\n    }\n    else\n    {\n      // If ImageIO has vector pixels, extract one component from it\n      if (!strcmp(imageIO->GetPixelTypeAsString(imageIO->GetPixelType()).c_str(), \"vector\"))\n      {\n        SET_INPUT_IMAGE_VECTOR_TYPE(float, 1)\n        SET_INPUT_IMAGE_VECTOR_TYPE(float, 2)\n        SET_INPUT_IMAGE_VECTOR_TYPE(float, 3)\n        SET_INPUT_IMAGE_VECTOR_TYPE(float, 4)\n        SET_INPUT_IMAGE_VECTOR_TYPE(float, 5)\n        SET_INPUT_IMAGE_VECTOR_TYPE(float, 6)\n        SET_INPUT_IMAGE_VECTOR_TYPE(double, 1)\n        SET_INPUT_IMAGE_VECTOR_TYPE(double, 2)\n        SET_INPUT_IMAGE_VECTOR_TYPE(double, 3)\n        SET_INPUT_IMAGE_VECTOR_TYPE(double, 4)\n        SET_INPUT_IMAGE_VECTOR_TYPE(double, 5)\n        SET_INPUT_IMAGE_VECTOR_TYPE(double, 6)\n      }\n      else\n      {\n        ///////////// Default: whatever the format, we assume that we directly\n        //// read the Projections\n        using ReaderType = itk::ImageSeriesReader<OutputImageType>;\n        auto reader = ReaderType::New();\n        m_RawDataReader = reader;\n      }\n\n      // Change information\n      using ChangeInfoType = itk::ChangeInformationImageFilter<OutputImageType>;\n      auto cif = ChangeInfoType::New();\n      m_ChangeInformationFilter = cif;\n\n      // Crop\n      using CropType = itk::CropImageFilter<OutputImageType, OutputImageType>;\n      auto crop = CropType::New();\n      m_CropFilter = crop;\n\n      // Conditional median\n      using ConditionalMedianType = rtk::ConditionalMedianImageFilter<OutputImageType>;\n      auto cond = ConditionalMedianType::New();\n      m_ConditionalMedianFilter = cond;\n\n      // Bin\n      using BinType = itk::BinShrinkImageFilter<OutputImageType, OutputImageType>;\n      auto bin = BinType::New();\n      m_BinningFilter = bin;\n    }\n\n    // Store imageIO to avoid creating the pipe more than necessary\n    m_ImageIO = imageIO;\n  }\n\n  // Parameter propagation\n  if (imageIO->GetComponentType() == itk::ImageIOBase::IOComponentEnum::USHORT)\n    PropagateParametersToMiniPipeline<itk::Image<unsigned short, OutputImageDimension>>();\n  else if (!strcmp(imageIO->GetNameOfClass(), \"HndImageIO\") || !strcmp(imageIO->GetNameOfClass(), \"XimImageIO\"))\n    PropagateParametersToMiniPipeline<itk::Image<unsigned int, OutputImageDimension>>();\n  else\n    PropagateParametersToMiniPipeline<OutputImageType>();\n\n  // Set output information as provided by the pipeline\n  m_StreamingFilter->UpdateOutputInformation();\n  TOutputImage * output = this->GetOutput();\n  output->SetOrigin(m_StreamingFilter->GetOutput()->GetOrigin());\n  output->SetSpacing(m_StreamingFilter->GetOutput()->GetSpacing());\n  output->SetDirection(m_StreamingFilter->GetOutput()->GetDirection());\n  output->SetLargestPossibleRegion(m_StreamingFilter->GetOutput()->GetLargestPossibleRegion());\n}\n\n//--------------------------------------------------------------------\ntemplate <class TOutputImage>\nvoid\nProjectionsReader<TOutputImage>::GenerateData()\n{\n  TOutputImage * output = this->GetOutput();\n  m_StreamingFilter->SetNumberOfStreamDivisions(output->GetRequestedRegion().GetSize(TOutputImage::ImageDimension - 1));\n  m_StreamingFilter->GetOutput()->SetRequestedRegion(output->GetRequestedRegion());\n  m_StreamingFilter->Update();\n  this->GraftOutput(m_StreamingFilter->GetOutput());\n}\n\n//--------------------------------------------------------------------\ntemplate <class TOutputImage>\ntemplate <class TInputImage>\nvoid\nProjectionsReader<TOutputImage>::PropagateParametersToMiniPipeline()\n{\n  TInputImage *     nextInput = nullptr;\n  OutputImageType * output = nullptr;\n\n  // Vector component selection\n  if (m_VectorComponentSelectionFilter.GetPointer() != nullptr)\n  {\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(float, 1)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(float, 2)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(float, 3)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(float, 4)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(float, 5)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(float, 6)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(double, 1)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(double, 2)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(double, 3)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(double, 4)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(double, 5)\n    PROPAGATE_INPUT_IMAGE_VECTOR_TYPE(double, 6)\n  }\n  else // Regular case\n  {\n    // Raw\n    using RawType = typename itk::ImageSeriesReader<TInputImage>;\n    auto * raw = dynamic_cast<RawType *>(m_RawDataReader.GetPointer());\n    assert(raw != nullptr);\n    raw->SetFileNames(this->GetFileNames());\n    raw->SetImageIO(m_ImageIO);\n    nextInput = raw->GetOutput();\n\n    // Image information\n    OutputImageSpacingType defaultSpacing;\n    defaultSpacing.Fill(itk::NumericTraits<typename OutputImageType::SpacingValueType>::max());\n    OutputImagePointType defaultOrigin;\n    defaultOrigin.Fill(itk::NumericTraits<typename OutputImageType::PointValueType>::max());\n    OutputImageDirectionType defaultDirection;\n    defaultDirection.Fill(itk::NumericTraits<typename OutputImageType::PointValueType>::max());\n    if (m_Spacing != defaultSpacing || m_Origin != defaultOrigin || m_Direction != defaultDirection)\n    {\n      if (m_ChangeInformationFilter.GetPointer() == nullptr)\n      {\n        itkGenericExceptionMacro(<< \"Can not change image information with this input (not implemented)\");\n      }\n      else\n      {\n        using ChangeInfoType = itk::ChangeInformationImageFilter<TInputImage>;\n        auto * cif = dynamic_cast<ChangeInfoType *>(m_ChangeInformationFilter.GetPointer());\n        assert(cif != nullptr);\n        if (m_Spacing != defaultSpacing)\n        {\n          cif->SetOutputSpacing(m_Spacing);\n          cif->ChangeSpacingOn();\n        }\n        if (m_Origin != defaultOrigin)\n        {\n          cif->SetOutputOrigin(m_Origin);\n          cif->ChangeOriginOn();\n        }\n        if (m_Direction != defaultDirection)\n        {\n          cif->SetOutputDirection(m_Direction);\n          cif->ChangeDirectionOn();\n        }\n        cif->SetInput(nextInput);\n        nextInput = cif->GetOutput();\n      }\n    }\n\n    // Crop\n    OutputImageSizeType defaultCropSize;\n    defaultCropSize.Fill(0);\n    if (m_LowerBoundaryCropSize != defaultCropSize || m_UpperBoundaryCropSize != defaultCropSize)\n    {\n      if (m_CropFilter.GetPointer() == nullptr)\n      {\n        itkGenericExceptionMacro(<< \"Can not crop images read with this input (not implemented)\");\n      }\n      else\n      {\n        using CropType = itk::CropImageFilter<TInputImage, TInputImage>;\n        auto * crop = dynamic_cast<CropType *>(m_CropFilter.GetPointer());\n        assert(crop != nullptr);\n        crop->SetLowerBoundaryCropSize(m_LowerBoundaryCropSize);\n        crop->SetUpperBoundaryCropSize(m_UpperBoundaryCropSize);\n        crop->SetInput(nextInput);\n        nextInput = crop->GetOutput();\n      }\n    }\n\n    // Elekta raw data converter\n    auto * nextInputBase = dynamic_cast<itk::ImageBase<OutputImageDimension> *>(nextInput);\n    assert(nextInputBase != nullptr);\n    ConnectElektaRawFilter(&nextInputBase);\n    nextInput = dynamic_cast<TInputImage *>(nextInputBase);\n    assert(nextInput != nullptr);\n\n    // Conditional median\n    MedianRadiusType defaultMedianRadius;\n    defaultMedianRadius.Fill(0);\n    if (m_MedianRadius != defaultMedianRadius)\n    {\n      if (m_ConditionalMedianFilter.GetPointer() == nullptr)\n      {\n        itkGenericExceptionMacro(<< \"Can not apply conditional median filter on this input (not implemented)\");\n      }\n      else\n      {\n        using ConditionalMedianType = rtk::ConditionalMedianImageFilter<TInputImage>;\n        auto * cond = dynamic_cast<ConditionalMedianType *>(m_ConditionalMedianFilter.GetPointer());\n        assert(cond != nullptr);\n        cond->SetRadius(m_MedianRadius);\n        cond->SetInput(nextInput);\n        cond->SetThresholdMultiplier(m_ConditionalMedianThresholdMultiplier);\n        nextInput = cond->GetOutput();\n      }\n    }\n\n    // Binning\n    ShrinkFactorsType defaultShrinkFactors;\n    defaultShrinkFactors.Fill(1);\n    if (m_ShrinkFactors != defaultShrinkFactors)\n    {\n      if (m_BinningFilter.GetPointer() == nullptr)\n      {\n        itkGenericExceptionMacro(<< \"Can not bin / shrink images read with this input (not implemented)\");\n      }\n      else\n      {\n        using BinType = itk::BinShrinkImageFilter<TInputImage, TInputImage>;\n        auto * bin = dynamic_cast<BinType *>(m_BinningFilter.GetPointer());\n        assert(bin != nullptr);\n        bin->SetShrinkFactors(m_ShrinkFactors);\n        bin->SetInput(nextInput);\n        nextInput = bin->GetOutput();\n      }\n    }\n\n    // Boellaard scatter correction\n    if (m_NonNegativityConstraintThreshold != itk::NumericTraits<double>::NonpositiveMin() ||\n        m_ScatterToPrimaryRatio != 0.)\n    {\n      if (m_ScatterFilter.GetPointer() == nullptr)\n      {\n        itkGenericExceptionMacro(<< \"Can not use Boellaard scatter correction with this input (not implemented)\");\n      }\n      else\n      {\n        using ScatterFilterType = rtk::BoellaardScatterCorrectionImageFilter<TInputImage, TInputImage>;\n        auto * scatter = dynamic_cast<ScatterFilterType *>(m_ScatterFilter.GetPointer());\n        assert(scatter != nullptr);\n        scatter->SetAirThreshold(m_AirThreshold);\n        scatter->SetScatterToPrimaryRatio(m_ScatterToPrimaryRatio);\n        if (m_NonNegativityConstraintThreshold != itk::NumericTraits<double>::NonpositiveMin())\n          scatter->SetNonNegativityConstraintThreshold(m_NonNegativityConstraintThreshold);\n        scatter->SetInput(nextInput);\n        nextInput = scatter->GetOutput();\n      }\n    }\n\n    // LUTbasedVariableI0RawToAttenuationImageFilter\n    if (m_I0 != itk::NumericTraits<double>::NonpositiveMin())\n    {\n      if (m_RawToAttenuationFilter.GetPointer() == nullptr)\n      {\n        itkGenericExceptionMacro(\n          << \"Can not use I0 in LUTbasedVariableI0RawToAttenuationImageFilter with this input (not implemented)\");\n      }\n      else\n      {\n        nextInputBase = dynamic_cast<itk::ImageBase<OutputImageDimension> *>(nextInput);\n        assert(nextInputBase != nullptr);\n        PropagateI0(&nextInputBase);\n        nextInput = dynamic_cast<TInputImage *>(nextInputBase);\n        assert(nextInput != nullptr);\n      }\n    }\n\n    // Raw to attenuation or cast filter, change of type\n    if (m_RawToAttenuationFilter.GetPointer() != nullptr)\n    {\n      // Check if Ora pointer\n      using OraRawType = rtk::OraLookupTableImageFilter<OutputImageType>;\n      auto * oraraw = dynamic_cast<OraRawType *>(m_RawToAttenuationFilter.GetPointer());\n      if (oraraw != nullptr)\n      {\n        oraraw->SetComputeLineIntegral(m_ComputeLineIntegral);\n        oraraw->SetFileNames(m_FileNames);\n      }\n\n      // Cast or convert to line integral depending on m_ComputeLineIntegral\n      using IToIFilterType = itk::ImageToImageFilter<TInputImage, OutputImageType>;\n      IToIFilterType * itoi = nullptr;\n      if (m_ComputeLineIntegral || oraraw != nullptr)\n        itoi = dynamic_cast<IToIFilterType *>(m_RawToAttenuationFilter.GetPointer());\n      else\n        itoi = dynamic_cast<IToIFilterType *>(m_RawCastFilter.GetPointer());\n      assert(itoi != nullptr);\n      itoi->SetInput(nextInput);\n      output = itoi->GetOutput();\n\n      // Release output data of m_RawDataReader if conversion occurs\n      itoi->ReleaseDataFlagOn();\n    }\n    else\n    {\n      output = dynamic_cast<OutputImageType *>(nextInput);\n      assert(output != nullptr);\n    }\n\n    // ESRF raw to attenuation converter also needs the filenames\n    auto * edf = dynamic_cast<rtk::EdfRawToAttenuationImageFilter<TInputImage, OutputImageType> *>(\n      m_RawToAttenuationFilter.GetPointer());\n    if (edf)\n      edf->SetFileNames(this->GetFileNames());\n\n    // Water coefficients\n    if (!m_WaterPrecorrectionCoefficients.empty())\n    {\n      m_WaterPrecorrectionFilter->SetCoefficients(m_WaterPrecorrectionCoefficients);\n      m_WaterPrecorrectionFilter->SetInput(output);\n      output = m_WaterPrecorrectionFilter->GetOutput();\n    }\n  }\n  // Streaming image filter\n  m_StreamingFilter->SetInput(output);\n}\n\n//--------------------------------------------------------------------\ntemplate <class TOutputImage>\nvoid\nProjectionsReader<TOutputImage>::ConnectElektaRawFilter(itk::ImageBase<OutputImageDimension> ** nextInputBase)\n{\n  if (m_ElektaRawFilter.GetPointer() != nullptr)\n  {\n    using ElektaRawType = rtk::ElektaSynergyRawLookupTableImageFilter<itk::Image<unsigned short, OutputImageDimension>,\n                                                                      itk::Image<unsigned short, OutputImageDimension>>;\n    auto * elektaRaw = dynamic_cast<ElektaRawType *>(m_ElektaRawFilter.GetPointer());\n    assert(elektaRaw != nullptr);\n    using InputImageType = typename itk::Image<unsigned short, OutputImageDimension>;\n    auto * nextInput = dynamic_cast<InputImageType *>(*nextInputBase);\n    elektaRaw->SetInput(nextInput);\n    *nextInputBase = elektaRaw->GetOutput();\n  }\n}\n\n//--------------------------------------------------------------------\ntemplate <class TOutputImage>\nvoid\nProjectionsReader<TOutputImage>::PropagateI0(itk::ImageBase<OutputImageDimension> ** nextInputBase)\n{\n  using UnsignedShortImageType = itk::Image<unsigned short, OutputImageDimension>;\n  auto * nextInputUShort = dynamic_cast<UnsignedShortImageType *>(*nextInputBase);\n  if (nextInputUShort != nullptr)\n  {\n    if (m_I0 == 0)\n    {\n      using I0EstimationType = rtk::I0EstimationProjectionFilter<UnsignedShortImageType, UnsignedShortImageType>;\n      auto * i0est = dynamic_cast<I0EstimationType *>(m_I0EstimationFilter.GetPointer());\n      assert(i0est != nullptr);\n      i0est->SetInput(nextInputUShort);\n      *nextInputBase = i0est->GetOutput();\n    }\n    using I0Type = rtk::LUTbasedVariableI0RawToAttenuationImageFilter<UnsignedShortImageType, OutputImageType>;\n    auto * i0 = dynamic_cast<I0Type *>(m_RawToAttenuationFilter.GetPointer());\n    i0->SetI0(m_I0);\n    i0->SetIDark(m_IDark);\n  }\n\n  using UnsignedIntImageType = itk::Image<unsigned int, OutputImageDimension>;\n  auto * nextInputUInt = dynamic_cast<UnsignedIntImageType *>(*nextInputBase);\n  if (nextInputUInt != nullptr)\n  {\n    if (m_I0 == 0)\n    {\n      using I0EstimationType = rtk::I0EstimationProjectionFilter<UnsignedIntImageType, UnsignedIntImageType>;\n      auto * i0est = dynamic_cast<I0EstimationType *>(m_I0EstimationFilter.GetPointer());\n      assert(i0est != nullptr);\n      i0est->SetInput(nextInputUInt);\n      *nextInputBase = i0est->GetOutput();\n    }\n    using I0Type = rtk::VarianObiRawImageFilter<UnsignedIntImageType, OutputImageType>;\n    auto * i0 = dynamic_cast<I0Type *>(m_RawToAttenuationFilter.GetPointer());\n    i0->SetI0(m_I0);\n    i0->SetIDark(m_IDark);\n  }\n  // Pipeline connection for m_RawToAttenuationFilter is done after the call to this function\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsRegionConstIteratorRayBased.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionsRegionConstIteratorRayBased_h\n#define rtkProjectionsRegionConstIteratorRayBased_h\n\n#include <itkImageConstIteratorWithIndex.h>\n\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n/** \\class ProjectionsRegionConstIteratorRayBased\n * \\brief Iterate over a projection stack with corresponding ray information\n *\n * Base class for iterating over the pixels of projection images with the\n * and having at the same time the geometry information for the corresponding\n * source to pixel ray, defined by a 3D source position and a 3D pixel position.\n * The iterator provides this information in mm, unless a 3D matrix is provided\n * to convert the mm value of the coordinates of the two points to some other\n * coordinate system. A typical example is the mm to voxel matrix to work in\n * voxel coordinates. The iterator only works with the\n * ThreeDCircularProjectionGeometry is purely virtual because this geometry\n * can handle parallel geometry with flat panels and cone-beam geometries with\n * flat and curved detectors.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <typename TImage>\nclass ProjectionsRegionConstIteratorRayBasedWithFlatPanel;\ntemplate <typename TImage>\nclass ProjectionsRegionConstIteratorRayBasedWithCylindricalPanel;\ntemplate <typename TImage>\nclass ProjectionsRegionConstIteratorRayBasedParallel;\n\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT ProjectionsRegionConstIteratorRayBased : public itk::ImageConstIteratorWithIndex<TImage>\n{\npublic:\n  /** Standard class type alias. */\n  using Self = ProjectionsRegionConstIteratorRayBased;\n  using Superclass = itk::ImageConstIteratorWithIndex<TImage>;\n\n  /**\n   * Index type alias support While these were already typdef'ed in the superclass\n   * they need to be redone here for this subclass to compile properly with gcc.\n   */\n  /** Types inherited from the Superclass */\n  using OffsetValueType = typename Superclass::OffsetValueType;\n  using RegionType = typename Superclass::RegionType;\n  using PointType = typename itk::Vector<double, 3>;\n  using IndexValueType = typename Superclass::IndexValueType;\n\n  using MatrixType = itk::Matrix<double, 3, 4>;\n  using HomogeneousMatrixType = itk::Matrix<double, 4, 4>;\n\n  /** Constructor establishes an iterator to walk a particular image and a\n   * particular region of that image.\n   * Set the matrix by which the 3D coordinates of the projection can be\n   * multiplied. A typical example is the conversion from 3D physical\n   * coordinates to voxel indices in an itk Image. */\n  ProjectionsRegionConstIteratorRayBased(const TImage *                           ptr,\n                                         const RegionType &                       region,\n                                         const ThreeDCircularProjectionGeometry * geometry,\n                                         const MatrixType &                       postMat);\n\n  static Self *\n  New(const TImage *                           ptr,\n      const RegionType &                       region,\n      const ThreeDCircularProjectionGeometry * geometry,\n      const MatrixType &                       postMat);\n\n  static Self *\n  New(const TImage *                           ptr,\n      const RegionType &                       region,\n      const ThreeDCircularProjectionGeometry * geometry,\n      const HomogeneousMatrixType &            postMat);\n\n  static Self *\n  New(const TImage * ptr, const RegionType & region, const ThreeDCircularProjectionGeometry * geometry);\n\n  /** Increment (prefix) the fastest moving dimension of the iterator's index.\n   * This operator will constrain the iterator within the region (i.e. the\n   * iterator will automatically wrap from the end of the row of the region\n   * to the beginning of the next row of the region) up until the iterator\n   * tries to moves past the last pixel of the region.  Here, the iterator\n   * will be set to be one pixel past the end of the region.\n   * \\sa operator-- */\n  Self &\n  operator++();\n\n  /** Go to the next pixel by simply calling the ++ operator. Should not be\n   * the ++ operator should be. The function is provided for cosmetic\n   * reasons, because pointers to these iterators will be used more than the\n   * iterator itself. */\n  void\n  Next()\n  {\n    ++*this;\n  }\n\n  /** Get ray information. A ray is described by the 3D coordinates of two points,\n   * the (current) SourcePosition and the (current) PixelPosition in the\n   * projection stack. The difference, SourceToPixel, is also computed and\n   * stored for every ray. */\n  const PointType &\n  GetSourcePosition()\n  {\n    return this->m_SourcePosition;\n  }\n  const PointType &\n  GetPixelPosition()\n  {\n    return this->m_PixelPosition;\n  }\n  const PointType &\n  GetSourceToPixel()\n  {\n    return this->m_SourceToPixel;\n  }\n\n  /** Computes and returns a unit vector pointing from the source to the\n   * current pixel, i.e., GetSourceToPixel()/||GetSourceToPixel()||. */\n  const PointType\n  GetDirection()\n  {\n    return m_SourceToPixel / m_SourceToPixel.GetNorm();\n  }\n\nprotected:\n  /** Init the parameters common to a new 2D projection in the 3D stack. */\n  virtual void\n  NewProjection() = 0;\n\n  /** Init a new pixel position in a 2D projection, assuming that the\n   * NewProjection method has already been called. */\n  virtual void\n  NewPixel() = 0;\n\n  ThreeDCircularProjectionGeometry::ConstPointer m_Geometry;\n  MatrixType                                     m_PostMultiplyMatrix;\n  PointType                                      m_SourcePosition;\n  PointType                                      m_PixelPosition;\n  PointType                                      m_SourceToPixel;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkProjectionsRegionConstIteratorRayBased.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsRegionConstIteratorRayBased.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkProjectionsRegionConstIteratorRayBased_hxx\n#define rtkProjectionsRegionConstIteratorRayBased_hxx\n\n#include \"rtkProjectionsRegionConstIteratorRayBasedParallel.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBasedWithFlatPanel.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBasedWithCylindricalPanel.h\"\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\ntemplate <typename TImage>\nProjectionsRegionConstIteratorRayBased<TImage>::ProjectionsRegionConstIteratorRayBased(\n  const TImage *                           ptr,\n  const RegionType &                       region,\n  const ThreeDCircularProjectionGeometry * geometry,\n  const MatrixType &                       postMat)\n  : itk::ImageConstIteratorWithIndex<TImage>(ptr, region)\n  , m_Geometry(geometry)\n  , m_PostMultiplyMatrix(postMat)\n{}\n\ntemplate <typename TImage>\nProjectionsRegionConstIteratorRayBased<TImage> &\nProjectionsRegionConstIteratorRayBased<TImage>::operator++()\n{\n  // This code is copy pasted from itkProjectionsRegionConstIteratorRayBased since\n  // operators are not virtual.\n  this->m_Remaining = false;\n  unsigned int in = 0;\n  for (in = 0; in < TImage::ImageDimension; in++)\n  {\n    this->m_PositionIndex[in]++;\n    if (this->m_PositionIndex[in] < this->m_EndIndex[in])\n    {\n      this->m_Position += this->m_OffsetTable[in];\n      this->m_Remaining = true;\n      break;\n    }\n    else\n    {\n      this->m_Position -= this->m_OffsetTable[in] * (static_cast<OffsetValueType>(this->m_Region.GetSize()[in]) - 1);\n      this->m_PositionIndex[in] = this->m_BeginIndex[in];\n    }\n  }\n\n  if (!this->m_Remaining) // It will not advance here otherwise\n  {\n    this->m_Position = this->m_End;\n    return *this;\n  }\n\n  if (in == 2)\n  {\n    NewProjection();\n  }\n  NewPixel();\n\n  return *this;\n}\n\ntemplate <typename TImage>\nProjectionsRegionConstIteratorRayBased<TImage> *\nProjectionsRegionConstIteratorRayBased<TImage>::New(const TImage *                           ptr,\n                                                    const RegionType &                       region,\n                                                    const ThreeDCircularProjectionGeometry * geometry,\n                                                    const MatrixType &                       postMat)\n{\n  if (geometry->GetSourceToDetectorDistances().empty())\n  {\n    itkGenericExceptionMacro(<< \"Geometry is empty, cannot determine iterator type.\");\n  }\n  if (geometry->GetSourceToDetectorDistances()[0] == 0.)\n  {\n    if (geometry->GetRadiusCylindricalDetector() != 0.)\n    {\n      itkGenericExceptionMacro(<< \"Parallel geometry assumes a flat panel detector.\");\n    }\n    using IteratorType = ProjectionsRegionConstIteratorRayBasedParallel<TImage>;\n    return new IteratorType(ptr, region, geometry, postMat);\n  }\n  else if (geometry->GetRadiusCylindricalDetector() == 0.)\n  {\n    using IteratorType = ProjectionsRegionConstIteratorRayBasedWithFlatPanel<TImage>;\n    return new IteratorType(ptr, region, geometry, postMat);\n  }\n  else\n  {\n    using IteratorType = ProjectionsRegionConstIteratorRayBasedWithCylindricalPanel<TImage>;\n    return new IteratorType(ptr, region, geometry, postMat);\n  }\n}\n\ntemplate <typename TImage>\nProjectionsRegionConstIteratorRayBased<TImage> *\nProjectionsRegionConstIteratorRayBased<TImage>::New(const TImage *                           ptr,\n                                                    const RegionType &                       region,\n                                                    const ThreeDCircularProjectionGeometry * geometry,\n                                                    const HomogeneousMatrixType &            postMat)\n{\n  MatrixType pm;\n  for (unsigned int i = 0; i < MatrixType::RowDimensions; i++)\n    for (unsigned int j = 0; j < MatrixType::ColumnDimensions; j++)\n      pm[i][j] = postMat[i][j];\n  return New(ptr, region, geometry, pm);\n}\n\ntemplate <class TImage>\nrtk::ProjectionsRegionConstIteratorRayBased<TImage> *\nProjectionsRegionConstIteratorRayBased<TImage>::New(const TImage *                           ptr,\n                                                    const RegionType &                       region,\n                                                    const ThreeDCircularProjectionGeometry * geometry)\n{\n  MatrixType postMat;\n  postMat.SetIdentity();\n  return New(ptr, region, geometry, postMat);\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsRegionConstIteratorRayBasedParallel.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionsRegionConstIteratorRayBasedParallel_h\n#define rtkProjectionsRegionConstIteratorRayBasedParallel_h\n\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\nnamespace rtk\n{\n/** \\class ProjectionsRegionConstIteratorRayBasedParallel\n *\n * \\brief Implements a ray-based iterator for a parallel beam and a flat panel.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT ProjectionsRegionConstIteratorRayBasedParallel\n  : public ProjectionsRegionConstIteratorRayBased<TImage>\n{\npublic:\n  /** Standard class type alias. */\n  using Self = ProjectionsRegionConstIteratorRayBasedParallel;\n  using Superclass = ProjectionsRegionConstIteratorRayBased<TImage>;\n\n  /**\n   * Index type alias support While these were already typdef'ed in the superclass\n   * they need to be redone here for this subclass to compile properly with gcc.\n   */\n  /** Types inherited from the Superclass */\n  using OffsetValueType = typename Superclass::OffsetValueType;\n  using RegionType = typename Superclass::RegionType;\n  using PointType = typename itk::Vector<double, 3>;\n  using MatrixType = typename Superclass::MatrixType;\n  using HomogeneousMatrixType = itk::Matrix<double, 4, 4>;\n  using RotationMatrixType = itk::Matrix<double, 3, 3>;\n\n  /** Constructor establishes an iterator to walk a particular image and a\n   * particular region of that image.\n   * Set the matrix by which the 3D coordinates of the projection can be\n   * multiplied. A typical example is the conversion from 3D physical\n   * coordinates to voxel indices in an itk Image. */\n  ProjectionsRegionConstIteratorRayBasedParallel(const TImage *                           ptr,\n                                                 const RegionType &                       region,\n                                                 const ThreeDCircularProjectionGeometry * geometry,\n                                                 const MatrixType &                       postMat);\n\nprotected:\n  /** Init the parameters common to a new 2D projection in the 3D stack. */\n  inline void\n  NewProjection() override;\n\n  /** Init a new pixel position in a 2D projection, assuming that the\n   * NewProjection method has already been called. */\n  inline void\n  NewPixel() override;\n\n  MatrixType         m_ProjectionIndexTransformMatrix;\n  RotationMatrixType m_PostRotationMatrix;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkProjectionsRegionConstIteratorRayBasedParallel.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsRegionConstIteratorRayBasedParallel.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkProjectionsRegionConstIteratorRayBasedParallel_hxx\n#define rtkProjectionsRegionConstIteratorRayBasedParallel_hxx\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\ntemplate <typename TImage>\nProjectionsRegionConstIteratorRayBasedParallel<TImage>::ProjectionsRegionConstIteratorRayBasedParallel(\n  const TImage *                           ptr,\n  const RegionType &                       region,\n  const ThreeDCircularProjectionGeometry * geometry,\n  const MatrixType &                       postMat)\n  : ProjectionsRegionConstIteratorRayBased<TImage>(ptr, region, geometry, postMat)\n{\n  m_PostRotationMatrix = postMat.GetVnlMatrix().extract(3, 3);\n  NewProjection();\n  NewPixel();\n}\n\ntemplate <typename TImage>\nvoid\nProjectionsRegionConstIteratorRayBasedParallel<TImage>::NewProjection()\n{\n  // Set source position in volume indices\n  // GetSourcePosition() returns coordinates in mm. Multiplying by\n  // volPPToIndex gives the corresponding volume index\n  this->m_SourceToPixel[0] = this->m_Geometry->GetRotationMatrices()[this->m_PositionIndex[2]][2][0];\n  this->m_SourceToPixel[1] = this->m_Geometry->GetRotationMatrices()[this->m_PositionIndex[2]][2][1];\n  this->m_SourceToPixel[2] = this->m_Geometry->GetRotationMatrices()[this->m_PositionIndex[2]][2][2];\n  this->m_SourceToPixel *= -2. * this->m_Geometry->GetSourceToIsocenterDistances()[this->m_PositionIndex[2]];\n  this->m_SourceToPixel = m_PostRotationMatrix * this->m_SourceToPixel;\n\n  // Compute matrix to transform projection index to volume index\n  // IndexToPhysicalPointMatrix maps the 2D index of a projection's pixel to its 2D position on the detector (in mm)\n  // ProjectionCoordinatesToFixedSystemMatrix maps the 2D position of a pixel on the detector to its 3D coordinates in\n  // volume's coordinates (still in mm) volPPToIndex maps 3D volume coordinates to a 3D index\n  m_ProjectionIndexTransformMatrix =\n    this->m_PostMultiplyMatrix.GetVnlMatrix() *\n    this->m_Geometry->GetProjectionCoordinatesToFixedSystemMatrix(this->m_PositionIndex[2]).GetVnlMatrix() *\n    GetIndexToPhysicalPointMatrix(this->m_Image.GetPointer()).GetVnlMatrix();\n}\n\ntemplate <typename TImage>\nvoid\nProjectionsRegionConstIteratorRayBasedParallel<TImage>::NewPixel()\n{\n  // Compute point coordinate in volume depending on projection index\n  for (unsigned int i = 0; i < this->GetImageDimension(); i++)\n  {\n    this->m_PixelPosition[i] = m_ProjectionIndexTransformMatrix[i][this->GetImageDimension()];\n    for (unsigned int j = 0; j < this->GetImageDimension(); j++)\n      this->m_PixelPosition[i] += m_ProjectionIndexTransformMatrix[i][j] * this->m_PositionIndex[j];\n  }\n\n  this->m_SourcePosition = this->m_PixelPosition - this->m_SourceToPixel;\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsRegionConstIteratorRayBasedWithCylindricalPanel.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionsRegionConstIteratorRayBasedWithCylindricalPanel_h\n#define rtkProjectionsRegionConstIteratorRayBasedWithCylindricalPanel_h\n\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\nnamespace rtk\n{\n/** \\class ProjectionsRegionConstIteratorRayBasedWithCylindricalPanel\n *\n * \\brief Implements a ray-based iterator for a point source and a cylindrical panel\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT ProjectionsRegionConstIteratorRayBasedWithCylindricalPanel\n  : public ProjectionsRegionConstIteratorRayBased<TImage>\n{\npublic:\n  /** Standard class type alias. */\n  using Self = ProjectionsRegionConstIteratorRayBasedWithCylindricalPanel;\n  using Superclass = ProjectionsRegionConstIteratorRayBased<TImage>;\n\n  /**\n   * Index type alias support While these were already typdef'ed in the superclass\n   * they need to be redone here for this subclass to compile properly with gcc.\n   */\n  /** Types inherited from the Superclass */\n  using OffsetValueType = typename Superclass::OffsetValueType;\n  using RegionType = typename Superclass::RegionType;\n  using MatrixType = typename Superclass::MatrixType;\n  using IndexValueType = typename Superclass::IndexValueType;\n\n  using PointType = typename itk::Vector<double, 3>;\n  using HomogeneousMatrixType = itk::Matrix<double, 4, 4>;\n\n  /** Constructor establishes an iterator to walk a particular image and a\n   * particular region of that image.\n   * Set the matrix by which the 3D coordinates of the projection can be\n   * multiplied. A typical example is the conversion from 3D physical\n   * coordinates to voxel indices in an itk Image. */\n  ProjectionsRegionConstIteratorRayBasedWithCylindricalPanel(const TImage *                           ptr,\n                                                             const RegionType &                       region,\n                                                             const ThreeDCircularProjectionGeometry * geometry,\n                                                             const MatrixType &                       postMat);\n\nprotected:\n  /** Init the parameters common to a new 2D projection in the 3D stack. */\n  inline void\n  NewProjection() override;\n\n  /** Init a new pixel position in a 2D projection, assuming that the\n   * NewProjection method has already been called. */\n  inline void\n  NewPixel() override;\n\n  HomogeneousMatrixType m_ProjectionIndexTransformMatrix;\n  MatrixType            m_VolumeTransformMatrix;\n  double                m_Radius;\n  double                m_InverseRadius;\n  double                m_SourceToIsocenterDistance;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkProjectionsRegionConstIteratorRayBasedWithCylindricalPanel.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsRegionConstIteratorRayBasedWithCylindricalPanel.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkProjectionsRegionConstIteratorRayBasedWithCylindricalPanel_hxx\n#define rtkProjectionsRegionConstIteratorRayBasedWithCylindricalPanel_hxx\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\ntemplate <typename TImage>\nProjectionsRegionConstIteratorRayBasedWithCylindricalPanel<\n  TImage>::ProjectionsRegionConstIteratorRayBasedWithCylindricalPanel(const TImage *                           ptr,\n                                                                      const RegionType &                       region,\n                                                                      const ThreeDCircularProjectionGeometry * geometry,\n                                                                      const MatrixType &                       postMat)\n  : ProjectionsRegionConstIteratorRayBased<TImage>(ptr, region, geometry, postMat)\n  , m_Radius(geometry->GetRadiusCylindricalDetector())\n  , m_InverseRadius(1. / geometry->GetRadiusCylindricalDetector())\n{\n  NewProjection();\n  NewPixel();\n}\n\ntemplate <typename TImage>\nvoid\nProjectionsRegionConstIteratorRayBasedWithCylindricalPanel<TImage>::NewProjection()\n{\n  // Index of the projection in the stack\n  IndexValueType iProj = this->m_PositionIndex[2];\n\n  m_SourceToIsocenterDistance = this->m_Geometry->GetSourceToIsocenterDistances()[iProj];\n\n  // Set source position in volume indices\n  // GetSourcePosition() returns coordinates in mm. Multiplying by\n  // volPPToIndex gives the corresponding volume index\n  this->m_SourcePosition = this->m_PostMultiplyMatrix * this->m_Geometry->GetSourcePosition(iProj);\n\n  // Compute matrix to transform projection index to position on a flat panel\n  // if the panel were flat, before accounting for the curvature\n  m_ProjectionIndexTransformMatrix =\n    this->m_Geometry->GetProjectionCoordinatesToDetectorSystemMatrix(iProj).GetVnlMatrix() *\n    GetIndexToPhysicalPointMatrix(this->m_Image.GetPointer()).GetVnlMatrix();\n\n  // Get transformation from coordinate in the (u,v,u^v) coordinate system to\n  // the tomography (fixed) coordinate system\n  m_VolumeTransformMatrix =\n    this->m_PostMultiplyMatrix.GetVnlMatrix() * this->m_Geometry->GetRotationMatrices()[iProj].GetInverse();\n}\n\ntemplate <typename TImage>\nvoid\nProjectionsRegionConstIteratorRayBasedWithCylindricalPanel<TImage>::NewPixel()\n{\n  // Position on the projection before applying rotations and m_PostMultiplyMatrix\n  PointType posProj;\n\n  // Compute point coordinate in volume depending on projection index\n  for (unsigned int i = 0; i < this->GetImageDimension(); i++)\n  {\n    posProj[i] = m_ProjectionIndexTransformMatrix[i][this->GetImageDimension()];\n    for (unsigned int j = 0; j < this->GetImageDimension(); j++)\n      posProj[i] += m_ProjectionIndexTransformMatrix[i][j] * this->m_PositionIndex[j];\n  }\n\n  // Convert cylindrical angle to coordinates in the (u,v,u^v) coordinate system\n  double a = m_InverseRadius * posProj[0];\n  posProj[0] = std::sin(a) * m_Radius;\n  posProj[2] += (1. - std::cos(a)) * m_Radius;\n\n  // Rotate and apply m_PostMultiplyMatrix\n  for (unsigned int i = 0; i < this->GetImageDimension(); i++)\n  {\n    this->m_PixelPosition[i] = m_VolumeTransformMatrix[i][this->GetImageDimension()];\n    for (unsigned int j = 0; j < this->GetImageDimension(); j++)\n      this->m_PixelPosition[i] += m_VolumeTransformMatrix[i][j] * posProj[j];\n  }\n\n  this->m_SourceToPixel = this->m_PixelPosition - this->m_SourcePosition;\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsRegionConstIteratorRayBasedWithFlatPanel.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkProjectionsRegionConstIteratorRayBasedWithFlatPanel_h\n#define rtkProjectionsRegionConstIteratorRayBasedWithFlatPanel_h\n\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\nnamespace rtk\n{\n/** \\class ProjectionsRegionConstIteratorRayBasedWithFlatPanel\n *\n * \\brief Implements a ray-based iterator for a point source and a flat panel\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT ProjectionsRegionConstIteratorRayBasedWithFlatPanel\n  : public ProjectionsRegionConstIteratorRayBased<TImage>\n{\npublic:\n  /** Standard class type alias. */\n  using Self = ProjectionsRegionConstIteratorRayBasedWithFlatPanel;\n  using Superclass = ProjectionsRegionConstIteratorRayBased<TImage>;\n\n  /**\n   * Index type alias support While these were already typdef'ed in the superclass\n   * they need to be redone here for this subclass to compile properly with gcc.\n   */\n  /** Types inherited from the Superclass */\n  using OffsetValueType = typename Superclass::OffsetValueType;\n  using RegionType = typename Superclass::RegionType;\n  using PointType = typename itk::Vector<double, 3>;\n  using MatrixType = typename Superclass::MatrixType;\n  using HomogeneousMatrixType = itk::Matrix<double, 4, 4>;\n\n  /** Constructor establishes an iterator to walk a particular image and a\n   * particular region of that image.\n   * Set the matrix by which the 3D coordinates of the projection can be\n   * multiplied. A typical example is the conversion from 3D physical\n   * coordinates to voxel indices in an itk Image. */\n  ProjectionsRegionConstIteratorRayBasedWithFlatPanel(const TImage *                           ptr,\n                                                      const RegionType &                       region,\n                                                      const ThreeDCircularProjectionGeometry * geometry,\n                                                      const MatrixType &                       postMat);\n\nprotected:\n  /** Init the parameters common to a new 2D projection in the 3D stack. */\n  inline void\n  NewProjection() override;\n\n  /** Init a new pixel position in a 2D projection, assuming that the\n   * NewProjection method has already been called. */\n  inline void\n  NewPixel() override;\n\n  MatrixType m_ProjectionIndexTransformMatrix;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkProjectionsRegionConstIteratorRayBasedWithFlatPanel.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkProjectionsRegionConstIteratorRayBasedWithFlatPanel.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkProjectionsRegionConstIteratorRayBasedWithFlatPanel_hxx\n#define rtkProjectionsRegionConstIteratorRayBasedWithFlatPanel_hxx\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\ntemplate <typename TImage>\nProjectionsRegionConstIteratorRayBasedWithFlatPanel<TImage>::ProjectionsRegionConstIteratorRayBasedWithFlatPanel(\n  const TImage *                           ptr,\n  const RegionType &                       region,\n  const ThreeDCircularProjectionGeometry * geometry,\n  const MatrixType &                       postMat)\n  : ProjectionsRegionConstIteratorRayBased<TImage>(ptr, region, geometry, postMat)\n{\n  NewProjection();\n  NewPixel();\n}\n\ntemplate <typename TImage>\nvoid\nProjectionsRegionConstIteratorRayBasedWithFlatPanel<TImage>::NewProjection()\n{\n  // Set source position in volume indices\n  // GetSourcePosition() returns coordinates in mm. Multiplying by\n  // volPPToIndex gives the corresponding volume index\n  this->m_SourcePosition = this->m_PostMultiplyMatrix * this->m_Geometry->GetSourcePosition(this->m_PositionIndex[2]);\n\n  // Compute matrix to transform projection index to volume index\n  // IndexToPhysicalPointMatrix maps the 2D index of a projection's pixel to its 2D position on the detector (in mm)\n  // ProjectionCoordinatesToFixedSystemMatrix maps the 2D position of a pixel on the detector to its 3D coordinates in\n  // volume's coordinates (still in mm) volPPToIndex maps 3D volume coordinates to a 3D index\n  m_ProjectionIndexTransformMatrix =\n    this->m_PostMultiplyMatrix.GetVnlMatrix() *\n    this->m_Geometry->GetProjectionCoordinatesToFixedSystemMatrix(this->m_PositionIndex[2]).GetVnlMatrix() *\n    GetIndexToPhysicalPointMatrix(this->m_Image.GetPointer()).GetVnlMatrix();\n}\n\ntemplate <typename TImage>\nvoid\nProjectionsRegionConstIteratorRayBasedWithFlatPanel<TImage>::NewPixel()\n{\n  // Compute point coordinate in volume depending on projection index\n  for (unsigned int i = 0; i < this->GetImageDimension(); i++)\n  {\n    this->m_PixelPosition[i] = m_ProjectionIndexTransformMatrix[i][this->GetImageDimension()];\n    for (unsigned int j = 0; j < this->GetImageDimension(); j++)\n      this->m_PixelPosition[i] += m_ProjectionIndexTransformMatrix[i][j] * this->m_PositionIndex[j];\n  }\n\n  this->m_SourceToPixel = this->m_PixelPosition - this->m_SourcePosition;\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkQuadricShape.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkQuadricShape_h\n#define rtkQuadricShape_h\n\n#include \"RTKExport.h\"\n#include <itkPoint.h>\n#include <rtkMacro.h>\n\n#include \"rtkConvexShape.h\"\n\nnamespace rtk\n{\n\n/** \\class QuadricShape\n * \\brief Defines a 3D quadric shape.\n *\n * A quadric shape has the equation\n * Ax^2 + By^2 + Cz^2 + Dxy+ Exz + Fyz + Gx + Hy + Iz + J = 0\n * It is assumed to be convex (which is not always true).\n *\n * \\test rtkforbildtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n *\n */\nclass RTK_EXPORT QuadricShape : public ConvexShape\n{\npublic:\n  /** Standard class type alias. */\n  using Self = QuadricShape;\n  using Superclass = ConvexShape;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using ScalarType = Superclass::ScalarType;\n  using PointType = Superclass::PointType;\n  using VectorType = Superclass::VectorType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(QuadricShape);\n\n  /** See rtk::ConvexShape::IsInside. */\n  bool\n  IsInside(const PointType & point) const override;\n\n  /** Idem as IsInside without the application of clip planes. */\n  bool\n  IsInsideQuadric(const PointType & point) const;\n\n  /** See rtk::ConvexShape::IsIntersectedByRay for the goal and\n   * https://education.siggraph.org/static/HyperGraph/raytrace/rtinter4.htm\n   * for the computation. */\n  bool\n  IsIntersectedByRay(const PointType &  rayOrigin,\n                     const VectorType & rayDirection,\n                     double &           nearDist,\n                     double &           farDist) const override;\n\n  /** Rescale object along each direction by a 3D vector. */\n  void\n  Rescale(const VectorType & r) override;\n\n  /** Translate object by a given 3D vector. */\n  void\n  Translate(const VectorType & t) override;\n\n  /** Rotate object by a given 3D matrix. */\n  void\n  Rotate(const RotationMatrixType & r) override;\n\n  itkGetConstMacro(A, ScalarType);\n  itkSetMacro(A, ScalarType);\n  itkGetConstMacro(B, ScalarType);\n  itkSetMacro(B, ScalarType);\n  itkGetConstMacro(C, ScalarType);\n  itkSetMacro(C, ScalarType);\n  itkGetConstMacro(D, ScalarType);\n  itkSetMacro(D, ScalarType);\n  itkGetConstMacro(E, ScalarType);\n  itkSetMacro(E, ScalarType);\n  itkGetConstMacro(F, ScalarType);\n  itkSetMacro(F, ScalarType);\n  itkGetConstMacro(G, ScalarType);\n  itkSetMacro(G, ScalarType);\n  itkGetConstMacro(H, ScalarType);\n  itkSetMacro(H, ScalarType);\n  itkGetConstMacro(I, ScalarType);\n  itkSetMacro(I, ScalarType);\n  itkGetConstMacro(J, ScalarType);\n  itkSetMacro(J, ScalarType);\n\n  void\n  SetEllipsoid(const PointType & center, const VectorType & axis, const ScalarType & yangle = 0);\n\n  itk::LightObject::Pointer\n  InternalClone() const override;\n\nprivate:\n  QuadricShape();\n\n  ScalarType m_A{ 0. };\n  ScalarType m_B{ 0. };\n  ScalarType m_C{ 0. };\n  ScalarType m_D{ 0. };\n  ScalarType m_E{ 0. };\n  ScalarType m_F{ 0. };\n  ScalarType m_G{ 0. };\n  ScalarType m_H{ 0. };\n  ScalarType m_I{ 0. };\n  ScalarType m_J{ 0. };\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkRayBoxIntersectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkRayBoxIntersectionImageFilter_h\n#define rtkRayBoxIntersectionImageFilter_h\n\n#include \"rtkRayConvexIntersectionImageFilter.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkBoxShape.h\"\n\nnamespace rtk\n{\n\n/** \\class RayBoxIntersectionImageFilter\n * \\brief Analytical projection of a BoxShape.\n *\n * \\test rtkdrawgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT RayBoxIntersectionImageFilter\n  : public RayConvexIntersectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(RayBoxIntersectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = RayBoxIntersectionImageFilter;\n  using Superclass = RayConvexIntersectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using PointType = BoxShape::PointType;\n  using VectorType = BoxShape::VectorType;\n  using ScalarType = BoxShape::ScalarType;\n  using RotationMatrixType = BoxShape::RotationMatrixType;\n  using ImageBaseType = BoxShape::ImageBaseType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(RayBoxIntersectionImageFilter);\n\n  /** Get / Set the constant density of the volume */\n  itkGetMacro(Density, ScalarType);\n  itkSetMacro(Density, ScalarType);\n\n  /** Get reference to vector of plane parameters. */\n  itkGetConstReferenceMacro(PlaneDirections, std::vector<VectorType>);\n  itkGetConstReferenceMacro(PlanePositions, std::vector<ScalarType>);\n\n  /** See ConvexShape for the definition of clip planes. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n\n  /** Set the box from an image. See rtk::BoxShape::SetBoxFromImage. */\n  void\n  SetBoxFromImage(const ImageBaseType * _arg, bool bWithExternalHalfPixelBorder = true);\n\n  /** Get/Set the box parameters. See rtk::BoxShape. */\n  itkGetMacro(BoxMin, PointType);\n  itkSetMacro(BoxMin, PointType);\n  itkGetMacro(BoxMax, PointType);\n  itkSetMacro(BoxMax, PointType);\n  itkGetMacro(Direction, RotationMatrixType);\n  itkSetMacro(Direction, RotationMatrixType);\n\nprotected:\n  RayBoxIntersectionImageFilter();\n  ~RayBoxIntersectionImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\nprivate:\n  ScalarType              m_Density{ 1. };\n  std::vector<VectorType> m_PlaneDirections;\n  std::vector<ScalarType> m_PlanePositions;\n\n  PointType          m_BoxMin{ 0. };\n  PointType          m_BoxMax{ 0. };\n  RotationMatrixType m_Direction;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkRayBoxIntersectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkRayBoxIntersectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkRayBoxIntersectionImageFilter_hxx\n#define rtkRayBoxIntersectionImageFilter_hxx\n\n#include <iostream>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n#include \"rtkBoxShape.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nRayBoxIntersectionImageFilter<TInputImage, TOutputImage>::RayBoxIntersectionImageFilter()\n{\n  m_Direction.SetIdentity();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayBoxIntersectionImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->GetConvexShape() == nullptr)\n    this->SetConvexShape(BoxShape::New().GetPointer());\n\n  Superclass::BeforeThreadedGenerateData();\n\n  auto * qo = dynamic_cast<BoxShape *>(this->GetModifiableConvexShape());\n  if (qo == nullptr)\n  {\n    itkExceptionMacro(\"This is not a BoxShape!\");\n  }\n\n  qo->SetDensity(this->GetDensity());\n  qo->SetClipPlanes(this->GetPlaneDirections(), this->GetPlanePositions());\n  qo->SetBoxMin(this->GetBoxMin());\n  qo->SetBoxMax(this->GetBoxMax());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayBoxIntersectionImageFilter<TInputImage, TOutputImage>::AddClipPlane(const VectorType & dir, const ScalarType & pos)\n{\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayBoxIntersectionImageFilter<TInputImage, TOutputImage>::SetBoxFromImage(const ImageBaseType * _arg,\n                                                                          bool bWithExternalHalfPixelBorder)\n{\n  if (this->GetConvexShape() == nullptr)\n    this->SetConvexShape(BoxShape::New().GetPointer());\n  auto * qo = dynamic_cast<BoxShape *>(this->GetModifiableConvexShape());\n  if (qo == nullptr)\n  {\n    itkExceptionMacro(\"This is not a BoxShape!\");\n  }\n  qo->SetBoxFromImage(_arg, bWithExternalHalfPixelBorder);\n  SetBoxMin(qo->GetBoxMin());\n  SetBoxMax(qo->GetBoxMax());\n  SetDirection(qo->GetDirection());\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkRayConvexIntersectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkRayConvexIntersectionImageFilter_h\n#define rtkRayConvexIntersectionImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkConfiguration.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkConvexShape.h\"\n\nnamespace rtk\n{\n\n/** \\class RayConvexIntersectionImageFilter\n * \\brief Analytical projection of ConvexShape\n *\n * \\test rtkfdktest.cxx, rtkforbildtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT RayConvexIntersectionImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(RayConvexIntersectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = RayConvexIntersectionImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  using GeometryConstPointer = typename GeometryType::ConstPointer;\n  using ConvexShapePointer = ConvexShape::Pointer;\n  using ScalarType = ConvexShape::ScalarType;\n  using PointType = ConvexShape::PointType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(RayConvexIntersectionImageFilter);\n\n  /** Get / Set the object pointer to the ConvexShape. */\n  itkGetModifiableObjectMacro(ConvexShape, ConvexShape);\n  itkSetObjectMacro(ConvexShape, ConvexShape);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetConstObjectMacro(Geometry, GeometryType);\n  itkSetConstObjectMacro(Geometry, GeometryType);\n\n  /** Get / Set the attenuation \\f$\\mu\\f$ to simulate the attenuated line integral. Default is 0.\n   * The attenuated line integral model is\n   * \\f[\n   * p=\\int f(\\underline s+r\\underline{d})\\exp(\\mu r)\\mathrm{d}r\n   * \\f]\n   * with \\f$\\underline s\\f$ and \\f$\\underline d\\f$ the ray source and direction. The value is therefore:\n   * \\f{eqnarray*}{\n   * p&=&\\int_{n}^{f} d\\exp(\\mu r)\\mathrm{d}r\\\\\n   * &=&\\dfrac{d}{\\mu}\\left(\\exp(\\mu {f})-\\exp(\\mu n)\\right)\n   * \\f}\n   * with \\f$n\\f$ and \\f$f\\f$ the distances from source to intersection points near and far from the source and \\f$d\\f$\n   * m_Density.\n   */\n  itkGetMacro(Attenuation, double);\n  itkSetMacro(Attenuation, double);\n\nprotected:\n  RayConvexIntersectionImageFilter();\n  ~RayConvexIntersectionImageFilter() override = default;\n\n  /** ConvexShape must be created in the BeforeThreadedGenerateData in the\n   * daugter classes. */\n  void\n  BeforeThreadedGenerateData() override;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Apply changes to the input image requested region. */\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  ConvexShapePointer   m_ConvexShape;\n  GeometryConstPointer m_Geometry;\n  double               m_Attenuation = 0.;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkRayConvexIntersectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkRayConvexIntersectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkRayConvexIntersectionImageFilter_hxx\n#define rtkRayConvexIntersectionImageFilter_hxx\n\n#include \"math.h\"\n\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nRayConvexIntersectionImageFilter<TInputImage, TOutputImage>::RayConvexIntersectionImageFilter()\n  : m_Geometry(nullptr)\n{}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayConvexIntersectionImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->m_ConvexShape.IsNull())\n    itkExceptionMacro(<< \"ConvexShape has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayConvexIntersectionImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayConvexIntersectionImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Iterators on input and output\n  using InputRegionIterator = ProjectionsRegionConstIteratorRayBased<TInputImage>;\n  InputRegionIterator * itIn = nullptr;\n  itIn = InputRegionIterator::New(this->GetInput(), outputRegionForThread, m_Geometry);\n  itk::ImageRegionIteratorWithIndex<TOutputImage> itOut(this->GetOutput(), outputRegionForThread);\n\n  // Go over each projection\n  const double r = m_ConvexShape->GetDensity() / m_Attenuation;\n  for (unsigned int pix = 0; pix < outputRegionForThread.GetNumberOfPixels(); pix++, itIn->Next(), ++itOut)\n  {\n    // Compute ray intersection length\n    ConvexShape::ScalarType nearDist = NAN, farDist = NAN;\n    if (m_ConvexShape->IsIntersectedByRay(itIn->GetSourcePosition(), itIn->GetDirection(), nearDist, farDist))\n    {\n      if (m_Attenuation == 0.)\n        itOut.Set(itIn->Get() + m_ConvexShape->GetDensity() * (farDist - nearDist));\n      else\n        itOut.Set(itIn->Get() + r * (std::exp(m_Attenuation * farDist) - std::exp(m_Attenuation * nearDist)));\n    }\n    else\n      itOut.Set(itIn->Get());\n  }\n\n  delete itIn;\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkRayEllipsoidIntersectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkRayEllipsoidIntersectionImageFilter_h\n#define rtkRayEllipsoidIntersectionImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkRayQuadricIntersectionImageFilter.h\"\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class RayEllipsoidIntersectionImageFilter\n * \\brief Analytical projection of ellipsoids\n *\n * \\test rtksarttest.cxx, rtkamsterdamshroudtest.cxx,\n *        rtkmotioncompensatedfdktest.cxx, rtkforbildtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT RayEllipsoidIntersectionImageFilter\n  : public RayConvexIntersectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(RayEllipsoidIntersectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = RayEllipsoidIntersectionImageFilter;\n  using Superclass = RayConvexIntersectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using PointType = ConvexShape::PointType;\n  using VectorType = ConvexShape::VectorType;\n  using ScalarType = ConvexShape::ScalarType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(RayEllipsoidIntersectionImageFilter);\n\n  /** Get / Set the constant density of the volume */\n  itkGetMacro(Density, ScalarType);\n  itkSetMacro(Density, ScalarType);\n\n  /** Get reference to vector of plane parameters. */\n  itkGetConstReferenceMacro(PlaneDirections, std::vector<VectorType>);\n  itkGetConstReferenceMacro(PlanePositions, std::vector<ScalarType>);\n\n  /** See ConvexShape for the definition of clip planes. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n\n  /** Get/Set the center of the ellipsoid. */\n  itkGetMacro(Center, PointType);\n  itkSetMacro(Center, PointType);\n\n  /** Get/Set the semi-principal axes of the ellipsoid. */\n  itkGetMacro(Axis, VectorType);\n  itkSetMacro(Axis, VectorType);\n\n  /** Get/Set the rotation angle around the y axis. */\n  itkGetMacro(Angle, ScalarType);\n  itkSetMacro(Angle, ScalarType);\n\nprotected:\n  RayEllipsoidIntersectionImageFilter();\n  ~RayEllipsoidIntersectionImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\nprivate:\n  ScalarType              m_Density{ 1. };\n  std::vector<VectorType> m_PlaneDirections;\n  std::vector<ScalarType> m_PlanePositions;\n\n  PointType  m_Center;\n  VectorType m_Axis;\n  ScalarType m_Angle{ 0. };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkRayEllipsoidIntersectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkRayEllipsoidIntersectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkRayEllipsoidIntersectionImageFilter_hxx\n#define rtkRayEllipsoidIntersectionImageFilter_hxx\n\n#include \"rtkQuadricShape.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nRayEllipsoidIntersectionImageFilter<TInputImage, TOutputImage>::RayEllipsoidIntersectionImageFilter()\n{\n  m_Center.Fill(0.);\n  m_Axis.Fill(0.);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayEllipsoidIntersectionImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->GetConvexShape() == nullptr)\n    this->SetConvexShape(QuadricShape::New().GetPointer());\n  Superclass::BeforeThreadedGenerateData();\n  auto * qo = dynamic_cast<QuadricShape *>(this->GetModifiableConvexShape());\n  if (qo == nullptr)\n  {\n    itkExceptionMacro(\"This is not a QuadricShape!\");\n  }\n  qo->SetEllipsoid(m_Center, m_Axis, m_Angle);\n  qo->SetDensity(m_Density);\n  qo->SetClipPlanes(this->GetPlaneDirections(), this->GetPlanePositions());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayEllipsoidIntersectionImageFilter<TInputImage, TOutputImage>::AddClipPlane(const VectorType & dir,\n                                                                             const ScalarType & pos)\n{\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkRayQuadricIntersectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkRayQuadricIntersectionImageFilter_h\n#define rtkRayQuadricIntersectionImageFilter_h\n\n#include \"rtkRayConvexIntersectionImageFilter.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class RayQuadricIntersectionImageFilter\n * \\brief Analytical projection of a QuadricShape\n *\n * \\test rtkdrawgeometricphantomtest.cxx, rtkforbildtest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT RayQuadricIntersectionImageFilter\n  : public RayConvexIntersectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(RayQuadricIntersectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = RayQuadricIntersectionImageFilter;\n  using Superclass = RayConvexIntersectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using PointType = ConvexShape::PointType;\n  using VectorType = ConvexShape::VectorType;\n  using ScalarType = ConvexShape::ScalarType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(RayQuadricIntersectionImageFilter);\n\n  /** Get / Set the constant density of the volume */\n  itkGetMacro(Density, ScalarType);\n  itkSetMacro(Density, ScalarType);\n\n  /** Get reference to vector of plane parameters. */\n  itkGetConstReferenceMacro(PlaneDirections, std::vector<VectorType>);\n  itkGetConstReferenceMacro(PlanePositions, std::vector<ScalarType>);\n\n  /** See ConvexShape for the definition of clip planes. */\n  void\n  AddClipPlane(const VectorType & dir, const ScalarType & pos);\n\n  /** Get/Set QuadricShape parameters. */\n  itkGetMacro(A, ScalarType);\n  itkSetMacro(A, ScalarType);\n  itkGetMacro(B, ScalarType);\n  itkSetMacro(B, ScalarType);\n  itkGetMacro(C, ScalarType);\n  itkSetMacro(C, ScalarType);\n  itkGetMacro(D, ScalarType);\n  itkSetMacro(D, ScalarType);\n  itkGetMacro(E, ScalarType);\n  itkSetMacro(E, ScalarType);\n  itkGetMacro(F, ScalarType);\n  itkSetMacro(F, ScalarType);\n  itkGetMacro(G, ScalarType);\n  itkSetMacro(G, ScalarType);\n  itkGetMacro(H, ScalarType);\n  itkSetMacro(H, ScalarType);\n  itkGetMacro(I, ScalarType);\n  itkSetMacro(I, ScalarType);\n  itkGetMacro(J, ScalarType);\n  itkSetMacro(J, ScalarType);\n\nprotected:\n  RayQuadricIntersectionImageFilter();\n  ~RayQuadricIntersectionImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\nprivate:\n  ScalarType              m_Density{ 1. };\n  std::vector<VectorType> m_PlaneDirections;\n  std::vector<ScalarType> m_PlanePositions;\n\n  ScalarType m_A{ 0. };\n  ScalarType m_B{ 0. };\n  ScalarType m_C{ 0. };\n  ScalarType m_D{ 0. };\n  ScalarType m_E{ 0. };\n  ScalarType m_F{ 0. };\n  ScalarType m_G{ 0. };\n  ScalarType m_H{ 0. };\n  ScalarType m_I{ 0. };\n  ScalarType m_J{ 0. };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkRayQuadricIntersectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkRayQuadricIntersectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkRayQuadricIntersectionImageFilter_hxx\n#define rtkRayQuadricIntersectionImageFilter_hxx\n\n#include <iostream>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n#include \"rtkQuadricShape.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nRayQuadricIntersectionImageFilter<TInputImage, TOutputImage>::RayQuadricIntersectionImageFilter() = default;\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayQuadricIntersectionImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  if (this->GetConvexShape() == nullptr)\n    this->SetConvexShape(QuadricShape::New().GetPointer());\n\n  Superclass::BeforeThreadedGenerateData();\n\n  auto * qo = dynamic_cast<QuadricShape *>(this->GetModifiableConvexShape());\n  if (qo == nullptr)\n  {\n    itkExceptionMacro(\"This is not a QuadricShape!\");\n  }\n\n  qo->SetDensity(this->GetDensity());\n  qo->SetClipPlanes(this->GetPlaneDirections(), this->GetPlanePositions());\n  qo->SetA(this->GetA());\n  qo->SetB(this->GetB());\n  qo->SetC(this->GetC());\n  qo->SetD(this->GetD());\n  qo->SetE(this->GetE());\n  qo->SetF(this->GetF());\n  qo->SetG(this->GetG());\n  qo->SetH(this->GetH());\n  qo->SetI(this->GetI());\n  qo->SetJ(this->GetJ());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nRayQuadricIntersectionImageFilter<TInputImage, TOutputImage>::AddClipPlane(const VectorType & dir,\n                                                                           const ScalarType & pos)\n{\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkReconstructImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReconstructImageFilter_h\n#define rtkReconstructImageFilter_h\n\n// Includes\n#include <itkImageToImageFilter.h>\n#include <itkMacro.h>\n#include <itkNaryAddImageFilter.h>\n\n#include \"rtkDaubechiesWaveletsConvolutionImageFilter.h\"\n#include \"rtkUpsampleImageFilter.h\"\n\nnamespace rtk\n{\n\n/**\n * \\class ReconstructImageFilter\n * \\brief An image filter that reconstructs an image using\n * Daubechies wavelets.\n *\n * This filter is inspired from Dan Mueller's GIFT package\n * https://www.insight-journal.org/browse/publication/103\n *\n * \\dot\n * digraph ReconstructImageFilter {\n *\n * Output [ label=\"Output\"];\n * Output [shape=Mdiamond];\n * Input0 [label=\"Input 0 (here, 2D)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (here, 2D)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (here, 2D)\"];\n * Input2 [shape=Mdiamond];\n * Input3 [label=\"Input 3 (here, 2D)\"];\n * Input3 [shape=Mdiamond];\n * Input4 [label=\"Input 4 (here, 2D)\"];\n * Input4 [shape=Mdiamond];\n * Input5 [label=\"Input 5 (here, 2D)\"];\n * Input5 [shape=Mdiamond];\n * Input6 [label=\"Input 6 (here, 2D)\"];\n * Input6 [shape=Mdiamond];\n *\n * node [shape=box];\n * Add0 [ label=\"itk::NaryAddImageFilter\" URL=\"\\ref itk::NaryAddImageFilter\"];\n * Add1 [ label=\"itk::NaryAddImageFilter\" URL=\"\\ref itk::NaryAddImageFilter\"];\n * Conv0 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Lowpass, Lowpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv1 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Lowpass, Highpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv2 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Highpass, Lowpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv3 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Highpass, Highpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv4 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Lowpass, Lowpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv5 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Lowpass, Highpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv6 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Highpass, Lowpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Conv7 [ label=\"rtk::DaubechiesWaveletsConvolutionImageFilter (Highpass, Highpass)\"\n *         URL=\"\\ref rtk::DaubechiesWaveletsConvolutionImageFilter\"];\n * Up0 [ label=\"rtk::UpsampleImageFilter (by 2)\" URL=\"\\ref rtk::UpsampleImageFilter\"];\n * Up1 [ label=\"rtk::UpsampleImageFilter (by 2)\" URL=\"\\ref rtk::UpsampleImageFilter\"];\n * Up2 [ label=\"rtk::UpsampleImageFilter (by 2)\" URL=\"\\ref rtk::UpsampleImageFilter\"];\n * Up3 [ label=\"rtk::UpsampleImageFilter (by 2)\" URL=\"\\ref rtk::UpsampleImageFilter\"];\n * Up4 [ label=\"rtk::UpsampleImageFilter (by 2)\" URL=\"\\ref rtk::UpsampleImageFilter\"];\n * Up5 [ label=\"rtk::UpsampleImageFilter (by 2)\" URL=\"\\ref rtk::UpsampleImageFilter\"];\n * Up6 [ label=\"rtk::UpsampleImageFilter (by 2)\" URL=\"\\ref rtk::UpsampleImageFilter\"];\n * Up7 [ label=\"rtk::UpsampleImageFilter (by 2)\" URL=\"\\ref rtk::UpsampleImageFilter\"];\n * Input0 -> Up0;\n * Input1 -> Up1;\n * Input2 -> Up2;\n * Input3 -> Up3;\n * Input4 -> Up5;\n * Input5 -> Up6;\n * Input6 -> Up7;\n * Up0 -> Conv0;\n * Up1 -> Conv1;\n * Up2 -> Conv2;\n * Up3 -> Conv3;\n * Up4 -> Conv4;\n * Up5 -> Conv5;\n * Up6 -> Conv6;\n * Up7 -> Conv7;\n * Conv0 -> Add0;\n * Conv1 -> Add0;\n * Conv2 -> Add0;\n * Conv3 -> Add0;\n * Conv4 -> Add1;\n * Conv5 -> Add1;\n * Conv6 -> Add1;\n * Conv7 -> Add1;\n * Add0 -> Up4;\n * Add1 -> Output;\n * }\n * \\enddot\n *\n * \\test rtkwaveletstest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <class TImage>\nclass ITK_TEMPLATE_EXPORT ReconstructImageFilter : public itk::ImageToImageFilter<TImage, TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ReconstructImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ReconstructImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImage, TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ReconstructImageFilter);\n\n  /** ImageDimension enumeration. */\n  static constexpr unsigned int ImageDimension = TImage::ImageDimension;\n\n  /** Inherit types from Superclass. */\n  using InputImageType = typename Superclass::InputImageType;\n  using OutputImageType = typename Superclass::OutputImageType;\n  using InputImagePointer = typename Superclass::InputImagePointer;\n  using OutputImagePointer = typename Superclass::OutputImagePointer;\n  using InputImageConstPointer = typename Superclass::InputImageConstPointer;\n  using PixelType = typename TImage::PixelType;\n  using InternalPixelType = typename TImage::InternalPixelType;\n\n  /** Typedefs for pipeline's subfilters */\n  using AddFilterType = itk::NaryAddImageFilter<InputImageType, InputImageType>;\n  using ConvolutionFilterType = rtk::DaubechiesWaveletsConvolutionImageFilter<InputImageType>;\n  using UpsampleImageFilterType = rtk::UpsampleImageFilter<InputImageType>;\n\n  /** Set the number of input levels. */\n  virtual void\n  SetNumberOfLevels(unsigned int levels)\n  {\n    this->m_NumberOfLevels = levels;\n    this->ModifyInputOutputStorage();\n  }\n\n  /** Get the number of input levels (per image). */\n  virtual unsigned int\n  GetNumberOfLevels()\n  {\n    return this->m_NumberOfLevels;\n  }\n\n  /** ReconstructImageFilter produces images which are of different size\n   *  than the input image. As such, we reimplement GenerateOutputInformation()\n   *  in order to inform the pipeline execution model.\n   */\n  void\n  GenerateOutputInformation() override;\n\n\n  /** ReconstructImageFilter requests the largest possible region of all its inputs.\n   */\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** ReconstructImageFilter uses input images of different sizes, therefore the\n   * VerifyInputInformation method has to be reimplemented.\n   */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  void\n  SetSizes(typename InputImageType::SizeType * sizesVector)\n  {\n    m_Sizes = sizesVector;\n  }\n\n  void\n  SetIndices(typename InputImageType::IndexType * indicesVector)\n  {\n    m_Indices = indicesVector;\n  }\n\n  /** Get/Set the order of the wavelet filters */\n  itkGetMacro(Order, unsigned int);\n  itkSetMacro(Order, unsigned int);\n\nprotected:\n  ReconstructImageFilter();\n  ~ReconstructImageFilter() override = default;\n\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  /** Modifies the storage for Input and Output images.\n   * Should be called after changes to levels, bands,\n   * Reconstruct, reconstruct, etc... */\n  void\n  ModifyInputOutputStorage();\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Calculates the number of ProcessObject output images */\n  virtual unsigned int\n  CalculateNumberOfInputs();\n\n  /** Creates and sets the kernel sources to generate all kernels. */\n  void\n  GeneratePassVectors();\n\nprivate:\n  unsigned int m_NumberOfLevels{ 5 }; // Holds the number of Reconstruction levels\n  unsigned int m_Order{ 3 };          // Holds the order of the wavelet filters\n  bool         m_PipelineConstructed{\n    false\n  }; // Filters instantiated by GenerateOutputInformation() should be instantiated only once\n\n  typename InputImageType::SizeType *                   m_Sizes;      // Holds the size of sub-images at each level\n  typename InputImageType::IndexType *                  m_Indices;    // Holds the size of sub-images at each level\n  typename std::vector<typename AddFilterType::Pointer> m_AddFilters; // Holds a vector of add filters\n  typename std::vector<typename ConvolutionFilterType::Pointer>\n    m_ConvolutionFilters; // Holds a vector of convolution filters\n  typename std::vector<typename UpsampleImageFilterType::Pointer>\n    m_UpsampleFilters; // Holds a vector of Upsample filters\n  // Holds a vector of PassVectors. A PassVector has Dimension components, each one storing either \"High\" or \"Low\"\n  typename std::vector<typename ConvolutionFilterType::PassVector> m_PassVectors;\n};\n\n} // namespace rtk\n\n// Include CXX\n#ifndef rtk_MANUAL_INSTANTIATION\n#  include \"rtkReconstructImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkReconstructImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReconstructImageFilter_hxx\n#define rtkReconstructImageFilter_hxx\n\n// Includes\n\nnamespace rtk\n{\n\n/////////////////////////////////////////////////////////\n// Default Constructor\ntemplate <class TImage>\nReconstructImageFilter<TImage>::ReconstructImageFilter() = default;\n\n\n/////////////////////////////////////////////////////////\n// PrintSelf()\ntemplate <class TImage>\nvoid\nReconstructImageFilter<TImage>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n}\n\n\n/////////////////////////////////////////////////////////\n// ModifyInputOutputStorage()\ntemplate <class TImage>\nvoid\nReconstructImageFilter<TImage>::ModifyInputOutputStorage()\n{\n  this->Modified();\n\n  // Set required number of inputs\n  unsigned int requiredNumberOfInputs = this->CalculateNumberOfInputs();\n  this->SetNumberOfRequiredInputs(requiredNumberOfInputs);\n}\n\ntemplate <class TImage>\nunsigned int\nReconstructImageFilter<TImage>::CalculateNumberOfInputs()\n{\n  int          dimension = TImage::ImageDimension;\n  unsigned int n = itk::Math::Round<double>(std::pow(2.0, dimension));\n  return (m_NumberOfLevels * (n - 1) + 1);\n}\n\ntemplate <class TImage>\nvoid\nReconstructImageFilter<TImage>::GeneratePassVectors()\n{\n  int          dimension = TImage::ImageDimension;\n  unsigned int n = itk::Math::Round<double>(std::pow(2.0, dimension));\n\n  // Create a vector of PassVector\n  m_PassVectors.clear();\n  for (unsigned int vectIndex = 0; vectIndex < n; vectIndex++)\n  {\n    typename ConvolutionFilterType::PassVector temp;\n    m_PassVectors.push_back(temp);\n  }\n\n  // Fill it with the right values\n  unsigned int powerOfTwo = 1;\n  for (int dim = 0; dim < dimension; dim++)\n  {\n    for (unsigned int vectIndex = 0; vectIndex < n; vectIndex++)\n    {\n      // vectIndex / powerOfTwo is a division between unsigned ints, and will return the quotient\n      // of their euclidian division\n      if ((vectIndex / powerOfTwo) % 2)\n        m_PassVectors[vectIndex][dim] = ConvolutionFilterType::High;\n      else\n        m_PassVectors[vectIndex][dim] = ConvolutionFilterType::Low;\n    }\n    powerOfTwo *= 2;\n  }\n}\n\ntemplate <class TImage>\nvoid\nReconstructImageFilter<TImage>::GenerateInputRequestedRegion()\n{\n  for (unsigned int i = 0; i < this->CalculateNumberOfInputs(); i++)\n  {\n    InputImagePointer inputPtr = const_cast<TImage *>(this->GetInput(i));\n    inputPtr->SetRequestedRegionToLargestPossibleRegion();\n  }\n}\n\ntemplate <class TImage>\nvoid\nReconstructImageFilter<TImage>::GenerateOutputInformation()\n{\n\n  if (!m_PipelineConstructed)\n  {\n    // n is the number of bands per level, including the ones\n    // that will be Reconstructed and won't appear in the outputs\n    int          dimension = TImage::ImageDimension;\n    unsigned int n = itk::Math::Round<double>(std::pow(2.0, dimension));\n\n    // Before the cascade pipeline\n    // Create and set the add filters\n    for (unsigned int l = 0; l < m_NumberOfLevels; l++)\n    {\n      m_AddFilters.push_back(AddFilterType::New());\n    }\n\n    // Create and set the kernel sources\n    this->GeneratePassVectors();\n\n    // Create all FFTProjectionsConvolution and Downsampling filters\n    for (unsigned int i = 0; i < n * m_NumberOfLevels; i++)\n    {\n      m_ConvolutionFilters.push_back(ConvolutionFilterType::New());\n      m_UpsampleFilters.push_back(UpsampleImageFilterType::New());\n    }\n\n    // Cascade pipeline\n    // Set all the filters and connect them together\n    auto * upsamplingFactors = new unsigned int[dimension];\n    for (int d = 0; d < dimension; d++)\n      upsamplingFactors[d] = 2;\n\n    for (unsigned int l = 0; l < m_NumberOfLevels; l++)\n    {\n      for (unsigned int band = 0; band < n; band++)\n      {\n        m_ConvolutionFilters[band + l * n]->SetInput(m_UpsampleFilters[band + l * n]->GetOutput());\n        m_ConvolutionFilters[band + l * n]->SetPass(m_PassVectors[band]);\n        m_ConvolutionFilters[band + l * n]->SetReconstruction();\n        m_ConvolutionFilters[band + l * n]->SetOrder(this->GetOrder());\n        m_ConvolutionFilters[band + l * n]->ReleaseDataFlagOn();\n\n        m_AddFilters[l]->SetInput(band, m_ConvolutionFilters[band + l * n]->GetOutput());\n        m_AddFilters[l]->ReleaseDataFlagOn();\n\n        m_UpsampleFilters[band + l * n]->SetFactors(upsamplingFactors);\n        m_UpsampleFilters[band + l * n]->SetOrder(this->m_Order);\n        m_UpsampleFilters[band + l * n]->SetOutputSize(this->m_Sizes[band + l * n]);\n        m_UpsampleFilters[band + l * n]->SetOutputIndex(this->m_Indices[band + l * n]);\n        m_UpsampleFilters[band + l * n]->ReleaseDataFlagOn();\n      }\n      if (l > 0)\n        m_UpsampleFilters[n * l]->SetInput(m_AddFilters[l - 1]->GetOutput());\n    }\n\n    // Connect the upsample filters to the inputs of the pipeline\n    unsigned int inputBand = 0;\n    for (unsigned int i = 0; i < n * m_NumberOfLevels; i++)\n    {\n      if ((i % n) || (i == 0))\n      {\n        m_UpsampleFilters[i]->SetInput(this->GetInput(inputBand));\n        inputBand++;\n      }\n    }\n\n    // Clean up\n    delete[] upsamplingFactors;\n  }\n  m_PipelineConstructed = true;\n\n  // Have the last filter calculate its output information\n  // and copy it as the output information of the composite filter\n  m_AddFilters[m_NumberOfLevels - 1]->UpdateOutputInformation();\n  this->GetOutput()->CopyInformation(m_AddFilters[m_NumberOfLevels - 1]->GetOutput());\n}\n\ntemplate <class TImage>\nvoid\nReconstructImageFilter<TImage>::GenerateData()\n{\n  //  std::cout << \"Starting reconstruction\" << std::endl;\n\n  int          dimension = TImage::ImageDimension;\n  unsigned int n = itk::Math::Round<double>(std::pow(2.0, dimension));\n\n  // Have the last filter calculate its output image\n  // and graft it to the output of the composite filter\n  for (unsigned int l = 0; l < m_NumberOfLevels; l++)\n  {\n    for (unsigned int band = 0; band < n; band++)\n    {\n      m_UpsampleFilters[band + l * n]->Update();\n      m_ConvolutionFilters[band + l * n]->Update();\n    }\n    m_AddFilters[l]->Update();\n  }\n  this->GraftOutput(m_AddFilters[m_NumberOfLevels - 1]->GetOutput());\n\n  //  std::cout << \"Done reconstruction\" << std::endl;\n}\n\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkReconstructionConjugateGradientOperator.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReconstructionConjugateGradientOperator_h\n#define rtkReconstructionConjugateGradientOperator_h\n\n#include <itkMultiplyImageFilter.h>\n#include <itkAddImageFilter.h>\n\n#include \"rtkConstantImageSource.h\"\n\n#include \"rtkConjugateGradientOperator.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkLaplacianImageFilter.h\"\n#include \"rtkBlockDiagonalMatrixVectorMultiplyImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaConstantVolumeSource.h\"\n#  include \"rtkCudaLaplacianImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n\n/** \\class ReconstructionConjugateGradientOperator\n * \\brief Implements the operator A used in conjugate gradient reconstruction\n *\n * This filter implements the operator A used in the conjugate gradient reconstruction method,\n * which attempts to find the f that minimizes\n * || sqrt(D) (Rf -p) ||_2^2 + gamma || grad f ||_2^2 + Tikhonov || f ||_2^2,\n * with R the forward projection operator,\n * p the measured projections, and D the displaced detector weighting operator.\n *\n * With gamma=0, this it is similar to the ART and SART methods. The difference lies\n * in the algorithm employed to minimize this cost function. ART uses the\n * Kaczmarz method (projects and back projects one ray at a time),\n * SART the block-Kaczmarz method (projects and back projects one projection\n * at a time), and ConjugateGradient a conjugate gradient method\n * (projects and back projects all projections together).\n *\n * This filter takes in input f and outputs R_t D R f + gamma Laplacian f + Tikhonov f\n *\n * \\dot\n * digraph ReconstructionConjugateGradientOperator {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (Weights)\"];\n * Input2 [shape=Mdiamond];\n * Input3 [label=\"Input Support Mask\"];\n * Input3 [shape=Mdiamond];\n * Output [label=\"Output (Volume)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * ConstantVolumeSource [label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ConstantProjectionsSource [label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * BackProjection [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * ForwardProjection [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * Multiply [ label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * MultiplyInput [ label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * MultiplyOutput [ label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * Laplacian [ label=\"rtk::LaplacianImageFilter\" URL=\"\\ref rtk::LaplacianImageFilter\"];\n * MultiplyLaplacian [ label=\"itk::MultiplyImageFilter (by gamma)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * MultiplyTikhonov [ label=\"itk::MultiplyImageFilter (by Tikhonov parameter)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * AddLaplacian [ label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n * AddTikhonov [ label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n *\n * Input0 -> MultiplyInput;\n * MultiplyInput -> MultiplyTikhonov;\n * Input3 -> MultiplyInput;\n * MultiplyInput -> ForwardProjection;\n * ConstantProjectionsSource -> ForwardProjection;\n * ConstantVolumeSource -> BackProjection;\n * ForwardProjection -> Multiply;\n * Input2 -> Multiply;\n * Multiply -> BackProjection;\n * BackProjection -> AddLaplacian;\n * Input3 -> MultiplyOutput;\n * MultiplyInput -> Laplacian;\n * Laplacian -> MultiplyLaplacian;\n * MultiplyLaplacian -> AddLaplacian;\n * AddLaplacian -> AddTikhonov;\n * MultiplyTikhonov -> AddTikhonov;\n * AddTikhonov -> MultiplyOutput;\n * MultiplyOutput -> Output;\n * }\n * \\enddot\n *\n * \\test rtkconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TOutputImage, typename TSingleComponentImage = TOutputImage, typename TWeightsImage = TOutputImage>\nclass ITK_TEMPLATE_EXPORT ReconstructionConjugateGradientOperator : public ConjugateGradientOperator<TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ReconstructionConjugateGradientOperator);\n\n  /** Standard class type alias. */\n  using Self = ReconstructionConjugateGradientOperator;\n  using Superclass = ConjugateGradientOperator<TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n#ifdef RTK_USE_CUDA\n  using GradientImageType =\n    itk::CudaImage<itk::CovariantVector<typename TOutputImage::PixelType, TOutputImage::ImageDimension>,\n                   TOutputImage::ImageDimension>;\n#else\n  using GradientImageType =\n    itk::Image<itk::CovariantVector<typename TOutputImage::PixelType, TOutputImage::ImageDimension>,\n               TOutputImage::ImageDimension>;\n#endif\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Setters for the inputs */\n  void\n  SetInputVolume(const TOutputImage * vol);\n  void\n  SetInputProjectionStack(const TOutputImage * projs);\n  void\n  SetInputWeights(const TWeightsImage * weights);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ReconstructionConjugateGradientOperator);\n\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<TOutputImage, TOutputImage>;\n  using BackProjectionFilterPointer = typename BackProjectionFilterType::Pointer;\n\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<TOutputImage, TOutputImage>;\n  using ForwardProjectionFilterPointer = typename ForwardProjectionFilterType::Pointer;\n\n  using ConstantSourceType = rtk::ConstantImageSource<TOutputImage>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<TOutputImage, TSingleComponentImage>;\n  using AddFilterType = itk::AddImageFilter<TOutputImage>;\n\n  // If TOutputImage is an itk::Image of floats or double, so are the weights, and a simple Multiply filter is required\n  // If TOutputImage is an itk::Image of itk::Vector<float (or double)>, a BlockDiagonalMatrixVectorMultiply filter\n  // is needed. Thus the meta-programming construct\n  using MatrixVectorMultiplyFilterType = rtk::BlockDiagonalMatrixVectorMultiplyImageFilter<TOutputImage, TWeightsImage>;\n  using PlainMultiplyFilterType = itk::MultiplyImageFilter<TOutputImage, TOutputImage, TOutputImage>;\n  using MultiplyWithWeightsFilterType = typename std::conditional_t<std::is_same_v<TSingleComponentImage, TOutputImage>,\n                                                                    PlainMultiplyFilterType,\n                                                                    MatrixVectorMultiplyFilterType>;\n\n  using OutputImagePointer = typename TOutputImage::Pointer;\n\n  /** Set the backprojection filter*/\n  void\n  SetBackProjectionFilter(BackProjectionFilterType * _arg);\n\n  /** Set the forward projection filter*/\n  void\n  SetForwardProjectionFilter(ForwardProjectionFilterType * _arg);\n\n  /** Set the support mask, if any, for support constraint in reconstruction */\n  void\n  SetSupportMask(const TSingleComponentImage * SupportMask);\n  typename TSingleComponentImage::ConstPointer\n  GetSupportMask();\n\n  /** Set local regularization weights. The map should have the same\n   * information (size, spacing, origin etc.) as the reconstructed volume. The\n   * same map is used in Laplacian and Tikhonov regularization. */\n  void\n  SetLocalRegularizationWeights(const TSingleComponentImage * localRegularizationWeights);\n  typename TSingleComponentImage::ConstPointer\n  GetLocalRegularizationWeights();\n\n  /** Set the geometry of both m_BackProjectionFilter and m_ForwardProjectionFilter */\n  itkSetConstObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Perform laplacian-based and/or Tikhonov regularization during\n   *  reconstruction (gamma is the strength of laplacian the regularization) */\n  itkSetMacro(Gamma, float);\n  itkGetMacro(Gamma, float);\n  itkSetMacro(Tikhonov, float);\n  itkGetMacro(Tikhonov, float);\n\nprotected:\n  ReconstructionConjugateGradientOperator();\n  ~ReconstructionConjugateGradientOperator() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  template <typename ImageType>\n  typename std::enable_if<std::is_same_v<TSingleComponentImage, ImageType>, ImageType>::type::Pointer\n  ConnectGradientRegularization();\n\n  template <typename ImageType>\n  typename std::enable_if<!std::is_same_v<TSingleComponentImage, ImageType>, ImageType>::type::Pointer\n  ConnectGradientRegularization();\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  BackProjectionFilterPointer    m_BackProjectionFilter;\n  ForwardProjectionFilterPointer m_ForwardProjectionFilter;\n\n  typename ConstantSourceType::Pointer                                  m_ConstantProjectionsSource;\n  typename ConstantSourceType::Pointer                                  m_ConstantVolumeSource;\n  typename MultiplyFilterType::Pointer                                  m_MultiplyOutputVolumeFilter;\n  typename MultiplyFilterType::Pointer                                  m_MultiplyInputVolumeFilter;\n  typename MultiplyFilterType::Pointer                                  m_MultiplyLaplacianFilter;\n  typename MultiplyFilterType::Pointer                                  m_MultiplyTikhonovFilter;\n  typename MultiplyFilterType::Pointer                                  m_MultiplyTikhonovWeightsFilter;\n  typename AddFilterType::Pointer                                       m_AddLaplacianFilter;\n  typename AddFilterType::Pointer                                       m_AddTikhonovFilter;\n  typename itk::ImageToImageFilter<TOutputImage, TOutputImage>::Pointer m_LaplacianFilter;\n  typename MultiplyWithWeightsFilterType::Pointer                       m_MultiplyWithWeightsFilter;\n\n  /** Member attributes */\n  rtk::ThreeDCircularProjectionGeometry::ConstPointer m_Geometry{ nullptr };\n  float                                               m_Gamma{ 0 };    // Strength of the laplacian regularization\n  float                                               m_Tikhonov{ 0 }; // Strength of the Tikhonov regularization\n\n  /** Pointers to intermediate images, used to simplify complex branching */\n  typename TOutputImage::Pointer m_FloatingInputPointer, m_FloatingOutputPointer;\n\n  /** When the inputs have the same type, ITK checks whether they occupy the\n   * same physical space or not. Obviously they dont, so we have to remove this check */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n\n  /** Getters for the inputs */\n  typename TOutputImage::ConstPointer\n  GetInputVolume();\n  typename TOutputImage::ConstPointer\n  GetInputProjectionStack();\n  typename TWeightsImage::ConstPointer\n  GetInputWeights();\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkReconstructionConjugateGradientOperator.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkReconstructionConjugateGradientOperator.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReconstructionConjugateGradientOperator_hxx\n#define rtkReconstructionConjugateGradientOperator_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  ReconstructionConjugateGradientOperator()\n{\n  this->SetNumberOfRequiredInputs(3);\n\n  // Create filters\n  // #ifdef RTK_USE_CUDA\n  //  m_ConstantProjectionsSource = rtk::CudaConstantVolumeSource::New();\n  //  m_ConstantVolumeSource = rtk::CudaConstantVolumeSource::New();\n  //  m_LaplacianFilter = rtk::CudaLaplacianImageFilter::New();\n  // #else\n  m_ConstantProjectionsSource = ConstantSourceType::New();\n  m_ConstantVolumeSource = ConstantSourceType::New();\n  // #endif\n  m_MultiplyWithWeightsFilter = MultiplyWithWeightsFilterType::New();\n  m_MultiplyOutputVolumeFilter = MultiplyFilterType::New();\n  m_MultiplyInputVolumeFilter = MultiplyFilterType::New();\n\n  // Set permanent parameters\n  m_ConstantProjectionsSource->SetConstant(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n  m_ConstantVolumeSource->SetConstant(itk::NumericTraits<typename TOutputImage::PixelType>::ZeroValue());\n\n  // Set memory management options\n  m_ConstantProjectionsSource->ReleaseDataFlagOn();\n  m_ConstantVolumeSource->ReleaseDataFlagOn();\n  //  m_LaplacianFilter->ReleaseDataFlagOn();\n  //  m_MultiplyLaplacianFilter->ReleaseDataFlagOn();\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::SetInputVolume(\n  const TOutputImage * vol)\n{\n  this->SetNthInput(0, const_cast<TOutputImage *>(vol));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::SetInputProjectionStack(\n  const TOutputImage * projs)\n{\n  this->SetNthInput(1, const_cast<TOutputImage *>(projs));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::SetInputWeights(\n  const TWeightsImage * weights)\n{\n  this->SetNthInput(2, const_cast<TWeightsImage *>(weights));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::SetSupportMask(\n  const TSingleComponentImage * SupportMask)\n{\n  this->SetInput(\"SupportMask\", const_cast<TSingleComponentImage *>(SupportMask));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TOutputImage::ConstPointer\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::GetInputVolume()\n{\n  return static_cast<const TOutputImage *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  SetLocalRegularizationWeights(const TSingleComponentImage * localRegularizationWeights)\n{\n  this->SetInput(\"LocalRegularizationWeights\", const_cast<TSingleComponentImage *>(localRegularizationWeights));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TOutputImage::ConstPointer\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::GetInputProjectionStack()\n{\n  return static_cast<const TOutputImage *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TWeightsImage::ConstPointer\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::GetInputWeights()\n{\n  return static_cast<const TWeightsImage *>(this->itk::ProcessObject::GetInput(2));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TSingleComponentImage::ConstPointer\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::GetSupportMask()\n{\n  return static_cast<const TSingleComponentImage *>(this->itk::ProcessObject::GetInput(\"SupportMask\"));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntypename TSingleComponentImage::ConstPointer\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  GetLocalRegularizationWeights()\n{\n  return static_cast<const TSingleComponentImage *>(this->itk::ProcessObject::GetInput(\"LocalRegularizationWeights\"));\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::SetBackProjectionFilter(\n  BackProjectionFilterType * _arg)\n{\n  m_BackProjectionFilter = _arg;\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::SetForwardProjectionFilter(\n  ForwardProjectionFilterType * _arg)\n{\n  m_ForwardProjectionFilter = _arg;\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  GenerateInputRequestedRegion()\n{\n  // Input 0 is the volume in which we backproject\n  typename TOutputImage::Pointer inputPtr0 = const_cast<TOutputImage *>(this->GetInputVolume().GetPointer());\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the stack of projections to backproject\n  typename TOutputImage::Pointer inputPtr1 = const_cast<TOutputImage *>(this->GetInputProjectionStack().GetPointer());\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(inputPtr1->GetLargestPossibleRegion());\n\n  // Input 2 is the weights map on projections, if any\n  typename TWeightsImage::Pointer inputWeights = const_cast<TWeightsImage *>(this->GetInputWeights().GetPointer());\n  if (!inputWeights)\n    return;\n  inputWeights->SetRequestedRegion(inputWeights->GetLargestPossibleRegion());\n\n  // Input \"SupportMask\" is the support constraint mask on volume, if any\n  if (this->GetSupportMask().IsNotNull())\n  {\n    typename TSingleComponentImage::Pointer inputSupportMaskPtr =\n      const_cast<TSingleComponentImage *>(this->GetSupportMask().GetPointer());\n    if (!inputSupportMaskPtr)\n      return;\n    inputSupportMaskPtr->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n  }\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::GenerateOutputInformation()\n{\n  // Set runtime connections, and connections with\n  // forward and back projection filters, which are set\n  // at runtime\n  m_ConstantVolumeSource->SetInformationFromImage(this->GetInputVolume());\n  m_ConstantProjectionsSource->SetInformationFromImage(this->GetInputProjectionStack());\n\n  m_FloatingInputPointer = const_cast<TOutputImage *>(this->GetInputVolume().GetPointer());\n\n  // Set the first multiply filter to use the Support Mask, if any\n  if (this->GetSupportMask().IsNotNull())\n  {\n    m_MultiplyInputVolumeFilter->SetInput1(m_FloatingInputPointer);\n    m_MultiplyInputVolumeFilter->SetInput2(this->GetSupportMask());\n    m_FloatingInputPointer = m_MultiplyInputVolumeFilter->GetOutput();\n  }\n\n  // Set the forward projection filter's inputs\n  m_ForwardProjectionFilter->SetInput(0, m_ConstantProjectionsSource->GetOutput());\n  m_ForwardProjectionFilter->SetInput(1, m_FloatingInputPointer);\n\n  // Set the multiply filter's inputs for the projection weights (for WLS minimization)\n  m_MultiplyWithWeightsFilter->SetInput1(m_ForwardProjectionFilter->GetOutput());\n  m_MultiplyWithWeightsFilter->SetInput2(this->GetInputWeights());\n\n  // Set the back projection filter's inputs\n  m_BackProjectionFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_MultiplyWithWeightsFilter->GetOutput());\n  m_FloatingOutputPointer = m_BackProjectionFilter->GetOutput();\n\n  // Set the filters to compute the laplacian regularization, if any\n  if (m_Gamma != 0)\n  {\n    m_FloatingOutputPointer = ConnectGradientRegularization<TOutputImage>();\n  }\n\n  // Set the filters to compute the Tikhonov regularization, if any\n  if (m_Tikhonov != 0)\n  {\n    m_AddTikhonovFilter = AddFilterType::New();\n    m_AddTikhonovFilter->SetInput(1, m_FloatingOutputPointer);\n\n    m_MultiplyTikhonovFilter = MultiplyFilterType::New();\n    m_MultiplyTikhonovFilter->SetInput(m_FloatingInputPointer);\n    m_MultiplyTikhonovFilter->SetConstant2(m_Tikhonov);\n    m_FloatingOutputPointer = m_MultiplyTikhonovFilter->GetOutput();\n\n    if (this->GetLocalRegularizationWeights().IsNotNull())\n    {\n      m_MultiplyTikhonovWeightsFilter = MultiplyFilterType::New();\n      m_MultiplyTikhonovWeightsFilter->SetInput1(m_FloatingOutputPointer);\n      m_MultiplyTikhonovWeightsFilter->SetInput2(this->GetLocalRegularizationWeights());\n      m_FloatingOutputPointer = m_MultiplyTikhonovWeightsFilter->GetOutput();\n    }\n\n    m_AddTikhonovFilter->SetInput(0, m_FloatingOutputPointer);\n\n    m_FloatingOutputPointer = m_AddTikhonovFilter->GetOutput();\n  }\n\n  // Set the second multiply filter to use the Support Mask, if any\n  if (this->GetSupportMask().IsNotNull())\n  {\n    m_MultiplyOutputVolumeFilter->SetInput1(m_FloatingOutputPointer);\n    m_MultiplyOutputVolumeFilter->SetInput2(this->GetSupportMask());\n    m_FloatingOutputPointer = m_MultiplyOutputVolumeFilter->GetOutput();\n  }\n\n  // Set geometry\n  m_ForwardProjectionFilter->SetGeometry(this->m_Geometry);\n  m_BackProjectionFilter->SetGeometry(this->m_Geometry.GetPointer());\n\n  // Set memory management parameters for forward\n  // and back projection filters\n  m_ForwardProjectionFilter->SetInPlace(true);\n  m_ForwardProjectionFilter->ReleaseDataFlagOn();\n  m_BackProjectionFilter->SetInPlace(true);\n  m_BackProjectionFilter->SetReleaseDataFlag(this->GetSupportMask().IsNotNull() || (m_Gamma != 0) || (m_Tikhonov != 0));\n\n  // Update output information on the last filter of the pipeline\n  m_FloatingOutputPointer->UpdateOutputInformation();\n  this->GetOutput()->CopyInformation(m_FloatingOutputPointer);\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\nvoid\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::GenerateData()\n{\n  // Execute Pipeline\n  m_FloatingOutputPointer->Update();\n  this->GraftOutput(m_FloatingOutputPointer);\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntemplate <typename ImageType>\ntypename std::enable_if<std::is_same_v<TSingleComponentImage, ImageType>, ImageType>::type::Pointer\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  ConnectGradientRegularization()\n{\n  m_LaplacianFilter = rtk::LaplacianImageFilter<TOutputImage>::New();\n  m_LaplacianFilter->SetInput(m_FloatingInputPointer);\n  m_MultiplyLaplacianFilter = MultiplyFilterType::New();\n  m_MultiplyLaplacianFilter->SetInput1(m_LaplacianFilter->GetOutput());\n  // Set \"-1.0*gamma\" because we need to perform \"-1.0*Laplacian\"\n  // for correctly applying quadratic regularization || grad f ||_2^2\n  m_MultiplyLaplacianFilter->SetConstant2(-1.0 * m_Gamma);\n\n  m_AddLaplacianFilter = AddFilterType::New();\n  m_AddLaplacianFilter->SetInput(0, m_BackProjectionFilter->GetOutput());\n  if (this->GetLocalRegularizationWeights().IsNotNull())\n  {\n    m_LaplacianFilter->SetInput(\"Weights\",\n                                const_cast<TWeightsImage *>(this->GetLocalRegularizationWeights().GetPointer()));\n  }\n  m_AddLaplacianFilter->SetInput(1, m_MultiplyLaplacianFilter->GetOutput());\n\n  return m_AddLaplacianFilter->GetOutput();\n}\n\ntemplate <typename TOutputImage, typename TSingleComponentImage, typename TWeightsImage>\ntemplate <typename ImageType>\ntypename std::enable_if<!std::is_same_v<TSingleComponentImage, ImageType>, ImageType>::type::Pointer\nReconstructionConjugateGradientOperator<TOutputImage, TSingleComponentImage, TWeightsImage>::\n  ConnectGradientRegularization()\n{\n  itkWarningMacro(<< \"Gradient regularization is not enabled for vector images, assuming Gamma 0\");\n  return m_FloatingOutputPointer;\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkReg1DExtractShroudSignalImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReg1DExtractShroudSignalImageFilter_h\n#define rtkReg1DExtractShroudSignalImageFilter_h\n\n#include <itkImageToImageFilter.h>\n\nnamespace rtk\n{\n/** \\class Reg1DExtractShroudSignalImageFilter\n * \\brief Reg1DExtract the signal corresponding to the breathing motion\n * (1D) from a shroud image (2D).\n *\n * \\test rtkamsterdamshroudtest.cxx\n *\n * \\author Vivien Delmon\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputPixel, class TOutputPixel>\nclass ITK_TEMPLATE_EXPORT Reg1DExtractShroudSignalImageFilter\n  : public itk::ImageToImageFilter<itk::Image<TInputPixel, 2>, itk::Image<TOutputPixel, 1>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(Reg1DExtractShroudSignalImageFilter);\n\n  /** Standard class type alias. */\n  using TInputImage = itk::Image<TInputPixel, 2>;\n  using TOutputImage = itk::Image<TOutputPixel, 1>;\n  using Self = Reg1DExtractShroudSignalImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n  static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension;\n  static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(Reg1DExtractShroudSignalImageFilter);\n\n\nprotected:\n  Reg1DExtractShroudSignalImageFilter();\n  ~Reg1DExtractShroudSignalImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateData() override;\n\nprivate:\n  using RegisterImageType = itk::Image<TInputPixel, 1>;\n  TOutputPixel\n  register1D(const RegisterImageType *, const RegisterImageType *);\n\n}; // end of class\n\n} // end of namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkReg1DExtractShroudSignalImageFilter.hxx\"\n#endif\n\n#endif // ! rtkReg1DExtractShroudSignalImageFilter_h\n"
  },
  {
    "path": "include/rtkReg1DExtractShroudSignalImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReg1DExtractShroudSignalImageFilter_hxx\n#define rtkReg1DExtractShroudSignalImageFilter_hxx\n\n\n#include <itkExtractImageFilter.h>\n#include <itkTranslationTransform.h>\n#include <itkRegularStepGradientDescentOptimizer.h>\n#include <itkMeanSquaresImageToImageMetric.h>\n#include <itkLinearInterpolateImageFunction.h>\n#include <itkImageRegistrationMethod.h>\n#include <itkImageDuplicator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputPixel, class TOutputPixel>\nReg1DExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::Reg1DExtractShroudSignalImageFilter() = default;\n\ntemplate <class TInputPixel, class TOutputPixel>\nvoid\nReg1DExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput());\n  if (!inputPtr)\n  {\n    return;\n  }\n  inputPtr->SetRequestedRegion(inputPtr->GetLargestPossibleRegion());\n}\n\ntemplate <class TInputPixel, class TOutputPixel>\nvoid\nReg1DExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::GenerateOutputInformation()\n{\n  // get pointers to the input and output\n  typename Superclass::InputImageConstPointer inputPtr = this->GetInput();\n  typename Superclass::OutputImagePointer     outputPtr = this->GetOutput();\n\n  if (!outputPtr || !inputPtr)\n  {\n    return;\n  }\n  typename TOutputImage::RegionType            outRegion;\n  typename TOutputImage::RegionType::SizeType  outSize;\n  typename TOutputImage::RegionType::IndexType outIdx;\n  outSize[0] = this->GetInput()->GetLargestPossibleRegion().GetSize()[1];\n  outIdx[0] = this->GetInput()->GetLargestPossibleRegion().GetIndex()[1];\n  outRegion.SetSize(outSize);\n  outRegion.SetIndex(outIdx);\n\n  const typename TInputImage::SpacingType & inputSpacing = inputPtr->GetSpacing();\n  typename TOutputImage::SpacingType        outputSpacing;\n  outputSpacing[0] = inputSpacing[1];\n  outputPtr->SetSpacing(outputSpacing);\n\n  typename TOutputImage::DirectionType outputDirection;\n  outputDirection[0][0] = 1;\n  outputPtr->SetDirection(outputDirection);\n\n  const typename TInputImage::PointType & inputOrigin = inputPtr->GetOrigin();\n  typename TOutputImage::PointType        outputOrigin;\n  outputOrigin[0] = inputOrigin[1];\n  outputPtr->SetOrigin(outputOrigin);\n\n  outputPtr->SetLargestPossibleRegion(outRegion);\n}\n\ntemplate <class TInputPixel, class TOutputPixel>\nTOutputPixel\nReg1DExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::register1D(const RegisterImageType * f,\n                                                                           const RegisterImageType * m)\n{\n  using RegistrationType = itk::ImageRegistrationMethod<RegisterImageType, RegisterImageType>;\n\n  auto metric = itk::MeanSquaresImageToImageMetric<RegisterImageType, RegisterImageType>::New();\n  auto transform = itk::TranslationTransform<TOutputPixel, 1>::New();\n  auto optimizer = itk::RegularStepGradientDescentOptimizer::New();\n  auto interpolator = itk::LinearInterpolateImageFunction<RegisterImageType, TOutputPixel>::New();\n  auto registration = RegistrationType::New();\n\n  registration->SetMetric(metric);\n  registration->SetOptimizer(optimizer);\n  registration->SetTransform(transform);\n  registration->SetInterpolator(interpolator);\n\n  registration->SetFixedImage(f);\n  registration->SetMovingImage(m);\n  registration->SetFixedImageRegion(f->GetLargestPossibleRegion());\n\n  typename RegistrationType::ParametersType initialParameters(transform->GetNumberOfParameters());\n  // Initial offset along X\n  initialParameters[0] = itk::NumericTraits<TOutputPixel>::Zero;\n\n  registration->SetInitialTransformParameters(initialParameters);\n  optimizer->SetMaximumStepLength(1.00);\n  optimizer->SetMinimumStepLength(0.1);\n\n  // Set a stopping criterion\n  optimizer->SetNumberOfIterations(1000);\n\n  registration->Update();\n\n  return registration->GetLastTransformParameters()[0];\n}\n\ntemplate <class TInputPixel, class TOutputPixel>\nvoid\nReg1DExtractShroudSignalImageFilter<TInputPixel, TOutputPixel>::GenerateData()\n{\n  this->AllocateOutputs();\n\n\n  typename TInputImage::ConstPointer input = this->GetInput();\n  typename TInputImage::RegionType   inputRegion = input->GetLargestPossibleRegion();\n  typename TInputImage::SizeType     inputSize = inputRegion.GetSize();\n\n  auto extractor = itk::ExtractImageFilter<TInputImage, RegisterImageType>::New();\n  extractor->SetInput(input);\n\n  typename TInputImage::RegionType extractRegion;\n  typename TInputImage::SizeType   extractSize = inputRegion.GetSize();\n  typename TInputImage::IndexType  extractIdx = inputRegion.GetIndex();\n\n  extractSize[1] = 0;\n  extractIdx[1] = 0;\n  extractRegion.SetSize(extractSize);\n  extractRegion.SetIndex(extractIdx);\n  extractor->SetExtractionRegion(extractRegion);\n  extractor->SetDirectionCollapseToIdentity();\n  extractor->Update();\n  auto duplicator = itk::ImageDuplicator<RegisterImageType>::New();\n  duplicator->SetInputImage(extractor->GetOutput());\n  duplicator->Update();\n  const RegisterImageType * prev = duplicator->GetOutput();\n  TOutputPixel              pos = itk::NumericTraits<TOutputPixel>::Zero;\n\n  typename Superclass::OutputImagePointer output = this->GetOutput();\n  output->Allocate();\n  typename TOutputImage::RegionType::IndexType outputIdx;\n  outputIdx[0] = 0;\n  (*output)[outputIdx] = pos;\n  for (unsigned int i = 1; i < inputSize[1]; ++i)\n  {\n    extractIdx[1] = i;\n    extractRegion.SetSize(extractSize);\n    extractRegion.SetIndex(extractIdx);\n    extractor->SetExtractionRegion(extractRegion);\n    extractor->SetDirectionCollapseToIdentity();\n    extractor->Update();\n    pos -= register1D(prev, extractor->GetOutput());\n    outputIdx[0] = i;\n    (*output)[outputIdx] = pos;\n    duplicator->SetInputImage(extractor->GetOutput());\n    duplicator->Update();\n    prev = duplicator->GetOutput();\n  }\n}\n\n} // end of namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkReg23ProjectionGeometry.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReg23ProjectionGeometry_h\n#define rtkReg23ProjectionGeometry_h\n\n// RTK\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"RTKExport.h\"\n\n// ITK\n#include <itkPoint.h>\n#include <itkMatrix.h>\n\nnamespace rtk\n{\n\n/** \\class Reg23ProjectionGeometry\n * \\brief {A simple utility class which makes the REG23 projection geometry\n * compatible with RTK's geometry.}\n *\n * REG23 geometry (open-radART, plastimatch) is very simplicistic: a perspective\n * projection is defined by a source position (S) in world coordinate system\n * (WCS), a detector position (R) in WCS and the detector orientation in WCS\n * by the detector row vector (r) and the detector column vector (c).\n *\n * In order to make RTK aware of this geometry, the parameters mentioned above\n * have to be brought into RTK's native geometry format. This is achieved by\n * deriving from RTK's circular 3D projection geometry class and adding a new\n * dedicated method for adding a REG23 projection. Internally, this method\n * converts the S,R,r,c set into Euler angles and offsets as required by RTK's\n * native projection geometry definition format.\n *\n * @warning {The detector offset and direction is fully modeled by the resultant\n * RTK geometry entry. This means that the projection stack input into back-\n * projection filters or forward-projectors is expected to have zero-origin and\n * identity-direction!}\n *\n * @see rtk::ThreeDCircularProjectionGeometry\n *\n * \\test {TestReg23ProjectionGeometry.cxx}\n *\n * @author phil steininger\n *\n * \\ingroup RTK\n * @version 1.0\n */\nclass RTK_EXPORT Reg23ProjectionGeometry : public rtk::ThreeDCircularProjectionGeometry\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(Reg23ProjectionGeometry);\n\n  /** General type alias **/\n  using Self = Reg23ProjectionGeometry;\n  using Superclass = rtk::ThreeDCircularProjectionGeometry;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /**\n   * @brief Add a REG23-based geometry set to the RTK projections list.\n   * @param sourcePosition absolute position of the point source S in WCS\n   * @param detectorPosition absolute position of the detector origin R in WCS\n   * @param detectorRowVector absolute direction vector indicating the\n   * orientation of the detector's rows r (sometimes referred to as v1)\n   * @param detectorColumnVector absolute direction vector indicating the\n   * orientation of the detector's columns c (sometimes referred to as v2)\n   * @return TRUE if the projection could be added to the RTK projections list\n   */\n  bool\n  AddReg23Projection(const PointType &  sourcePosition,\n                     const PointType &  detectorPosition,\n                     const VectorType & detectorRowVector,\n                     const VectorType & detectorColumnVector);\n\nprotected:\n  /** Standard constructor. **/\n  Reg23ProjectionGeometry();\n  /** Destructor. **/\n  ~Reg23ProjectionGeometry() override;\n};\n\n} // namespace rtk\n\n#endif // rtkReg23ProjectionGeometry_h\n"
  },
  {
    "path": "include/rtkRegularizedConjugateGradientConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkRegularizedConjugateGradientConeBeamReconstructionFilter_h\n#define rtkRegularizedConjugateGradientConeBeamReconstructionFilter_h\n\n#include \"rtkConjugateGradientConeBeamReconstructionFilter.h\"\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaTotalVariationDenoisingBPDQImageFilter.h\"\n#else\n#  include \"rtkTotalVariationDenoisingBPDQImageFilter.h\"\n#endif\n#include \"rtkDeconstructSoftThresholdReconstructImageFilter.h\"\n\n#include <itkThresholdImageFilter.h>\n\nnamespace rtk\n{\n/** \\class RegularizedConjugateGradientConeBeamReconstructionFilter\n * \\brief Performs 3D regularized reconstruction\n *\n * Performs 3D Conjugate Gradient reconstruction, then\n * - Replaces all negative values by zero\n * - Applies total variation denoising in space\n * - Applies wavelets denoising in space\n * and starting over as many times as the number of main loop iterations desired.\n *\n * \\dot\n * digraph RegularizedConjugateGradientConeBeamReconstructionFilter {\n *\n * PrimaryInput [label=\"Primary input (3D image)\"];\n * PrimaryInput [shape=Mdiamond];\n * InputProjectionStack [label=\"Input projection stack\"];\n * InputProjectionStack [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction: 3D image)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * CG [ label=\"rtk::ConjugateGradientConeBeamReconstructionFilter\"\n *      URL=\"\\ref rtk::ConjugateGradientConeBeamReconstructionFilter\"];\n * Positivity [group=regul, label=\"itk::ThresholdImageFilter (positivity)\" URL=\"\\ref itk::ThresholdImageFilter\"];\n * TV [group=regul, label=\"rtk::TotalVariationDenoisingBPDQImageFilter\"\n *     URL=\"\\ref rtk::TotalVariationDenoisingBPDQImageFilter\"];\n * Wavelets [group=regul, label=\"rtk::DeconstructSoftThresholdReconstructImageFilter\"\n *           URL=\"\\ref rtk::DeconstructSoftThresholdReconstructImageFilter\"];\n * SoftThreshold [group=regul, label=\"rtk::SoftThresholdImageFilter\" URL=\"\\ref rtk::SoftThresholdImageFilter\"];\n *\n * AfterPrimaryInput [group=invisible, label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterCG [group=invisible, label=\"m_PerformPositivity ?\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterPositivity [group=invisible, label=\"m_PerformTVSpatialDenoising ?\",\n *                  fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterTV [group=invisible, label=\"m_PerformWaveletsSpatialDenoising ?\",\n *          fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterWavelets [group=invisible, label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterSoftThreshold [group=invisible, label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * PrimaryInput -> AfterPrimaryInput [arrowhead=none];\n * AfterPrimaryInput -> CG;\n * InputProjectionStack -> CG;\n * CG -> AfterCG;\n * AfterCG -> Positivity [label=\"true\"];\n * Positivity -> AfterPositivity;\n * AfterPositivity -> TV [label=\"true\"];\n * TV -> AfterTV;\n * AfterTV -> Wavelets [label=\"true\"];\n * Wavelets -> AfterWavelets;\n * AfterWavelets -> SoftThreshold [label=\"true\"];\n * SoftThreshold -> AfterSoftThreshold;\n * AfterSoftThreshold -> Output;\n * AfterSoftThreshold -> AfterPrimaryInput [style=dashed];\n *\n * AfterCG -> AfterPositivity  [label=\"false\"];\n * AfterPositivity -> AfterTV [label=\"false\"];\n * AfterTV -> AfterWavelets [label=\"false\"];\n * AfterWavelets -> AfterSoftThreshold [label=\"false\"];\n *\n * // Invisible edges between the regularization filters\n * edge[style=invis];\n * Positivity -> TV;\n * TV -> Wavelets;\n * Wavelets -> SoftThreshold;\n * }\n * \\enddot\n *\n * \\test rtkregularizedconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT RegularizedConjugateGradientConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<TImage, TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(RegularizedConjugateGradientConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = RegularizedConjugateGradientConeBeamReconstructionFilter;\n  using Superclass = rtk::IterativeConeBeamReconstructionFilter<TImage, TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using CovariantVectorForSpatialGradient = itk::CovariantVector<typename TImage::ValueType, TImage::ImageDimension>;\n\n#ifdef RTK_USE_CUDA\n  using GradientImageType = itk::CudaImage<CovariantVectorForSpatialGradient, TImage::ImageDimension>;\n#else\n  using GradientImageType = itk::Image<CovariantVectorForSpatialGradient, TImage::ImageDimension>;\n#endif\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(RegularizedConjugateGradientConeBeamReconstructionFilter);\n\n  /** The image to be updated.*/\n  void\n  SetInputVolume(const TImage * Volume);\n  typename TImage::ConstPointer\n  GetInputVolume();\n\n  /** The stack of measured projections */\n  void\n  SetInputProjectionStack(const TImage * Projection);\n  typename TImage::Pointer\n  GetInputProjectionStack();\n\n  /** The weights map (Weighted least squares optimization in the conjugate gradient filter)*/\n  void\n  SetInputWeights(const TImage * Weights);\n  typename TImage::Pointer\n  GetInputWeights();\n\n  /** Set the support mask, if any, for support constraint in reconstruction */\n  void\n  SetSupportMask(const TImage * SupportMask);\n  typename TImage::ConstPointer\n  GetSupportMask();\n\n  using CGFilterType = rtk::ConjugateGradientConeBeamReconstructionFilter<TImage>;\n  using ThresholdFilterType = itk::ThresholdImageFilter<TImage>;\n  using TVDenoisingFilterType = rtk::TotalVariationDenoisingBPDQImageFilter<TImage, GradientImageType>;\n  using WaveletsDenoisingFilterType = rtk::DeconstructSoftThresholdReconstructImageFilter<TImage>;\n  using SoftThresholdFilterType = rtk::SoftThresholdImageFilter<TImage, TImage>;\n\n  // Regularization steps to perform\n  itkSetMacro(PerformPositivity, bool);\n  itkGetMacro(PerformPositivity, bool);\n  itkSetMacro(PerformTVSpatialDenoising, bool);\n  itkGetMacro(PerformTVSpatialDenoising, bool);\n  itkSetMacro(PerformWaveletsSpatialDenoising, bool);\n  itkGetMacro(PerformWaveletsSpatialDenoising, bool);\n  itkSetMacro(PerformSoftThresholdOnImage, bool);\n  itkGetMacro(PerformSoftThresholdOnImage, bool);\n\n  // Regularization parameters\n  itkSetMacro(GammaTV, float);\n  itkGetMacro(GammaTV, float);\n  itkSetMacro(SoftThresholdWavelets, float);\n  itkGetMacro(SoftThresholdWavelets, float);\n  itkSetMacro(SoftThresholdOnImage, float);\n  itkGetMacro(SoftThresholdOnImage, float);\n\n  /** Set the number of levels of the wavelets decomposition */\n  itkGetMacro(NumberOfLevels, unsigned int);\n  itkSetMacro(NumberOfLevels, unsigned int);\n\n  /** Sets the order of the Daubechies wavelet used to deconstruct/reconstruct the image pyramid */\n  itkGetMacro(Order, unsigned int);\n  itkSetMacro(Order, unsigned int);\n\n  // Iterations\n  itkSetMacro(MainLoop_iterations, int);\n  itkGetMacro(MainLoop_iterations, int);\n  itkSetMacro(CG_iterations, int);\n  itkGetMacro(CG_iterations, int);\n  itkSetMacro(TV_iterations, int);\n  itkGetMacro(TV_iterations, int);\n\n  // Geometry\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkGetModifiableObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Preconditioning flag for the conjugate gradient filter */\n  itkSetMacro(Preconditioned, bool);\n  itkGetMacro(Preconditioned, bool);\n\n  /** Quadratic regularization for the conjugate gradient filter */\n  itkSetMacro(Tikhonov, float);\n  itkGetMacro(Tikhonov, float);\n  itkSetMacro(Gamma, float);\n  itkGetMacro(Gamma, float);\n\n  /** Perform CG operations on GPU ? */\n  itkSetMacro(CudaConjugateGradient, bool);\n  itkGetMacro(CudaConjugateGradient, bool);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\nprotected:\n  RegularizedConjugateGradientConeBeamReconstructionFilter();\n  ~RegularizedConjugateGradientConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  // Inputs are not supposed to occupy the same physical space,\n  // so there is nothing to verify\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename CGFilterType::Pointer                m_CGFilter;\n  typename ThresholdFilterType::Pointer         m_PositivityFilter;\n  typename TVDenoisingFilterType::Pointer       m_TVDenoising;\n  typename WaveletsDenoisingFilterType::Pointer m_WaveletsDenoising;\n  typename SoftThresholdFilterType::Pointer     m_SoftThresholdFilter;\n\n  // Booleans for each regularization (should it be performed or not)\n  // as well as to choose whether CG should be on GPU or not\n  bool m_PerformPositivity;\n  bool m_PerformTVSpatialDenoising;\n  bool m_PerformWaveletsSpatialDenoising;\n  bool m_CudaConjugateGradient;\n  bool m_PerformSoftThresholdOnImage;\n\n  // Regularization parameters\n  float m_GammaTV;\n  float m_Gamma;\n  float m_Tikhonov;\n  float m_SoftThresholdWavelets;\n  float m_SoftThresholdOnImage;\n  bool  m_DimensionsProcessedForTV[TImage::ImageDimension];\n  bool  m_Preconditioned;\n  bool  m_RegularizedCG;\n\n  /** Information for the wavelets denoising filter */\n  unsigned int m_Order;\n  unsigned int m_NumberOfLevels;\n\n  /** Conjugate gradient parameters */\n  bool m_DisableDisplacedDetectorFilter;\n\n  // Iterations\n  int m_MainLoop_iterations;\n  int m_CG_iterations;\n  int m_TV_iterations;\n\n  // Geometry\n  typename rtk::ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkRegularizedConjugateGradientConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkRegularizedConjugateGradientConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkRegularizedConjugateGradientConeBeamReconstructionFilter_hxx\n#define rtkRegularizedConjugateGradientConeBeamReconstructionFilter_hxx\n\n\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\n\ntemplate <typename TImage>\nRegularizedConjugateGradientConeBeamReconstructionFilter<\n  TImage>::RegularizedConjugateGradientConeBeamReconstructionFilter()\n{\n  // Set the default values of member parameters\n  m_GammaTV = 0.00005;\n  m_Gamma = 0;    // Laplacian regularization\n  m_Tikhonov = 0; // Tikhonov regularization\n  m_SoftThresholdWavelets = 0.001;\n  m_SoftThresholdOnImage = 0.001;\n  m_Preconditioned = false;\n  m_RegularizedCG = false;\n\n  m_TV_iterations = 10;\n  m_MainLoop_iterations = 10;\n  m_CG_iterations = 4;\n\n  // Default pipeline: CG, positivity, spatial TV\n  m_PerformPositivity = true;\n  m_PerformTVSpatialDenoising = true;\n  m_PerformWaveletsSpatialDenoising = false;\n  m_PerformSoftThresholdOnImage = false;\n\n  // Dimensions processed for TV, default is all\n  for (unsigned int i = 0; i < TImage::ImageDimension; i++)\n    m_DimensionsProcessedForTV[i] = true;\n\n  // Other parameters\n  m_CudaConjugateGradient = true; // 3D volumes of usual size fit on GPUs\n  m_Order = 5;\n  m_NumberOfLevels = 3;\n  m_DisableDisplacedDetectorFilter = false;\n\n  // Create the filters\n  m_CGFilter = CGFilterType::New();\n  m_PositivityFilter = ThresholdFilterType::New();\n  m_TVDenoising = TVDenoisingFilterType::New();\n  m_WaveletsDenoising = WaveletsDenoisingFilterType::New();\n  m_SoftThresholdFilter = SoftThresholdFilterType::New();\n}\n\ntemplate <typename TImage>\nvoid\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::SetInputVolume(const TImage * Volume)\n{\n  this->SetPrimaryInput(const_cast<TImage *>(Volume));\n}\n\ntemplate <typename TImage>\nvoid\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::SetInputProjectionStack(const TImage * Projection)\n{\n  this->SetInput(\"ProjectionStack\", const_cast<TImage *>(Projection));\n}\n\ntemplate <typename TImage>\nvoid\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::SetInputWeights(const TImage * Weights)\n{\n  this->SetInput(\"Weights\", const_cast<TImage *>(Weights));\n}\n\ntemplate <typename TOutputImage>\nvoid\nRegularizedConjugateGradientConeBeamReconstructionFilter<TOutputImage>::SetSupportMask(const TOutputImage * SupportMask)\n{\n  this->SetInput(\"SupportMask\", const_cast<TOutputImage *>(SupportMask));\n}\n\ntemplate <typename TImage>\ntypename TImage::ConstPointer\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::GetInputVolume()\n{\n  return static_cast<const TImage *>(this->itk::ProcessObject::GetInput(\"Primary\"));\n}\n\ntemplate <typename TImage>\ntypename TImage::Pointer\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::GetInputProjectionStack()\n{\n  return static_cast<TImage *>(this->itk::ProcessObject::GetInput(\"ProjectionStack\"));\n}\n\ntemplate <typename TImage>\ntypename TImage::Pointer\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::GetInputWeights()\n{\n  return static_cast<TImage *>(this->itk::ProcessObject::GetInput(\"Weights\"));\n}\n\ntemplate <typename TOutputImage>\ntypename TOutputImage::ConstPointer\nRegularizedConjugateGradientConeBeamReconstructionFilter<TOutputImage>::GetSupportMask()\n{\n  return static_cast<const TOutputImage *>(this->itk::ProcessObject::GetInput(\"SupportMask\"));\n}\n\ntemplate <typename TImage>\nvoid\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <typename TImage>\nvoid\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Let the CG subfilters compute the requested regions for the projections\n  // stack and the input volume\n  m_CGFilter->PropagateRequestedRegion(m_CGFilter->GetOutput());\n}\n\ntemplate <typename TImage>\nvoid\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::GenerateOutputInformation()\n{\n  // Construct the pipeline, adding regularization filters if the user wants them\n  // Connect the last filter's output to the next filter's input using the currentDownstreamFilter pointer\n  typename itk::ImageToImageFilter<TImage, TImage>::Pointer currentDownstreamFilter;\n\n  // Set projection filters\n  m_CGFilter->SetForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n  m_CGFilter->SetBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n\n  // The conjugate gradient filter is the only part that must be in the pipeline\n  // whatever was the user wants\n  m_CGFilter->SetInput(0, this->GetInputVolume());\n  m_CGFilter->SetInput(1, this->GetInputProjectionStack());\n  m_CGFilter->SetInput(2, this->GetInputWeights());\n  m_CGFilter->SetSupportMask(this->GetSupportMask());\n  m_CGFilter->SetGeometry(this->m_Geometry);\n  m_CGFilter->SetNumberOfIterations(this->m_CG_iterations);\n  m_CGFilter->SetCudaConjugateGradient(this->GetCudaConjugateGradient());\n  m_CGFilter->SetGamma(this->m_Gamma);\n  m_CGFilter->SetTikhonov(this->m_Tikhonov);\n  m_CGFilter->SetDisableDisplacedDetectorFilter(m_DisableDisplacedDetectorFilter);\n\n  currentDownstreamFilter = m_CGFilter;\n\n  // Plug the positivity filter if requested\n  if (m_PerformPositivity)\n  {\n    m_PositivityFilter->SetInPlace(false);\n\n    m_PositivityFilter->SetOutsideValue(0.0);\n    m_PositivityFilter->ThresholdBelow(0.0);\n    m_PositivityFilter->SetInput(currentDownstreamFilter->GetOutput());\n\n    currentDownstreamFilter = m_PositivityFilter;\n  }\n\n  if (m_PerformTVSpatialDenoising)\n  {\n    currentDownstreamFilter->ReleaseDataFlagOn();\n\n    m_TVDenoising->SetInput(currentDownstreamFilter->GetOutput());\n    m_TVDenoising->SetNumberOfIterations(this->m_TV_iterations);\n    m_TVDenoising->SetGamma(this->m_GammaTV);\n    m_TVDenoising->SetDimensionsProcessed(this->m_DimensionsProcessedForTV);\n\n    currentDownstreamFilter = m_TVDenoising;\n  }\n\n  if (m_PerformWaveletsSpatialDenoising)\n  {\n    m_WaveletsDenoising->SetInput(currentDownstreamFilter->GetOutput());\n    m_WaveletsDenoising->SetOrder(m_Order);\n    m_WaveletsDenoising->SetThreshold(m_SoftThresholdWavelets);\n    m_WaveletsDenoising->SetNumberOfLevels(m_NumberOfLevels);\n\n    currentDownstreamFilter = m_WaveletsDenoising;\n  }\n\n  if (m_PerformSoftThresholdOnImage)\n  {\n    currentDownstreamFilter->ReleaseDataFlagOn();\n\n    m_SoftThresholdFilter->SetInput(currentDownstreamFilter->GetOutput());\n    m_SoftThresholdFilter->SetThreshold(m_SoftThresholdOnImage);\n\n    currentDownstreamFilter = m_SoftThresholdFilter;\n  }\n\n  // Have the last filter calculate its output information\n  currentDownstreamFilter->ReleaseDataFlagOff();\n  currentDownstreamFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(currentDownstreamFilter->GetOutput());\n}\n\ntemplate <typename TImage>\nvoid\nRegularizedConjugateGradientConeBeamReconstructionFilter<TImage>::GenerateData()\n{\n  // Declare the pointer that will be used to plug the output back as input\n  typename itk::ImageToImageFilter<TImage, TImage>::Pointer currentDownstreamFilter;\n  typename TImage::Pointer                                  pimg;\n\n  itk::IterationReporter iterationReporter(this, 0, 1);\n\n  for (int i = 0; i < m_MainLoop_iterations; i++)\n  {\n    // After the first iteration, we need to use the output as input\n    if (i > 0)\n    {\n      pimg = currentDownstreamFilter->GetOutput();\n\n      pimg->DisconnectPipeline();\n      m_CGFilter->SetInput(0, pimg);\n\n      // The input volume is no longer needed on the GPU, so we transfer it back to the CPU\n      this->GetInputVolume()->GetBufferPointer();\n    }\n\n    currentDownstreamFilter = m_CGFilter;\n    if (m_PerformPositivity)\n    {\n      currentDownstreamFilter = m_PositivityFilter;\n    }\n    if (m_PerformTVSpatialDenoising)\n    {\n      currentDownstreamFilter = m_TVDenoising;\n    }\n    if (m_PerformWaveletsSpatialDenoising)\n    {\n      currentDownstreamFilter = m_WaveletsDenoising;\n    }\n    if (m_PerformSoftThresholdOnImage)\n    {\n      currentDownstreamFilter = m_SoftThresholdFilter;\n    }\n\n    currentDownstreamFilter->Update();\n    this->GraftOutput(currentDownstreamFilter->GetOutput());\n    iterationReporter.CompletedStep();\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkReorderProjectionsImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReorderProjectionsImageFilter_h\n#define rtkReorderProjectionsImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\n/** \\class ReorderProjectionsImageFilter\n * \\brief Sorts or shuffle projections and geometry inputs\n *\n * This filter permutes projections and geometry with the same permutation.\n * The permutation is either the one that sorts projections by ascending phase,\n * so that the ones with the same phase can be forward and back projected together\n * (which is faster than one-by-one), or it is a random shuffle, useful for subset\n * processings.\n *\n * \\test\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT ReorderProjectionsImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ReorderProjectionsImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ReorderProjectionsImageFilter;\n\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n  using PermutationType = enum { NONE = 0, SORT = 1, SHUFFLE = 2 };\n\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using GeometryConstPointer = GeometryType::ConstPointer;\n  using GeometryPointer = GeometryType::Pointer;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(ReorderProjectionsImageFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(OutputGeometry, GeometryType);\n  itkSetConstObjectMacro(InputGeometry, ThreeDCircularProjectionGeometry);\n\n  /** Get / Set the kind of permutation requested */\n  itkGetMacro(Permutation, PermutationType);\n  itkSetMacro(Permutation, PermutationType);\n\n  /** Set the input signal */\n  void\n  SetInputSignal(const std::vector<double> signal);\n  std::vector<double>\n  GetOutputSignal();\n\nprotected:\n  ReorderProjectionsImageFilter();\n\n  ~ReorderProjectionsImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\nprivate:\n  /** RTK geometry objects */\n  GeometryConstPointer m_InputGeometry;\n  GeometryPointer      m_OutputGeometry;\n\n  /** Input and output signal vectors */\n  std::vector<double> m_InputSignal;\n  std::vector<double> m_OutputSignal;\n\n  /** Permutation type */\n  PermutationType m_Permutation;\n\n  /** Indices in the original stack for the new stack */\n  std::vector<unsigned int> m_NewIndices;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkReorderProjectionsImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkReorderProjectionsImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkReorderProjectionsImageFilter_hxx\n#define rtkReorderProjectionsImageFilter_hxx\n\n\n#include \"rtkGeneralPurposeFunctions.h\"\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n#include <algorithm> // std::shuffle\n#include <random>    // std::default_random_engine\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nReorderProjectionsImageFilter<TInputImage, TOutputImage>::ReorderProjectionsImageFilter()\n{\n  m_OutputGeometry = GeometryType::New();\n  m_Permutation = NONE;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nReorderProjectionsImageFilter<TInputImage, TOutputImage>::SetInputSignal(const std::vector<double> signal)\n{\n  m_InputSignal = signal;\n  m_Permutation = SORT;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nstd::vector<double>\nReorderProjectionsImageFilter<TInputImage, TOutputImage>::GetOutputSignal()\n{\n  return m_OutputSignal;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nReorderProjectionsImageFilter<TInputImage, TOutputImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_InputGeometry.IsNull() || this->m_OutputGeometry.IsNull())\n    itkExceptionMacro(<< \"Geometries have not been set.\");\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nReorderProjectionsImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  Superclass::GenerateOutputInformation();\n\n  unsigned int NumberOfProjections =\n    this->GetInput()->GetLargestPossibleRegion().GetSize()[TInputImage::ImageDimension - 1];\n  m_NewIndices.clear();\n  switch (m_Permutation)\n  {\n    case (NONE):\n    {\n      for (unsigned int i = 0; i < NumberOfProjections; i++)\n        m_NewIndices.push_back(i);\n      break;\n    }\n    case (SORT):\n    {\n      // Define a vector of pairs (signal value, and index)\n      std::vector<std::pair<double, unsigned int>> pairsVector;\n\n      // Fill it with the signal values, and with the integers from 0 to m_InputSignal.size() - 1\n      for (unsigned int i = 0; i < NumberOfProjections; i++)\n        pairsVector.emplace_back(m_InputSignal[i], i);\n\n      // Sort it according to values\n      std::sort(pairsVector.begin(), pairsVector.end());\n\n      // Extract the permutated indices\n      for (unsigned int i = 0; i < NumberOfProjections; i++)\n        m_NewIndices.push_back(pairsVector[i].second);\n      break;\n    }\n    case (SHUFFLE):\n    {\n      for (unsigned int i = 0; i < NumberOfProjections; i++)\n        m_NewIndices.push_back(i);\n      std::default_random_engine randomGenerator(0); // The seed is hard-coded to 0 to make the behavior reproducible\n      std::shuffle(m_NewIndices.begin(), m_NewIndices.end(), randomGenerator);\n      break;\n    }\n    default:\n      itkGenericExceptionMacro(<< \"Unhandled projection reordering method\");\n  }\n\n  // Initialize objects (otherwise, if the filter runs several times,\n  // the outputs become incorrect)\n  m_OutputGeometry->Clear();\n  m_OutputSignal.clear();\n\n  // Perform the copies\n  for (unsigned int proj = 0; proj < NumberOfProjections; proj++)\n  {\n    // Copy the geometry\n    m_OutputGeometry->SetRadiusCylindricalDetector(m_InputGeometry->GetRadiusCylindricalDetector());\n    m_OutputGeometry->AddProjectionInRadians(m_InputGeometry->GetSourceToIsocenterDistances()[m_NewIndices[proj]],\n                                             m_InputGeometry->GetSourceToDetectorDistances()[m_NewIndices[proj]],\n                                             m_InputGeometry->GetGantryAngles()[m_NewIndices[proj]],\n                                             m_InputGeometry->GetProjectionOffsetsX()[m_NewIndices[proj]],\n                                             m_InputGeometry->GetProjectionOffsetsY()[m_NewIndices[proj]],\n                                             m_InputGeometry->GetOutOfPlaneAngles()[m_NewIndices[proj]],\n                                             m_InputGeometry->GetInPlaneAngles()[m_NewIndices[proj]],\n                                             m_InputGeometry->GetSourceOffsetsX()[m_NewIndices[proj]],\n                                             m_InputGeometry->GetSourceOffsetsY()[m_NewIndices[proj]]);\n    m_OutputGeometry->SetCollimationOfLastProjection(m_InputGeometry->GetCollimationUInf()[m_NewIndices[proj]],\n                                                     m_InputGeometry->GetCollimationUSup()[m_NewIndices[proj]],\n                                                     m_InputGeometry->GetCollimationVInf()[m_NewIndices[proj]],\n                                                     m_InputGeometry->GetCollimationVSup()[m_NewIndices[proj]]);\n\n    // Copy the signal, if any\n    if (m_Permutation == SORT)\n      m_OutputSignal.push_back(m_InputSignal[m_NewIndices[proj]]);\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nReorderProjectionsImageFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  // Allocate the pixels of the output\n  this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetRequestedRegion());\n  this->GetOutput()->Allocate();\n\n  // Declare regions used in the loop\n  typename TInputImage::RegionType inputRegion = this->GetOutput()->GetRequestedRegion();\n  typename TInputImage::RegionType outputRegion = this->GetOutput()->GetRequestedRegion();\n  inputRegion.SetSize(2, 1);\n  outputRegion.SetSize(2, 1);\n\n  // Copy the projection data\n  for (unsigned int i = 0; i < this->GetOutput()->GetRequestedRegion().GetSize()[2]; i++)\n  {\n    const unsigned int proj = i + this->GetOutput()->GetRequestedRegion().GetIndex()[2];\n\n    // Regions\n    inputRegion.SetIndex(2, m_NewIndices[proj]);\n    outputRegion.SetIndex(2, proj);\n\n    itk::ImageRegionConstIterator<TInputImage> inputProjsIt(this->GetInput(), inputRegion);\n    itk::ImageRegionIterator<TOutputImage>     outputProjsIt(this->GetOutput(), outputRegion);\n\n    // Actual copy\n    while (!outputProjsIt.IsAtEnd())\n    {\n      outputProjsIt.Set(inputProjsIt.Get());\n      ++outputProjsIt;\n      ++inputProjsIt;\n    }\n  }\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkResourceProbesCollector.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkResourceProbesCollector_h\n#define rtkResourceProbesCollector_h\n\n#include \"RTKExport.h\"\n#include \"rtkConfiguration.h\"\n#include <itkTimeProbe.h>\n#include <itkMemoryProbe.h>\n\n#ifdef RTK_USE_CUDA\n#  include <itkCudaMemoryProbe.h>\n#endif\n\nnamespace rtk\n{\n/** \\class ResourceProbesCollector\n *  \\brief Aggregates a set of time, memory and cuda memory probes.\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT ResourceProbesCollector\n{\npublic:\n  using IdType = std::string;\n  using TimeMapType = std::map<IdType, itk::TimeProbe>;\n  using MemoryMapType = std::map<IdType, itk::MemoryProbe>;\n#ifdef RTK_USE_CUDA\n  using CudaMemoryMapType = std::map<IdType, itk::CudaMemoryProbe>;\n#endif\n\n  /** destructor */\n  virtual ~ResourceProbesCollector() = default;\n\n  /** Start a probe with a particular name. If the time probe does not\n   * exist, it will be created */\n  virtual void\n  Start(const char * id);\n\n  /** Stop a time probe identified with a name */\n  virtual void\n  Stop(const char * id);\n\n  /** Report the summary of results from all probes */\n  virtual void\n  Report(std::ostream & os = std::cout) const;\n\n  /** Destroy the set of probes. New probes can be created after invoking this\n    method. */\n  virtual void\n  Clear();\n\nprotected:\n  TimeMapType   m_TimeProbes;\n  MemoryMapType m_MemoryProbes;\n#ifdef RTK_USE_CUDA\n  CudaMemoryMapType m_CudaMemoryProbes;\n#endif\n};\n} // namespace rtk\n\n#endif // rtkResourceProbesCollector_h\n"
  },
  {
    "path": "include/rtkSARTConeBeamReconstructionFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSARTConeBeamReconstructionFilter_h\n#define rtkSARTConeBeamReconstructionFilter_h\n\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkRayBoxIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkIterativeConeBeamReconstructionFilter.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n#include \"rtkNesterovUpdateImageFilter.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n#include <itkSubtractImageFilter.h>\n#include <itkAddImageAdaptor.h>\n#include <itkAddImageFilter.h>\n#include <itkDivideOrZeroOutImageFilter.h>\n#include <itkThresholdImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class SARTConeBeamReconstructionFilter\n * \\brief Implements the Simultaneous Algebraic Reconstruction Technique [Andersen, 1984]\n *\n * SARTConeBeamReconstructionFilter is a composite filter which combines\n * the different steps of the SART cone-beam reconstruction, mainly:\n * - ExtractFilterType to work on one projection at a time\n * - ForwardProjectionImageFilter,\n * - SubtractImageFilter,\n * - BackProjectionImageFilter.\n * The input stack of projections is processed piece by piece (the size is\n * controlled with ProjectionSubsetSize) via the use of itk::ExtractImageFilter\n * to extract sub-stacks.\n *\n * Two weighting steps must be applied when processing a given projection:\n * - each pixel of the forward projection must be divided by the total length of the\n * intersection between the ray and the reconstructed volume. This weighting step\n * is performed using the part of the pipeline that contains RayBoxIntersectionImageFilter\n * - each voxel of the back projection must be divided by the value it would take if\n * a projection filled with ones was being reprojected. This weighting step is not\n * performed when using a voxel-based back projection, as the weights are all equal to one\n * in this case. When using a ray-based backprojector, typically Joseph,it must be performed.\n * It is implemented in NormalizedJosephBackProjectionImageFilter, which\n * is used in the SART pipeline.\n *\n * \\dot\n * digraph SARTConeBeamReconstructionFilter {\n *\n * Input0 [ label=\"Input 0 (Volume)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Reconstruction)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * ForwardProject [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * Extract [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n * MultiplyByZero [ label=\"itk::MultiplyImageFilter (by zero)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * AfterExtract [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n * MultiplyByLambda [ label=\"itk::MultiplyImageFilter (by lambda)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n * DivideProj [ label=\"itk::DivideOrZeroOutImageFilter\" URL=\"\\ref itk::DivideOrZeroOutImageFilter\"];\n * DivideVol [ label=\"itk::DivideOrZeroOutImageFilter\" URL=\"\\ref itk::DivideOrZeroOutImageFilter\"];\n * GatingWeight [ label=\"itk::MultiplyImageFilter (by gating weight)\"\n *                URL=\"\\ref itk::MultiplyImageFilter\", style=dashed];\n * Displaced [ label=\"rtk::DisplacedDetectorImageFilter\" URL=\"\\ref rtk::DisplacedDetectorImageFilter\"];\n * ConstantProjectionStack [ label=\"rtk::ConstantImageSource (0)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ExtractConstantProjection [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n * RayBox [ label=\"rtk::RayBoxIntersectionImageFilter\" URL=\"\\ref rtk::RayBoxIntersectionImageFilter\"];\n * ConstantVolume [ label=\"rtk::ConstantImageSource (0)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * BackProjection [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * ConstantProjDenom [ label=\"rtk::ConstantImageSource (1)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * BackProjectionDenom [ label=\"rtk::BackProjectionImageFilter\" URL=\"\\ref rtk::BackProjectionImageFilter\"];\n * Add [ label=\"itk::AddImageFilter or rtk::NesterovUpdateImageFilter\" URL=\"\\ref rtk::NesterovUpdateImageFilter\"];\n * OutofInput0 [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Threshold [ label=\"itk::ThresholdImageFilter\" URL=\"\\ref itk::ThresholdImageFilter\"];\n * OutofThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * OutofBP [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * BeforeBP [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * BeforeAdd [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Input0 -> OutofInput0 [arrowhead=none];\n * OutofInput0 -> ForwardProject;\n * OutofInput0 -> BeforeAdd [arrowhead=none];\n * BeforeAdd -> Add;\n * ConstantVolume -> BeforeBP [arrowhead=none];\n * BeforeBP -> BackProjection;\n * Extract -> AfterExtract[arrowhead=none];\n * AfterExtract -> MultiplyByZero;\n * AfterExtract -> Subtract;\n * MultiplyByZero -> ForwardProject;\n * Input1 -> Extract;\n * ForwardProject -> Subtract;\n * Subtract -> MultiplyByLambda;\n * MultiplyByLambda -> DivideProj;\n * DivideProj -> GatingWeight;\n * GatingWeight -> Displaced;\n * ConstantProjectionStack -> ExtractConstantProjection;\n * ExtractConstantProjection -> RayBox;\n * RayBox -> DivideProj;\n * Displaced -> BackProjection;\n * BackProjection -> OutofBP [arrowhead=none];\n * ConstantProjDenom -> BackProjectionDenom;\n * OutofBP -> DivideVol\n * BeforeBP -> BackProjectionDenom;\n * BackProjectionDenom -> DivideVol;\n * DivideVol -> Add;\n * Add -> Threshold;\n * Threshold -> OutofThreshold [arrowhead=none];\n * OutofThreshold -> OutofInput0 [headport=\"se\", style=dashed];\n * OutofThreshold -> Output;\n * }\n * \\enddot\n *\n * \\test rtksarttest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\ntemplate <class TVolumeImage, class TProjectionImage = TVolumeImage>\nclass ITK_TEMPLATE_EXPORT SARTConeBeamReconstructionFilter\n  : public rtk::IterativeConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SARTConeBeamReconstructionFilter);\n\n  /** Standard class type alias. */\n  using Self = SARTConeBeamReconstructionFilter;\n  using Superclass = IterativeConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using VolumeType = TVolumeImage;\n  using ProjectionType = TProjectionImage;\n  using ProjectionPixelType = typename ProjectionType::PixelType;\n\n  /** Typedefs of each subfilter of this composite filter */\n  using ExtractFilterType = itk::ExtractImageFilter<ProjectionType, ProjectionType>;\n  using MultiplyFilterType = itk::MultiplyImageFilter<ProjectionType, ProjectionType, ProjectionType>;\n  using ForwardProjectionFilterType = rtk::ForwardProjectionImageFilter<ProjectionType, VolumeType>;\n  using SubtractFilterType = itk::SubtractImageFilter<ProjectionType, ProjectionType>;\n  using AddFilterType = itk::AddImageFilter<VolumeType, VolumeType>;\n  using NesterovFilterType = rtk::NesterovUpdateImageFilter<VolumeType>;\n  using BackProjectionFilterType = rtk::BackProjectionImageFilter<VolumeType, ProjectionType>;\n  using RayBoxIntersectionFilterType = rtk::RayBoxIntersectionImageFilter<ProjectionType, ProjectionType>;\n  using DivideProjectionFilterType = itk::DivideOrZeroOutImageFilter<ProjectionType, ProjectionType, ProjectionType>;\n  using DivideVolumeFilterType = itk::DivideOrZeroOutImageFilter<VolumeType, VolumeType, VolumeType>;\n  using ConstantVolumeSourceType = rtk::ConstantImageSource<VolumeType>;\n  using ConstantProjectionSourceType = rtk::ConstantImageSource<ProjectionType>;\n  using ThresholdFilterType = itk::ThresholdImageFilter<VolumeType>;\n  using DisplacedDetectorFilterType = rtk::DisplacedDetectorImageFilter<ProjectionType>;\n  using GatingWeightsFilterType = itk::MultiplyImageFilter<ProjectionType, ProjectionType, ProjectionType>;\n\n  using ForwardProjectionType = typename Superclass::ForwardProjectionType;\n  using BackProjectionType = typename Superclass::BackProjectionType;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(SARTConeBeamReconstructionFilter);\n\n  /** Get / Set the object pointer to projection geometry */\n  itkGetModifiableObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n  itkSetObjectMacro(Geometry, ThreeDCircularProjectionGeometry);\n\n  /** Get / Set the number of iterations. Default is 3. */\n  itkGetMacro(NumberOfIterations, unsigned int);\n  itkSetMacro(NumberOfIterations, unsigned int);\n\n  /** Get / Set the number of projections per subset. Default is 1. */\n  itkGetMacro(NumberOfProjectionsPerSubset, unsigned int);\n  itkSetMacro(NumberOfProjectionsPerSubset, unsigned int);\n\n  /** Get / Set the convergence factor. Default is 0.3. */\n  itkGetMacro(Lambda, double);\n  itkSetMacro(Lambda, double);\n\n  /** Get / Set the positivity enforcement behaviour */\n  itkGetMacro(EnforcePositivity, bool);\n  itkSetMacro(EnforcePositivity, bool);\n\n  /** In the case of a gated SART, set the gating weights */\n  void\n  SetGatingWeights(std::vector<float> weights);\n\n  /** Set / Get whether the displaced detector filter should be disabled */\n  itkSetMacro(DisableDisplacedDetectorFilter, bool);\n  itkGetMacro(DisableDisplacedDetectorFilter, bool);\n\n  /** Set the threshold below which pixels in the denominator in the projection space are considered zero. The division\n   * by zero will then be evaluated at zero. Avoid noise magnification from low projections values when working with\n   * noisy and/or simulated data.\n   */\n  itkSetMacro(DivisionThreshold, ProjectionPixelType);\n  itkGetMacro(DivisionThreshold, ProjectionPixelType);\n\n  /** Parameter to trigger Nesterov's reset. The value is a number of subsets\n  ** which can be larger than the number of subsets per iteration. 1 means no\n  ** Nesterov acceleration (default). */\n  itkSetMacro(ResetNesterovEvery, int);\n  itkGetMacro(ResetNesterovEvery, int);\n\nprotected:\n  SARTConeBeamReconstructionFilter();\n  ~SARTConeBeamReconstructionFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Pointers to each subfilter of this composite filter */\n  typename ExtractFilterType::Pointer            m_ExtractFilter;\n  typename ExtractFilterType::Pointer            m_ExtractFilterRayBox;\n  typename MultiplyFilterType::Pointer           m_ZeroMultiplyFilter;\n  typename ForwardProjectionFilterType::Pointer  m_ForwardProjectionFilter;\n  typename SubtractFilterType::Pointer           m_SubtractFilter;\n  typename AddFilterType::Pointer                m_AddFilter;\n  typename MultiplyFilterType::Pointer           m_MultiplyFilter;\n  typename BackProjectionFilterType::Pointer     m_BackProjectionFilter;\n  typename BackProjectionFilterType::Pointer     m_BackProjectionNormalizationFilter;\n  typename RayBoxIntersectionFilterType::Pointer m_RayBoxFilter;\n  typename DivideProjectionFilterType::Pointer   m_DivideProjectionFilter;\n  typename DivideVolumeFilterType::Pointer       m_DivideVolumeFilter;\n  typename ConstantProjectionSourceType::Pointer m_ConstantProjectionStackSource;\n  typename ConstantProjectionSourceType::Pointer m_OneConstantProjectionStackSource;\n  typename ConstantVolumeSourceType::Pointer     m_ConstantVolumeSource;\n  typename ThresholdFilterType::Pointer          m_ThresholdFilter;\n  typename DisplacedDetectorFilterType::Pointer  m_DisplacedDetectorFilter;\n  typename GatingWeightsFilterType::Pointer      m_GatingWeightsFilter;\n  typename NesterovFilterType::Pointer           m_NesterovFilter;\n\n  ProjectionPixelType m_DivisionThreshold;\n\n  bool m_EnforcePositivity;\n  bool m_DisableDisplacedDetectorFilter{};\n\nprivate:\n  /** Number of projections processed before the volume is updated (1 for SART,\n   * several for OS-SART, all for SIRT) */\n  unsigned int m_NumberOfProjectionsPerSubset{ 1 };\n\n  /** Geometry object */\n  ThreeDCircularProjectionGeometry::Pointer m_Geometry;\n\n  /** Number of iterations */\n  unsigned int m_NumberOfIterations;\n\n  /** Convergence factor according to Andersen's publications which relates\n   * to the step size of the gradient descent. Default 0.3, Must be in (0,2). */\n  double m_Lambda;\n\n  /** Have gating weights been set ? If so, apply them, otherwise ignore\n   * the gating weights filter */\n  bool               m_IsGated{};\n  std::vector<float> m_GatingWeights;\n\n  /** Nesterov reset. */\n  int m_ResetNesterovEvery{ 1 };\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSARTConeBeamReconstructionFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSARTConeBeamReconstructionFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSARTConeBeamReconstructionFilter_hxx\n#define rtkSARTConeBeamReconstructionFilter_hxx\n\n\n#include <algorithm>\n#include <itkIterationReporter.h>\n\nnamespace rtk\n{\ntemplate <class TVolumeImage, class TProjectionImage>\nSARTConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::SARTConeBeamReconstructionFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set default parameters\n  m_EnforcePositivity = false;\n  m_IsGated = false;\n  m_NumberOfIterations = 3;\n  m_Lambda = 0.3;\n\n  // Create each filter of the composite filter\n  m_ExtractFilter = ExtractFilterType::New();\n  m_ZeroMultiplyFilter = MultiplyFilterType::New();\n  m_SubtractFilter = SubtractFilterType::New();\n  m_AddFilter = AddFilterType::New();\n  m_NesterovFilter = NesterovFilterType::New();\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n  m_MultiplyFilter = MultiplyFilterType::New();\n  m_GatingWeightsFilter = GatingWeightsFilterType::New();\n  m_ConstantVolumeSource = ConstantVolumeSourceType::New();\n\n  // Create the filters required for correct weighting of the difference\n  // projection\n  m_ExtractFilterRayBox = ExtractFilterType::New();\n  m_RayBoxFilter = RayBoxIntersectionFilterType::New();\n  m_DivideProjectionFilter = DivideProjectionFilterType::New();\n  m_ConstantProjectionStackSource = ConstantProjectionSourceType::New();\n\n  // Create the filter that enforces positivity\n  m_ThresholdFilter = ThresholdFilterType::New();\n\n  // Create the filters required for the normalization of the\n  // backprojection\n  m_OneConstantProjectionStackSource = ConstantProjectionSourceType::New();\n  m_DivideVolumeFilter = DivideVolumeFilterType::New();\n  m_DivisionThreshold = m_DivideVolumeFilter->GetThreshold();\n\n  // Permanent internal connections\n  m_ZeroMultiplyFilter->SetInput1(itk::NumericTraits<typename ProjectionType::PixelType>::ZeroValue());\n  m_ZeroMultiplyFilter->SetInput2(m_ExtractFilter->GetOutput());\n\n  m_SubtractFilter->SetInput(0, m_ExtractFilter->GetOutput());\n\n  m_MultiplyFilter->SetInput1(m_Lambda);\n  m_MultiplyFilter->SetInput2(m_SubtractFilter->GetOutput());\n\n  m_ExtractFilterRayBox->SetInput(m_ConstantProjectionStackSource->GetOutput());\n  m_RayBoxFilter->SetInput(m_ExtractFilterRayBox->GetOutput());\n  m_DivideProjectionFilter->SetInput1(m_MultiplyFilter->GetOutput());\n  m_DivideProjectionFilter->SetInput2(m_RayBoxFilter->GetOutput());\n  m_DisplacedDetectorFilter->SetInput(m_DivideProjectionFilter->GetOutput());\n\n  // Default parameters\n  m_ExtractFilter->SetDirectionCollapseToSubmatrix();\n  m_ExtractFilterRayBox->SetDirectionCollapseToSubmatrix();\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nSARTConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::SetGatingWeights(std::vector<float> weights)\n{\n  m_GatingWeights = weights;\n  m_IsGated = true;\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nSARTConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_Geometry.IsNull())\n    itkExceptionMacro(<< \"Geometry has not been set.\");\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nSARTConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::GenerateInputRequestedRegion()\n{\n  typename Superclass::InputImagePointer inputPtr = const_cast<TVolumeImage *>(this->GetInput());\n\n  if (!inputPtr)\n    return;\n\n  if (m_EnforcePositivity)\n  {\n    m_ThresholdFilter->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n    m_ThresholdFilter->GetOutput()->PropagateRequestedRegion();\n  }\n  else\n  {\n    m_BackProjectionFilter->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n    m_BackProjectionFilter->GetOutput()->PropagateRequestedRegion();\n  }\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nSARTConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::GenerateOutputInformation()\n{\n  m_DisplacedDetectorFilter->SetDisable(m_DisableDisplacedDetectorFilter);\n  m_DivideProjectionFilter->SetThreshold(m_DivisionThreshold);\n\n  // We only set the first sub-stack at that point, the rest will be\n  // requested in the GenerateData function\n  typename ExtractFilterType::InputImageRegionType projRegion;\n\n  projRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  m_ExtractFilter->SetExtractionRegion(projRegion);\n  m_ExtractFilterRayBox->SetExtractionRegion(projRegion);\n\n  // Set forward projection filter\n  m_ForwardProjectionFilter = this->InstantiateForwardProjectionFilter(this->m_CurrentForwardProjectionConfiguration);\n\n  // Set back projection filter\n  m_BackProjectionFilter = this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n  m_BackProjectionNormalizationFilter =\n    this->InstantiateBackProjectionFilter(this->m_CurrentBackProjectionConfiguration);\n\n  // Links with the forward and back projection filters should be set here\n  // and not in the constructor, as these filters are set at runtime\n  m_ConstantVolumeSource->SetInformationFromImage(const_cast<TVolumeImage *>(this->GetInput(0)));\n  m_ConstantVolumeSource->SetConstant(0);\n  m_ConstantVolumeSource->UpdateOutputInformation();\n\n  m_OneConstantProjectionStackSource->SetInformationFromImage(\n    const_cast<TProjectionImage *>(m_ExtractFilter->GetOutput()));\n  m_OneConstantProjectionStackSource->SetConstant(1);\n\n  m_BackProjectionFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_DisplacedDetectorFilter->GetOutput());\n  m_BackProjectionFilter->SetTranspose(false);\n\n  m_BackProjectionNormalizationFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n  m_BackProjectionNormalizationFilter->SetInput(1, m_OneConstantProjectionStackSource->GetOutput());\n  m_BackProjectionNormalizationFilter->SetTranspose(false);\n\n  m_DivideVolumeFilter->SetInput1(m_BackProjectionFilter->GetOutput());\n  m_DivideVolumeFilter->SetInput2(m_BackProjectionNormalizationFilter->GetOutput());\n  m_DivideVolumeFilter->SetConstant(0);\n\n  typename VolumeType::Pointer lastOutput;\n  if (m_ResetNesterovEvery == 1)\n  {\n    m_MultiplyFilter->SetInput1((typename ProjectionType::PixelType)(m_Lambda));\n    m_AddFilter->SetInput1(m_DivideVolumeFilter->GetOutput());\n    m_AddFilter->SetInput2(this->GetInput(0));\n    lastOutput = m_AddFilter->GetOutput();\n  }\n  else\n  {\n    m_MultiplyFilter->SetInput1((typename ProjectionType::PixelType)(-m_Lambda));\n    m_NesterovFilter->SetInput(0, this->GetInput(0));\n    m_NesterovFilter->SetInput(1, m_DivideVolumeFilter->GetOutput());\n    lastOutput = m_NesterovFilter->GetOutput();\n  }\n\n  m_ForwardProjectionFilter->SetInput(0, m_ZeroMultiplyFilter->GetOutput());\n  m_ForwardProjectionFilter->SetInput(1, this->GetInput(0));\n  m_ExtractFilter->SetInput(this->GetInput(1));\n  m_SubtractFilter->SetInput(1, m_ForwardProjectionFilter->GetOutput());\n\n  m_ForwardProjectionFilter->SetGeometry(this->m_Geometry);\n  m_BackProjectionFilter->SetGeometry(this->m_Geometry);\n  m_BackProjectionNormalizationFilter->SetGeometry(this->m_Geometry);\n  m_DisplacedDetectorFilter->SetGeometry(this->m_Geometry);\n\n  if (m_IsGated) // For gated SART, insert a gating filter into the pipeline\n  {\n    m_GatingWeightsFilter->SetInput1(m_DivideProjectionFilter->GetOutput());\n    m_GatingWeightsFilter->SetConstant2(1);\n    m_DisplacedDetectorFilter->SetInput(m_GatingWeightsFilter->GetOutput());\n  }\n\n  m_ConstantProjectionStackSource->SetInformationFromImage(const_cast<TProjectionImage *>(this->GetInput(1)));\n  m_ConstantProjectionStackSource->SetConstant(0);\n  m_ConstantProjectionStackSource->UpdateOutputInformation();\n\n\n  // Create the m_RayBoxFiltersectionImageFilter\n  m_RayBoxFilter->SetGeometry(this->GetGeometry());\n\n  m_RayBoxFilter->SetBoxFromImage(this->GetInput(0), false);\n\n  if (m_EnforcePositivity)\n  {\n    m_ThresholdFilter->SetOutsideValue(0);\n    m_ThresholdFilter->ThresholdBelow(0);\n    m_ThresholdFilter->SetInput(lastOutput);\n    lastOutput = m_ThresholdFilter->GetOutput();\n  }\n\n  // Update output information\n  lastOutput->UpdateOutputInformation();\n  this->GetOutput()->SetOrigin(lastOutput->GetOrigin());\n  this->GetOutput()->SetSpacing(lastOutput->GetSpacing());\n  this->GetOutput()->SetDirection(lastOutput->GetDirection());\n  this->GetOutput()->SetLargestPossibleRegion(lastOutput->GetLargestPossibleRegion());\n\n  // Set memory management flags\n  m_ZeroMultiplyFilter->ReleaseDataFlagOn();\n  m_ForwardProjectionFilter->ReleaseDataFlagOn();\n  m_SubtractFilter->ReleaseDataFlagOn();\n  m_MultiplyFilter->ReleaseDataFlagOn();\n  m_RayBoxFilter->ReleaseDataFlagOn();\n  m_DivideProjectionFilter->ReleaseDataFlagOn();\n  m_DisplacedDetectorFilter->ReleaseDataFlagOn();\n  m_DivideVolumeFilter->ReleaseDataFlagOn();\n\n  if (m_EnforcePositivity)\n  {\n    m_AddFilter->ReleaseDataFlagOn();\n    m_NesterovFilter->ReleaseDataFlagOn();\n  }\n}\n\ntemplate <class TVolumeImage, class TProjectionImage>\nvoid\nSARTConeBeamReconstructionFilter<TVolumeImage, TProjectionImage>::GenerateData()\n{\n  const unsigned int Dimension = this->InputImageDimension;\n\n  // The backprojection works on one projection at a time\n  typename ExtractFilterType::InputImageRegionType subsetRegion;\n  subsetRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  unsigned int nProj = subsetRegion.GetSize(Dimension - 1);\n  subsetRegion.SetSize(Dimension - 1, 1);\n\n  // Fill and shuffle randomly the projection order.\n  // Should be tunable with other solutions.\n  std::vector<unsigned int> projOrder(nProj);\n\n  for (unsigned int i = 0; i < nProj; i++)\n    projOrder[i] = i;\n  std::shuffle(projOrder.begin(), projOrder.end(), Superclass::m_DefaultRandomEngine);\n\n  // Create the zero projection stack used as input by RayBoxIntersectionFilter\n  m_ConstantProjectionStackSource->Update();\n\n  // Declare the image used in the main loop\n  typename TVolumeImage::Pointer pimg;\n  typename TVolumeImage::Pointer norm;\n\n  itk::IterationReporter iterationReporter(this, 0, 1); // report every iteration\n\n  // For each iteration, go over each projection\n  for (unsigned int iter = 0; iter < m_NumberOfIterations; iter++)\n  {\n    unsigned int projectionsProcessedInSubset = 0;\n    for (unsigned int i = 0; i < nProj; i++)\n    {\n      // Change projection subset\n      subsetRegion.SetIndex(Dimension - 1, projOrder[i]);\n      m_ExtractFilter->SetExtractionRegion(subsetRegion);\n      m_ExtractFilterRayBox->SetExtractionRegion(subsetRegion);\n      m_ExtractFilter->UpdateOutputInformation();\n\n      m_OneConstantProjectionStackSource->SetInformationFromImage(\n        const_cast<TProjectionImage *>(m_ExtractFilter->GetOutput()));\n\n      // Set gating weight for the current projection\n      if (m_IsGated)\n      {\n        m_GatingWeightsFilter->SetConstant2(m_GatingWeights[i]);\n      }\n\n      // This is required to reset the full pipeline\n      m_BackProjectionFilter->GetOutput()->UpdateOutputInformation();\n      m_BackProjectionFilter->GetOutput()->PropagateRequestedRegion();\n      m_BackProjectionNormalizationFilter->GetOutput()->UpdateOutputInformation();\n      m_BackProjectionNormalizationFilter->GetOutput()->PropagateRequestedRegion();\n\n      projectionsProcessedInSubset++;\n      if ((projectionsProcessedInSubset == m_NumberOfProjectionsPerSubset) || (i == nProj - 1))\n      {\n        m_DivideVolumeFilter->SetInput2(m_BackProjectionNormalizationFilter->GetOutput());\n        m_DivideVolumeFilter->SetInput1(m_BackProjectionFilter->GetOutput());\n        if (m_EnforcePositivity)\n          pimg = m_ThresholdFilter->GetOutput();\n        else if (m_ResetNesterovEvery == 1)\n        {\n          m_AddFilter->SetInput1(m_DivideVolumeFilter->GetOutput());\n          pimg = m_AddFilter->GetOutput();\n        }\n        else\n        {\n          m_NesterovFilter->SetInput(1, m_DivideVolumeFilter->GetOutput());\n          pimg = m_NesterovFilter->GetOutput();\n        }\n\n        // To start a new subset:\n        // - plug the output of the pipeline back into the Forward projection filter\n        // - set the input of the Back projection filter to zero\n        pimg->Update();\n        pimg->DisconnectPipeline();\n\n        m_ForwardProjectionFilter->SetInput(1, pimg);\n        if (m_ResetNesterovEvery == 1)\n          m_AddFilter->SetInput2(pimg);\n        else\n          m_NesterovFilter->SetInput(pimg);\n        m_BackProjectionFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n        m_BackProjectionNormalizationFilter->SetInput(0, m_ConstantVolumeSource->GetOutput());\n\n        projectionsProcessedInSubset = 0;\n      }\n      // Backproject in the same image otherwise.\n      else\n      {\n        m_BackProjectionFilter->Update();\n        m_BackProjectionNormalizationFilter->Update();\n        pimg = m_BackProjectionFilter->GetOutput();\n        pimg->DisconnectPipeline();\n        m_BackProjectionFilter->SetInput(0, pimg);\n        norm = m_BackProjectionNormalizationFilter->GetOutput();\n        norm->DisconnectPipeline();\n        m_BackProjectionNormalizationFilter->SetInput(0, norm);\n      }\n    }\n    this->GraftOutput(pimg);\n    iterationReporter.CompletedStep();\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkSARTConeBeamReconstructionFilter_hxx\n"
  },
  {
    "path": "include/rtkScatterGlareCorrectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkScatterGlareCorrectionImageFilter_h\n#define rtkScatterGlareCorrectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n#include \"rtkFFTProjectionsConvolutionImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class ScatterGlareCorrectionImageFilter\n * \\brief Implements the scatter glare correction as described in [Poludniowski, PMB 2011].\n *\n * The filter code is based on FFTConvolutionImageFilter by Gaetan Lehmann\n * (see https://hdl.handle.net/10380/3154)\n *\n * \\test rtkscatterglaretest.cxx\n *\n * \\author Sebastien Brousmiche\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage = TInputImage, class TFFTPrecision = double>\nclass ITK_TEMPLATE_EXPORT ScatterGlareCorrectionImageFilter\n  : public rtk::FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ScatterGlareCorrectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = ScatterGlareCorrectionImageFilter;\n  using Superclass = rtk::FFTProjectionsConvolutionImageFilter<TInputImage, TOutputImage, TFFTPrecision>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using FFTPrecisionType = TFFTPrecision;\n  using IndexType = typename InputImageType::IndexType;\n  using SizeType = typename InputImageType::SizeType;\n\n  using FFTInputImageType = typename Superclass::FFTInputImageType;\n  using FFTInputImagePointer = typename FFTInputImageType::Pointer;\n  using FFTOutputImageType = typename Superclass::FFTOutputImageType;\n  using FFTOutputImagePointer = typename FFTOutputImageType::Pointer;\n\n  using CoefficientVectorType = typename std::vector<float>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(ScatterGlareCorrectionImageFilter);\n\n  itkGetConstMacro(Coefficients, CoefficientVectorType);\n  virtual void\n  SetCoefficients(const CoefficientVectorType coefficients)\n  {\n    if (this->m_Coefficients != coefficients)\n    {\n      this->m_Coefficients = coefficients;\n      this->Modified();\n    }\n  }\n\nprotected:\n  ScatterGlareCorrectionImageFilter();\n  ~ScatterGlareCorrectionImageFilter() override = default;\n\n  /** Create the deconvolution kernel\n   */\n  void\n  UpdateFFTProjectionsConvolutionKernel(const SizeType size) override;\n\nprivate:\n  CoefficientVectorType m_Coefficients;\n  CoefficientVectorType m_PreviousCoefficients;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkScatterGlareCorrectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkScatterGlareCorrectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkScatterGlareCorrectionImageFilter_hxx\n#define rtkScatterGlareCorrectionImageFilter_hxx\n\n\n// Use local RTK FFTW files taken from Gaëtan Lehmann's code for\n// thread safety: https://hdl.handle.net/10380/3154\n#include <itkRealToHalfHermitianForwardFFTImageFilter.h>\n#include <itkHalfHermitianToRealInverseFFTImageFilter.h>\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkDivideImageFilter.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nScatterGlareCorrectionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::ScatterGlareCorrectionImageFilter()\n{\n  this->m_KernelDimension = 2;\n}\n\ntemplate <class TInputImage, class TOutputImage, class TFFTPrecision>\nvoid\nScatterGlareCorrectionImageFilter<TInputImage, TOutputImage, TFFTPrecision>::UpdateFFTProjectionsConvolutionKernel(\n  const SizeType size)\n{\n  if (m_Coefficients.size() != 2)\n  {\n    itkGenericExceptionMacro(<< \"Expecting 2 coefficients in m_Coefficients)\");\n  }\n  double                dx = this->GetInput()->GetSpacing()[0];\n  double                dy = this->GetInput()->GetSpacing()[1];\n  CoefficientVectorType coeffs = m_Coefficients;\n  coeffs.push_back(dx);\n  coeffs.push_back(dy);\n  coeffs.push_back(size[0]);\n  coeffs.push_back(size[1]);\n  if (coeffs == m_PreviousCoefficients)\n    return; // Up-to-date\n  m_PreviousCoefficients = coeffs;\n\n  FFTInputImagePointer kernel = FFTInputImageType::New();\n  kernel->SetRegions(size);\n  kernel->Allocate();\n\n  double a3 = m_Coefficients[0];\n  double b3 = m_Coefficients[1];\n  double b3sq = b3 * b3;\n  double halfXSz = size[0] / 2.;\n  double halfYSz = size[1] / 2.;\n\n  itk::ImageRegionIteratorWithIndex<FFTInputImageType> itK(kernel, kernel->GetLargestPossibleRegion());\n  itK.GoToBegin();\n\n  // Central value\n  double g = (1 - a3) + a3 * dx * dy / (2. * itk::Math::pi * b3sq);\n  itK.Set(g);\n  ++itK;\n\n  typename FFTInputImageType::IndexType idx;\n  while (!itK.IsAtEnd())\n  {\n    idx = itK.GetIndex();\n    double xx = halfXSz - itk::Math::abs(halfXSz - idx[0]); // Distance to nearest x border\n    double yy = halfYSz - itk::Math::abs(halfYSz - idx[1]); // Distance to nearest y border\n    double rr2 = (xx * xx + yy * yy);\n    g = (a3 * dx * dy / (2. * itk::Math::pi * b3sq)) / std::pow((1. + rr2 / b3sq), 1.5);\n    itK.Set(g);\n    ++itK;\n  }\n\n  // FFT kernel\n  auto fftK = itk::RealToHalfHermitianForwardFFTImageFilter<FFTInputImageType, FFTOutputImageType>::New();\n  fftK->SetInput(kernel);\n  fftK->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  fftK->Update();\n\n  // Inverse\n  auto div = itk::DivideImageFilter<FFTOutputImageType, FFTOutputImageType, FFTOutputImageType>::New();\n  div->SetConstant1(1.);\n  div->SetInput(1, fftK->GetOutput());\n  div->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());\n  div->Update();\n\n  this->m_KernelFFT = div->GetOutput();\n  this->m_KernelFFT->DisconnectPipeline();\n}\n\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkSchlomka2008NegativeLogLikelihood.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSchlomka2008NegativeLogLikelihood_h\n#define rtkSchlomka2008NegativeLogLikelihood_h\n\n#include \"rtkProjectionsDecompositionNegativeLogLikelihood.h\"\n#include \"rtkMacro.h\"\n\n#include <itkVectorImage.h>\n#include <itkVariableLengthVector.h>\n#include <itkVariableSizeMatrix.h>\n\nnamespace rtk\n{\n/** \\class rtkSchlomka2008NegativeLogLikelihood\n * \\brief Cost function from the Schlomka 2008 PMB paper\n *\n * This class requires the method \"Initialize()\" to be run once, before it\n * is passed to the simplex minimizer\n * See the reference paper: \"Experimental feasibility of multi-energy photon-counting\n * K-edge imaging in pre-clinical computed tomography\", Schlomka et al, PMB 2008\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\n// We have to define the cost function first\nclass Schlomka2008NegativeLogLikelihood : public rtk::ProjectionsDecompositionNegativeLogLikelihood\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(Schlomka2008NegativeLogLikelihood);\n\n  using Self = Schlomka2008NegativeLogLikelihood;\n  using Superclass = rtk::ProjectionsDecompositionNegativeLogLikelihood;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods) */\n  itkOverrideGetNameOfClassMacro(Schlomka2008NegativeLogLikelihood);\n\n  using ParametersType = Superclass::ParametersType;\n  using DerivativeType = Superclass::DerivativeType;\n  using MeasureType = Superclass::MeasureType;\n\n  using DetectorResponseType = Superclass::DetectorResponseType;\n  using MaterialAttenuationsType = Superclass::MaterialAttenuationsType;\n  using MeasuredDataType = Superclass::MeasuredDataType;\n  using IncidentSpectrumType = Superclass::IncidentSpectrumType;\n\n  // Constructor\n  Schlomka2008NegativeLogLikelihood() { m_NumberOfSpectralBins = 0; }\n\n  // Destructor\n  ~Schlomka2008NegativeLogLikelihood() override = default;\n\n  void\n  Initialize() override\n  {\n    // This method computes the combined m_IncidentSpectrumAndDetectorResponseProduct\n    // from m_DetectorResponse and m_IncidentSpectrum\n\n    // In spectral CT, m_DetectorResponse has as many rows as the number of bins,\n    // and m_IncidentSpectrum has only one row (there is only one spectrum illuminating\n    // the object)\n    m_IncidentSpectrumAndDetectorResponseProduct.set_size(m_DetectorResponse.rows(), m_DetectorResponse.cols());\n    for (unsigned int i = 0; i < m_DetectorResponse.rows(); i++)\n      for (unsigned int j = 0; j < m_DetectorResponse.cols(); j++)\n        m_IncidentSpectrumAndDetectorResponseProduct[i][j] = m_DetectorResponse[i][j] * m_IncidentSpectrum[0][j];\n  }\n\n  // Not used with a simplex optimizer, but may be useful later\n  // for gradient based methods\n  void\n  GetDerivative(const ParametersType & lineIntegrals, DerivativeType & derivatives) const override\n  {\n    // Set the size of the derivatives vector\n    derivatives.set_size(m_NumberOfMaterials);\n\n    // Get some required data\n    vnl_vector<double> attenuationFactors;\n    attenuationFactors.set_size(this->m_NumberOfEnergies);\n    GetAttenuationFactors(lineIntegrals, attenuationFactors);\n    vnl_vector<double> lambdas = ForwardModel(lineIntegrals);\n\n    // Compute the vector of 1 - m_b / lambda_b\n    vnl_vector<double> weights;\n    weights.set_size(m_NumberOfSpectralBins);\n    for (unsigned int i = 0; i < m_NumberOfSpectralBins; i++)\n      weights[i] = 1 - (m_MeasuredData[i] / lambdas[i]);\n\n    // Prepare intermediate variables\n    vnl_vector<double> intermediate_a;\n    vnl_vector<double> partial_derivative_a;\n\n    for (unsigned int a = 0; a < m_NumberOfMaterials; a++)\n    {\n      // Compute the partial derivatives of lambda_b with respect to the material line integrals\n      intermediate_a = element_product(-attenuationFactors, m_MaterialAttenuations.get_column(a));\n      partial_derivative_a = m_IncidentSpectrumAndDetectorResponseProduct * intermediate_a;\n\n      // Multiply them together element-wise, then dot product with the weights\n      derivatives[a] = dot_product(partial_derivative_a, weights);\n    }\n  }\n\n  // Main method\n  MeasureType\n  GetValue(const ParametersType & parameters) const override\n  {\n    // Forward model: compute the expected number of counts in each bin\n    vnl_vector<double> forward = ForwardModel(parameters);\n\n    long double measure = 0;\n    // Compute the negative log likelihood from the lambdas\n    for (unsigned int i = 0; i < m_NumberOfSpectralBins; i++)\n      measure += forward[i] - std::log((long double)forward[i]) * m_MeasuredData[i];\n    return measure;\n  }\n\n  void\n  ComputeFischerMatrix(const ParametersType & lineIntegrals) override\n  {\n    // Get some required data\n    vnl_vector<double> attenuationFactors;\n    attenuationFactors.set_size(this->m_NumberOfEnergies);\n    GetAttenuationFactors(lineIntegrals, attenuationFactors);\n    vnl_vector<double> lambdas = ForwardModel(lineIntegrals);\n\n    // Compute the vector of m_b / lambda_b^2\n    vnl_vector<double> weights;\n    weights.set_size(m_NumberOfSpectralBins);\n    for (unsigned int i = 0; i < m_NumberOfSpectralBins; i++)\n      weights[i] = m_MeasuredData[i] / (lambdas[i] * lambdas[i]);\n\n    // Prepare intermediate variables\n    vnl_vector<double> intermediate_a;\n    vnl_vector<double> intermediate_a_prime;\n    vnl_vector<double> partial_derivative_a;\n    vnl_vector<double> partial_derivative_a_prime;\n\n    // Compute the Fischer information matrix\n    m_Fischer.SetSize(m_NumberOfMaterials, m_NumberOfMaterials);\n    for (unsigned int a = 0; a < m_NumberOfMaterials; a++)\n    {\n      for (unsigned int a_prime = 0; a_prime < m_NumberOfMaterials; a_prime++)\n      {\n        // Compute the partial derivatives of lambda_b with respect to the material line integrals\n        intermediate_a = element_product(-attenuationFactors, m_MaterialAttenuations.get_column(a));\n        intermediate_a_prime = element_product(-attenuationFactors, m_MaterialAttenuations.get_column(a_prime));\n\n        partial_derivative_a = m_IncidentSpectrumAndDetectorResponseProduct * intermediate_a;\n        partial_derivative_a_prime = m_IncidentSpectrumAndDetectorResponseProduct * intermediate_a_prime;\n\n        // Multiply them together element-wise, then dot product with the weights\n        partial_derivative_a_prime = element_product(partial_derivative_a, partial_derivative_a_prime);\n        m_Fischer[a][a_prime] = dot_product(partial_derivative_a_prime, weights);\n      }\n    }\n  }\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkSelectOneProjectionPerCycleImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkSelectOneProjectionPerCycleImageFilter_h\n#define rtkSelectOneProjectionPerCycleImageFilter_h\n\n#include \"rtkSubSelectImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class SelectOneProjectionPerCycleImageFilter\n * \\brief Subselects one projection per respiratory cycle from a phase signal\n *\n * The selection selects for each respiratory cycle the projection that is the\n * nearest to the phase parameter. The phase signal is assumed to be between\n * 0 and 1 and monotonic.\n *\n * \\test rtkselectoneprojpercycletest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT SelectOneProjectionPerCycleImageFilter : public SubSelectImageFilter<ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SelectOneProjectionPerCycleImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SelectOneProjectionPerCycleImageFilter;\n  using Superclass = SubSelectImageFilter<ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SelectOneProjectionPerCycleImageFilter);\n\n  /** File name of a text file with one phase value between 0 and 1 per line. */\n  itkGetMacro(SignalFilename, std::string);\n  itkSetMacro(SignalFilename, std::string);\n\n  /** Phase value for which we want the closest projection image per cycle. */\n  itkSetMacro(Phase, double);\n  itkGetMacro(Phase, double);\n\nprotected:\n  SelectOneProjectionPerCycleImageFilter();\n  ~SelectOneProjectionPerCycleImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\nprivate:\n  std::string         m_SignalFilename;\n  double              m_Phase{ 0. };\n  std::vector<double> m_Signal;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSelectOneProjectionPerCycleImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSelectOneProjectionPerCycleImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkSelectOneProjectionPerCycleImageFilter_hxx\n#define rtkSelectOneProjectionPerCycleImageFilter_hxx\n\n#include <itkCSVArray2DFileReader.h>\n\nnamespace rtk\n{\n\ntemplate <typename ProjectionStackType>\nSelectOneProjectionPerCycleImageFilter<ProjectionStackType>::SelectOneProjectionPerCycleImageFilter() = default;\n\ntemplate <typename ProjectionStackType>\nvoid\nSelectOneProjectionPerCycleImageFilter<ProjectionStackType>::GenerateOutputInformation()\n{\n  // Read signal file\n  auto reader = itk::CSVArray2DFileReader<double>::New();\n  reader->SetFileName(m_SignalFilename);\n  reader->SetFieldDelimiterCharacter(';');\n  reader->HasRowHeadersOff();\n  reader->HasColumnHeadersOff();\n  reader->Update();\n  m_Signal = reader->GetArray2DDataObject()->GetColumn(0);\n\n  this->m_NbSelectedProjs = 0;\n  this->m_SelectedProjections.resize(m_Signal.size());\n  std::fill(this->m_SelectedProjections.begin(), this->m_SelectedProjections.end(), false);\n  for (unsigned int i = 0; i < m_Signal.size() - 1; i++)\n  {\n    // Put phase between -0.5 and 0.5 with 0 the ref phase\n    double valPrev = m_Signal[i] - m_Phase;\n    valPrev -= itk::Math::floor(valPrev);\n    if (valPrev > 0.5)\n      valPrev -= 1.;\n    double valAfter = m_Signal[i + 1] - m_Phase;\n    valAfter -= itk::Math::floor(valAfter);\n    if (valAfter > 0.5)\n      valAfter -= 1.;\n\n    // Frame is selected if phase is increasing and has opposite signs\n    if (valPrev < valAfter && valAfter * valPrev <= 0.)\n    {\n      if (itk::Math::abs(valPrev) > itk::Math::abs(valAfter))\n      {\n        this->m_SelectedProjections[i + 1] = true;\n        this->m_NbSelectedProjs++;\n      }\n      else if (!this->m_SelectedProjections[i])\n      {\n        this->m_SelectedProjections[i] = true;\n        this->m_NbSelectedProjs++;\n      }\n    }\n  }\n\n  Superclass::GenerateOutputInformation();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkSeparableQuadraticSurrogateRegularizationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSeparableQuadraticSurrogateRegularizationImageFilter_h\n#define rtkSeparableQuadraticSurrogateRegularizationImageFilter_h\n\n#include <itkConstNeighborhoodIterator.h>\n#include <itkImageRegionIterator.h>\n#include <itkImageToImageFilter.h>\n\nnamespace rtk\n{\n\n/** \\class SeparableQuadraticSurrogateRegularizationImageFilter\n * \\brief For one-step inversion of spectral CT data by the method Mechlem2017, computes regularization term's first and\n * second derivatives\n *\n * In SQS-based methods (Long2014, Weidinger2016, Mechlem2017), the regularization term is typically\n * the sum of the \"absolute values\" of the differences between each pixel and its neighbours. Instead of\n * the actual absolute value function, which can't be differentiated in zero, smooth approximations are used,\n * e.g. the Huber function. Here, we employ another approximation, described in \"Bayesian Reconstructions\n * From Emission Tomography Data Using a Modified EM Algorithm\", by Peter J. Green, IEEE TMI 1990.\n * With respect to Huber, it has the advantage of not requiring a cut-off parameter.\n *\n * \\ingroup RTK IntensityImageFilters\n */\n\ntemplate <typename TImage>\nclass ITK_TEMPLATE_EXPORT SeparableQuadraticSurrogateRegularizationImageFilter\n  : public itk::ImageToImageFilter<TImage, TImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SeparableQuadraticSurrogateRegularizationImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SeparableQuadraticSurrogateRegularizationImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImage, TImage>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SeparableQuadraticSurrogateRegularizationImageFilter);\n\n  /** Set/Get for the radius */\n  itkSetMacro(Radius, typename TImage::RegionType::SizeType);\n  itkGetMacro(Radius, typename TImage::RegionType::SizeType);\n\n  /** Set/Get for the regularization weights */\n  itkSetMacro(RegularizationWeights, typename TImage::PixelType);\n  itkGetMacro(RegularizationWeights, typename TImage::PixelType);\n\nprotected:\n  SeparableQuadraticSurrogateRegularizationImageFilter();\n  ~SeparableQuadraticSurrogateRegularizationImageFilter() override = default;\n\n  /** Creates the Outputs */\n  itk::ProcessObject::DataObjectPointer\n  MakeOutput(itk::ProcessObject::DataObjectPointerArraySizeType idx) override;\n  itk::ProcessObject::DataObjectPointer\n  MakeOutput(const itk::ProcessObject::DataObjectIdentifierType &) override;\n\n  /** Does the real work. */\n  void\n  DynamicThreadedGenerateData(const typename TImage::RegionType & outputRegionForThread) override;\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Derivatives of the absolute value approximation */\n  typename TImage::PixelType\n  GreenPriorFirstDerivative(typename TImage::PixelType pix);\n  typename TImage::PixelType\n  GreenPriorSecondDerivative(typename TImage::PixelType pix);\n\n  /** Member variables */\n  typename TImage::RegionType::SizeType                            m_Radius;\n  typename itk::PixelTraits<typename TImage::PixelType>::ValueType m_C1;\n  typename itk::PixelTraits<typename TImage::PixelType>::ValueType m_C2;\n  typename TImage::PixelType                                       m_RegularizationWeights;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSeparableQuadraticSurrogateRegularizationImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSeparableQuadraticSurrogateRegularizationImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSeparableQuadraticSurrogateRegularizationImageFilter_hxx\n#define rtkSeparableQuadraticSurrogateRegularizationImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TImage>\nSeparableQuadraticSurrogateRegularizationImageFilter<TImage>::SeparableQuadraticSurrogateRegularizationImageFilter()\n{\n  // Create the outputs\n  this->SetNthOutput(0, this->MakeOutput(0));\n  this->SetNthOutput(1, this->MakeOutput(1));\n\n  // Default radius is 0\n  m_Radius.Fill(0);\n\n  // Set default regularization weights to 0\n  m_RegularizationWeights.Fill(0);\n\n  // Constants used in Green's prior, not modifiable by the user\n  m_C1 = 27.0 / 128.0;\n  m_C2 = 16.0 / (3.0 * std::sqrt(3.0));\n}\n\ntemplate <typename TImage>\nitk::ProcessObject::DataObjectPointer\nSeparableQuadraticSurrogateRegularizationImageFilter<TImage>::MakeOutput(\n  itk::ProcessObject::DataObjectPointerArraySizeType idx)\n{\n  itk::DataObject::Pointer output;\n\n  switch (idx)\n  {\n    case 0:\n      output = (TImage::New()).GetPointer();\n      break;\n    case 1:\n      output = (TImage::New()).GetPointer();\n      break;\n    default:\n      std::cerr << \"No output \" << idx << std::endl;\n      output = nullptr;\n      break;\n  }\n  return output.GetPointer();\n}\n\ntemplate <typename TImage>\nitk::ProcessObject::DataObjectPointer\nSeparableQuadraticSurrogateRegularizationImageFilter<TImage>::MakeOutput(\n  const itk::ProcessObject::DataObjectIdentifierType & idx)\n{\n  return Superclass::MakeOutput(idx);\n}\n\ntemplate <typename TImage>\nvoid\nSeparableQuadraticSurrogateRegularizationImageFilter<TImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get the requested regions on both outputs (should be identical)\n  typename TImage::RegionType outputRequested1 = this->GetOutput(0)->GetRequestedRegion();\n  typename TImage::RegionType outputRequested2 = this->GetOutput(1)->GetRequestedRegion();\n  if (outputRequested1 != outputRequested2)\n    itkGenericExceptionMacro(\n      << \"In rtkWeidingerForwardModelImageFilter: requested regions for outputs 1 and 2 should be identical\");\n\n  // Get pointer to the input\n  typename TImage::ConstPointer smart = this->GetInput();\n  typename TImage::Pointer      inputPtr = const_cast<TImage *>(smart.GetPointer());\n  //  typename TImage::Pointer inputPtr = const_cast<TImage*>(this->GetInput().GetPointer());\n\n  // Pad by the radius of the neighborhood, and crop to the largest possible region\n  typename TImage::RegionType inputRequested = outputRequested1;\n  inputRequested.PadByRadius(m_Radius);\n  inputRequested.Crop(inputPtr->GetLargestPossibleRegion());\n\n  // Set the requested region\n  inputPtr->SetRequestedRegion(inputRequested);\n}\n\ntemplate <typename TImage>\ntypename TImage::PixelType\nSeparableQuadraticSurrogateRegularizationImageFilter<TImage>::GreenPriorFirstDerivative(typename TImage::PixelType pix)\n{\n  typename TImage::PixelType out;\n  for (unsigned int i = 0; i < TImage::PixelType::Dimension; i++)\n    out[i] = 2 * m_RegularizationWeights[i] * m_C1 * m_C2 * tanh(m_C2 * pix[i]);\n\n  return out;\n}\n\ntemplate <typename TImage>\ntypename TImage::PixelType\nSeparableQuadraticSurrogateRegularizationImageFilter<TImage>::GreenPriorSecondDerivative(typename TImage::PixelType pix)\n{\n  typename TImage::PixelType out;\n  for (unsigned int i = 0; i < TImage::PixelType::Dimension; i++)\n    out[i] = 4 * m_RegularizationWeights[i] * m_C1 * m_C2 * m_C2 / (cosh(m_C2 * pix[i]) * cosh(m_C2 * pix[i]));\n\n  return out;\n}\n\ntemplate <typename TImage>\nvoid\nSeparableQuadraticSurrogateRegularizationImageFilter<TImage>::DynamicThreadedGenerateData(\n  const typename TImage::RegionType & outputRegionForThread)\n{\n  // Create iterators for all inputs and outputs\n  itk::ImageRegionIterator<TImage>       out1It(this->GetOutput(0), outputRegionForThread);\n  itk::ImageRegionIterator<TImage>       out2It(this->GetOutput(1), outputRegionForThread);\n  itk::ConstNeighborhoodIterator<TImage> nIt(m_Radius, this->GetInput(), outputRegionForThread);\n\n  // Precompute the offset of center pixel\n  auto c = (itk::SizeValueType)(nIt.Size() / 2);\n\n  // Declare intermediate variables\n  typename TImage::PixelType diff, out1, out2;\n\n  // Walk the output image\n  while (!out1It.IsAtEnd())\n  {\n    out1 = itk::NumericTraits<typename TImage::PixelType>::ZeroValue();\n    out2 = itk::NumericTraits<typename TImage::PixelType>::ZeroValue();\n\n    // Walk the neighborhood of the current pixel in the input image\n    for (unsigned int i = 0; i < nIt.Size(); i++)\n    {\n      // Compute the difference between central pixel and neighbor pixel\n      diff = nIt.GetPixel(c) - nIt.GetPixel(i);\n\n      // Compute the first and second derivatives of Green's prior at diff\n      // and accumulate them in the output\n      out1 += GreenPriorFirstDerivative(diff);\n      out2 += GreenPriorSecondDerivative(diff);\n    }\n\n    // Set the outputs\n    out1It.Set(out1);\n    out2It.Set(out2);\n\n    // Move to next pixel\n    ++nIt;\n    ++out1It;\n    ++out2It;\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkSheppLoganPhantom.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSheppLoganPhantom_h\n#define rtkSheppLoganPhantom_h\n\n#include \"RTKExport.h\"\n#include \"rtkGeometricPhantom.h\"\n#include \"rtkQuadricShape.h\"\n\nnamespace rtk\n{\n/** \\class SheppLoganPhantom\n * \\brief SheppLogan phantom as defined in \"Principles of CT imaging\" by Kak & Slaney\n *\n * See https://www.slaney.org/pct/pct-errata.html for the correction of the\n * phantom definition.\n *\n * \\test rtkfdktest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n *\n */\nclass RTK_EXPORT SheppLoganPhantom : public GeometricPhantom\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SheppLoganPhantom);\n\n  /** Standard class type alias. */\n  using Self = SheppLoganPhantom;\n  using Superclass = itk::DataObject;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using ScalarType = QuadricShape::ScalarType;\n  using PointType = QuadricShape::PointType;\n  using VectorType = QuadricShape::VectorType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SheppLoganPhantom);\n\nprotected:\n  SheppLoganPhantom();\n  ~SheppLoganPhantom() override = default;\n\nprivate:\n  void\n  SetEllipsoid(ScalarType spax,\n               ScalarType spay,\n               ScalarType spaz,\n               ScalarType centerx,\n               ScalarType centery,\n               ScalarType centerz,\n               ScalarType angle,\n               ScalarType density);\n};\n\n} // namespace rtk\n#endif // rtkSheppLoganPhantom_h\n"
  },
  {
    "path": "include/rtkSheppLoganPhantomFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSheppLoganPhantomFilter_h\n#define rtkSheppLoganPhantomFilter_h\n\n#include \"rtkProjectGeometricPhantomImageFilter.h\"\n\nnamespace rtk\n{\n\n/** \\class SheppLoganPhantomFilter\n * \\brief Analytical projection of a SheppLoganPhantom with a 128 (default) scale.\n *\n * \\test rtkRaycastInterpolatorForwardProjectionTest.cxx,\n * rtkprojectgeometricphantomtest.cxx, rtkfdktest.cxx, rtkrampfiltertest.cxx,\n * rtkforwardprojectiontest.cxx, rtkdisplaceddetectortest.cxx,\n * rtkshortscantest.cxx\n *\n * \\author Marc Vila, Simon Rit\n *\n * \\ingroup RTK InPlaceImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT SheppLoganPhantomFilter : public ProjectGeometricPhantomImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SheppLoganPhantomFilter);\n\n  /** Standard class type alias. */\n  using Self = SheppLoganPhantomFilter;\n  using Superclass = ProjectGeometricPhantomImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SheppLoganPhantomFilter);\n\nprotected:\n  SheppLoganPhantomFilter();\n  ~SheppLoganPhantomFilter() override = default;\n\n  void\n  GenerateData() override;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSheppLoganPhantomFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSheppLoganPhantomFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSheppLoganPhantomFilter_hxx\n#define rtkSheppLoganPhantomFilter_hxx\n\n#include \"rtkSheppLoganPhantom.h\"\n\nnamespace rtk\n{\ntemplate <class TInputImage, class TOutputImage>\nSheppLoganPhantomFilter<TInputImage, TOutputImage>::SheppLoganPhantomFilter()\n{\n  this->SetPhantomScale(ConvexShape::VectorType(128));\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nSheppLoganPhantomFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  this->SetGeometricPhantom(SheppLoganPhantom::New().GetPointer());\n  this->SetConfigFile(\"\");\n  Superclass::GenerateData();\n}\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkSignalToInterpolationWeights.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSignalToInterpolationWeights_h\n#define rtkSignalToInterpolationWeights_h\n\n#include \"RTKExport.h\"\n#include \"itkCSVFileReaderBase.h\"\n#include \"itkArray2D.h\"\n\nnamespace rtk\n{\n\n/** \\class SignalToInterpolationWeights\n * \\brief Computes interpolation weights for 4D reconstruction\n *\n * Computes the interpolation weights (along time) for 4D reconstruction\n * from the input signal (the phase at which each projection has been acquired).\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\nclass RTK_EXPORT SignalToInterpolationWeights : public itk::CSVFileReaderBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SignalToInterpolationWeights);\n\n  /** Standard class type alias */\n  using Self = SignalToInterpolationWeights;\n  using Superclass = CSVFileReaderBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods) */\n  itkOverrideGetNameOfClassMacro(SignalToInterpolationWeights);\n\n  /** DataFrame Object types */\n  using Array2DType = itk::Array2D<float>;\n\n  /** The value type of the dataset. */\n  using ValueType = float;\n\n  /** Required, but not used */\n  void\n  Parse() override\n  {}\n\n  /** Does the real work */\n  virtual void\n  Update();\n\n  /** Aliased to the GetDataFrameObject() method to be consistent with the\n   *  rest of the pipeline */\n  virtual Array2DType\n  GetOutput();\n\n  /** Configure the filter to use uneven temporal spacing (finer temporal resolution during systole) */\n  itkSetMacro(NumberOfReconstructedFrames, int);\n  itkGetMacro(NumberOfReconstructedFrames, int);\n\n  /** Set the input signal */\n  void\n  SetSignal(const std::vector<double> signal);\n\nprotected:\n  SignalToInterpolationWeights();\n  ~SignalToInterpolationWeights() override = default;\n\n  /** Print the reader. */\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\nprivate:\n  Array2DType         m_Array2D;\n  int                 m_NumberOfReconstructedFrames;\n  std::vector<double> m_Signal;\n};\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkSimplexSpectralProjectionsDecompositionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSimplexSpectralProjectionsDecompositionImageFilter_h\n#define rtkSimplexSpectralProjectionsDecompositionImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkAmoebaOptimizer.h>\n#include \"rtkSchlomka2008NegativeLogLikelihood.h\"\n#include \"rtkDualEnergyNegativeLogLikelihood.h\"\n#include \"rtkVectorImageToImageFilter.h\"\n\n#include <itkPermuteAxesImageFilter.h>\n\nnamespace rtk\n{\n/** \\class SimplexSpectralProjectionsDecompositionImageFilter\n * \\brief Decomposition of spectral projection images into material projections\n *\n * See the reference paper: \"Experimental feasibility of multi-energy photon-counting\n * K-edge imaging in pre-clinical computed tomography\", Schlomka et al, PMB 2008\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType = itk::Image<float, 3>,\n          typename DetectorResponseImageType = itk::Image<float, 2>,\n          typename MaterialAttenuationsImageType = itk::Image<float, 2>>\nclass ITK_TEMPLATE_EXPORT SimplexSpectralProjectionsDecompositionImageFilter\n  : public itk::ImageToImageFilter<DecomposedProjectionsType, DecomposedProjectionsType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SimplexSpectralProjectionsDecompositionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SimplexSpectralProjectionsDecompositionImageFilter;\n  using Superclass = itk::ImageToImageFilter<DecomposedProjectionsType, DecomposedProjectionsType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = DecomposedProjectionsType;\n  using OutputImageType = DecomposedProjectionsType;\n\n  /** Convenient information */\n  using ThresholdsType = itk::VariableLengthVector<double>;\n  using MeanAttenuationInBinType = itk::VariableSizeMatrix<double>;\n  using DetectorResponseType = vnl_matrix<double>;\n  using MaterialAttenuationsType = vnl_matrix<double>;\n  using CostFunctionType = ProjectionsDecompositionNegativeLogLikelihood;\n  using DecomposedProjectionsDataType = typename DecomposedProjectionsType::PixelType::ValueType;\n  using MeasuredProjectionsDataType = typename MeasuredProjectionsType::PixelType::ValueType;\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  /** Additional types to overload SetInputIncidentSpectrum */\n  using VectorSpectrumImageType = itk::VectorImage<float, 2>;\n  using FlattenVectorFilterType = rtk::VectorImageToImageFilter<VectorSpectrumImageType, IncidentSpectrumImageType>;\n  using PermuteFilterType = itk::PermuteAxesImageFilter<IncidentSpectrumImageType>;\n#endif\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(SimplexSpectralProjectionsDecompositionImageFilter);\n\n  /** Set/Get the input material-decomposed stack of projections (only used for initialization) */\n  void\n  SetInputDecomposedProjections(\n    const typename itk::ImageBase<DecomposedProjectionsType::ImageDimension> * DecomposedProjections);\n  template <unsigned int VNumberOfMaterials>\n  void\n  SetInputFixedVectorLengthDecomposedProjections(\n    const itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,\n                     DecomposedProjectionsType::ImageDimension> * DecomposedProjections);\n  typename DecomposedProjectionsType::ConstPointer\n  GetInputDecomposedProjections();\n\n  /** Set/Get the input stack of measured projections (to be decomposed in materials) */\n  void\n  SetInputMeasuredProjections(\n    const typename itk::ImageBase<MeasuredProjectionsType::ImageDimension> * MeasuredProjections);\n  template <unsigned int VNumberOfSpectralBins>\n  void\n  SetInputFixedVectorLengthMeasuredProjections(\n    const itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,\n                     MeasuredProjectionsType::ImageDimension> * MeasuredProjections);\n  typename MeasuredProjectionsType::ConstPointer\n  GetInputMeasuredProjections();\n\n\n  /** Set/Get the detector response as an image */\n  void\n  SetDetectorResponse(const DetectorResponseImageType * DetectorResponse);\n  typename DetectorResponseImageType::ConstPointer\n  GetDetectorResponse();\n\n  /** Set/Get the material attenuations as an image */\n  void\n  SetMaterialAttenuations(const MaterialAttenuationsImageType * MaterialAttenuations);\n  typename MaterialAttenuationsImageType::ConstPointer\n  GetMaterialAttenuations();\n\n  /** Set/Get the incident spectrum input images */\n  void\n  SetInputIncidentSpectrum(const IncidentSpectrumImageType * IncidentSpectrum);\n  void\n  SetInputSecondIncidentSpectrum(const IncidentSpectrumImageType * SecondIncidentSpectrum);\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  void\n  SetInputIncidentSpectrum(const VectorSpectrumImageType * IncidentSpectrum);\n  void\n  SetInputSecondIncidentSpectrum(const VectorSpectrumImageType * SecondIncidentSpectrum);\n#endif\n  typename IncidentSpectrumImageType::ConstPointer\n  GetInputIncidentSpectrum();\n  typename IncidentSpectrumImageType::ConstPointer\n  GetInputSecondIncidentSpectrum();\n\n  /** Get / Set the number of iterations. Default is 300. */\n  itkGetMacro(NumberOfIterations, unsigned int);\n  itkSetMacro(NumberOfIterations, unsigned int);\n\n  itkSetMacro(NumberOfEnergies, unsigned int);\n  itkGetMacro(NumberOfEnergies, unsigned int);\n\n  itkSetMacro(NumberOfMaterials, unsigned int);\n  itkGetMacro(NumberOfMaterials, unsigned int);\n\n  itkSetMacro(OptimizeWithRestarts, bool);\n  itkGetMacro(OptimizeWithRestarts, bool);\n\n  itkSetMacro(Thresholds, ThresholdsType);\n  itkGetMacro(Thresholds, ThresholdsType);\n\n  itkSetMacro(NumberOfSpectralBins, unsigned int);\n  itkGetMacro(NumberOfSpectralBins, unsigned int);\n\n  itkSetMacro(OutputInverseCramerRaoLowerBound, bool);\n  itkGetMacro(OutputInverseCramerRaoLowerBound, bool);\n\n  itkSetMacro(OutputFischerMatrix, bool);\n  itkGetMacro(OutputFischerMatrix, bool);\n\n  itkSetMacro(LogTransformEachBin, bool);\n  itkGetMacro(LogTransformEachBin, bool);\n\n  itkSetMacro(GuessInitialization, bool);\n  itkGetMacro(GuessInitialization, bool);\n\n  itkSetMacro(IsSpectralCT, bool);\n  itkGetMacro(IsSpectralCT, bool);\n\nprotected:\n  SimplexSpectralProjectionsDecompositionImageFilter();\n  ~SimplexSpectralProjectionsDecompositionImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  BeforeThreadedGenerateData() override;\n  void\n  DynamicThreadedGenerateData(const typename DecomposedProjectionsType::RegionType & outputRegionForThread) override;\n\n  /**  Create the Output */\n  using DataObjectPointerArraySizeType = itk::ProcessObject::DataObjectPointerArraySizeType;\n  using Superclass::MakeOutput;\n  itk::DataObject::Pointer\n  MakeOutput(DataObjectPointerArraySizeType idx) override;\n\n  /** The inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Parameters */\n  MaterialAttenuationsType m_MaterialAttenuations;\n  DetectorResponseType     m_DetectorResponse;\n  ThresholdsType           m_Thresholds;\n  MeanAttenuationInBinType m_MeanAttenuationInBin;\n  bool                     m_OutputInverseCramerRaoLowerBound;\n  bool                     m_OutputFischerMatrix;\n  bool                     m_LogTransformEachBin;\n  bool                     m_GuessInitialization;\n  bool                     m_IsSpectralCT; // If not, it is dual energy CT\n  bool                     m_OptimizeWithRestarts;\n  unsigned int             m_NumberOfIterations;\n  unsigned int             m_NumberOfMaterials;\n  unsigned int             m_NumberOfEnergies;\n  unsigned int             m_NumberOfSpectralBins;\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  /** Filters required for the overload of SetInputIncidentSpectrum */\n  typename FlattenVectorFilterType::Pointer m_FlattenFilter;\n  typename FlattenVectorFilterType::Pointer m_FlattenSecondFilter;\n  typename PermuteFilterType::Pointer       m_PermuteFilter;\n  typename PermuteFilterType::Pointer       m_PermuteSecondFilter;\n#endif\n\n}; // end of class\n\n} // end namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSimplexSpectralProjectionsDecompositionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSimplexSpectralProjectionsDecompositionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSimplexSpectralProjectionsDecompositionImageFilter_hxx\n#define rtkSimplexSpectralProjectionsDecompositionImageFilter_hxx\n\n#include \"rtkSpectralForwardModelImageFilter.h\"\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n\nnamespace rtk\n{\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nSimplexSpectralProjectionsDecompositionImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SimplexSpectralProjectionsDecompositionImageFilter()\n{\n  this->SetNumberOfIndexedOutputs(2); // decomposed projections, inverse variance of decomposition noise\n\n  // Decomposed projections\n  this->SetNthOutput(0, this->MakeOutput(0));\n\n  // Inverse variance of decomposition noise\n  this->SetNthOutput(1, this->MakeOutput(1));\n\n  // Fischer matrix (estimate of inverse covariance of decomposition)\n  this->SetNthOutput(2, this->MakeOutput(2));\n\n  // Set the default values of member parameters\n  m_NumberOfIterations = 300;\n  m_NumberOfMaterials = 4;\n  m_NumberOfEnergies = 100;\n  m_OptimizeWithRestarts = false;\n\n  // Fill in the vectors and matrices with zeros\n  m_MaterialAttenuations.fill(0.); // Not sure this works\n  m_DetectorResponse.fill(0.);\n\n  // Initial lengths, set to incorrect values to make sure that they are indeed updated\n  m_NumberOfSpectralBins = 8;\n  m_OutputInverseCramerRaoLowerBound = false;\n  m_OutputFischerMatrix = false;\n  m_LogTransformEachBin = false;\n  m_GuessInitialization = false;\n  m_IsSpectralCT = true;\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  // Instantiate the filters required in the overload of SetInputIncidentSpectrum\n  m_FlattenFilter = FlattenVectorFilterType::New();\n  m_FlattenSecondFilter = FlattenVectorFilterType::New();\n  m_PermuteFilter = PermuteFilterType::New();\n  m_PermuteSecondFilter = PermuteFilterType::New();\n#endif\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::\n  SetInputDecomposedProjections(\n    const typename itk::ImageBase<DecomposedProjectionsType::ImageDimension> * DecomposedProjections)\n{\n  // Attempt to dynamic_cast DecomposedProjections into the default DecomposedProjectionsType\n  const DecomposedProjectionsType * default_ptr =\n    dynamic_cast<const DecomposedProjectionsType *>(DecomposedProjections);\n  if (default_ptr)\n  {\n    this->SetNthInput(0, const_cast<DecomposedProjectionsType *>(default_ptr));\n  }\n  else\n  {\n    // Attempt to dynamic_cast DecomposedProjections into one of the supported fixed vector length types\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 1>, DecomposedProjectionsType::ImageDimension> Type1;\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 2>, DecomposedProjectionsType::ImageDimension> Type2;\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 3>, DecomposedProjectionsType::ImageDimension> Type3;\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 4>, DecomposedProjectionsType::ImageDimension> Type4;\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 5>, DecomposedProjectionsType::ImageDimension> Type5;\n    const Type1 * ptr1 = dynamic_cast<const Type1 *>(DecomposedProjections);\n    const Type2 * ptr2 = dynamic_cast<const Type2 *>(DecomposedProjections);\n    const Type3 * ptr3 = dynamic_cast<const Type3 *>(DecomposedProjections);\n    const Type4 * ptr4 = dynamic_cast<const Type4 *>(DecomposedProjections);\n    const Type5 * ptr5 = dynamic_cast<const Type5 *>(DecomposedProjections);\n\n    if (ptr1)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<1>(ptr1);\n    }\n    else if (ptr2)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<2>(ptr2);\n    }\n    else if (ptr3)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<3>(ptr3);\n    }\n    else if (ptr4)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<4>(ptr4);\n    }\n    else if (ptr5)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<5>(ptr5);\n    }\n    else\n    {\n      itkWarningMacro(\"The input does not match any of the supported types, and has been ignored\");\n    }\n  }\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntemplate <unsigned int VNumberOfMaterials>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::\n  SetInputFixedVectorLengthDecomposedProjections(\n    const itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,\n                     DecomposedProjectionsType::ImageDimension> * DecomposedProjections)\n{\n  using ActualInputType = itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,\n                                     DecomposedProjectionsType::ImageDimension>;\n  using CastFilterType = itk::CastImageFilter<ActualInputType, DecomposedProjectionsType>;\n  auto castPointer = CastFilterType::New();\n  castPointer->SetInput(DecomposedProjections);\n  castPointer->Update();\n  this->SetNthInput(0, const_cast<DecomposedProjectionsType *>(castPointer->GetOutput()));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::\n  SetInputMeasuredProjections(\n    const typename itk::ImageBase<MeasuredProjectionsType::ImageDimension> * MeasuredProjections)\n{\n  // Attempt to dynamic_cast MeasuredProjections into the default type MeasuredProjectionsType\n  const MeasuredProjectionsType * default_ptr = dynamic_cast<const MeasuredProjectionsType *>(MeasuredProjections);\n  if (default_ptr)\n  {\n    this->SetInput(\"MeasuredProjections\", const_cast<MeasuredProjectionsType *>(default_ptr));\n  }\n  else\n  {\n    // Attempt to dynamic_cast MeasuredProjections into one of the supported types\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 1>, MeasuredProjectionsType::ImageDimension> Type1;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 2>, MeasuredProjectionsType::ImageDimension> Type2;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 3>, MeasuredProjectionsType::ImageDimension> Type3;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 4>, MeasuredProjectionsType::ImageDimension> Type4;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 5>, MeasuredProjectionsType::ImageDimension> Type5;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 6>, MeasuredProjectionsType::ImageDimension> Type6;\n    const Type1 * ptr1 = dynamic_cast<const Type1 *>(MeasuredProjections);\n    const Type2 * ptr2 = dynamic_cast<const Type2 *>(MeasuredProjections);\n    const Type3 * ptr3 = dynamic_cast<const Type3 *>(MeasuredProjections);\n    const Type4 * ptr4 = dynamic_cast<const Type4 *>(MeasuredProjections);\n    const Type5 * ptr5 = dynamic_cast<const Type5 *>(MeasuredProjections);\n    const Type6 * ptr6 = dynamic_cast<const Type6 *>(MeasuredProjections);\n\n    if (ptr1)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<1>(ptr1);\n    }\n    else if (ptr2)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<2>(ptr2);\n    }\n    else if (ptr3)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<3>(ptr3);\n    }\n    else if (ptr4)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<4>(ptr4);\n    }\n    else if (ptr5)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<5>(ptr5);\n    }\n    else if (ptr6)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<6>(ptr6);\n    }\n    else\n    {\n      itkWarningMacro(\"The input does not match any of the supported types, and has been ignored\");\n    }\n  }\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntemplate <unsigned int VNumberOfSpectralBins>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::\n  SetInputFixedVectorLengthMeasuredProjections(\n    const itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,\n                     MeasuredProjectionsType::ImageDimension> * MeasuredProjections)\n{\n  using ActualInputType = itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,\n                                     MeasuredProjectionsType::ImageDimension>;\n  using CastFilterType = itk::CastImageFilter<ActualInputType, MeasuredProjectionsType>;\n  auto castPointer = CastFilterType::New();\n  castPointer->SetInput(MeasuredProjections);\n  castPointer->UpdateLargestPossibleRegion();\n  this->SetInput(\"MeasuredProjections\", const_cast<MeasuredProjectionsType *>(castPointer->GetOutput()));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SetDetectorResponse(const DetectorResponseImageType * DetectorResponse)\n{\n  this->SetInput(\"DetectorResponse\", const_cast<DetectorResponseImageType *>(DetectorResponse));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SetMaterialAttenuations(const MaterialAttenuationsImageType * MaterialAttenuations)\n{\n  this->SetInput(\"MaterialAttenuations\", const_cast<MaterialAttenuationsImageType *>(MaterialAttenuations));\n}\n\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SetInputIncidentSpectrum(const IncidentSpectrumImageType * IncidentSpectrum)\n{\n  this->SetInput(\"IncidentSpectrum\", const_cast<IncidentSpectrumImageType *>(IncidentSpectrum));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::\n  SetInputSecondIncidentSpectrum(const IncidentSpectrumImageType * SecondIncidentSpectrum)\n{\n  this->SetInput(\"SecondIncidentSpectrum\", const_cast<IncidentSpectrumImageType *>(SecondIncidentSpectrum));\n}\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SetInputIncidentSpectrum(const VectorSpectrumImageType * IncidentSpectrum)\n{\n  this->m_FlattenFilter->SetInput(IncidentSpectrum);\n  this->m_PermuteFilter->SetInput(this->m_FlattenFilter->GetOutput());\n  typename PermuteFilterType::PermuteOrderArrayType order;\n  order[0] = 2;\n  order[1] = 0;\n  order[2] = 1;\n  this->m_PermuteFilter->SetOrder(order);\n  this->SetInputIncidentSpectrum(m_PermuteFilter->GetOutput());\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SetInputSecondIncidentSpectrum(const VectorSpectrumImageType * SecondIncidentSpectrum)\n{\n  this->m_FlattenSecondFilter->SetInput(SecondIncidentSpectrum);\n  this->m_PermuteSecondFilter->SetInput(this->m_FlattenSecondFilter->GetOutput());\n  typename PermuteFilterType::PermuteOrderArrayType order;\n  order[0] = 2;\n  order[1] = 0;\n  order[2] = 1;\n  this->m_PermuteSecondFilter->SetOrder(order);\n  this->SetInputSecondIncidentSpectrum(m_PermuteSecondFilter->GetOutput());\n}\n#endif\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename DecomposedProjectionsType::ConstPointer\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::GetInputDecomposedProjections()\n{\n  return static_cast<const DecomposedProjectionsType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename MeasuredProjectionsType::ConstPointer\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::GetInputMeasuredProjections()\n{\n  return static_cast<const MeasuredProjectionsType *>(this->itk::ProcessObject::GetInput(\"MeasuredProjections\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename DetectorResponseImageType::ConstPointer\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::GetDetectorResponse()\n{\n  return static_cast<const DetectorResponseImageType *>(this->itk::ProcessObject::GetInput(\"DetectorResponse\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename MaterialAttenuationsImageType::ConstPointer\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::GetMaterialAttenuations()\n{\n  return static_cast<const MaterialAttenuationsImageType *>(this->itk::ProcessObject::GetInput(\"MaterialAttenuations\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename IncidentSpectrumImageType::ConstPointer\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::GetInputIncidentSpectrum()\n{\n  return static_cast<const IncidentSpectrumImageType *>(this->itk::ProcessObject::GetInput(\"IncidentSpectrum\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename IncidentSpectrumImageType::ConstPointer\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::GetInputSecondIncidentSpectrum()\n{\n  return static_cast<const IncidentSpectrumImageType *>(this->itk::ProcessObject::GetInput(\"SecondIncidentSpectrum\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nitk::DataObject::Pointer\nSimplexSpectralProjectionsDecompositionImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::MakeOutput(DataObjectPointerArraySizeType idx)\n{\n  itk::DataObject::Pointer output;\n\n  switch (idx)\n  {\n    case 0:\n      output = (DecomposedProjectionsType::New()).GetPointer();\n      break;\n    case 1:\n      output = (DecomposedProjectionsType::New()).GetPointer();\n      break;\n    case 2:\n      output = (DecomposedProjectionsType::New()).GetPointer();\n      break;\n  }\n  return output.GetPointer();\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::GenerateOutputInformation()\n{\n  Superclass::GenerateOutputInformation();\n  this->GetOutput(0)->SetLargestPossibleRegion(this->GetInputDecomposedProjections()->GetLargestPossibleRegion());\n  this->GetOutput(1)->SetLargestPossibleRegion(this->GetInputDecomposedProjections()->GetLargestPossibleRegion());\n  this->GetOutput(2)->SetLargestPossibleRegion(this->GetInputDecomposedProjections()->GetLargestPossibleRegion());\n\n  this->m_NumberOfSpectralBins = this->GetInputMeasuredProjections()->GetVectorLength();\n  this->m_NumberOfMaterials = this->GetInputDecomposedProjections()->GetVectorLength();\n  this->m_NumberOfEnergies = this->GetInputIncidentSpectrum()->GetLargestPossibleRegion().GetSize(0);\n\n  // Set vector length for the fischer matrix\n  this->GetOutput(2)->SetVectorLength(this->m_NumberOfMaterials * this->m_NumberOfMaterials);\n\n  // Change vector length for the decomposed projections, if required\n  if (m_LogTransformEachBin)\n    this->GetOutput(0)->SetVectorLength(this->m_NumberOfMaterials + this->m_NumberOfSpectralBins);\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n\n  // Input 0 is the initial decomposed projections\n  typename DecomposedProjectionsType::Pointer inputPtr0 =\n    const_cast<DecomposedProjectionsType *>(this->GetInputDecomposedProjections().GetPointer());\n  if (!inputPtr0)\n    return;\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the spectral projections\n  typename MeasuredProjectionsType::Pointer inputPtr1 =\n    const_cast<MeasuredProjectionsType *>(this->GetInputMeasuredProjections().GetPointer());\n  if (!inputPtr1)\n    return;\n  inputPtr1->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 2 is the incident spectrum image\n  typename IncidentSpectrumImageType::Pointer inputPtr2 =\n    const_cast<IncidentSpectrumImageType *>(this->GetInputIncidentSpectrum().GetPointer());\n  if (!inputPtr2)\n    return;\n\n  typename IncidentSpectrumImageType::RegionType requested =\n    this->GetInputIncidentSpectrum()->GetLargestPossibleRegion();\n  typename IncidentSpectrumImageType::IndexType indexRequested = requested.GetIndex();\n  typename IncidentSpectrumImageType::SizeType  sizeRequested = requested.GetSize();\n  for (unsigned int i = 0; i < IncidentSpectrumImageType::GetImageDimension() - 1; i++)\n  {\n    indexRequested[i + 1] = this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n    sizeRequested[i + 1] = this->GetOutput()->GetRequestedRegion().GetSize()[i];\n  }\n\n  inputPtr2->SetRequestedRegion(requested);\n\n  // Input 3 is the detector response image (2D float)\n  typename DetectorResponseImageType::Pointer inputPtr3 =\n    const_cast<DetectorResponseImageType *>(this->GetDetectorResponse().GetPointer());\n  if (!inputPtr3)\n    return;\n  inputPtr3->SetRequestedRegion(inputPtr3->GetLargestPossibleRegion());\n\n  // Input 4 is the material attenuations image (2D float)\n  typename MaterialAttenuationsImageType::Pointer inputPtr4 =\n    const_cast<MaterialAttenuationsImageType *>(this->GetMaterialAttenuations().GetPointer());\n  if (!inputPtr4)\n    return;\n  inputPtr4->SetRequestedRegion(inputPtr4->GetLargestPossibleRegion());\n}\n\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::BeforeThreadedGenerateData()\n{\n  Superclass::BeforeThreadedGenerateData();\n\n  // Read the material attenuations image as a matrix\n  typename MaterialAttenuationsImageType::IndexType indexMat;\n  this->m_MaterialAttenuations.set_size(this->m_NumberOfEnergies, this->m_NumberOfMaterials);\n  for (unsigned int energy = 0; energy < this->m_NumberOfEnergies; energy++)\n  {\n    indexMat[1] = energy;\n    for (unsigned int material = 0; material < this->m_NumberOfMaterials; material++)\n    {\n      indexMat[0] = material;\n      this->m_MaterialAttenuations[energy][material] = this->GetMaterialAttenuations()->GetPixel(indexMat);\n    }\n  }\n\n  if (this->GetInputSecondIncidentSpectrum())\n  {\n    // Read the detector response image as a matrix\n    this->m_DetectorResponse.set_size(1, this->m_NumberOfEnergies);\n    this->m_DetectorResponse.fill(0);\n    typename DetectorResponseImageType::IndexType indexDet;\n    for (unsigned int energy = 0; energy < this->m_NumberOfEnergies; energy++)\n    {\n      indexDet[0] = energy;\n      indexDet[1] = 0;\n      this->m_DetectorResponse[0][energy] += this->GetDetectorResponse()->GetPixel(indexDet);\n    }\n  }\n  else\n  {\n    this->m_DetectorResponse = SpectralBinDetectorResponse<DetectorResponseType::element_type>(\n      this->GetDetectorResponse().GetPointer(), m_Thresholds, m_NumberOfEnergies);\n  }\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                   MeasuredProjectionsType,\n                                                   IncidentSpectrumImageType,\n                                                   DetectorResponseImageType,\n                                                   MaterialAttenuationsImageType>::\n  DynamicThreadedGenerateData(const typename DecomposedProjectionsType::RegionType & outputRegionForThread)\n{\n  ////////////////////////////////////////////////////////////////////\n  // Create a Nelder-Mead simplex optimizer and its cost function\n  auto                                                        optimizer = itk::AmoebaOptimizer::New();\n  rtk::ProjectionsDecompositionNegativeLogLikelihood::Pointer cost;\n  if (m_IsSpectralCT)\n    cost = rtk::Schlomka2008NegativeLogLikelihood::New();\n  else\n    cost = rtk::DualEnergyNegativeLogLikelihood::New();\n\n  cost->SetNumberOfEnergies(this->GetNumberOfEnergies());\n  cost->SetNumberOfMaterials(this->GetNumberOfMaterials());\n  cost->SetNumberOfSpectralBins(this->GetNumberOfSpectralBins());\n\n  // Pass the attenuation functions to the cost function\n  cost->SetMaterialAttenuations(this->m_MaterialAttenuations);\n  if (m_GuessInitialization && (!this->GetInputSecondIncidentSpectrum()))\n    cost->SetThresholds(this->m_Thresholds);\n\n  // Pass the binned detector response to the cost function\n  cost->SetDetectorResponse(this->m_DetectorResponse);\n\n  // Set the optimizer\n  optimizer->SetCostFunction(cost);\n  optimizer->SetMaximumNumberOfIterations(this->m_NumberOfIterations);\n\n  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n  // Walk the output projection stack. For each pixel, set the cost function's member variables and run the optimizer.\n  itk::ImageRegionIterator<DecomposedProjectionsType>      output0It(this->GetOutput(0), outputRegionForThread);\n  itk::ImageRegionIterator<DecomposedProjectionsType>      output1It(this->GetOutput(1), outputRegionForThread);\n  itk::ImageRegionIterator<DecomposedProjectionsType>      output2It(this->GetOutput(2), outputRegionForThread);\n  itk::ImageRegionConstIterator<DecomposedProjectionsType> inputIt(this->GetInputDecomposedProjections(),\n                                                                   outputRegionForThread);\n  itk::ImageRegionConstIterator<MeasuredProjectionsType>   spectralProjIt(this->GetInputMeasuredProjections(),\n                                                                        outputRegionForThread);\n\n  typename IncidentSpectrumImageType::RegionType incidentSpectrumRegionForThread =\n    this->GetInputIncidentSpectrum()->GetLargestPossibleRegion();\n  for (unsigned int dim = 0; dim < IncidentSpectrumImageType::GetImageDimension() - 1; dim++)\n  {\n    incidentSpectrumRegionForThread.SetIndex(dim + 1, outputRegionForThread.GetIndex()[dim]);\n    incidentSpectrumRegionForThread.SetSize(dim + 1, outputRegionForThread.GetSize()[dim]);\n  }\n  itk::ImageRegionConstIterator<IncidentSpectrumImageType> spectrumIt(this->GetInputIncidentSpectrum(),\n                                                                      incidentSpectrumRegionForThread);\n\n  // Special case for the dual energy CT\n  itk::ImageRegionConstIterator<IncidentSpectrumImageType> secondSpectrumIt;\n  if (this->GetInputSecondIncidentSpectrum())\n    secondSpectrumIt = itk::ImageRegionConstIterator<IncidentSpectrumImageType>(this->GetInputSecondIncidentSpectrum(),\n                                                                                incidentSpectrumRegionForThread);\n\n  while (!output0It.IsAtEnd())\n  {\n    // The input incident spectrum image typically has lower dimension than\n    // This condition makes the iterator cycle over and over on the same image, following the other ones\n    if (spectrumIt.IsAtEnd())\n    {\n      spectrumIt.GoToBegin();\n      if (this->GetInputSecondIncidentSpectrum())\n        secondSpectrumIt.GoToBegin();\n    }\n\n    // Build a vnl_matrix out of the high and low energy incident spectra (if DECT)\n    // or out of single spectrum (if spectral)\n    vnl_matrix<float> spectra;\n    if (this->GetInputSecondIncidentSpectrum()) // Dual energy CT\n    {\n      spectra.set_size(2, m_NumberOfEnergies);\n      for (unsigned int e = 0; e < m_NumberOfEnergies; e++)\n      {\n        spectra.put(0, e, spectrumIt.Get());\n        spectra.put(1, e, secondSpectrumIt.Get());\n        ++spectrumIt;\n        ++secondSpectrumIt;\n      }\n    }\n    else\n    {\n      spectra.set_size(1, m_NumberOfEnergies);\n      for (unsigned int e = 0; e < m_NumberOfEnergies; e++)\n      {\n        spectra.put(0, e, spectrumIt.Get());\n        ++spectrumIt;\n      }\n    }\n\n    // Pass the incident spectrum vector to cost function\n    cost->SetIncidentSpectrum(spectra);\n    cost->Initialize();\n\n    // Pass the detector counts vector to cost function\n    cost->SetMeasuredData(spectralProjIt.Get());\n\n    // Run the optimizer\n    typename rtk::ProjectionsDecompositionNegativeLogLikelihood::ParametersType startingPosition(\n      this->m_NumberOfMaterials);\n    if (m_GuessInitialization)\n    {\n      itk::VariableLengthVector<double> guess = cost->GuessInitialization();\n      for (unsigned int m = 0; m < this->m_NumberOfMaterials; m++)\n        startingPosition[m] = guess[m];\n    }\n    else\n    {\n      for (unsigned int m = 0; m < this->m_NumberOfMaterials; m++)\n        startingPosition[m] = inputIt.Get()[m];\n    }\n\n    optimizer->SetInitialPosition(startingPosition);\n    optimizer->SetAutomaticInitialSimplex(true);\n    optimizer->SetOptimizeWithRestarts(this->m_OptimizeWithRestarts);\n    optimizer->StartOptimization();\n\n    typename DecomposedProjectionsType::PixelType outputPixel;\n    if (m_LogTransformEachBin)\n    {\n      outputPixel.SetSize(this->m_NumberOfMaterials + this->m_NumberOfSpectralBins);\n      for (unsigned int bin = 0; bin < this->m_NumberOfSpectralBins; bin++)\n        outputPixel[bin + this->m_NumberOfMaterials] = cost->BinwiseLogTransform()[bin];\n    }\n    else\n      outputPixel.SetSize(this->m_NumberOfMaterials);\n\n    for (unsigned int m = 0; m < this->m_NumberOfMaterials; m++)\n      outputPixel[m] = optimizer->GetCurrentPosition()[m];\n\n    output0It.Set(outputPixel);\n\n    // If required, compute the Fischer matrix\n    if (m_OutputInverseCramerRaoLowerBound || m_OutputFischerMatrix)\n      cost->ComputeFischerMatrix(optimizer->GetCurrentPosition());\n\n    // If requested, compute the inverse variance of decomposition noise, and store it into output(1)\n    if (m_OutputInverseCramerRaoLowerBound)\n      output1It.Set(cost->GetInverseCramerRaoLowerBound());\n\n    // If requested, store the Fischer matrix into output(2)\n    if (m_OutputFischerMatrix)\n      output2It.Set(cost->GetFischerMatrix());\n\n    // Move forward\n    ++output0It;\n    ++output1It;\n    ++output2It;\n    ++inputIt;\n    ++spectralProjIt;\n  }\n}\n\n} // end namespace rtk\n\n#endif // rtkSimplexSpectralProjectionsDecompositionImageFilter_hxx\n"
  },
  {
    "path": "include/rtkSingularValueThresholdImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSingularValueThresholdImageFilter_h\n#define rtkSingularValueThresholdImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include <itkVector.h>\n\n#include <itkImageRegionSplitterDirection.h>\n\nnamespace rtk\n{\n/** \\class SingularValueThresholdImageFilter\n *\n * \\brief Performs thresholding on the singular values\n *\n * The image is assumed to be of dimension N+1, and to contain\n * itk::CovariantVector of length N. The last dimension is assumed\n * to be the channel dimension (color, or time, or materials in spectral CT), of size L.\n * The input image must contain the spatial gradient of each channel.\n *\n * The filter walks the pixels of a single channel. For each of these pixels,\n * it constructs a matrix by concatenating the gradient vectors of the L channels.\n * The matrix is decomposed using SVD, its singular values are thresholded, and\n * then reconstructed. The resulting matrix is then cut back into L gradient vectors,\n * which are written in output.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <typename TInputImage, typename TRealType = float, typename TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT SingularValueThresholdImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SingularValueThresholdImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SingularValueThresholdImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods) */\n  itkOverrideGetNameOfClassMacro(SingularValueThresholdImageFilter);\n\n  /** Extract some information from the image types.  Dimensionality\n   * of the two images is assumed to be the same. */\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using InputPixelType = typename TInputImage::PixelType;\n\n  /** Image type alias support */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n\n  /** The dimensionality of the input and output images. */\n  static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;\n\n  /** Length of the vector pixel type of the input image. */\n  static constexpr unsigned int VectorDimension = InputPixelType::Dimension;\n\n  /** Define the data type and the vector of data type used in calculations. */\n  using RealType = TRealType;\n  using RealVectorType = itk::Vector<TRealType, InputPixelType::Dimension>;\n  using RealVectorImageType = itk::Image<RealVectorType, TInputImage::ImageDimension>;\n\n  /** Superclass type alias. */\n  using OutputImageRegionType = typename Superclass::OutputImageRegionType;\n\n  /** Begin concept checking */\n  itkConceptMacro(InputHasNumericTraitsCheck, (itk::Concept::HasNumericTraits<typename InputPixelType::ValueType>));\n  itkConceptMacro(RealTypeHasNumericTraitsCheck, (itk::Concept::HasNumericTraits<RealType>));\n  /** End concept checking */\n\n  itkGetMacro(Threshold, TRealType);\n  itkSetMacro(Threshold, TRealType);\n\nprotected:\n  SingularValueThresholdImageFilter();\n  ~SingularValueThresholdImageFilter() override = default;\n\n  void\n  ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, itk::ThreadIdType threadId) override;\n\n  /** Splits the OutputRequestedRegion along the first direction, not the last */\n  const itk::ImageRegionSplitterBase *\n                                             GetImageRegionSplitter() const override;\n  itk::ImageRegionSplitterDirection::Pointer m_Splitter;\n\nprivate:\n  TRealType m_Threshold;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSingularValueThresholdImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSingularValueThresholdImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSingularValueThresholdImageFilter_hxx\n#define rtkSingularValueThresholdImageFilter_hxx\n\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n\n#include <itkProgressReporter.h>\n\nnamespace rtk\n{\n\ntemplate <typename TInputImage, typename TRealType, typename TOutputImage>\nSingularValueThresholdImageFilter<TInputImage, TRealType, TOutputImage>::SingularValueThresholdImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n  m_Threshold = 0;\n\n  // Set the direction along which the output requested region should NOT be split\n  m_Splitter = itk::ImageRegionSplitterDirection::New();\n  m_Splitter->SetDirection(TInputImage::ImageDimension - 1);\n}\n\ntemplate <typename TInputImage, typename TRealType, typename TOutputImage>\nconst itk::ImageRegionSplitterBase *\nSingularValueThresholdImageFilter<TInputImage, TRealType, TOutputImage>::GetImageRegionSplitter() const\n{\n  return m_Splitter;\n}\n\ntemplate <typename TInputImage, typename TRealType, typename TOutputImage>\nvoid\nSingularValueThresholdImageFilter<TInputImage, TRealType, TOutputImage>::ThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread,\n  itk::ThreadIdType /*threadId*/)\n{\n  // Walks the first frame of the outputRegionForThread\n  // For each voxel, creates an input iterator that walks\n  // the last dimension and computes the average, and\n  // a similar output iterator that replaces the output\n  // by their average along last dimension if ROI=1\n\n  // Create a region containing only the first frame of outputRegionForThread\n  typename TInputImage::RegionType FirstFrameRegion = outputRegionForThread;\n  FirstFrameRegion.SetSize(TInputImage::ImageDimension - 1, 1);\n\n  // Iterate on these regions\n  itk::ImageRegionIteratorWithIndex<TInputImage> FakeIterator(this->GetOutput(), FirstFrameRegion);\n\n  // Create a single-voxel region traversing last dimension\n  typename TInputImage::RegionType SingleVoxelRegion = outputRegionForThread;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension - 1; dim++)\n    SingleVoxelRegion.SetSize(dim, 1);\n\n  // Create a variable to store the jacobian matrix\n  vnl_matrix<double> jacobian(outputRegionForThread.GetSize()[TInputImage::ImageDimension - 1],\n                              TInputImage::ImageDimension - 1);\n\n  while (!FakeIterator.IsAtEnd())\n  {\n    // Configure the SingleVoxelRegion correctly to follow the FakeIterator\n    // It is the only purpose of this FakeIterator\n    SingleVoxelRegion.SetIndex(FakeIterator.GetIndex());\n\n    // Walk the input along last dimension for this voxel, filling in the jacobian along the way\n    itk::ImageRegionConstIterator<TInputImage> inputIterator(this->GetInput(), SingleVoxelRegion);\n    unsigned int                               row = 0;\n    for (inputIterator.GoToBegin(); !inputIterator.IsAtEnd(); ++inputIterator, row++)\n    {\n      typename TInputImage::PixelType gradient = inputIterator.Get();\n      for (unsigned int column = 0; column < TInputImage::ImageDimension - 1; column++)\n      {\n        jacobian[row][column] = gradient[column];\n      }\n    }\n\n    // Perform the singular value decomposition of the jacobian matrix\n    vnl_svd<double> svd(jacobian);\n\n    // Threshold the singular values. Since they are sorted in descending order, we\n    // can stop as soon as we reach one that is below threshold\n    for (unsigned int i = 0; (i < TInputImage::ImageDimension && svd.W(i) > m_Threshold); i++)\n    {\n      svd.W(i) = m_Threshold;\n    }\n\n    // Reconstruct the jacobian\n    jacobian = svd.recompose();\n\n    // Walk the output along last dimension for this voxel,\n    // replacing gradient vectors with their newly computed value\n    itk::ImageRegionIterator<TInputImage> outputIterator(this->GetOutput(), SingleVoxelRegion);\n    row = 0;\n    for (outputIterator.GoToBegin(); !outputIterator.IsAtEnd(); ++outputIterator, row++)\n    {\n      typename TInputImage::PixelType vector;\n      for (unsigned int column = 0; column < jacobian.cols(); column++)\n        vector[column] = jacobian[row][column];\n\n      outputIterator.Set(vector);\n    }\n\n    ++FakeIterator;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkSoftThresholdImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSoftThresholdImageFilter_h\n#define rtkSoftThresholdImageFilter_h\n\n#include \"itkUnaryFunctorImageFilter.h\"\n#include \"itkConceptChecking.h\"\n#include \"itkSimpleDataObjectDecorator.h\"\n\nnamespace rtk\n{\n\n/** \\class SoftThresholdImageFilter\n *\n * \\brief Soft thresholds an image\n *\n * This filter produces an output image whose pixels\n * are max(x-t,0).sign(x) where x is the corresponding\n * input pixel value and t the threshold\n *\n * \\ingroup RTK IntensityImageFilters  Multithreaded\n */\n\nnamespace Functor\n{\n\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT SoftThreshold\n{\npublic:\n  SoftThreshold() { m_Threshold = itk::NumericTraits<TInput>::Zero; }\n  ~SoftThreshold() = default;\n\n  void\n  SetThreshold(const TInput & thresh)\n  {\n    m_Threshold = thresh;\n  }\n\n  bool\n  operator!=(const SoftThreshold & other) const\n  {\n    if (m_Threshold != other.m_Threshold)\n    {\n      return true;\n    }\n    return false;\n  }\n  bool\n  operator==(const SoftThreshold & other) const\n  {\n    return !(*this != other);\n  }\n\n  inline TOutput\n  operator()(const TInput & A) const\n  {\n    return (itk::Math::sgn(A) * std::max((TInput)itk::Math::abs(A) - m_Threshold, (TInput)0.0));\n  }\n\nprivate:\n  TInput m_Threshold;\n};\n} // namespace Functor\n\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT SoftThresholdImageFilter\n  : public itk::UnaryFunctorImageFilter<\n      TInputImage,\n      TOutputImage,\n      Functor::SoftThreshold<typename TInputImage::PixelType, typename TOutputImage::PixelType>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SoftThresholdImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SoftThresholdImageFilter;\n  typedef itk::UnaryFunctorImageFilter<\n    TInputImage,\n    TOutputImage,\n    Functor::SoftThreshold<typename TInputImage::PixelType, typename TOutputImage::PixelType>>\n    Superclass;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SoftThresholdImageFilter);\n\n  /** Pixel types. */\n  using InputPixelType = typename TInputImage::PixelType;\n  using OutputPixelType = typename TOutputImage::PixelType;\n\n  /** Type of DataObjects to use for scalar inputs */\n  using InputPixelObjectType = itk::SimpleDataObjectDecorator<InputPixelType>;\n\n  /** Set the threshold */\n  virtual void\n  SetThreshold(const InputPixelType threshold);\n\n  /** Begin concept checking */\n  itkConceptMacro(OutputEqualityComparableCheck, (itk::Concept::EqualityComparable<OutputPixelType>));\n  itkConceptMacro(InputPixelTypeComparable, (itk::Concept::Comparable<InputPixelType>));\n  itkConceptMacro(InputOStreamWritableCheck, (itk::Concept::OStreamWritable<InputPixelType>));\n  itkConceptMacro(OutputOStreamWritableCheck, (itk::Concept::OStreamWritable<OutputPixelType>));\n  /** End concept checking */\n\nprotected:\n  SoftThresholdImageFilter();\n  ~SoftThresholdImageFilter() override = default;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSoftThresholdImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSoftThresholdImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSoftThresholdImageFilter_hxx\n#define rtkSoftThresholdImageFilter_hxx\n\n\nnamespace rtk\n{\n\n/**\n *\n */\ntemplate <class TInputImage, class TOutputImage>\nSoftThresholdImageFilter<TInputImage, TOutputImage>::SoftThresholdImageFilter()\n{\n  this->SetThreshold(itk::NumericTraits<InputPixelType>::Zero);\n}\n\n/**\n *\n */\ntemplate <class TInputImage, class TOutputImage>\nvoid\nSoftThresholdImageFilter<TInputImage, TOutputImage>::SetThreshold(const InputPixelType threshold)\n{\n  this->GetFunctor().SetThreshold(threshold);\n  this->Modified();\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkSoftThresholdTVImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSoftThresholdTVImageFilter_h\n#define rtkSoftThresholdTVImageFilter_h\n\n#include <itkNeighborhoodIterator.h>\n#include <itkImageToImageFilter.h>\n#include <itkImage.h>\n#include <itkVector.h>\n#include \"vnl/vnl_matrix.h\"\n#include \"vnl/vnl_vector_fixed.h\"\n#include \"vnl/algo/vnl_symmetric_eigensystem.h\"\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n/** \\class SoftThresholdTVImageFilter\n *\n * \\brief Computes the Total Variation from a gradient input image\n * (pixels are vectors), soft thresholds it, and outputs a\n *  multiple channel image with vectors colinear to the input vectors\n *  but having a smaller norm.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <typename TInputImage, typename TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT SoftThresholdTVImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SoftThresholdTVImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SoftThresholdTVImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods) */\n  itkOverrideGetNameOfClassMacro(SoftThresholdTVImageFilter);\n\n  /** Extract some information from the image types.  Dimensionality\n   * of the two images is assumed to be the same. */\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using InputPixelType = typename TInputImage::PixelType;\n\n  /** Image type alias support */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n\n  /** The dimensionality of the input and output images. */\n  static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;\n\n  /** Length of the vector pixel type of the input image. */\n  static constexpr unsigned int VectorDimension = InputPixelType::Dimension;\n\n  /** Superclass type alias. */\n  using OutputImageRegionType = typename Superclass::OutputImageRegionType;\n\n  /** Begin concept checking */\n  itkConceptMacro(InputHasNumericTraitsCheck, (itk::Concept::HasNumericTraits<typename InputPixelType::ValueType>));\n  /** End concept checking */\n\n  itkGetMacro(Threshold, float);\n  itkSetMacro(Threshold, float);\n\nprotected:\n  SoftThresholdTVImageFilter();\n  ~SoftThresholdTVImageFilter() override = default;\n\n  /** Do any necessary casting/copying of the input data.  Input pixel types\n     whose value types are not real number types must be cast to real number\n     types. */\n  //    void BeforeThreadedGenerateData();\n\n  /** SoftThresholdTVImageFilter can be implemented as a\n   * multithreaded filter.  Therefore, this implementation provides a\n   * ThreadedGenerateData() routine which is called for each\n   * processing thread. The output image data is allocated\n   * automatically by the superclass prior to calling\n   * ThreadedGenerateData().  ThreadedGenerateData can only write to\n   * the portion of the output image specified by the parameter\n   * \"outputRegionForThread\"\n   *\n   * \\sa ImageToImageFilter::ThreadedGenerateData(),\n   *     ImageToImageFilter::GenerateData() */\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\n  //    using ImageBaseType = typename InputImageType::Superclass;\n\nprivate:\n  float        m_Threshold;\n  ThreadIdType m_RequestedNumberOfThreads;\n};\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSoftThresholdTVImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSoftThresholdTVImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSoftThresholdTVImageFilter_hxx\n#define rtkSoftThresholdTVImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkProgressReporter.h>\n#include <itkPixelTraits.h>\n\nnamespace rtk\n{\n\ntemplate <typename TInputImage, typename TOutputImage>\nSoftThresholdTVImageFilter<TInputImage, TOutputImage>::SoftThresholdTVImageFilter()\n{\n  m_RequestedNumberOfThreads = this->GetNumberOfWorkUnits();\n  m_Threshold = 0;\n}\n\ntemplate <typename TInputImage, typename TOutputImage>\nvoid\nSoftThresholdTVImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  itk::ImageRegionConstIterator<TInputImage> InputIt;\n  itk::ImageRegionIterator<TOutputImage>     OutputIt;\n\n  InputIt = itk::ImageRegionConstIterator<TInputImage>(this->GetInput(), outputRegionForThread);\n  OutputIt = itk::ImageRegionIterator<TOutputImage>(this->GetOutput(), outputRegionForThread);\n\n  while (!InputIt.IsAtEnd())\n  {\n    using ValueType = typename itk::PixelTraits<typename OutputImageType::PixelType>::ValueType;\n    ValueType TV = 0;\n    for (unsigned int i = 0; i < ImageDimension; ++i)\n    {\n      TV += InputIt.Get()[i] * InputIt.Get()[i];\n    }\n    TV = sqrt(TV); // TV is non-negative\n    ValueType ratio = NAN;\n    ValueType temp = TV - m_Threshold;\n    if (temp > 0)\n      ratio = temp / TV;\n    else\n      ratio = 0;\n\n    OutputIt.Set(ratio * InputIt.Get());\n    ++InputIt;\n    ++OutputIt;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkSpectralForwardModelImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSpectralForwardModelImageFilter_h\n#define rtkSpectralForwardModelImageFilter_h\n\n#include \"rtkSchlomka2008NegativeLogLikelihood.h\"\n#include \"rtkDualEnergyNegativeLogLikelihood.h\"\n#include \"rtkVectorImageToImageFilter.h\"\n\n#include <itkPermuteAxesImageFilter.h>\n#include <itkInPlaceImageFilter.h>\n#include <itkCastImageFilter.h>\n\nnamespace rtk\n{\n/** \\class SpectralForwardModelImageFilter\n * \\brief Forward model for the decomposition of spectral projection images into material projections.\n *\n * Computes the photon counts from the decomposed projections, the incident spectrum,\n * the detector response and the material attenuation curves.\n * See the reference paper: \"Experimental feasibility of multi-energy photon-counting\n * K-edge imaging in pre-clinical computed tomography\", Schlomka et al, PMB 2008\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType = itk::Image<float, 3>,\n          typename DetectorResponseImageType = itk::Image<float, 2>,\n          typename MaterialAttenuationsImageType = itk::Image<float, 2>>\nclass ITK_TEMPLATE_EXPORT SpectralForwardModelImageFilter\n  : public itk::InPlaceImageFilter<MeasuredProjectionsType, MeasuredProjectionsType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SpectralForwardModelImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SpectralForwardModelImageFilter;\n  using Superclass = itk::ImageToImageFilter<MeasuredProjectionsType, MeasuredProjectionsType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = MeasuredProjectionsType;\n  using OutputImageType = MeasuredProjectionsType;\n\n  /** Convenient information */\n  using ThresholdsType = itk::VariableLengthVector<double>;\n  using DetectorResponseType = vnl_matrix<double>;\n  using MaterialAttenuationsType = vnl_matrix<double>;\n  using DecomposedProjectionsDataType = typename DecomposedProjectionsType::PixelType::ValueType;\n  using MeasuredProjectionsDataType = typename MeasuredProjectionsType::PixelType::ValueType;\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  /** Additional types to overload SetInputIncidentSpectrum */\n  using VectorSpectrumImageType = itk::VectorImage<float, 2>;\n  using FlattenVectorFilterType = rtk::VectorImageToImageFilter<VectorSpectrumImageType, IncidentSpectrumImageType>;\n  using PermuteFilterType = itk::PermuteAxesImageFilter<IncidentSpectrumImageType>;\n#endif\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(SpectralForwardModelImageFilter);\n\n  /** Set/Get the incident spectrum input images */\n  void\n  SetInputIncidentSpectrum(const IncidentSpectrumImageType * IncidentSpectrum);\n  void\n  SetInputSecondIncidentSpectrum(const IncidentSpectrumImageType * SecondIncidentSpectrum);\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  void\n  SetInputIncidentSpectrum(const VectorSpectrumImageType * IncidentSpectrum);\n  void\n  SetInputSecondIncidentSpectrum(const VectorSpectrumImageType * SecondIncidentSpectrum);\n#endif\n  typename IncidentSpectrumImageType::ConstPointer\n  GetInputIncidentSpectrum();\n  typename IncidentSpectrumImageType::ConstPointer\n  GetInputSecondIncidentSpectrum();\n\n  /** Set/Get the input material-decomposed stack of projections (only used for initialization) */\n  void\n  SetInputDecomposedProjections(\n    const typename itk::ImageBase<DecomposedProjectionsType::ImageDimension> * DecomposedProjections);\n  template <unsigned int VNumberOfMaterials>\n  void\n  SetInputFixedVectorLengthDecomposedProjections(\n    const itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,\n                     DecomposedProjectionsType::ImageDimension> * DecomposedProjections);\n  typename DecomposedProjectionsType::ConstPointer\n  GetInputDecomposedProjections();\n\n  /** Set/Get the input stack of measured projections (to be decomposed in materials) */\n  void\n  SetInputMeasuredProjections(\n    const typename itk::ImageBase<MeasuredProjectionsType::ImageDimension> * MeasuredProjections);\n  template <unsigned int VNumberOfSpectralBins>\n  void\n  SetInputFixedVectorLengthMeasuredProjections(\n    const itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,\n                     MeasuredProjectionsType::ImageDimension> * MeasuredProjections);\n  typename MeasuredProjectionsType::ConstPointer\n  GetInputMeasuredProjections();\n\n  /** Set/Get the detector response as an image */\n  void\n  SetDetectorResponse(const DetectorResponseImageType * DetectorResponse);\n  typename DetectorResponseImageType::ConstPointer\n  GetDetectorResponse();\n\n  /** Set/Get the material attenuations as an image */\n  void\n  SetMaterialAttenuations(const MaterialAttenuationsImageType * MaterialAttenuations);\n  typename MaterialAttenuationsImageType::ConstPointer\n  GetMaterialAttenuations();\n\n  typename DecomposedProjectionsType::ConstPointer\n  GetOutputCramerRaoLowerBound();\n\n  typename MeasuredProjectionsType::ConstPointer\n  GetOutputVariances();\n\n  itkSetMacro(Thresholds, ThresholdsType);\n  itkGetMacro(Thresholds, ThresholdsType);\n\n  itkSetMacro(NumberOfSpectralBins, unsigned int);\n  itkGetMacro(NumberOfSpectralBins, unsigned int);\n\n  itkSetMacro(NumberOfMaterials, unsigned int);\n  itkGetMacro(NumberOfMaterials, unsigned int);\n\n  itkSetMacro(NumberOfEnergies, unsigned int);\n  itkGetMacro(NumberOfEnergies, unsigned int);\n\n  itkSetMacro(IsSpectralCT, bool);\n  itkGetMacro(IsSpectralCT, bool);\n\n  itkSetMacro(ComputeVariances, bool);\n  itkGetMacro(ComputeVariances, bool);\n\n  itkSetMacro(ComputeCramerRaoLowerBound, bool);\n  itkGetMacro(ComputeCramerRaoLowerBound, bool);\n\nprotected:\n  SpectralForwardModelImageFilter();\n  ~SpectralForwardModelImageFilter() override = default;\n\n  /**  Create the Output */\n  using DataObjectPointerArraySizeType = itk::ProcessObject::DataObjectPointerArraySizeType;\n  using Superclass::MakeOutput;\n  itk::DataObject::Pointer\n  MakeOutput(DataObjectPointerArraySizeType idx) override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  BeforeThreadedGenerateData() override;\n  void\n  DynamicThreadedGenerateData(const typename OutputImageType::RegionType & outputRegionForThread) override;\n\n  /** The inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  ThresholdsType m_Thresholds;\n  unsigned int   m_NumberOfSpectralBins;\n\n  MaterialAttenuationsType m_MaterialAttenuations;\n  DetectorResponseType     m_DetectorResponse;\n  unsigned int             m_NumberOfEnergies;\n\n  /** Parameters */\n  unsigned int m_NumberOfIterations;\n  unsigned int m_NumberOfMaterials;\n  bool         m_OptimizeWithRestarts;\n  bool         m_IsSpectralCT;               // If not, it is dual energy CT\n  bool         m_ComputeVariances;           // Only implemented for dual energy CT\n  bool         m_ComputeCramerRaoLowerBound; // Only implemented for spectral CT\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  /** Filters required for the overload of SetInputIncidentSpectrum */\n  typename FlattenVectorFilterType::Pointer m_FlattenFilter;\n  typename FlattenVectorFilterType::Pointer m_FlattenSecondFilter;\n  typename PermuteFilterType::Pointer       m_PermuteFilter;\n  typename PermuteFilterType::Pointer       m_PermuteSecondFilter;\n#endif\n\n}; // end of class\n\n// Function to bin a detector response matrix according to given energy thresholds\ntemplate <typename OutputElementType, typename DetectorResponseImageType, typename ThresholdsType>\nvnl_matrix<OutputElementType>\nSpectralBinDetectorResponse(const DetectorResponseImageType * drm,\n                            const ThresholdsType &            thresholds,\n                            const unsigned int                numberOfEnergies);\n\n} // end namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSpectralForwardModelImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSpectralForwardModelImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSpectralForwardModelImageFilter_hxx\n#define rtkSpectralForwardModelImageFilter_hxx\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n\nnamespace rtk\n{\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::SpectralForwardModelImageFilter()\n{\n  // Initial lengths, set to incorrect values to make sure that they are indeed updated\n  m_NumberOfSpectralBins = 8;\n  m_IsSpectralCT = true;\n  m_ComputeVariances = false;\n  m_ComputeCramerRaoLowerBound = false;\n\n  this->SetNumberOfIndexedOutputs(\n    3); // dual energy/ photon counts, variance of the distribution, Cramer-Rao lower bound.\n\n  // Dual energy projections (mean of the distribution) or photon counts in case of spectral CT.\n  this->SetNthOutput(0, this->MakeOutput(0));\n\n  // Variance of the distribution\n  this->SetNthOutput(1, this->MakeOutput(1));\n\n  // Cramer-rao lower bound\n  this->SetNthOutput(2, this->MakeOutput(2));\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  // Instantiate the filters required in the overload of SetInputIncidentSpectrum\n  m_FlattenFilter = FlattenVectorFilterType::New();\n  m_FlattenSecondFilter = FlattenVectorFilterType::New();\n  m_PermuteFilter = PermuteFilterType::New();\n  m_PermuteSecondFilter = PermuteFilterType::New();\n#endif\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::\n  SetInputDecomposedProjections(\n    const typename itk::ImageBase<DecomposedProjectionsType::ImageDimension> * DecomposedProjections)\n{\n  // Attempt to dynamic_cast DecomposedProjections into the default DecomposedProjectionsType\n  const DecomposedProjectionsType * default_ptr =\n    dynamic_cast<const DecomposedProjectionsType *>(DecomposedProjections);\n  if (default_ptr)\n  {\n    this->SetInput(\"DecomposedProjections\", const_cast<DecomposedProjectionsType *>(default_ptr));\n  }\n  else\n  {\n    // Attempt to dynamic_cast DecomposedProjections into one of the supported fixed vector length types\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 1>, DecomposedProjectionsType::ImageDimension> Type1;\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 2>, DecomposedProjectionsType::ImageDimension> Type2;\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 3>, DecomposedProjectionsType::ImageDimension> Type3;\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 4>, DecomposedProjectionsType::ImageDimension> Type4;\n    typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 5>, DecomposedProjectionsType::ImageDimension> Type5;\n    const Type1 * ptr1 = dynamic_cast<const Type1 *>(DecomposedProjections);\n    const Type2 * ptr2 = dynamic_cast<const Type2 *>(DecomposedProjections);\n    const Type3 * ptr3 = dynamic_cast<const Type3 *>(DecomposedProjections);\n    const Type4 * ptr4 = dynamic_cast<const Type4 *>(DecomposedProjections);\n    const Type5 * ptr5 = dynamic_cast<const Type5 *>(DecomposedProjections);\n\n    if (ptr1)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<1>(ptr1);\n    }\n    else if (ptr2)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<2>(ptr2);\n    }\n    else if (ptr3)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<3>(ptr3);\n    }\n    else if (ptr4)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<4>(ptr4);\n    }\n    else if (ptr5)\n    {\n      this->SetInputFixedVectorLengthDecomposedProjections<5>(ptr5);\n    }\n    else\n    {\n      itkWarningMacro(\"The input does not match any of the supported types, and has been ignored\");\n    }\n  }\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntemplate <unsigned int VNumberOfMaterials>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::\n  SetInputFixedVectorLengthDecomposedProjections(\n    const itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,\n                     DecomposedProjectionsType::ImageDimension> * DecomposedProjections)\n{\n  using ActualInputType = itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,\n                                     DecomposedProjectionsType::ImageDimension>;\n  using CastFilterType = itk::CastImageFilter<ActualInputType, DecomposedProjectionsType>;\n  auto castPointer = CastFilterType::New();\n  castPointer->SetInput(DecomposedProjections);\n  castPointer->Update();\n  this->SetInput(\"DecomposedProjections\", const_cast<DecomposedProjectionsType *>(castPointer->GetOutput()));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::\n  SetInputMeasuredProjections(\n    const typename itk::ImageBase<MeasuredProjectionsType::ImageDimension> * MeasuredProjections)\n{\n  // Attempt to dynamic_cast MeasuredProjections into the default type MeasuredProjectionsType\n  const MeasuredProjectionsType * default_ptr = dynamic_cast<const MeasuredProjectionsType *>(MeasuredProjections);\n  if (default_ptr)\n  {\n    this->SetNthInput(0, const_cast<MeasuredProjectionsType *>(default_ptr));\n  }\n  else\n  {\n    // Attempt to dynamic_cast MeasuredProjections into one of the supported types\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 1>, MeasuredProjectionsType::ImageDimension> Type1;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 2>, MeasuredProjectionsType::ImageDimension> Type2;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 3>, MeasuredProjectionsType::ImageDimension> Type3;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 4>, MeasuredProjectionsType::ImageDimension> Type4;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 5>, MeasuredProjectionsType::ImageDimension> Type5;\n    typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 6>, MeasuredProjectionsType::ImageDimension> Type6;\n    const Type1 * ptr1 = dynamic_cast<const Type1 *>(MeasuredProjections);\n    const Type2 * ptr2 = dynamic_cast<const Type2 *>(MeasuredProjections);\n    const Type3 * ptr3 = dynamic_cast<const Type3 *>(MeasuredProjections);\n    const Type4 * ptr4 = dynamic_cast<const Type4 *>(MeasuredProjections);\n    const Type5 * ptr5 = dynamic_cast<const Type5 *>(MeasuredProjections);\n    const Type6 * ptr6 = dynamic_cast<const Type6 *>(MeasuredProjections);\n\n    if (ptr1)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<1>(ptr1);\n    }\n    else if (ptr2)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<2>(ptr2);\n    }\n    else if (ptr3)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<3>(ptr3);\n    }\n    else if (ptr4)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<4>(ptr4);\n    }\n    else if (ptr5)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<5>(ptr5);\n    }\n    else if (ptr6)\n    {\n      this->SetInputFixedVectorLengthMeasuredProjections<6>(ptr6);\n    }\n    else\n    {\n      itkWarningMacro(\"The input does not match any of the supported types, and has been ignored\");\n    }\n  }\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntemplate <unsigned int VNumberOfSpectralBins>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::\n  SetInputFixedVectorLengthMeasuredProjections(\n    const itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,\n                     MeasuredProjectionsType::ImageDimension> * MeasuredProjections)\n{\n  using ActualInputType = itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,\n                                     MeasuredProjectionsType::ImageDimension>;\n  using CastFilterType = itk::CastImageFilter<ActualInputType, MeasuredProjectionsType>;\n  auto castPointer = CastFilterType::New();\n  castPointer->SetInput(MeasuredProjections);\n  castPointer->UpdateLargestPossibleRegion();\n  this->SetNthInput(0, const_cast<MeasuredProjectionsType *>(castPointer->GetOutput()));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SetInputIncidentSpectrum(const IncidentSpectrumImageType * IncidentSpectrum)\n{\n  this->SetInput(\"IncidentSpectrum\", const_cast<IncidentSpectrumImageType *>(IncidentSpectrum));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::\n  SetInputSecondIncidentSpectrum(const IncidentSpectrumImageType * SecondIncidentSpectrum)\n{\n  this->SetInput(\"SecondIncidentSpectrum\", const_cast<IncidentSpectrumImageType *>(SecondIncidentSpectrum));\n}\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::SetInputIncidentSpectrum(const VectorSpectrumImageType *\n                                                                                           IncidentSpectrum)\n{\n  this->m_FlattenFilter->SetInput(IncidentSpectrum);\n  this->m_PermuteFilter->SetInput(this->m_FlattenFilter->GetOutput());\n  typename PermuteFilterType::PermuteOrderArrayType order;\n  order[0] = 2;\n  order[1] = 0;\n  order[2] = 1;\n  this->m_PermuteFilter->SetOrder(order);\n  this->SetInputIncidentSpectrum(m_PermuteFilter->GetOutput());\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SetInputSecondIncidentSpectrum(const VectorSpectrumImageType * SecondIncidentSpectrum)\n{\n  this->m_FlattenSecondFilter->SetInput(SecondIncidentSpectrum);\n  this->m_PermuteSecondFilter->SetInput(this->m_FlattenSecondFilter->GetOutput());\n  typename PermuteFilterType::PermuteOrderArrayType order;\n  order[0] = 2;\n  order[1] = 0;\n  order[2] = 1;\n  this->m_PermuteSecondFilter->SetOrder(order);\n  this->SetInputSecondIncidentSpectrum(m_PermuteSecondFilter->GetOutput());\n}\n#endif\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::SetDetectorResponse(const DetectorResponseImageType *\n                                                                                      DetectorResponse)\n{\n  this->SetInput(\"DetectorResponse\", const_cast<DetectorResponseImageType *>(DetectorResponse));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<\n  DecomposedProjectionsType,\n  MeasuredProjectionsType,\n  IncidentSpectrumImageType,\n  DetectorResponseImageType,\n  MaterialAttenuationsImageType>::SetMaterialAttenuations(const MaterialAttenuationsImageType * MaterialAttenuations)\n{\n  this->SetInput(\"MaterialAttenuations\", const_cast<MaterialAttenuationsImageType *>(MaterialAttenuations));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename MeasuredProjectionsType::ConstPointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GetInputMeasuredProjections()\n{\n  return static_cast<const MeasuredProjectionsType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename IncidentSpectrumImageType::ConstPointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GetInputIncidentSpectrum()\n{\n  return static_cast<const IncidentSpectrumImageType *>(this->itk::ProcessObject::GetInput(\"IncidentSpectrum\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename IncidentSpectrumImageType::ConstPointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GetInputSecondIncidentSpectrum()\n{\n  return static_cast<const IncidentSpectrumImageType *>(this->itk::ProcessObject::GetInput(\"SecondIncidentSpectrum\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename DecomposedProjectionsType::ConstPointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GetInputDecomposedProjections()\n{\n  return static_cast<const DecomposedProjectionsType *>(this->itk::ProcessObject::GetInput(\"DecomposedProjections\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename DetectorResponseImageType::ConstPointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GetDetectorResponse()\n{\n  return static_cast<const DetectorResponseImageType *>(this->itk::ProcessObject::GetInput(\"DetectorResponse\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename MaterialAttenuationsImageType::ConstPointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GetMaterialAttenuations()\n{\n  return static_cast<const MaterialAttenuationsImageType *>(this->itk::ProcessObject::GetInput(\"MaterialAttenuations\"));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename DecomposedProjectionsType::ConstPointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GetOutputCramerRaoLowerBound()\n{\n  return static_cast<const DecomposedProjectionsType *>(this->GetOutput(2));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\ntypename MeasuredProjectionsType::ConstPointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GetOutputVariances()\n{\n  return static_cast<const MeasuredProjectionsType *>(this->GetOutput(1));\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nitk::DataObject::Pointer\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::MakeOutput(DataObjectPointerArraySizeType idx)\n{\n  itk::DataObject::Pointer output;\n\n  switch (idx)\n  {\n    case 0:\n      output = (MeasuredProjectionsType::New()).GetPointer();\n      break;\n    case 1:\n      output = (MeasuredProjectionsType::New()).GetPointer();\n      break;\n    case 2:\n      output = (DecomposedProjectionsType::New()).GetPointer();\n  }\n  return output.GetPointer();\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GenerateOutputInformation()\n{\n  Superclass::GenerateOutputInformation();\n  this->m_NumberOfSpectralBins = this->GetInputMeasuredProjections()->GetVectorLength();\n  this->m_NumberOfMaterials = this->GetInputDecomposedProjections()->GetVectorLength();\n  this->m_NumberOfEnergies = this->GetInputIncidentSpectrum()->GetLargestPossibleRegion().GetSize(0);\n  this->GetOutput(2)->SetLargestPossibleRegion(this->GetInputDecomposedProjections()->GetLargestPossibleRegion());\n  this->GetOutput(2)->SetVectorLength(this->m_NumberOfMaterials);\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n\n  // Input 2 is the incident spectrum image\n  typename IncidentSpectrumImageType::Pointer inputPtr2 =\n    const_cast<IncidentSpectrumImageType *>(this->GetInputIncidentSpectrum().GetPointer());\n  if (!inputPtr2)\n    return;\n\n  typename IncidentSpectrumImageType::RegionType requested =\n    this->GetInputIncidentSpectrum()->GetLargestPossibleRegion();\n  typename IncidentSpectrumImageType::IndexType indexRequested = requested.GetIndex();\n  typename IncidentSpectrumImageType::SizeType  sizeRequested = requested.GetSize();\n  for (unsigned int i = 0; i < IncidentSpectrumImageType::GetImageDimension() - 1; i++)\n  {\n    indexRequested[i + 1] = this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n    sizeRequested[i + 1] = this->GetOutput()->GetRequestedRegion().GetSize()[i];\n  }\n\n  requested.SetIndex(indexRequested);\n  requested.SetSize(sizeRequested);\n\n  inputPtr2->SetRequestedRegion(requested);\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::BeforeThreadedGenerateData()\n{\n  Superclass::BeforeThreadedGenerateData();\n\n  // Read the material attenuations image as a matrix\n  typename MaterialAttenuationsImageType::IndexType indexMat;\n  this->m_MaterialAttenuations.set_size(m_NumberOfEnergies, m_NumberOfMaterials);\n  for (unsigned int energy = 0; energy < m_NumberOfEnergies; energy++)\n  {\n    indexMat[1] = energy;\n    for (unsigned int material = 0; material < m_NumberOfMaterials; material++)\n    {\n      indexMat[0] = material;\n      m_MaterialAttenuations[energy][material] = this->GetMaterialAttenuations()->GetPixel(indexMat);\n    }\n  }\n\n  if (this->GetInputSecondIncidentSpectrum())\n  {\n    // Read the detector response image as a matrix\n    this->m_DetectorResponse.set_size(1, this->m_NumberOfEnergies);\n    this->m_DetectorResponse.fill(0);\n    typename DetectorResponseImageType::IndexType indexDet;\n    for (unsigned int energy = 0; energy < this->m_NumberOfEnergies; energy++)\n    {\n      indexDet[0] = energy;\n      indexDet[1] = 0;\n      this->m_DetectorResponse[0][energy] += this->GetDetectorResponse()->GetPixel(indexDet);\n    }\n  }\n  else\n  {\n    this->m_DetectorResponse = SpectralBinDetectorResponse<DetectorResponseType::element_type>(\n      this->GetDetectorResponse().GetPointer(), m_Thresholds, m_NumberOfEnergies);\n  }\n}\n\ntemplate <typename DecomposedProjectionsType,\n          typename MeasuredProjectionsType,\n          typename IncidentSpectrumImageType,\n          typename DetectorResponseImageType,\n          typename MaterialAttenuationsImageType>\nvoid\nSpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                MeasuredProjectionsType,\n                                IncidentSpectrumImageType,\n                                DetectorResponseImageType,\n                                MaterialAttenuationsImageType>::\n  DynamicThreadedGenerateData(const typename OutputImageType::RegionType & outputRegionForThread)\n{\n  ////////////////////////////////////////////////////////////////////\n  // Create a Nelder-Mead simplex optimizer and its cost function\n  rtk::ProjectionsDecompositionNegativeLogLikelihood::Pointer cost;\n  if (m_IsSpectralCT)\n    cost = rtk::Schlomka2008NegativeLogLikelihood::New();\n  else\n    cost = rtk::DualEnergyNegativeLogLikelihood::New();\n\n  cost->SetNumberOfEnergies(this->GetNumberOfEnergies());\n  cost->SetNumberOfMaterials(this->GetNumberOfMaterials());\n  cost->SetNumberOfSpectralBins(this->GetNumberOfSpectralBins());\n\n  // Pass the attenuation functions to the cost function\n  cost->SetMaterialAttenuations(this->m_MaterialAttenuations);\n\n  // Pass the binned detector response to the cost function\n  cost->SetDetectorResponse(this->m_DetectorResponse);\n\n  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n  // Walk the output projection stack. For each pixel, set the cost function's member variables and run the optimizer.\n  itk::ImageRegionIterator<MeasuredProjectionsType>        output0It(this->GetOutput(0), outputRegionForThread);\n  itk::ImageRegionIterator<MeasuredProjectionsType>        output1It(this->GetOutput(1), outputRegionForThread);\n  itk::ImageRegionIterator<DecomposedProjectionsType>      output2It(this->GetOutput(2), outputRegionForThread);\n  itk::ImageRegionConstIterator<DecomposedProjectionsType> inIt(this->GetInputDecomposedProjections(),\n                                                                outputRegionForThread);\n\n  typename IncidentSpectrumImageType::RegionType incidentSpectrumRegionForThread =\n    this->GetInputIncidentSpectrum()->GetLargestPossibleRegion();\n  for (unsigned int dim = 0; dim < IncidentSpectrumImageType::GetImageDimension() - 1; dim++)\n  {\n    incidentSpectrumRegionForThread.SetIndex(dim + 1, outputRegionForThread.GetIndex()[dim]);\n    incidentSpectrumRegionForThread.SetSize(dim + 1, outputRegionForThread.GetSize()[dim]);\n  }\n  itk::ImageRegionConstIterator<IncidentSpectrumImageType> spectrumIt(this->GetInputIncidentSpectrum(),\n                                                                      incidentSpectrumRegionForThread);\n\n  // Special case for the dual energy CT\n  itk::ImageRegionConstIterator<IncidentSpectrumImageType> secondSpectrumIt;\n  if (this->GetInputSecondIncidentSpectrum())\n    secondSpectrumIt = itk::ImageRegionConstIterator<IncidentSpectrumImageType>(this->GetInputSecondIncidentSpectrum(),\n                                                                                incidentSpectrumRegionForThread);\n\n  // Instantiate a vnl_matrix for the high and low energy incident spectra (if DECT)\n  // or the single spectrum (if spectral) and set its size.\n  vnl_matrix<float> spectra;\n  if (this->GetInputSecondIncidentSpectrum()) // Dual energy CT\n  {\n    spectra.set_size(2, m_NumberOfEnergies);\n  }\n  else\n  {\n    spectra.set_size(1, m_NumberOfEnergies);\n  }\n\n  while (!output0It.IsAtEnd())\n  {\n    // The input incident spectrum image typically has lower dimension than decomposed projections\n    // This condition makes the iterator cycle over and over on the same image, following the other ones\n    if (spectrumIt.IsAtEnd())\n    {\n      spectrumIt.GoToBegin();\n      if (this->GetInputSecondIncidentSpectrum())\n        secondSpectrumIt.GoToBegin();\n    }\n\n    // Fill in the spectra matrix\n    if (this->GetInputSecondIncidentSpectrum()) // Dual energy CT\n    {\n      for (unsigned int e = 0; e < m_NumberOfEnergies; e++)\n      {\n        spectra.put(0, e, spectrumIt.Get());\n        spectra.put(1, e, secondSpectrumIt.Get());\n        ++spectrumIt;\n        ++secondSpectrumIt;\n      }\n    }\n    else\n    {\n      for (unsigned int e = 0; e < m_NumberOfEnergies; e++)\n      {\n        spectra.put(0, e, spectrumIt.Get());\n        ++spectrumIt;\n      }\n    }\n\n    // Pass the incident spectrum vector to cost function\n    cost->SetIncidentSpectrum(spectra);\n    cost->Initialize();\n\n    // Run the optimizer\n    typename rtk::ProjectionsDecompositionNegativeLogLikelihood::ParametersType in(this->m_NumberOfMaterials);\n    for (unsigned int m = 0; m < this->m_NumberOfMaterials; m++)\n      in[m] = inIt.Get()[m];\n\n    // Compute the expected forward projection\n    vnl_vector<double> forward = cost->ForwardModel(in);\n\n    // Fill a fixed-sized vector with the computed photon counts in each bin\n    typename MeasuredProjectionsType::PixelType outputPixel;\n    outputPixel.SetSize(this->m_NumberOfSpectralBins);\n    for (unsigned int m = 0; m < this->m_NumberOfSpectralBins; m++)\n      outputPixel[m] = forward[m];\n\n    // Write it to the output\n    output0It.Set(outputPixel);\n\n    // If requested, store the variances into output(1)\n    if (m_ComputeVariances)\n    {\n      if (m_IsSpectralCT)\n      {\n        // For spectral CT, Poisson noise is assumed therefore the variances is equal to the photon counts.\n        output1It.Set(outputPixel);\n      }\n      else\n      {\n        output1It.Set(\n          itk::VariableLengthVector<double>(cost->GetVariances(in).data_block(), this->m_NumberOfSpectralBins));\n      }\n      ++output1It;\n    }\n\n    // If requested, compute the Cramer Rao Lower bound (only for spectral CT).\n    if (m_IsSpectralCT)\n    {\n      if (m_ComputeCramerRaoLowerBound)\n      {\n        rtk::ProjectionsDecompositionNegativeLogLikelihood::MeasuredDataType photon_counts;\n        photon_counts.SetSize(forward.size());\n        photon_counts.SetData(forward.data_block());\n        cost->SetMeasuredData(photon_counts);\n        cost->ComputeFischerMatrix(in);\n        output2It.Set(cost->GetCramerRaoLowerBound());\n        ++output2It;\n      }\n    }\n\n    // Move forward\n    ++output0It;\n    ++inIt;\n  }\n}\n\ntemplate <typename OutputElementType, typename DetectorResponseImageType, typename ThresholdsType>\nvnl_matrix<OutputElementType>\nSpectralBinDetectorResponse(const DetectorResponseImageType * drm,\n                            const ThresholdsType &            thresholds,\n                            const unsigned int                numberOfEnergies)\n{\n  vnl_matrix<OutputElementType> binnedResponse;\n  int                           numberOfSpectralBins = thresholds.GetSize() - 1;\n  binnedResponse.set_size(numberOfSpectralBins, numberOfEnergies);\n  binnedResponse.fill(0);\n  typename DetectorResponseImageType::IndexType indexDet;\n  for (unsigned int energy = 0; energy < numberOfEnergies; energy++)\n  {\n    indexDet[0] = energy;\n    for (int bin = 0; bin < numberOfSpectralBins; bin++)\n    {\n      // First and last couple of values:\n      // use trapezoidal rule with linear interpolation\n      unsigned int infPulse = itk::Math::floor(thresholds[bin]);\n      if (infPulse < 1)\n      {\n        itkGenericExceptionMacro(<< \"Threshold \" << thresholds[bin] << \" below 0 keV.\");\n      }\n      unsigned int supPulse = itk::Math::floor(thresholds[bin + 1]);\n      if (double(supPulse) == thresholds[bin + 1])\n        supPulse--;\n      if (supPulse - infPulse < 3)\n      {\n        itkGenericExceptionMacro(<< \"Thresholds are too close for the current code.\");\n      }\n\n      double wInf = infPulse + 1. - thresholds[bin];\n      indexDet[1] = infPulse - 1; // Index 0 is 1 keV\n      binnedResponse[bin][energy] += 0.5 * wInf * wInf * drm->GetPixel(indexDet);\n      indexDet[1]++;\n      binnedResponse[bin][energy] += 0.5 * (1. + wInf * (2. - wInf)) * drm->GetPixel(indexDet);\n\n      double wSup = thresholds[bin + 1] - supPulse;\n      indexDet[1] = supPulse; // Index 0 is 1 keV\n      binnedResponse[bin][energy] += 0.5 * wSup * wSup * drm->GetPixel(indexDet);\n      if (supPulse >= drm->GetLargestPossibleRegion().GetSize(1))\n      {\n        itkGenericExceptionMacro(<< \"Threshold \" << thresholds[bin + 1] << \" above max \"\n                                 << drm->GetLargestPossibleRegion().GetSize(1) + 1);\n      }\n      indexDet[1]--;\n      binnedResponse[bin][energy] += 0.5 * (1. + wSup * (2. - wSup)) * drm->GetPixel(indexDet);\n\n      // Intermediate values\n      for (unsigned int pulseHeight = infPulse + 1; pulseHeight < supPulse - 1; pulseHeight++)\n      {\n        indexDet[1] = pulseHeight;\n        binnedResponse[bin][energy] += drm->GetPixel(indexDet);\n      }\n    }\n  }\n  return binnedResponse;\n}\n\n} // end namespace rtk\n\n#endif // rtkSpectralForwardModelImageFilter_hxx\n"
  },
  {
    "path": "include/rtkSplatWithKnownWeightsImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkSplatWithKnownWeightsImageFilter_h\n#define rtkSplatWithKnownWeightsImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n#include <itkArray2D.h>\n\n#include <itkImageRegionSplitterDirection.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class SplatWithKnownWeightsImageFilter\n * \\brief Splats (linearly) a 3D volume into a 3D+t sequence of volumes\n *\n * See the reference paper: \"Cardiac C-arm computed tomography using\n * a 3D + time ROI reconstruction method with spatial and temporal regularization\"\n * by Mory et al.\n *\n * 4D conjugate gradient reconstruction consists in iteratively\n * minimizing the following cost function:\n *\n * Sum_over_theta || R_theta S_theta f - p_theta ||_2^2\n *\n * with\n * - f a 4D series of 3D volumes, each one being the reconstruction\n * at a given respiratory/cardiac phase\n * - p_theta is the projection measured at angle theta\n * - S_theta an interpolation operator which, from the 3D + time sequence f,\n * estimates the 3D volume through which projection p_theta has been acquired\n * - R_theta is the X-ray transform (the forward projection operator) for angle theta\n *\n * Computing the gradient of this cost function yields:\n *\n * S_theta^T R_theta^T R_theta S_theta f - S_theta^T R_theta^T p_theta\n *\n * where A^T means the adjoint of operator A.\n *\n * SplatWithKnownWeightsImageFilter implements S_theta^T.\n *\n *\n * \\test rtkfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename VolumeType>\nclass ITK_TEMPLATE_EXPORT SplatWithKnownWeightsImageFilter\n  : public itk::InPlaceImageFilter<VolumeSeriesType, VolumeSeriesType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SplatWithKnownWeightsImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SplatWithKnownWeightsImageFilter;\n  using Superclass = itk::ImageToImageFilter<VolumeSeriesType, VolumeSeriesType>;\n  using Pointer = itk::SmartPointer<Self>;\n  using OutputImageRegionType = typename VolumeSeriesType::RegionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SplatWithKnownWeightsImageFilter);\n\n  /** The 4D image to be updated.*/\n  void\n  SetInputVolumeSeries(const VolumeSeriesType * VolumeSeries);\n\n  /** The 3D image that will be added, with coefficients, to each 3D volume of the 4D image.*/\n  void\n  SetInputVolume(const VolumeType * Volume);\n\n  /** Macros that take care of implementing the Get and Set methods for Weights and projectionNumber.*/\n  itkGetMacro(Weights, itk::Array2D<float>);\n  itkSetMacro(Weights, itk::Array2D<float>);\n\n  itkGetMacro(ProjectionNumber, int);\n  void\n  SetProjectionNumber(int n);\n\nprotected:\n  SplatWithKnownWeightsImageFilter();\n  ~SplatWithKnownWeightsImageFilter() override = default;\n\n  typename VolumeSeriesType::ConstPointer\n  GetInputVolumeSeries();\n  typename VolumeType::Pointer\n  GetInputVolume();\n\n  /** Does the real work. */\n  void\n  ThreadedGenerateData(const typename VolumeSeriesType::RegionType & outputRegionForThread,\n                       itk::ThreadIdType                             itkNotUsed(threadId)) override;\n\n  /** Splits the OutputRequestedRegion along the first direction, not the last */\n  const itk::ImageRegionSplitterBase *\n                                             GetImageRegionSplitter() const override;\n  itk::ImageRegionSplitterDirection::Pointer m_Splitter;\n\n  itk::Array2D<float> m_Weights;\n  int                 m_ProjectionNumber;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSplatWithKnownWeightsImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSplatWithKnownWeightsImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkSplatWithKnownWeightsImageFilter_hxx\n#define rtkSplatWithKnownWeightsImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include \"itkObjectFactory.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename VolumeType>\nSplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>::SplatWithKnownWeightsImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n  this->SetNumberOfRequiredInputs(2);\n  this->SetInPlace(true);\n  m_ProjectionNumber = 0;\n\n  // Set the direction along which the output requested region should NOT be split\n  m_Splitter = itk::ImageRegionSplitterDirection::New();\n  m_Splitter->SetDirection(VolumeSeriesType::ImageDimension - 1);\n}\n\ntemplate <typename VolumeSeriesType, typename VolumeType>\nvoid\nSplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>::SetInputVolumeSeries(\n  const VolumeSeriesType * VolumeSeries)\n{\n  this->SetNthInput(0, const_cast<VolumeSeriesType *>(VolumeSeries));\n}\n\ntemplate <typename VolumeSeriesType, typename VolumeType>\nvoid\nSplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>::SetInputVolume(const VolumeType * Volume)\n{\n  this->SetNthInput(1, const_cast<VolumeType *>(Volume));\n}\n\ntemplate <typename VolumeSeriesType, typename VolumeType>\ntypename VolumeSeriesType::ConstPointer\nSplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>::GetInputVolumeSeries()\n{\n  return static_cast<const VolumeSeriesType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename VolumeSeriesType, typename VolumeType>\ntypename VolumeType::Pointer\nSplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>::GetInputVolume()\n{\n  return static_cast<VolumeType *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename VolumeType, typename VolumeSeriesType>\nvoid\nSplatWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::SetProjectionNumber(int n)\n{\n  // Check whether the weights change from the old projection number to the new one\n  for (unsigned int row = 0; row < m_Weights.rows(); row++)\n  {\n    if (m_Weights[row][m_ProjectionNumber] != m_Weights[row][n])\n      this->Modified();\n  }\n\n  // Change the member variable whatever the result\n  m_ProjectionNumber = n;\n}\n\ntemplate <typename VolumeSeriesType, typename VolumeType>\nconst itk::ImageRegionSplitterBase *\nSplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>::GetImageRegionSplitter() const\n{\n  return m_Splitter;\n}\n\ntemplate <typename VolumeSeriesType, typename VolumeType>\nvoid\nSplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>::ThreadedGenerateData(\n  const typename VolumeSeriesType::RegionType & outputRegionForThread,\n  itk::ThreadIdType                             itkNotUsed(threadId))\n{\n  typename VolumeType::Pointer volume = this->GetInputVolume();\n\n  unsigned int Dimension = volume->GetImageDimension();\n\n  typename VolumeType::RegionType volumeRegion;\n  typename VolumeType::SizeType   volumeSize;\n  typename VolumeType::IndexType  volumeIndex;\n\n  typename VolumeSeriesType::RegionType volumeSeriesRegion;\n\n  float weight = NAN;\n\n  // Initialize output region with input region in case the filter is not in\n  // place\n  if (this->GetInput() != this->GetOutput())\n  {\n    itk::ImageRegionIterator<VolumeSeriesType>      itOut(this->GetOutput(), outputRegionForThread);\n    itk::ImageRegionConstIterator<VolumeSeriesType> itIn(this->GetInputVolumeSeries(), outputRegionForThread);\n    while (!itOut.IsAtEnd())\n    {\n      itOut.Set(itIn.Get());\n      ++itOut;\n      ++itIn;\n    }\n  }\n\n  // Update each phase\n  for (unsigned int phase = 0; phase < m_Weights.rows(); phase++)\n  {\n\n    weight = m_Weights[phase][m_ProjectionNumber];\n    volumeRegion = volume->GetLargestPossibleRegion();\n\n    for (unsigned int i = 0; i < Dimension; i++)\n    {\n      volumeSize[i] = outputRegionForThread.GetSize()[i];\n      volumeIndex[i] = outputRegionForThread.GetIndex()[i];\n    }\n    volumeRegion.SetSize(volumeSize);\n    volumeRegion.SetIndex(volumeIndex);\n\n    volumeSeriesRegion = outputRegionForThread;\n    volumeSeriesRegion.SetSize(Dimension, 1);\n    volumeSeriesRegion.SetIndex(Dimension, phase);\n\n    itk::ImageRegionIterator<VolumeSeriesType> outputIterator(this->GetOutput(), volumeSeriesRegion);\n    itk::ImageRegionIterator<VolumeType>       volumeIterator(volume, volumeRegion);\n\n    while (!volumeIterator.IsAtEnd())\n    {\n      outputIterator.Set(outputIterator.Get() + weight * volumeIterator.Get());\n      ++volumeIterator;\n      ++outputIterator;\n    }\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkSubSelectFromListImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkSubSelectFromListImageFilter_h\n#define rtkSubSelectFromListImageFilter_h\n\n#include \"rtkSubSelectImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n\nnamespace rtk\n{\n/** \\class SubSelectFromListImageFilter\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT SubSelectFromListImageFilter : public SubSelectImageFilter<ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SubSelectFromListImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SubSelectFromListImageFilter;\n  using Superclass = SubSelectImageFilter<ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SubSelectFromListImageFilter);\n\n  void\n  SetSelectedProjections(std::vector<bool> sprojs);\n\nprotected:\n  SubSelectFromListImageFilter();\n  ~SubSelectFromListImageFilter() = default;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSubSelectFromListImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSubSelectFromListImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkSubSelectFromListImageFilter_hxx\n#define rtkSubSelectFromListImageFilter_hxx\n\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n\n#include \"math.h\"\n\nnamespace rtk\n{\n\ntemplate <typename ProjectionStackType>\nSubSelectFromListImageFilter<ProjectionStackType>::SubSelectFromListImageFilter()\n{}\n\ntemplate <typename ProjectionStackType>\nvoid\nSubSelectFromListImageFilter<ProjectionStackType>::SetSelectedProjections(std::vector<bool> sprojs)\n{\n  // Set the selected projection boolean vector\n  this->m_SelectedProjections = sprojs;\n\n  // Update the number of selected projections\n  this->m_NbSelectedProjs = 0;\n  for (unsigned int i = 0; i < this->m_SelectedProjections.size(); i++)\n    if (this->m_SelectedProjections[i])\n      this->m_NbSelectedProjs += 1;\n\n  // Notify the filter that it has been modified\n  this->Modified();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkSubSelectImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkSubSelectImageFilter_h\n#define rtkSubSelectImageFilter_h\n\n#include <itkPasteImageFilter.h>\n#include <itkExtractImageFilter.h>\n#include \"rtkConstantImageSource.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class SubSelectImageFilter\n * \\brief Subselects projections from a stack of projections\n *\n * This abstract class takes as input a stack of projections and the\n * corresponding geometry and creates an output stack of projections and\n * its corresponding geometry using the two members m_NbSelectedProjs and\n * m_SelectedProjections. The members must be set before\n * GenerateOutputInformation is called. Streaming of the output is possible.\n * The output is produced from the following mini-pipeline:\n *\n * \\dot\n * digraph SubSelectImageFilter {\n * Input [label=\"Input (Projections)\", shape=Mdiamond];\n * Output [label=\"Output (Projections)\", shape=Mdiamond];\n *\n * node [shape=box];\n *\n * Constant [label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * Extract [label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n * Paste [label=\"itk::PasteImageFilter\" URL=\"\\ref itk::PasteImageFilter\"];\n *\n * Input->Extract\n * Extract->Paste\n * Paste->Output\n * Constant->Paste\n * }\n * \\enddot\n *\n * \\test rtkadmmtotalvariationtest.cxx, rtkselectoneprojpercycletest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\ntemplate <typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT SubSelectImageFilter\n  : public itk::ImageToImageFilter<ProjectionStackType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SubSelectImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SubSelectImageFilter;\n  using Superclass = itk::ImageToImageFilter<ProjectionStackType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SubSelectImageFilter);\n\n  /** The set of projections from which a subset will be extracted */\n  void\n  SetInputProjectionStack(const ProjectionStackType * Projections);\n  typename ProjectionStackType::ConstPointer\n  GetInputProjectionStack();\n\n  using PasteFilterType = itk::PasteImageFilter<ProjectionStackType>;\n  using ExtractFilterType = itk::ExtractImageFilter<ProjectionStackType, ProjectionStackType>;\n  using EmptyProjectionStackSourceType = rtk::ConstantImageSource<ProjectionStackType>;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n\n  itkSetObjectMacro(InputGeometry, GeometryType);\n  itkGetModifiableObjectMacro(InputGeometry, GeometryType);\n\n  itkGetMacro(SelectedProjections, std::vector<bool>);\n\n  GeometryType::Pointer\n  GetOutputGeometry();\n\nprotected:\n  SubSelectImageFilter();\n  ~SubSelectImageFilter() override = default;\n\n  /** Checks that inputs are correctly set. */\n  void\n  VerifyPreconditions() const override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member variables */\n  GeometryType::Pointer m_InputGeometry;\n  GeometryType::Pointer m_OutputGeometry;\n  std::vector<bool>     m_SelectedProjections;\n  int                   m_NbSelectedProjs;\n\nprivate:\n  typename EmptyProjectionStackSourceType::Pointer m_EmptyProjectionStackSource;\n  typename ExtractFilterType::Pointer              m_ExtractFilter;\n  typename PasteFilterType::Pointer                m_PasteFilter;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSubSelectImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSubSelectImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkSubSelectImageFilter_hxx\n#define rtkSubSelectImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename ProjectionStackType>\nSubSelectImageFilter<ProjectionStackType>::SubSelectImageFilter()\n  : m_OutputGeometry(GeometryType::New())\n  , m_EmptyProjectionStackSource(EmptyProjectionStackSourceType::New())\n  , m_ExtractFilter(ExtractFilterType::New())\n  , m_PasteFilter(PasteFilterType::New())\n{}\n\ntemplate <typename ProjectionStackType>\nvoid\nSubSelectImageFilter<ProjectionStackType>::SetInputProjectionStack(const ProjectionStackType * Projections)\n{\n  this->SetNthInput(0, const_cast<ProjectionStackType *>(Projections));\n}\n\ntemplate <typename ProjectionStackType>\ntypename ProjectionStackType::ConstPointer\nSubSelectImageFilter<ProjectionStackType>::GetInputProjectionStack()\n{\n  return static_cast<const ProjectionStackType *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <typename ProjectionStackType>\nvoid\nSubSelectImageFilter<ProjectionStackType>::VerifyPreconditions() const\n{\n  this->Superclass::VerifyPreconditions();\n\n  if (this->m_InputGeometry.IsNull() || this->m_OutputGeometry.IsNull())\n    itkExceptionMacro(<< \"Geometries have not been set.\");\n}\n\ntemplate <typename ProjectionStackType>\nvoid\nSubSelectImageFilter<ProjectionStackType>::GenerateInputRequestedRegion()\n{\n  const unsigned int Dimension = this->InputImageDimension;\n\n  // Find first selected projection (if it exists)\n  unsigned int firstSel = 0;\n  for (firstSel = 0; firstSel < m_SelectedProjections.size() && !(m_SelectedProjections[firstSel]); firstSel++)\n    ;\n  if (firstSel == m_SelectedProjections.size())\n  {\n    itkGenericExceptionMacro(<< \"No projection selected.\");\n  }\n\n  // Only request the first projection at first\n  typename ExtractFilterType::InputImageRegionType projRegion;\n  projRegion = this->GetOutput()->GetRequestedRegion();\n  projRegion.SetSize(Dimension - 1, 1);\n  projRegion.SetIndex(Dimension - 1, firstSel);\n  m_ExtractFilter->SetExtractionRegion(projRegion);\n  m_ExtractFilter->UpdateOutputInformation();\n  m_ExtractFilter->GetOutput()->SetRequestedRegion(projRegion);\n  m_ExtractFilter->GetOutput()->PropagateRequestedRegion();\n}\n\ntemplate <typename ProjectionStackType>\nvoid\nSubSelectImageFilter<ProjectionStackType>::GenerateOutputInformation()\n{\n  unsigned int                             Dimension = this->GetInput(0)->GetImageDimension();\n  typename ProjectionStackType::RegionType outputLargestPossibleRegion = this->GetInput(0)->GetLargestPossibleRegion();\n  outputLargestPossibleRegion.SetSize(Dimension - 1, m_NbSelectedProjs);\n\n  // Create a stack of empty projection images\n  typename ProjectionStackType::SizeType ProjectionStackSize;\n  ProjectionStackSize = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetSize();\n  ProjectionStackSize[Dimension - 1] = m_NbSelectedProjs;\n  m_EmptyProjectionStackSource->SetInformationFromImage(this->GetInputProjectionStack());\n  m_EmptyProjectionStackSource->SetSize(ProjectionStackSize);\n  m_EmptyProjectionStackSource->UpdateOutputInformation();\n  this->GetOutput()->CopyInformation(m_EmptyProjectionStackSource->GetOutput());\n\n  // Mini-pipeline connections\n  m_ExtractFilter->SetInput(this->GetInput());\n  m_PasteFilter->SetSourceImage(m_ExtractFilter->GetOutput());\n  m_PasteFilter->SetDestinationImage(m_EmptyProjectionStackSource->GetOutput());\n\n  // Update output geometry\n  // NOTE : The output geometry must be computed here, not in the GenerateData(),\n  // because downstream forward and backprojection filters will need this geometry\n  // to compute their output information and input requested region\n  m_OutputGeometry->Clear();\n  m_OutputGeometry->SetRadiusCylindricalDetector(m_InputGeometry->GetRadiusCylindricalDetector());\n\n  for (unsigned long i = 0; i < m_SelectedProjections.size(); i++)\n  {\n    if (m_SelectedProjections[i])\n    {\n      m_OutputGeometry->AddProjectionInRadians(m_InputGeometry->GetSourceToIsocenterDistances()[i],\n                                               m_InputGeometry->GetSourceToDetectorDistances()[i],\n                                               m_InputGeometry->GetGantryAngles()[i],\n                                               m_InputGeometry->GetProjectionOffsetsX()[i],\n                                               m_InputGeometry->GetProjectionOffsetsY()[i],\n                                               m_InputGeometry->GetOutOfPlaneAngles()[i],\n                                               m_InputGeometry->GetInPlaneAngles()[i],\n                                               m_InputGeometry->GetSourceOffsetsX()[i],\n                                               m_InputGeometry->GetSourceOffsetsY()[i]);\n      m_OutputGeometry->SetCollimationOfLastProjection(m_InputGeometry->GetCollimationUInf()[i],\n                                                       m_InputGeometry->GetCollimationUSup()[i],\n                                                       m_InputGeometry->GetCollimationVInf()[i],\n                                                       m_InputGeometry->GetCollimationVSup()[i]);\n    }\n  }\n}\n\ntemplate <typename ProjectionStackType>\ntypename rtk::ThreeDCircularProjectionGeometry::Pointer\nSubSelectImageFilter<ProjectionStackType>::GetOutputGeometry()\n{\n  return m_OutputGeometry;\n}\n\ntemplate <typename ProjectionStackType>\nvoid\nSubSelectImageFilter<ProjectionStackType>::GenerateData()\n{\n  unsigned int Dimension = this->GetInput(0)->GetImageDimension();\n\n  // Set the extract filter\n  typename ExtractFilterType::InputImageRegionType projRegion;\n  projRegion = this->GetOutput()->GetRequestedRegion();\n  projRegion.SetSize(Dimension - 1, 1);\n  m_ExtractFilter->SetExtractionRegion(projRegion);\n\n  // Count the projections actually used in constructing the output\n  int counter = 0;\n\n  for (unsigned int i = 0; i < m_SelectedProjections.size(); i++)\n  {\n    if (m_SelectedProjections[i])\n    {\n      // After the first update, we need to use the output as input.\n      if (counter > 0)\n      {\n        typename ProjectionStackType::Pointer pimg = m_PasteFilter->GetOutput();\n        pimg->DisconnectPipeline();\n        m_PasteFilter->SetDestinationImage(pimg);\n      }\n\n      // Set the Extract Filter\n      projRegion.SetIndex(Dimension - 1, i);\n      m_ExtractFilter->SetExtractionRegion(projRegion);\n\n      // Set the Paste filter\n      m_PasteFilter->SetSourceRegion(projRegion);\n      typename ProjectionStackType::IndexType DestinationIndex = projRegion.GetIndex();\n      DestinationIndex[Dimension - 1] = counter;\n      m_PasteFilter->SetDestinationIndex(DestinationIndex);\n\n      // Update the filters\n      projRegion.SetIndex(Dimension - 1, counter);\n      m_PasteFilter->UpdateLargestPossibleRegion();\n\n      counter++;\n    }\n  }\n\n  this->GraftOutput(m_PasteFilter->GetOutput());\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkSumOfSquaresImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSumOfSquaresImageFilter_h\n#define rtkSumOfSquaresImageFilter_h\n\n#include <itkInPlaceImageFilter.h>\n\n/** \\class SumOfSquaresImageFilter\n * \\brief Computes the sum of squared differences between two images\n *\n * Works on vector images too.\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\nnamespace rtk\n{\n\ntemplate <class TOutputImage>\nclass ITK_TEMPLATE_EXPORT SumOfSquaresImageFilter : public itk::InPlaceImageFilter<TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(SumOfSquaresImageFilter);\n\n  /** Standard class type alias. */\n  using Self = SumOfSquaresImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using OutputInternalPixelType = typename TOutputImage::InternalPixelType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(SumOfSquaresImageFilter);\n\n  /** Macro to get the SSD */\n  itkGetMacro(SumOfSquares, OutputInternalPixelType);\n\nprotected:\n  SumOfSquaresImageFilter();\n  ~SumOfSquaresImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData();\n  void\n  ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, itk::ThreadIdType threadId) override;\n  void\n  AfterThreadedGenerateData();\n\n  OutputInternalPixelType              m_SumOfSquares;\n  std::vector<OutputInternalPixelType> m_VectorOfPartialSSs;\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkSumOfSquaresImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkSumOfSquaresImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkSumOfSquaresImageFilter_hxx\n#define rtkSumOfSquaresImageFilter_hxx\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TOutputImage>\nSumOfSquaresImageFilter<TOutputImage>::SumOfSquaresImageFilter()\n{\n  m_SumOfSquares = 0;\n  m_VectorOfPartialSSs.clear();\n  this->SetDynamicMultiThreading(false);\n}\n\ntemplate <class TOutputImage>\nvoid\nSumOfSquaresImageFilter<TOutputImage>::BeforeThreadedGenerateData()\n{\n  m_VectorOfPartialSSs.clear();\n  for (unsigned int thread = 0; thread < this->GetNumberOfWorkUnits(); thread++)\n    m_VectorOfPartialSSs.push_back(0);\n}\n\ntemplate <class TOutputImage>\nvoid\nSumOfSquaresImageFilter<TOutputImage>::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,\n                                                            itk::ThreadIdType             threadId)\n{\n  itk::ImageRegionConstIterator<TOutputImage> inIt(this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<TOutputImage>      outIt(this->GetOutput(), outputRegionForThread);\n\n  while (!outIt.IsAtEnd())\n  {\n    m_VectorOfPartialSSs[threadId] += inIt.Get() * inIt.Get();\n\n    // Pass the first input through unmodified\n    outIt.Set(inIt.Get());\n\n    // Move iterators\n    ++inIt;\n    ++outIt;\n  }\n}\n\ntemplate <class TOutputImage>\nvoid\nSumOfSquaresImageFilter<TOutputImage>::AfterThreadedGenerateData()\n{\n  m_SumOfSquares = 0;\n  for (unsigned int thread = 0; thread < this->GetNumberOfWorkUnits(); thread++)\n    m_SumOfSquares += m_VectorOfPartialSSs[thread];\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkThreeDCircularProjectionGeometry.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkThreeDCircularProjectionGeometry_h\n#define rtkThreeDCircularProjectionGeometry_h\n\n#include \"RTKExport.h\"\n#include \"rtkProjectionGeometry.h\"\n\nnamespace rtk\n{\n/** \\class ThreeDCircularProjectionGeometry\n * \\brief Projection geometry for a source and a 2-D flat panel.\n *\n * The source and the detector rotate around a circle paremeterized\n * with the SourceToDetectorDistance and the SourceToIsocenterDistance.\n * The position of each projection along this circle is parameterized\n * by the GantryAngle.\n * The detector can be shifted in plane with the ProjectionOffsetsX\n * and the ProjectionOffsetsY. It can be also rotated with InPlaneAngles\n * and OutOfPlaneAngles. All angles are in radians except for the function\n * AddProjection that takes angles in degrees.\n * The source can be shifted in plane with the SourceOffsetsX\n * and the SourceOffsetsY.\n *\n * If SDD equals 0., then one is dealing with a parallel geometry.\n *\n * See https://docs.openrtk.org/en/latest/documentation/docs/Geometry.html\n * for more information.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ProjectionGeometry\n */\n\nclass RTK_EXPORT ThreeDCircularProjectionGeometry : public ProjectionGeometry<3>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ThreeDCircularProjectionGeometry);\n\n  using Self = ThreeDCircularProjectionGeometry;\n  using Superclass = ProjectionGeometry<3>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  using VectorType = itk::Vector<double, 3>;\n  using HomogeneousVectorType = itk::Vector<double, 4>;\n  using TwoDHomogeneousMatrixType = itk::Matrix<double, 3, 3>;\n  using ThreeDHomogeneousMatrixType = itk::Matrix<double, 4, 4>;\n  using PointType = itk::Point<double, 3>;\n  using Matrix3x3Type = itk::Matrix<double, 3, 3>;\n  using HomogeneousProjectionMatrixType = Superclass::MatrixType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Add projection to geometry. One projection is defined with the rotation\n   * angle in degrees and the in-plane translation of the detector in physical\n   * units (e.g. mm). The rotation axis is assumed to be (0,1,0).\n   */\n  void\n  AddProjection(const double sid,\n                const double sdd,\n                const double gantryAngle,\n                const double projOffsetX = 0.,\n                const double projOffsetY = 0.,\n                const double outOfPlaneAngle = 0.,\n                const double inPlaneAngle = 0.,\n                const double sourceOffsetX = 0.,\n                const double sourceOffsetY = 0.);\n\n  /** Idem with angles in radians. */\n  virtual void\n  AddProjectionInRadians(const double sid,\n                         const double sdd,\n                         const double gantryAngle,\n                         const double projOffsetX = 0.,\n                         const double projOffsetY = 0.,\n                         const double outOfPlaneAngle = 0.,\n                         const double inPlaneAngle = 0.,\n                         const double sourceOffsetX = 0.,\n                         const double sourceOffsetY = 0.);\n\n  /**\n   * @brief Add a REG23-based geometry set to the RTK projections list.\n   * @param sourcePosition absolute position of the point source S in WCS\n   * @param detectorPosition absolute position of the detector origin R in WCS\n   * @param detectorRowVector absolute direction vector indicating the\n   * orientation of the detector's rows r (sometimes referred to as v1)\n   * @param detectorColumnVector absolute direction vector indicating the\n   * orientation of the detector's columns c (sometimes referred to as v2)\n   * @return TRUE if the projection could be added to the RTK projections list\n   */\n  bool\n  AddProjection(const PointType &  sourcePosition,\n                const PointType &  detectorPosition,\n                const VectorType & detectorRowVector,\n                const VectorType & detectorColumnVector);\n\n\n  /** Add projection from a projection matrix. A projection matrix is defined\n   * up to a scaling factor. The function here Assumes that the input matrix\n   * pMat is normalized such that pMat*(x,y,z,1)'=(u,v,1)'.\n   * This code assumes that the SourceToDetectorDistance is positive.\n   * If the projection is for parallel geometry, then\n   * the SourceToIsocenterDistance is set to 1000 mm.\n   *\n   * \\note The projection matrix has a special form for a parallel geometry.\n   *\n   * | Column-1 | Column-2 | Column-3 |      Column-4      |\n   * |:--------:|:--------:|:--------:|:------------------:|\n   * | R11      | R12      | R13      | -ProjectionOffsetX |\n   * | R21      | R22      | R23      | -ProjectionOffsetY |\n   * |  0       |  0       |  0       |          1         |\n   *\n   * where\n   *\n   * | Column-1 | Column-2 | Column-3 |\n   * |:--------:|:--------:|:--------:|\n   * |    R11   |    R12   |   R13    |\n   * |    R21   |    R22   |   R23    |\n   * |     0    |     0    |    0     |\n   *\n   * is a cropped 3x3 rotation matrix.\n   *\n   * \\warning The outOfPlaneAngle for a parallel geometry must be\n   * within (-90, 90) degrees range, otherwise the rotation\n   * angles could be miscalculated.\n   *\n   */\n  bool\n  AddProjection(const HomogeneousProjectionMatrixType & pMat);\n\n  /** Empty the geometry object. */\n  void\n  Clear() override;\n\n  /** Get the vector of geometry parameters (one per projection). Angles are\n   * in radians.*/\n  const std::vector<double> &\n  GetGantryAngles() const\n  {\n    return this->m_GantryAngles;\n  }\n  const std::vector<double> &\n  GetOutOfPlaneAngles() const\n  {\n    return this->m_OutOfPlaneAngles;\n  }\n  const std::vector<double> &\n  GetInPlaneAngles() const\n  {\n    return this->m_InPlaneAngles;\n  }\n  const std::vector<double> &\n  GetSourceToIsocenterDistances() const\n  {\n    return this->m_SourceToIsocenterDistances;\n  }\n  const std::vector<double> &\n  GetSourceOffsetsX() const\n  {\n    return this->m_SourceOffsetsX;\n  }\n  const std::vector<double> &\n  GetSourceOffsetsY() const\n  {\n    return this->m_SourceOffsetsY;\n  }\n  const std::vector<double> &\n  GetSourceToDetectorDistances() const\n  {\n    return this->m_SourceToDetectorDistances;\n  }\n  const std::vector<double> &\n  GetProjectionOffsetsX() const\n  {\n    return this->m_ProjectionOffsetsX;\n  }\n  const std::vector<double> &\n  GetProjectionOffsetsY() const\n  {\n    return this->m_ProjectionOffsetsY;\n  }\n\n  /** Get a vector containing the source angles in radians. The source angle is\n   * defined as the angle between the z-axis and the isocenter-source line\n   * projected on the central plane. */\n  const std::vector<double> &\n  GetSourceAngles() const\n  {\n    return this->m_SourceAngles;\n  }\n\n  /** Get a vector containing the tilt angles in radians. The tilt angle is\n   * defined as the difference between -GantryAngle and the SourceAngle. */\n  const std::vector<double>\n  GetTiltAngles() const;\n\n  /** Get a multimap containing all sorted angles in radians and corresponding\n   * index. */\n  const std::multimap<double, unsigned int>\n  GetSortedAngles(const std::vector<double> & angles) const;\n\n  /** Get a map containing unique sorted angles in radians and corresponding\n   * index. */\n  const std::map<double, unsigned int>\n  GetUniqueSortedAngles(const std::vector<double> & angles) const;\n\n  /** Get for each projection the angular gaps with next projection in radians. */\n  const std::vector<double>\n  GetAngularGapsWithNext(const std::vector<double> & angles) const;\n\n  /** Get for each projection half the angular distance between the previous\n   *  and the next projection in radians. */\n  const std::vector<double>\n  GetAngularGaps(const std::vector<double> & angles);\n\n  /** Compute rotation matrix in homogeneous coordinates from 3 angles in\n   * degrees. The convention is the default in itk, i.e. ZXY of Euler angles.*/\n  static ThreeDHomogeneousMatrixType\n  ComputeRotationHomogeneousMatrix(double angleX, double angleY, double angleZ);\n\n  /** Compute translation matrix in homogeneous coordinates from translation parameters.*/\n  static TwoDHomogeneousMatrixType\n  ComputeTranslationHomogeneousMatrix(double transX, double transY);\n  static ThreeDHomogeneousMatrixType\n  ComputeTranslationHomogeneousMatrix(double transX, double transY, double transZ);\n\n  /** Compute the magnification matrix from 3D to 2D given a source to detector\n   * and to isocenter distance. */\n  static Superclass::MatrixType\n  ComputeProjectionMagnificationMatrix(double sdd, double sid);\n\n  /** Get the vector containing the sub matrices used to compute the main\n   * projection matrix. */\n  const std::vector<TwoDHomogeneousMatrixType> &\n  GetProjectionTranslationMatrices() const\n  {\n    return this->m_ProjectionTranslationMatrices;\n  }\n  TwoDHomogeneousMatrixType\n  GetProjectionTranslationMatrix(const unsigned int i) const\n  {\n    return this->m_ProjectionTranslationMatrices[i];\n  }\n\n  const std::vector<ThreeDHomogeneousMatrixType> &\n  GetRotationMatrices() const\n  {\n    return this->m_RotationMatrices;\n  }\n  ThreeDHomogeneousMatrixType\n  GetRotationMatrix(const unsigned int i) const\n  {\n    return this->m_RotationMatrices[i];\n  }\n\n  const std::vector<ThreeDHomogeneousMatrixType> &\n  GetSourceTranslationMatrices() const\n  {\n    return this->m_SourceTranslationMatrices;\n  }\n  ThreeDHomogeneousMatrixType\n  GetSourceTranslationMatrices(const unsigned int i) const\n  {\n    return this->m_SourceTranslationMatrices[i];\n  }\n\n  const std::vector<Superclass::MatrixType> &\n  GetMagnificationMatrices() const\n  {\n    return this->m_MagnificationMatrices;\n  }\n  Superclass::MatrixType\n  GetMagnificationMatrices(const unsigned int i) const\n  {\n    return this->m_MagnificationMatrices[i];\n  }\n\n  /** Get the vector containing the collimation jaw parameters. */\n  const std::vector<double> &\n  GetCollimationUInf() const\n  {\n    return this->m_CollimationUInf;\n  }\n  const std::vector<double> &\n  GetCollimationUSup() const\n  {\n    return this->m_CollimationUSup;\n  }\n  const std::vector<double> &\n  GetCollimationVInf() const\n  {\n    return this->m_CollimationVInf;\n  }\n  const std::vector<double> &\n  GetCollimationVSup() const\n  {\n    return this->m_CollimationVSup;\n  }\n\n  /** Set the collimation of the latest added projection (to be called after\n   * AddProjection). */\n  void\n  SetCollimationOfLastProjection(const double uinf, const double usup, const double vinf, const double vsup);\n\n  /** Get the source position for the ith projection in the fixed reference\n   * system and in homogeneous coordinates. */\n  const HomogeneousVectorType\n  GetSourcePosition(const unsigned int i) const;\n\n  /** Compute the ith matrix to convert projection coordinates to coordinates\n   * in the detector coordinate system (u,v,u^v). Note that the matrix is square but the\n   * third element of the projection coordinates is ignored because projection\n   * coordinates are 2D. This is meant to manipulate more easily stack of\n   * projection images. */\n  const ThreeDHomogeneousMatrixType\n  GetProjectionCoordinatesToDetectorSystemMatrix(const unsigned int i) const;\n\n  /** Compute the ith matrix to convert projection coordinates to coordinates\n   * in the fixed coordinate system. Note that the matrix is square but the\n   * third element of the projection coordinates is ignored because projection\n   * coordinates are 2D. This is meant to manipulate more easily stack of\n   * projection images. */\n  const ThreeDHomogeneousMatrixType\n  GetProjectionCoordinatesToFixedSystemMatrix(const unsigned int i) const;\n\n  /** This function wraps an angle value between 0 and 360 degrees. */\n  static double\n  ConvertAngleBetween0And360Degrees(const double a);\n\n  /** This function wraps an angle value between 0 and 2*PI radians. */\n  static double\n  ConvertAngleBetween0And2PIRadians(const double a);\n\n  /** This function wraps an angle value between -PI and PI radians. */\n  static double\n  ConvertAngleBetweenMinusAndPlusPIRadians(const double a);\n\n  /** Changes the coordinate on the projection image to the coordinate on a\n   * virtual detector that is perpendicular to the source to isocenter line and\n   * positioned at the isocenter.\n   * It is assumed that OutOfPlaneAngle=0 and InPlaneAngle=0.*/\n  double\n  ToUntiltedCoordinateAtIsocenter(const unsigned int noProj, const double tiltedCoord) const;\n\n  /** Accessor for the radius of curved detector. The default is 0 and it means\n   * a flat detector. */\n  itkGetConstMacro(RadiusCylindricalDetector, double);\n  itkSetMacro(RadiusCylindricalDetector, double);\n\n  /** Accessor for the internal tolerance on angles. */\n  itkGetConstMacro(VerifyAnglesTolerance, double);\n  itkSetMacro(VerifyAnglesTolerance, double);\n\n  itkGetConstMacro(FixAnglesTolerance, double);\n  itkSetMacro(FixAnglesTolerance, double);\n\nprotected:\n  ThreeDCircularProjectionGeometry();\n  ~ThreeDCircularProjectionGeometry() override = default;\n\n  virtual void\n  AddProjectionTranslationMatrix(const TwoDHomogeneousMatrixType & m)\n  {\n    this->m_ProjectionTranslationMatrices.push_back(m);\n    this->Modified();\n  }\n  virtual void\n  AddRotationMatrix(const ThreeDHomogeneousMatrixType & m)\n  {\n    this->m_RotationMatrices.push_back(m);\n    this->Modified();\n  }\n  virtual void\n  AddSourceTranslationMatrix(const ThreeDHomogeneousMatrixType & m)\n  {\n    this->m_SourceTranslationMatrices.push_back(m);\n    this->Modified();\n  }\n  virtual void\n  AddMagnificationMatrix(const Superclass::MatrixType & m)\n  {\n    this->m_MagnificationMatrices.push_back(m);\n    this->Modified();\n  }\n\n  /** Verify that the specified Euler angles in ZXY result in a rotation matrix\n   * which corresponds to the specified detector orientation. Rationale for this\n   * utility method is that in some situations numerical instabilities (e.g. if\n   * gantry=+90deg,in-plane=-90deg or vice versa, \"invalid\" angles may be\n   * computed using the standard ITK Euler transform) may occur.\n   * @param outOfPlaneAngleRAD out-of-plane angle of the detector in radians\n   * @param gantryAngleRAD gantry angle of the detector in radians\n   * @param inPlaneAngleRAD in-plane angle of the detector in radians\n   * @param referenceMatrix reference matrix which reflects detector orientation\n   * in WCS\n   * @return TRUE if the angles correspond the implicitly specified final\n   * rotation matrix; if FALSE is returned, the angles should be fixed\n   * (@see FixAngles())\n   * @warning {Internally, the matrix check is performed with a tolerance level\n   * of 1e-6!}\n   */\n  bool\n  VerifyAngles(const double          outOfPlaneAngleRAD,\n               const double          gantryAngleRAD,\n               const double          inPlaneAngleRAD,\n               const Matrix3x3Type & referenceMatrix) const;\n\n  /** Try to fix Euler angles, which were found incorrect, to match the specified\n   * reference matrix.\n   * @param [out] outOfPlaneAngleRAD out-of-plane angle of the detector in radians;\n   * if this method returns TRUE, this angle can be safely considered\n   * @param [out] gantryAngleRAD gantry angle of the detector in radians;\n   * if this method returns TRUE, this angle can be safely considered\n   * @param [out] inPlaneAngleRAD in-plane angle of the detector in radians;\n   * if this method returns TRUE, this angle can be safely considered\n   * @param referenceMatrix reference matrix which reflects detector orientation\n   * in WCS\n   * @return TRUE if the angles were fixed and can be safely considered;\n   * if FALSE is returned, the method could not find angles which generate the\n   * desired matrix with respect to ZXY Euler order and the internal tolerance\n   * level\n   * @see VerifyAngles()\n   * @warning {Internally, the matrix check is performed with a tolerance level\n   * of 1e-6!}\n   */\n  bool\n  FixAngles(double &              outOfPlaneAngleRAD,\n            double &              gantryAngleRAD,\n            double &              inPlaneAngleRAD,\n            const Matrix3x3Type & referenceMatrix) const;\n\n  /** Clone the geometry object in a new one. */\n  itk::LightObject::Pointer\n  InternalClone() const override;\n\n  /** Circular geometry parameters per projection (angles in degrees between 0\n    and 360). */\n  std::vector<double> m_GantryAngles;\n  std::vector<double> m_OutOfPlaneAngles;\n  std::vector<double> m_InPlaneAngles;\n  std::vector<double> m_SourceAngles;\n  std::vector<double> m_SourceToIsocenterDistances;\n  std::vector<double> m_SourceOffsetsX;\n  std::vector<double> m_SourceOffsetsY;\n  std::vector<double> m_SourceToDetectorDistances;\n  std::vector<double> m_ProjectionOffsetsX;\n  std::vector<double> m_ProjectionOffsetsY;\n\n  /** Radius of curved detector. The default is 0 and it means a flat detector. */\n  double m_RadiusCylindricalDetector{ 0. };\n\n  /** Parameters of the collimation jaws.\n   * The collimation position is with respect to the distance of the m_RotationCenter along\n   * - the m_RotationAxis for the m_CollimationVInf and m_CollimationVSup,\n   * - the m_SourceCenter ^ m_RotationAxis for the m_CollimationUInf and m_CollimationUSup.\n   * The default is +infinity (itk::NumericTraits<double>::max) is completely\n   * opened, negative values are allowed if the collimation travels beyond the m_RotationCenter.\n   */\n  std::vector<double> m_CollimationUInf;\n  std::vector<double> m_CollimationUSup;\n  std::vector<double> m_CollimationVInf;\n  std::vector<double> m_CollimationVSup;\n\n  /** Matrices to change coordiate systems. */\n  std::vector<TwoDHomogeneousMatrixType>   m_ProjectionTranslationMatrices;\n  std::vector<Superclass::MatrixType>      m_MagnificationMatrices;\n  std::vector<ThreeDHomogeneousMatrixType> m_RotationMatrices;\n  std::vector<ThreeDHomogeneousMatrixType> m_SourceTranslationMatrices;\n\n  /** Internal tolerance parameters. */\n  double m_VerifyAnglesTolerance{ 1e-4 };\n  double m_FixAnglesTolerance{ 1e-6 };\n};\n} // namespace rtk\n\n\n#endif // __rtkThreeDCircularProjectionGeometry_h\n"
  },
  {
    "path": "include/rtkThreeDCircularProjectionGeometryXMLFile.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkThreeDCircularProjectionGeometryXMLFile_h\n#define rtkThreeDCircularProjectionGeometryXMLFile_h\n\n\n// This file is kept for backward compability but thre reader and the writer\n// are now plit in two separate files.\n#include \"rtkThreeDCircularProjectionGeometryXMLFileReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFileWriter.h\"\n\n#endif\n"
  },
  {
    "path": "include/rtkThreeDCircularProjectionGeometryXMLFileReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkThreeDCircularProjectionGeometryXMLFileReader_h\n#define rtkThreeDCircularProjectionGeometryXMLFileReader_h\n\n#ifdef _MSC_VER\n#  pragma warning(disable : 4786)\n#endif\n\n#include <itkXMLFile.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class ThreeDCircularProjectionGeometryXMLFileReader\n *\n * Reads an XML-format file containing geometry for reconstruction\n *\n * \\test rtkgeometryfiletest.cxx, rtkvariantest.cxx, rtkxradtest.cxx,\n * rtkdigisenstest.cxx, rtkelektatest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT ThreeDCircularProjectionGeometryXMLFileReader : public itk::XMLReader<ThreeDCircularProjectionGeometry>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ThreeDCircularProjectionGeometryXMLFileReader);\n\n  /** Standard type alias */\n  using Self = ThreeDCircularProjectionGeometryXMLFileReader;\n  using Superclass = itk::XMLReader<ThreeDCircularProjectionGeometry>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using GeometryPointer = GeometryType::Pointer;\n\n  /** Latest version */\n  static const unsigned int CurrentVersion = 3;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ThreeDCircularProjectionGeometryXMLFileReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Determine if a file can be read */\n  int\n  CanReadFile(const char * name) override;\n\n  /** Get smart pointer to projection geometry. */\n  itkGetModifiableObjectMacro(Geometry, GeometryType);\n\nprotected:\n  ThreeDCircularProjectionGeometryXMLFileReader();\n  ~ThreeDCircularProjectionGeometryXMLFileReader() override = default;\n\n  /** Callback function -- called from XML parser with start-of-element\n   * information.\n   */\n  void\n  StartElement(const char * name, const char ** atts) override;\n\n  void\n  StartElement(const char * name);\n\n  void\n  EndElement(const char * name) override;\n\n  void\n  CharacterDataHandler(const char * inData, int inLength) override;\n\nprivate:\n  GeometryPointer m_Geometry{ GeometryType::New() };\n\n  std::string m_CurCharacterData{ \"\" };\n\n  /** Projection parameters */\n  double m_InPlaneAngle{ 0. };\n  double m_OutOfPlaneAngle{ 0. };\n  double m_GantryAngle{ 0. };\n  double m_SourceToIsocenterDistance{ 0. };\n  double m_SourceOffsetX{ 0. };\n  double m_SourceOffsetY{ 0. };\n  double m_SourceToDetectorDistance{ 0. };\n  double m_ProjectionOffsetX{ 0. };\n  double m_ProjectionOffsetY{ 0. };\n  double m_CollimationUInf{ std::numeric_limits<double>::max() };\n  double m_CollimationUSup{ std::numeric_limits<double>::max() };\n  double m_CollimationVInf{ std::numeric_limits<double>::max() };\n  double m_CollimationVSup{ std::numeric_limits<double>::max() };\n\n  /** Projection matrix */\n  ThreeDCircularProjectionGeometry::MatrixType m_Matrix;\n\n  /** File format version */\n  unsigned int m_Version{ 0 };\n};\n\n/** Convenience function for reading a geometry XML file.\n *\n * The function reads the geometry from the specified XML file, and returns the\n * geometry that it has read.\n * */\nRTK_EXPORT ThreeDCircularProjectionGeometry::Pointer\n           ReadGeometry(const std::string & filename);\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkThreeDCircularProjectionGeometryXMLFileWriter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkThreeDCircularProjectionGeometryXMLFileWriter_h\n#define rtkThreeDCircularProjectionGeometryXMLFileWriter_h\n\n#ifdef _MSC_VER\n#  pragma warning(disable : 4786)\n#endif\n\n#include \"RTKExport.h\"\n#include <itkXMLFile.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class ThreeDCircularProjectionGeometryXMLFileWriter\n *\n * Writes an XML-format file containing geometry for reconstruction\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT ThreeDCircularProjectionGeometryXMLFileWriter\n  : public itk::XMLWriterBase<ThreeDCircularProjectionGeometry>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(ThreeDCircularProjectionGeometryXMLFileWriter);\n\n  /** standard type alias */\n  using Superclass = itk::XMLWriterBase<ThreeDCircularProjectionGeometry>;\n  using Self = ThreeDCircularProjectionGeometryXMLFileWriter;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ThreeDCircularProjectionGeometryXMLFileWriter);\n\n  /** Test whether a file is writable. */\n  int\n  CanWriteFile(const char * name) override;\n\n  /** Actually write out the file in question */\n  int\n  WriteFile() override;\n\nprotected:\n  ThreeDCircularProjectionGeometryXMLFileWriter() = default;\n  ~ThreeDCircularProjectionGeometryXMLFileWriter() override = default;\n\n  /** If all values are equal in v, write first value (if not 0.) in\n      output file with parameter value s and return true. Return false\n      otherwise.\n   */\n  bool\n  WriteGlobalParameter(std::ofstream &             output,\n                       const std::string &         indent,\n                       const std::vector<double> & v,\n                       const std::string &         s,\n                       bool                        convertToDegrees = false,\n                       double                      defval = 0.);\n\n  /** Write projection specific parameter with name s. */\n  void\n  WriteLocalParameter(std::ofstream & output, const std::string & indent, const double & v, const std::string & s);\n};\n\n/** Convenience function for writing an geometry.\n *\n * The geometry parameter may be a either SmartPointer or a raw pointer and const or non-const.\n * */\ntemplate <typename TGeometryPointer>\nITK_TEMPLATE_EXPORT void\nWriteGeometry(TGeometryPointer && geometry, const std::string & filename)\n{\n  using NonReferenceImagePointer = std::remove_reference_t<TGeometryPointer>;\n  static_assert(std::is_pointer<NonReferenceImagePointer>::value ||\n                  itk::mpl::IsSmartPointer<NonReferenceImagePointer>::Value,\n                \"WriteGeometry requires a raw pointer or SmartPointer.\");\n\n  auto writer = ThreeDCircularProjectionGeometryXMLFileWriter::New();\n  writer->SetObject(geometry);\n  writer->SetFilename(filename);\n  writer->WriteFile();\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkTotalNuclearVariationDenoisingBPDQImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTotalNuclearVariationDenoisingBPDQImageFilter_h\n#define rtkTotalNuclearVariationDenoisingBPDQImageFilter_h\n\n#include \"rtkSingularValueThresholdImageFilter.h\"\n#include \"rtkDenoisingBPDQImageFilter.h\"\n\nnamespace rtk\n{\n/** \\class TotalNuclearVariationDenoisingBPDQImageFilter\n * \\brief Performs total nuclear variation denoising\n *\n * This filter implements \"Joint reconstruction of multi-channel, spectral CT data\n * via constrained total nuclear variation minimization\", by Rigie & LaRiviere, in\n * Physics in Medicine and Biology 2015.\n *\n * It uses basis pursuit dequantization, and is (mathematically) only a generalization\n * of the TotalVariationDenoisingBPDQImageFilter to process multiple channel images.\n * It outputs a multiple channel image close to the input one, for which the spatial\n * gradient of each channel is sparser, and the gradient vectors are more similar (ie. colinear) across channels,\n * than in the input.\n *\n * The order of the channels is not taken into account, which makes this regularization\n * more suitable when the channels describe materials (i.e. in spectral CT) or\n * colors (i.e. in RGB images) than when they describe time frames (i.e. in dynamic CT).\n *\n * \\dot\n * digraph TotalNuclearVariationDenoisingBPDQImageFilter\n * {\n *\n * subgraph clusterFirstIteration\n *   {\n *   label=\"First iteration\"\n *\n *   FI_Input [label=\"Input\"];\n *   FI_Input [shape=Mdiamond];\n *\n *   node [shape=box];\n *   FI_Multiply [ label=\"itk::MultiplyImageFilter (by beta)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n *   FI_Gradient [ label=\"rtk::ForwardDifferenceGradientImageFilter\"\n *                 URL=\"\\ref rtk::ForwardDifferenceGradientImageFilter\"];\n *   FI_SingularValueThreshold [ label=\"rtk::SingularValueThresholdImageFilter\"\n *                               URL=\"\\ref rtk::SingularValueThresholdImageFilter\"];\n *   FI_OutOfSingularValueThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n *   FI_Input -> FI_Multiply;\n *   FI_Multiply -> FI_Gradient;\n *   FI_Gradient -> FI_SingularValueThreshold;\n *   FI_SingularValueThreshold -> FI_OutOfSingularValueThreshold [style=dashed];\n *   }\n *\n * subgraph clusterAfterFirstIteration\n *   {\n *   label=\"After first iteration\"\n *\n *   Input [label=\"Input\"];\n *   Input [shape=Mdiamond];\n *   Output [label=\"Output\"];\n *   Output [shape=Mdiamond];\n *\n *   node [shape=box];\n *   Divergence [ label=\"rtk::BackwardDifferenceDivergenceImageFilter\"\n *                URL=\"\\ref rtk::BackwardDifferenceDivergenceImageFilter\"];\n *   Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n *   Multiply [ label=\"itk::MultiplyImageFilter (by beta)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n *   Gradient [ label=\"rtk::ForwardDifferenceGradientImageFilter\" URL=\"\\ref rtk::ForwardDifferenceGradientImageFilter\"];\n *   SubtractGradient [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n *   SingularValueThreshold [ label=\"rtk::SingularValueThresholdImageFilter\"\n *                            URL=\"\\ref rtk::SingularValueThresholdImageFilter\"];\n *   OutOfSubtract [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *   OutOfSingularValueThreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *   BeforeDivergence [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n *   Input -> Subtract;\n *   Divergence -> Subtract;\n *   Subtract -> OutOfSubtract;\n *   OutOfSubtract -> Output;\n *   OutOfSubtract -> Multiply;\n *   Multiply -> Gradient;\n *   Gradient -> SubtractGradient;\n *   SubtractGradient -> SingularValueThreshold;\n *   SingularValueThreshold -> OutOfSingularValueThreshold;\n *   OutOfSingularValueThreshold -> BeforeDivergence [style=dashed, constraint=false];\n *   BeforeDivergence -> Divergence;\n *   BeforeDivergence -> SubtractGradient;\n *   }\n *\n * }\n * \\enddot\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK IntensityImageFilters\n */\n\ntemplate <typename TOutputImage,\n          typename TGradientImage =\n            itk::Image<itk::CovariantVector<typename TOutputImage::ValueType, TOutputImage::ImageDimension - 1>,\n                       TOutputImage::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT TotalNuclearVariationDenoisingBPDQImageFilter\n  : public rtk::DenoisingBPDQImageFilter<TOutputImage, TGradientImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(TotalNuclearVariationDenoisingBPDQImageFilter);\n\n  /** Standard class type alias. */\n  using Self = TotalNuclearVariationDenoisingBPDQImageFilter;\n  using Superclass = rtk::DenoisingBPDQImageFilter<TOutputImage, TGradientImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(TotalNuclearVariationDenoisingBPDQImageFilter);\n\n  /** Sub filter type definitions */\n  using SingularValueThresholdFilterType = SingularValueThresholdImageFilter<TGradientImage>;\n\nprotected:\n  TotalNuclearVariationDenoisingBPDQImageFilter();\n  ~TotalNuclearVariationDenoisingBPDQImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  /** Sub filter pointers */\n  typename SingularValueThresholdFilterType::Pointer m_ThresholdFilter;\n  typename Superclass::ThresholdFilterType *\n  GetThresholdFilter() override\n  {\n    return dynamic_cast<typename Superclass::ThresholdFilterType *>(this->m_ThresholdFilter.GetPointer());\n  }\n};\n\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkTotalNuclearVariationDenoisingBPDQImageFilter.hxx\"\n#endif\n\n#endif //__rtkTotalNuclearVariationDenoisingBPDQImageFilter__\n"
  },
  {
    "path": "include/rtkTotalNuclearVariationDenoisingBPDQImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTotalNuclearVariationDenoisingBPDQImageFilter_hxx\n#define rtkTotalNuclearVariationDenoisingBPDQImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage, typename TGradientImage>\nTotalNuclearVariationDenoisingBPDQImageFilter<TOutputImage,\n                                              TGradientImage>::TotalNuclearVariationDenoisingBPDQImageFilter()\n{\n  // Default behaviour is to process all spatial dimensions, i.e. all but the last one, which contains channels\n  for (unsigned int dim = 0; dim < TOutputImage::ImageDimension - 1; dim++)\n  {\n    this->m_DimensionsProcessed[dim] = true;\n  }\n  this->m_DimensionsProcessed[TOutputImage::ImageDimension - 1] = false;\n\n  // Create the SingularValueThresholdFilter to replace the generic filter\n  // used in the base class\n  this->m_ThresholdFilter = SingularValueThresholdFilterType::New();\n}\n\ntemplate <typename TOutputImage, typename TGradientImage>\nvoid\nTotalNuclearVariationDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::GenerateOutputInformation()\n{\n  Superclass::GenerateOutputInformation();\n\n  this->m_ThresholdFilter->SetThreshold(this->m_Gamma);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkTotalVariationDenoiseSequenceImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTotalVariationDenoiseSequenceImageFilter_h\n#define rtkTotalVariationDenoiseSequenceImageFilter_h\n\n#include \"rtkConstantImageSource.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkPasteImageFilter.h>\n#include <itkCastImageFilter.h>\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaTotalVariationDenoisingBPDQImageFilter.h\"\n#else\n#  include \"rtkTotalVariationDenoisingBPDQImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class TotalVariationDenoiseSequenceImageFilter\n * \\brief Applies 3D total variation denoising to a 3D + time sequence of images\n *\n * Most of the work in this filter is performed by the underlying rtkTotalVariationDenoisingBPDQImageFilter\n * or its CUDA version\n *\n * \\dot\n * digraph TotalVariationDenoiseSequenceImageFilter {\n *\n * Input0 [ label=\"Input 0 (Sequence of images)\"];\n * Input0 [shape=Mdiamond];\n * Output [label=\"Output (Sequence of images)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * Extract [label=\"itk::ExtractImageFilter (for images)\" URL=\"\\ref itk::ExtractImageFilter\"];\n * TVDenoising [ label=\"rtk::TotalVariationDenoisingBPDQImageFilter\"\n *               URL=\"\\ref rtk::TotalVariationDenoisingBPDQImageFilter\"];\n * Cast [ label=\"itk::CastImageFilter\" URL=\"\\ref itk::CastImageFilter\"];\n * Paste [ label=\"itk::PasteImageFilter\" URL=\"\\ref itk::PasteImageFilter\"];\n * ConstantSource [ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * BeforePaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterPaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * Input0 -> Extract;\n * Extract -> TVDenoising;\n * TVDenoising -> Cast;\n * Cast -> BeforePaste [arrowhead=none];\n * BeforePaste -> Paste;\n * Paste -> AfterPaste [arrowhead=none];\n * AfterPaste -> BeforePaste [style=dashed];\n * AfterPaste -> Output [style=dashed];\n * }\n * \\enddot\n *\n * \\test rtkfourdroostertest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TImageSequence>\nclass ITK_TEMPLATE_EXPORT TotalVariationDenoiseSequenceImageFilter\n  : public itk::ImageToImageFilter<TImageSequence, TImageSequence>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(TotalVariationDenoiseSequenceImageFilter);\n\n  /** Standard class type alias. */\n  using Self = TotalVariationDenoiseSequenceImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImageSequence, TImageSequence>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(TotalVariationDenoiseSequenceImageFilter);\n\n  /** Set/Get for the TotalVariationDenoisingBPDQImageFilter */\n  itkGetMacro(Gamma, double);\n  itkSetMacro(Gamma, double);\n\n  itkGetMacro(NumberOfIterations, int);\n  itkSetMacro(NumberOfIterations, int);\n\n  void\n  SetDimensionsProcessed(bool * arg);\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUImageSequenceType = typename itk::Image<typename TImageSequence::PixelType, TImageSequence::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using ImageType =\n    typename std::conditional_t<std::is_same_v<TImageSequence, CPUImageSequenceType>,\n                                itk::Image<typename TImageSequence::PixelType, TImageSequence::ImageDimension - 1>,\n                                itk::CudaImage<typename TImageSequence::PixelType, TImageSequence::ImageDimension - 1>>;\n  using TVDenoisingFilterType = typename std::conditional_t<std::is_same_v<TImageSequence, CPUImageSequenceType>,\n                                                            TotalVariationDenoisingBPDQImageFilter<ImageType>,\n                                                            CudaTotalVariationDenoisingBPDQImageFilter>;\n#else\n  using ImageType = itk::Image<typename TImageSequence::PixelType, TImageSequence::ImageDimension - 1>;\n  using TVDenoisingFilterType = rtk::TotalVariationDenoisingBPDQImageFilter<ImageType>;\n#endif\n  using ExtractFilterType = itk::ExtractImageFilter<TImageSequence, ImageType>;\n  using PasteFilterType = itk::PasteImageFilter<TImageSequence, TImageSequence>;\n  using CastFilterType = itk::CastImageFilter<ImageType, TImageSequence>;\n  using ConstantImageSourceType = rtk::ConstantImageSource<TImageSequence>;\n\nprotected:\n  TotalVariationDenoiseSequenceImageFilter();\n  ~TotalVariationDenoiseSequenceImageFilter() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename TVDenoisingFilterType::Pointer   m_TVDenoisingFilter;\n  typename ExtractFilterType::Pointer       m_ExtractFilter;\n  typename PasteFilterType::Pointer         m_PasteFilter;\n  typename CastFilterType::Pointer          m_CastFilter;\n  typename ConstantImageSourceType::Pointer m_ConstantSource;\n\n  /** Extraction regions for both extract filters */\n  typename TImageSequence::RegionType m_ExtractAndPasteRegion;\n\n  /** Information for the total variation denoising filter */\n  double m_Gamma{ 1. };\n  int    m_NumberOfIterations{ 1 };\n  bool   m_DimensionsProcessed[ImageType::ImageDimension];\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkTotalVariationDenoiseSequenceImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkTotalVariationDenoiseSequenceImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTotalVariationDenoiseSequenceImageFilter_hxx\n#define rtkTotalVariationDenoiseSequenceImageFilter_hxx\n\n#include <itkImageFileWriter.h>\n\nnamespace rtk\n{\n\ntemplate <typename TImageSequence>\nTotalVariationDenoiseSequenceImageFilter<TImageSequence>::TotalVariationDenoiseSequenceImageFilter()\n{\n  // Create the filters\n  m_TVDenoisingFilter = TVDenoisingFilterType::New();\n  m_ExtractFilter = ExtractFilterType::New();\n  m_PasteFilter = PasteFilterType::New();\n  m_CastFilter = CastFilterType::New();\n  m_ConstantSource = ConstantImageSourceType::New();\n\n  // Set permanent connections\n  m_TVDenoisingFilter->SetInput(m_ExtractFilter->GetOutput());\n  m_CastFilter->SetInput(m_TVDenoisingFilter->GetOutput());\n  m_PasteFilter->SetSourceImage(m_CastFilter->GetOutput());\n\n  // Set default behavior to spatial regularization\n  for (unsigned int dim = 0; dim < TImageSequence::ImageDimension - 1; dim++)\n    m_DimensionsProcessed[dim] = true;\n\n  // Set permanent parameters\n  m_ExtractFilter->SetDirectionCollapseToIdentity();\n\n  // Set memory management parameters\n  m_CastFilter->SetInPlace(false);\n}\n\ntemplate <typename TImageSequence>\nvoid\nTotalVariationDenoiseSequenceImageFilter<TImageSequence>::GenerateOutputInformation()\n{\n  int Dimension = TImageSequence::ImageDimension;\n\n  // Set runtime connections\n  m_ExtractFilter->SetInput(this->GetInput());\n\n  // Initialize the source\n  m_ConstantSource->SetInformationFromImage(this->GetInput());\n  m_ConstantSource->Update();\n  m_PasteFilter->SetDestinationImage(m_ConstantSource->GetOutput());\n\n  // Set runtime parameters\n  m_TVDenoisingFilter->SetGamma(m_Gamma);\n  m_TVDenoisingFilter->SetDimensionsProcessed(m_DimensionsProcessed);\n  m_TVDenoisingFilter->SetNumberOfIterations(m_NumberOfIterations);\n\n  // Set extraction regions and indices\n  m_ExtractAndPasteRegion = this->GetInput()->GetLargestPossibleRegion();\n  m_ExtractAndPasteRegion.SetSize(Dimension - 1, 0);\n  m_ExtractAndPasteRegion.SetIndex(Dimension - 1, 0);\n\n  m_ExtractFilter->SetExtractionRegion(m_ExtractAndPasteRegion);\n  m_ExtractFilter->UpdateOutputInformation();\n  m_CastFilter->UpdateOutputInformation();\n\n  m_PasteFilter->SetSourceRegion(m_CastFilter->GetOutput()->GetLargestPossibleRegion());\n  m_PasteFilter->SetDestinationIndex(m_ExtractAndPasteRegion.GetIndex());\n\n  // Have the last filter calculate its output information\n  m_PasteFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_PasteFilter->GetOutput());\n}\n\n\ntemplate <typename TImageSequence>\nvoid\nTotalVariationDenoiseSequenceImageFilter<TImageSequence>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get pointers to the input and output\n  typename TImageSequence::Pointer inputPtr = const_cast<TImageSequence *>(this->GetInput());\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename TImageSequence>\nvoid\nTotalVariationDenoiseSequenceImageFilter<TImageSequence>::SetDimensionsProcessed(bool * arg)\n{\n  bool bModif = false;\n  for (unsigned int dim = 0; dim < ImageType::ImageDimension; dim++)\n  {\n    if (m_DimensionsProcessed[dim] != arg[dim])\n    {\n      m_DimensionsProcessed[dim] = arg[dim];\n      bModif = true;\n    }\n  }\n  if (bModif)\n    this->Modified();\n}\n\ntemplate <typename TImageSequence>\nvoid\nTotalVariationDenoiseSequenceImageFilter<TImageSequence>::GenerateData()\n{\n  int Dimension = TImageSequence::ImageDimension;\n\n  // Declare an image pointer to disconnect the output of paste\n  typename TImageSequence::Pointer pimg;\n\n  for (unsigned int frame = 0; frame < this->GetInput(0)->GetLargestPossibleRegion().GetSize(Dimension - 1); frame++)\n  {\n    if (frame > 0) // After the first frame, use the output of paste as input\n    {\n      pimg = m_PasteFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      m_PasteFilter->SetDestinationImage(pimg);\n    }\n\n    m_ExtractAndPasteRegion.SetIndex(Dimension - 1, frame);\n\n    m_ExtractFilter->SetExtractionRegion(m_ExtractAndPasteRegion);\n    m_ExtractFilter->UpdateLargestPossibleRegion();\n\n    m_TVDenoisingFilter->Update();\n\n    m_CastFilter->Update();\n\n    m_PasteFilter->SetSourceRegion(m_CastFilter->GetOutput()->GetLargestPossibleRegion());\n    m_PasteFilter->SetDestinationIndex(m_ExtractAndPasteRegion.GetIndex());\n\n    m_PasteFilter->UpdateLargestPossibleRegion();\n  }\n  this->GraftOutput(m_PasteFilter->GetOutput());\n\n  m_ExtractFilter->GetOutput()->ReleaseData();\n  m_TVDenoisingFilter->GetOutput()->ReleaseData();\n  m_CastFilter->GetOutput()->ReleaseData();\n}\n\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkTotalVariationDenoisingBPDQImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTotalVariationDenoisingBPDQImageFilter_h\n#define rtkTotalVariationDenoisingBPDQImageFilter_h\n\n#include \"rtkDenoisingBPDQImageFilter.h\"\n#include \"rtkMagnitudeThresholdImageFilter.h\"\n\n#include <itkPeriodicBoundaryCondition.h>\n\nnamespace rtk\n{\n/** \\class TotalVariationDenoisingBPDQImageFilter\n * \\brief Applies a total variation denoising, only alm_SingularValueThresholdFilterong the dimensions specified, on an\n * image.\n *\n * This filter finds the minimum of || f - f_0 ||_2^2 + gamma * TV(f)\n * using basis pursuit dequantization, where f is the current image, f_0 the\n * input image, and TV the total variation calculated with only the gradients\n * along the dimensions specified. This filter can be used, for example, to\n * perform 3D total variation denoising on a 4D dataset\n * (by calling SetDimensionsProcessed([true true true false]).\n * More information on the algorithm can be found at\n * https://wiki.epfl.ch/bpdq#download\n *\n * \\dot\n * digraph TotalVariationDenoisingBPDQImageFilter\n * {\n *\n * subgraph clusterFirstIteration\n *   {\n *   label=\"First iteration\"\n *\n *   FI_Input [label=\"Input\"];\n *   FI_Input [shape=Mdiamond];\n *\n *   node [shape=box];\n *   FI_Multiply [ label=\"itk::MultiplyImageFilter (by beta)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n *   FI_Gradient [ label=\"rtk::ForwardDifferenceGradientImageFilter\"\n *                 URL=\"\\ref rtk::ForwardDifferenceGradientImageFilter\"];\n *   FI_MagnitudeThreshold [ label=\"rtk::MagnitudeThresholdImageFilter\" URL=\"\\ref rtk::MagnitudeThresholdImageFilter\"];\n *   FI_OutOfMagnitudeTreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n *   FI_Input -> FI_Multiply;\n *   FI_Multiply -> FI_Gradient;\n *   FI_Gradient -> FI_MagnitudeThreshold;\n *   FI_MagnitudeThreshold -> FI_OutOfMagnitudeTreshold [style=dashed];\n *   }\n *\n * subgraph clusterAfterFirstIteration\n *   {\n *   label=\"After first iteration\"\n *\n *   Input [label=\"Input\"];\n *   Input [shape=Mdiamond];\n *   Output [label=\"Output\"];\n *   Output [shape=Mdiamond];\n *\n *   node [shape=box];\n *   Divergence [ label=\"rtk::BackwardDifferenceDivergenceImageFilter\"\n *                URL=\"\\ref rtk::BackwardDifferenceDivergenceImageFilter\"];\n *   Subtract [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n *   Multiply [ label=\"itk::MultiplyImageFilter (by beta)\" URL=\"\\ref itk::MultiplyImageFilter\"];\n *   Gradient [ label=\"rtk::ForwardDifferenceGradientImageFilter\" URL=\"\\ref rtk::ForwardDifferenceGradientImageFilter\"];\n *   SubtractGradient [ label=\"itk::SubtractImageFilter\" URL=\"\\ref itk::SubtractImageFilter\"];\n *   MagnitudeThreshold [ label=\"rtk::MagnitudeThresholdImageFilter\" URL=\"\\ref rtk::MagnitudeThresholdImageFilter\"];\n *   OutOfSubtract [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *   OutOfMagnitudeTreshold [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *   BeforeDivergence [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n *   Input -> Subtract;\n *   Divergence -> Subtract;\n *   Subtract -> OutOfSubtract;\n *   OutOfSubtract -> Output;\n *   OutOfSubtract -> Multiply;\n *   Multiply -> Gradient;\n *   Gradient -> SubtractGradient;\n *   SubtractGradient -> MagnitudeThreshold;\n *   MagnitudeThreshold -> OutOfMagnitudeTreshold;\n *   OutOfMagnitudeTreshold -> BeforeDivergence [style=dashed, constraint=false];\n *   BeforeDivergence -> Divergence;\n *   BeforeDivergence -> SubtractGradient;\n *   }\n *\n * }\n * \\enddot\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK IntensityImageFilters\n */\n\ntemplate <typename TOutputImage,\n          typename TGradientImage =\n            itk::Image<itk::CovariantVector<typename TOutputImage::ValueType, TOutputImage::ImageDimension>,\n                       TOutputImage::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT TotalVariationDenoisingBPDQImageFilter\n  : public rtk::DenoisingBPDQImageFilter<TOutputImage, TGradientImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(TotalVariationDenoisingBPDQImageFilter);\n\n  /** Standard class type alias. */\n  using Self = TotalVariationDenoisingBPDQImageFilter;\n  using Superclass = rtk::DenoisingBPDQImageFilter<TOutputImage, TGradientImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(TotalVariationDenoisingBPDQImageFilter);\n\n  /** Sub filter type definitions */\n  using MagnitudeThresholdFilterType =\n    MagnitudeThresholdImageFilter<TGradientImage, typename TOutputImage::ValueType, TGradientImage>;\n\n  void\n  SetDimensionsProcessed(bool * arg);\n\n  /** In some cases, regularization must use periodic boundary condition */\n  void\n  SetBoundaryConditionToPeriodic();\n\nprotected:\n  TotalVariationDenoisingBPDQImageFilter();\n  ~TotalVariationDenoisingBPDQImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n\n  /** Sub filter pointers */\n  typename MagnitudeThresholdFilterType::Pointer m_ThresholdFilter;\n  typename Superclass::ThresholdFilterType *\n  GetThresholdFilter() override\n  {\n    return dynamic_cast<typename Superclass::ThresholdFilterType *>(this->m_ThresholdFilter.GetPointer());\n  }\n};\n\n} // namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkTotalVariationDenoisingBPDQImageFilter.hxx\"\n#endif\n\n#endif //__rtkTotalVariationDenoisingBPDQImageFilter__\n"
  },
  {
    "path": "include/rtkTotalVariationDenoisingBPDQImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTotalVariationDenoisingBPDQImageFilter_hxx\n#define rtkTotalVariationDenoisingBPDQImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TOutputImage, typename TGradientImage>\nTotalVariationDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::TotalVariationDenoisingBPDQImageFilter()\n{\n  // Default behaviour is to process all dimensions\n  for (unsigned int dim = 0; dim < TOutputImage::ImageDimension; dim++)\n  {\n    this->m_DimensionsProcessed[dim] = true;\n  }\n\n  // Create the sub filters\n  m_ThresholdFilter = MagnitudeThresholdFilterType::New();\n}\n\ntemplate <typename TOutputImage, typename TGradientImage>\nvoid\nTotalVariationDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::SetDimensionsProcessed(bool * arg)\n{\n  bool bModif = false;\n  for (unsigned int dim = 0; dim < TOutputImage::ImageDimension; dim++)\n  {\n    if (this->m_DimensionsProcessed[dim] != arg[dim])\n    {\n      this->m_DimensionsProcessed[dim] = arg[dim];\n      bModif = true;\n    }\n  }\n  if (bModif)\n    this->Modified();\n}\n\ntemplate <typename TOutputImage, typename TGradientImage>\nvoid\nTotalVariationDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::SetBoundaryConditionToPeriodic()\n{\n  this->m_GradientFilter->OverrideBoundaryCondition(new itk::PeriodicBoundaryCondition<TOutputImage>());\n  this->m_DivergenceFilter->OverrideBoundaryCondition(new itk::PeriodicBoundaryCondition<TGradientImage>());\n}\n\ntemplate <typename TOutputImage, typename TGradientImage>\nvoid\nTotalVariationDenoisingBPDQImageFilter<TOutputImage, TGradientImage>::GenerateOutputInformation()\n{\n  Superclass::GenerateOutputInformation();\n\n  this->m_ThresholdFilter->SetThreshold(this->m_Gamma);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkTotalVariationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTotalVariationImageFilter_h\n#define rtkTotalVariationImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkNumericTraits.h>\n#include <itkArray.h>\n#include <itkSimpleDataObjectDecorator.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n/** \\class TotalVariationImageFilter\n * \\brief Compute the total variation of an Image.\n *\n * TotalVariationImageFilter computes the total variation, defined\n * as the L1 norm of the image of the L2 norm of the gradient,\n * of an image. The filter needs all of its input image.  It\n * behaves as a filter with an input and output. Thus it can be inserted\n * in a pipeline with other filters and the total variation will only be\n * recomputed if a downstream filter changes.\n *\n * The filter passes its input through unmodified. The filter is\n * threaded.\n *\n * \\ingroup RTK MathematicalStatisticsImageFilters\n * \\ingroup RTK ITKImageStatistics\n *\n */\n\ntemplate <typename TInputImage>\nclass ITK_TEMPLATE_EXPORT TotalVariationImageFilter : public itk::ImageToImageFilter<TInputImage, TInputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(TotalVariationImageFilter);\n\n  /** Standard Self type alias */\n  using Self = TotalVariationImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TInputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(TotalVariationImageFilter);\n\n  /** Image related type alias. */\n  using InputImagePointer = typename TInputImage::Pointer;\n\n  using RegionType = typename TInputImage::RegionType;\n  using SizeType = typename TInputImage::SizeType;\n  using IndexType = typename TInputImage::IndexType;\n  using PixelType = typename TInputImage::PixelType;\n\n  /** Image related type alias. */\n  static constexpr unsigned int ImageDimension = TInputImage::ImageDimension;\n\n  /** Type to use for computations. */\n  using RealType = typename itk::NumericTraits<PixelType>::RealType;\n\n  /** Smart Pointer type to a DataObject. */\n  using DataObjectPointer = typename itk::DataObject::Pointer;\n\n  /** Type of DataObjects used for scalar outputs */\n  using RealObjectType = itk::SimpleDataObjectDecorator<RealType>;\n  //  using PixelObjectType = SimpleDataObjectDecorator< PixelType >;\n\n  /** Return the computed Minimum. */\n  RealType\n  GetTotalVariation() const\n  {\n    return this->GetTotalVariationOutput()->Get();\n  }\n  RealObjectType *\n  GetTotalVariationOutput();\n\n  const RealObjectType *\n  GetTotalVariationOutput() const;\n\n  /** Make a DataObject of the correct type to be used as the specified\n   * output. */\n  using DataObjectPointerArraySizeType = itk::ProcessObject::DataObjectPointerArraySizeType;\n  using Superclass::MakeOutput;\n  DataObjectPointer\n  MakeOutput(DataObjectPointerArraySizeType output) override;\n\n  // Begin concept checking\n  itkConceptMacro(InputHasNumericTraitsCheck, (itk::Concept::HasNumericTraits<PixelType>));\n  // End concept checking\n\n  /** Use the image spacing information in calculations. Use this option if you\n   *  want derivatives in physical space. Default is UseImageSpacingOn. */\n  void\n  SetUseImageSpacingOn()\n  {\n    this->SetUseImageSpacing(true);\n  }\n\n  /** Ignore the image spacing. Use this option if you want derivatives in\n      isotropic pixel space.  Default is UseImageSpacingOn. */\n  void\n  SetUseImageSpacingOff()\n  {\n    this->SetUseImageSpacing(false);\n  }\n\n  /** Set/Get whether or not the filter will use the spacing of the input\n      image in its calculations */\n  itkSetMacro(UseImageSpacing, bool);\n  itkGetConstMacro(UseImageSpacing, bool);\n\nprotected:\n  TotalVariationImageFilter();\n  ~TotalVariationImageFilter() override = default;\n  void\n  PrintSelf(std::ostream & os, itk::Indent indent) const override;\n\n  /** Pass the input through unmodified. Do this by Grafting in the\n   *  AllocateOutputs method.\n   */\n  void\n  AllocateOutputs() override;\n\n  /** Initialize some accumulators before the threads run. */\n  void\n  BeforeThreadedGenerateData() override;\n\n  /** Do final mean and variance computation from data accumulated in threads.\n   */\n  void\n  AfterThreadedGenerateData() override;\n\n  /** Multi-thread version GenerateData. */\n  void\n  ThreadedGenerateData(const RegionType & outputRegionForThread, itk::ThreadIdType threadId) override;\n\n  // Override since the filter needs all the data for the algorithm\n  void\n  GenerateInputRequestedRegion() override;\n\n  // Override since the filter produces all of its output\n  void\n  EnlargeOutputRequestedRegion(itk::DataObject * data) override;\n\n  bool m_UseImageSpacing;\n\nprivate:\n  itk::Array<RealType> m_SumOfSquareRoots;\n}; // end of class\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkTotalVariationImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkTotalVariationImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTotalVariationImageFilter_hxx\n#define rtkTotalVariationImageFilter_hxx\n#include \"math.h\"\n\n\n#include \"itkConstNeighborhoodIterator.h\"\n#include \"itkProgressReporter.h\"\n\n\nnamespace rtk\n{\n\ntemplate <typename TInputImage>\nTotalVariationImageFilter<TInputImage>::TotalVariationImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n\n  // first output is a copy of the image, DataObject created by\n  // superclass\n  m_SumOfSquareRoots.Fill(1);\n\n  // allocate the data object for the output which is\n  // just a decorator around real type\n  typename RealObjectType::Pointer output = static_cast<RealObjectType *>(this->MakeOutput(1).GetPointer());\n  this->itk::ProcessObject::SetNthOutput(1, output.GetPointer());\n\n  this->GetTotalVariationOutput()->Set(itk::NumericTraits<RealType>::Zero);\n\n  // Initialize\n  m_UseImageSpacing = true;\n}\n\ntemplate <typename TInputImage>\nitk::DataObject::Pointer\nTotalVariationImageFilter<TInputImage>::MakeOutput(DataObjectPointerArraySizeType output)\n{\n  switch (output)\n  {\n    case 0:\n      return TInputImage::New().GetPointer();\n      break;\n    case 1:\n      return RealObjectType::New().GetPointer();\n      break;\n    default:\n      // might as well make an image\n      return TInputImage::New().GetPointer();\n      break;\n  }\n}\n\ntemplate <typename TInputImage>\ntypename TotalVariationImageFilter<TInputImage>::RealObjectType *\nTotalVariationImageFilter<TInputImage>::GetTotalVariationOutput()\n{\n  return static_cast<RealObjectType *>(this->itk::ProcessObject::GetOutput(1));\n}\n\ntemplate <typename TInputImage>\nconst typename TotalVariationImageFilter<TInputImage>::RealObjectType *\nTotalVariationImageFilter<TInputImage>::GetTotalVariationOutput() const\n{\n  return static_cast<const RealObjectType *>(this->itk::ProcessObject::GetOutput(1));\n}\n\ntemplate <typename TInputImage>\nvoid\nTotalVariationImageFilter<TInputImage>::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n  if (this->GetInput())\n  {\n    InputImagePointer image = const_cast<typename Superclass::InputImageType *>(this->GetInput());\n    image->SetRequestedRegionToLargestPossibleRegion();\n  }\n}\n\ntemplate <typename TInputImage>\nvoid\nTotalVariationImageFilter<TInputImage>::EnlargeOutputRequestedRegion(itk::DataObject * data)\n{\n  Superclass::EnlargeOutputRequestedRegion(data);\n  data->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename TInputImage>\nvoid\nTotalVariationImageFilter<TInputImage>::AllocateOutputs()\n{\n  // Pass the input through as the output\n  InputImagePointer image = const_cast<TInputImage *>(this->GetInput());\n\n  this->GraftOutput(image);\n\n  // Nothing that needs to be allocated for the remaining outputs\n}\n\ntemplate <typename TInputImage>\nvoid\nTotalVariationImageFilter<TInputImage>::BeforeThreadedGenerateData()\n{\n  itk::ThreadIdType numberOfThreads = this->GetNumberOfWorkUnits();\n\n  // Resize the thread temporaries\n  m_SumOfSquareRoots.SetSize(numberOfThreads);\n\n  // Initialize the temporaries\n  m_SumOfSquareRoots.Fill(itk::NumericTraits<RealType>::Zero);\n}\n\ntemplate <typename TInputImage>\nvoid\nTotalVariationImageFilter<TInputImage>::AfterThreadedGenerateData()\n{\n  RealType          totalVariation = 0;\n  itk::ThreadIdType numberOfThreads = this->GetNumberOfWorkUnits();\n\n  // Add up the results from all threads\n  for (itk::ThreadIdType i = 0; i < numberOfThreads; i++)\n  {\n    totalVariation += m_SumOfSquareRoots[i];\n  }\n\n  // Set the output\n  this->GetTotalVariationOutput()->Set(totalVariation);\n}\n\ntemplate <typename TInputImage>\nvoid\nTotalVariationImageFilter<TInputImage>::ThreadedGenerateData(const RegionType & outputRegionForThread,\n                                                             itk::ThreadIdType  threadId)\n{\n  const itk::SizeValueType size0 = outputRegionForThread.GetSize(0);\n  if (size0 == 0)\n  {\n    return;\n  }\n  RealType                           sumOfSquareRoots = itk::NumericTraits<RealType>::Zero;\n  typename TInputImage::ConstPointer input = this->GetInput(0);\n\n  itk::Size<ImageDimension> radius;\n  radius.Fill(1);\n\n  itk::ConstNeighborhoodIterator<TInputImage> iit(radius, input, outputRegionForThread);\n  iit.GoToBegin();\n  itk::ZeroFluxNeumannBoundaryCondition<TInputImage> boundaryCondition;\n  iit.OverrideBoundaryCondition(&boundaryCondition);\n\n  auto                                  c = (itk::SizeValueType)(iit.Size() / 2); // get offset of center pixel\n  itk::SizeValueType                    strides[ImageDimension]; // get offsets to access neighboring pixels\n  itk::Vector<RealType, ImageDimension> invSpacingCoeffs;\n  for (unsigned int dim = 0; dim < ImageDimension; dim++)\n  {\n    strides[dim] = iit.GetStride(dim);\n\n    invSpacingCoeffs[dim] = 1;\n    if (m_UseImageSpacing == true)\n    {\n      invSpacingCoeffs[dim] = 1.0 / this->GetOutput()->GetSpacing()[dim];\n    }\n  }\n\n  // Run through the image\n  while (!iit.IsAtEnd())\n  {\n    // Compute the local differences around the central pixel\n    float difference = NAN;\n    float sumOfSquaredDifferences = 0;\n    for (unsigned int dim = 0; dim < ImageDimension; dim++)\n    {\n      difference = (iit.GetPixel(c + strides[dim]) - iit.GetPixel(c)) * invSpacingCoeffs[dim];\n      sumOfSquaredDifferences += difference * difference;\n    }\n    sumOfSquareRoots += sqrt(sumOfSquaredDifferences);\n    ++iit;\n  }\n\n  m_SumOfSquareRoots[threadId] = sumOfSquareRoots;\n}\n\ntemplate <typename TInputImage>\nvoid\nTotalVariationImageFilter<TInputImage>::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n\n  os << indent << \"Total Variation: \" << this->GetTotalVariation() << std::endl;\n}\n} // end namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkUnwarpSequenceConjugateGradientOperator.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkUnwarpSequenceConjugateGradientOperator_h\n#define rtkUnwarpSequenceConjugateGradientOperator_h\n\n#include \"rtkWarpSequenceImageFilter.h\"\n#include \"rtkConjugateGradientOperator.h\"\n\nnamespace rtk\n{\n\n/** \\class UnwarpSequenceConjugateGradientOperator\n * \\brief Implements the operator A used in the conjugate gradient unwarp sequence filter\n *\n * \\dot\n * digraph UnwarpSequenceConjugateGradientOperator {\n *\n * Input0 [ label=\"Input 0 (4D volume sequence)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (4D DVF)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (4D volume sequence)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * WarpSequenceBackward [ label=\"rtk::WarpSequenceImageFilter\" URL=\"\\ref rtk::WarpSequenceImageFilter\"];\n * WarpSequenceForward [ label=\"rtk::WarpSequenceImageFilter (forward)\" URL=\"\\ref rtk::WarpSequenceImageFilter\"];\n *\n * Input0 -> WarpSequenceBackward;\n * WarpSequenceBackward -> WarpSequenceForward;\n * WarpSequenceForward -> Output;\n *\n * }\n * \\enddot\n *\n * \\test rtkunwarpsequencetest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\ntemplate <typename TImageSequence,\n          typename TDVFImageSequence =\n            itk::Image<itk::CovariantVector<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n                       TImageSequence::ImageDimension>,\n          typename TImage = itk::Image<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n          typename TDVFImage =\n            itk::Image<itk::CovariantVector<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n                       TImageSequence::ImageDimension - 1>>\nclass ITK_TEMPLATE_EXPORT UnwarpSequenceConjugateGradientOperator : public ConjugateGradientOperator<TImageSequence>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(UnwarpSequenceConjugateGradientOperator);\n\n  /** Standard class type alias. */\n  using Self = UnwarpSequenceConjugateGradientOperator;\n  using Superclass = ConjugateGradientOperator<TImageSequence>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(UnwarpSequenceConjugateGradientOperator);\n\n  using WarpSequenceFilterType = rtk::WarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>;\n\n  /** Set the motion vector field used in input 1 */\n  void\n  SetDisplacementField(const TDVFImageSequence * DVFs);\n\n  /** Get the motion vector field used in input 1 */\n  typename TDVFImageSequence::Pointer\n  GetDisplacementField();\n\n  /** Phase shift to simulate phase estimation errors */\n  itkSetMacro(PhaseShift, float);\n  itkGetMacro(PhaseShift, float);\n\n  itkSetMacro(UseNearestNeighborInterpolationInWarping, bool);\n  itkGetMacro(UseNearestNeighborInterpolationInWarping, bool);\n\n  /** Set and Get for the UseCudaCyclicDeformation variable */\n  itkSetMacro(UseCudaCyclicDeformation, bool);\n  itkGetMacro(UseCudaCyclicDeformation, bool);\n\nprotected:\n  UnwarpSequenceConjugateGradientOperator();\n  ~UnwarpSequenceConjugateGradientOperator() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename WarpSequenceFilterType::Pointer m_WarpSequenceBackwardFilter;\n  typename WarpSequenceFilterType::Pointer m_WarpSequenceForwardFilter;\n\n  float m_PhaseShift;\n  bool  m_UseNearestNeighborInterpolationInWarping; // Default is false, linear interpolation is used instead\n\n  /** When the inputs have the same type, ITK checks whether they occupy the\n   * same physical space or not. Obviously they dont, so we have to remove this check\n   */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n\n  bool m_UseCudaCyclicDeformation;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkUnwarpSequenceConjugateGradientOperator.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkUnwarpSequenceConjugateGradientOperator.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkUnwarpSequenceConjugateGradientOperator_hxx\n#define rtkUnwarpSequenceConjugateGradientOperator_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nUnwarpSequenceConjugateGradientOperator<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::\n  UnwarpSequenceConjugateGradientOperator()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Default member variables\n  m_PhaseShift = 0;\n  m_UseNearestNeighborInterpolationInWarping = false;\n  m_UseCudaCyclicDeformation = false;\n\n  // Create filters\n  m_WarpSequenceBackwardFilter = WarpSequenceFilterType::New();\n  m_WarpSequenceForwardFilter = WarpSequenceFilterType::New();\n\n  // Set permanent connections\n  m_WarpSequenceForwardFilter->SetInput(m_WarpSequenceBackwardFilter->GetOutput());\n\n  // Set permanent parameters\n  m_WarpSequenceForwardFilter->SetForwardWarp(true);\n\n  // Set memory management options\n  m_WarpSequenceBackwardFilter->ReleaseDataFlagOn();\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nUnwarpSequenceConjugateGradientOperator<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::SetDisplacementField(\n  const TDVFImageSequence * DVFs)\n{\n  this->SetNthInput(1, const_cast<TDVFImageSequence *>(DVFs));\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\ntypename TDVFImageSequence::Pointer\nUnwarpSequenceConjugateGradientOperator<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GetDisplacementField()\n{\n  return static_cast<TDVFImageSequence *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nUnwarpSequenceConjugateGradientOperator<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::\n  GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get pointers to the input and output\n  typename TImageSequence::Pointer inputPtr = const_cast<TImageSequence *>(this->GetInput(0));\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n\n  typename TDVFImageSequence::Pointer inputDVFPtr = this->GetDisplacementField();\n  inputDVFPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nUnwarpSequenceConjugateGradientOperator<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::\n  GenerateOutputInformation()\n{\n  // Set runtime connections, and connections with\n  // forward and back projection filters, which are set\n  // at runtime\n  m_WarpSequenceBackwardFilter->SetInput(this->GetInput(0));\n  m_WarpSequenceBackwardFilter->SetDisplacementField(this->GetDisplacementField());\n  m_WarpSequenceForwardFilter->SetDisplacementField(this->GetDisplacementField());\n\n  // Set runtime parameters\n  m_WarpSequenceBackwardFilter->SetPhaseShift(this->m_PhaseShift);\n  m_WarpSequenceBackwardFilter->SetUseNearestNeighborInterpolationInWarping(m_UseNearestNeighborInterpolationInWarping);\n  m_WarpSequenceBackwardFilter->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n  m_WarpSequenceForwardFilter->SetPhaseShift(this->m_PhaseShift);\n  m_WarpSequenceForwardFilter->SetUseNearestNeighborInterpolationInWarping(m_UseNearestNeighborInterpolationInWarping);\n  m_WarpSequenceForwardFilter->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n\n  // Have the last filter calculate its output information\n  m_WarpSequenceForwardFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_WarpSequenceForwardFilter->GetOutput());\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nUnwarpSequenceConjugateGradientOperator<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GenerateData()\n{\n  // Execute Pipeline\n  m_WarpSequenceForwardFilter->Update();\n\n  // Get the output\n  this->GraftOutput(m_WarpSequenceForwardFilter->GetOutput());\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkUnwarpSequenceImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkUnwarpSequenceImageFilter_h\n#define rtkUnwarpSequenceImageFilter_h\n\n#include \"rtkConjugateGradientImageFilter.h\"\n#include \"rtkUnwarpSequenceConjugateGradientOperator.h\"\n#include \"rtkWarpSequenceImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaConjugateGradientImageFilter.h\"\n#  include \"rtkCudaConstantVolumeSeriesSource.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class UnwarpSequenceImageFilter\n * \\brief Finds the image sequence that, once warped, equals the input image sequence.\n *\n * This filter attempts to invert a deformation by Conjugate Gradient optimization.\n *\n * \\dot\n * digraph UnwarpSequenceImageFilter {\n *\n * Input0 [ label=\"Input 0 (4D volume sequence)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (4D DVF)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (4D volume sequence)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * ConstantSource [label=\"rtk::ConstantImageSource (4D volume sequence)\" URL=\"\\ref rtk::WarpSequenceImageFilter\"];\n * WarpSequenceForward [label=\"rtk::WarpSequenceImageFilter (forward mapping)\"\n *                      URL=\"\\ref rtk::WarpSequenceImageFilter\"];\n * ConjugateGradient[ label=\"rtk::ConjugateGradientImageFilter\" URL=\"\\ref rtk::ConjugateGradientImageFilter\"];\n * CyclicDeformation [label=\"rtk::CyclicDeformationImageFilter (for DVFs)\"\n *                    URL=\"\\ref rtk::CyclicDeformationImageFilter\"];\n *\n * Input0 -> WarpSequenceForward;\n * Input1 -> CyclicDeformation;\n * CyclicDeformation -> WarpSequenceForward;\n * ConstantSource -> ConjugateGradient;\n * WarpSequenceForward -> ConjugateGradient;\n * ConjugateGradient -> Output;\n * }\n * \\enddot\n *\n * \\test rtkunwarpsequencetest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TImageSequence,\n          typename TDVFImageSequence =\n            itk::Image<itk::CovariantVector<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n                       TImageSequence::ImageDimension>,\n          typename TImage = itk::Image<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n          typename TDVFImage =\n            itk::Image<itk::CovariantVector<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n                       TImageSequence::ImageDimension - 1>>\nclass ITK_TEMPLATE_EXPORT UnwarpSequenceImageFilter : public itk::ImageToImageFilter<TImageSequence, TImageSequence>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(UnwarpSequenceImageFilter);\n\n  /** Standard class type alias. */\n  using Self = UnwarpSequenceImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImageSequence, TImageSequence>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(UnwarpSequenceImageFilter);\n\n  using CGOperatorFilterType =\n    UnwarpSequenceConjugateGradientOperator<TImageSequence, TDVFImageSequence, TImage, TDVFImage>;\n  using WarpForwardFilterType = WarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>;\n  using ConjugateGradientFilterType = ConjugateGradientImageFilter<TImageSequence>;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUImageSequence = typename itk::Image<typename TImageSequence::PixelType, TImageSequence::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using ConstantSourceType = typename std::conditional_t<std::is_same_v<TImageSequence, CPUImageSequence>,\n                                                         ConstantImageSource<TImageSequence>,\n                                                         CudaConstantVolumeSeriesSource>;\n  using CudaConjugateGradientType = typename std::conditional_t<std::is_same_v<TImageSequence, CPUImageSequence>,\n                                                                ConjugateGradientFilterType,\n                                                                CudaConjugateGradientImageFilter<TImageSequence>>;\n#else\n  using ConstantSourceType = ConstantImageSource<TImageSequence>;\n  using CudaConjugateGradientType = ConjugateGradientFilterType;\n#endif\n\n  /** Set the motion vector field used in input 1 */\n  void\n  SetDisplacementField(const TDVFImageSequence * DVFs);\n\n  /** Get the motion vector field used in input 1 */\n  typename TDVFImageSequence::Pointer\n  GetDisplacementField();\n\n  /** Number of conjugate gradient iterations */\n  itkSetMacro(NumberOfIterations, float);\n  itkGetMacro(NumberOfIterations, float);\n\n  /** Phase shift to simulate phase estimation errors */\n  itkSetMacro(PhaseShift, float);\n  itkGetMacro(PhaseShift, float);\n\n  itkSetMacro(UseNearestNeighborInterpolationInWarping, bool);\n  itkGetMacro(UseNearestNeighborInterpolationInWarping, bool);\n\n  itkSetMacro(CudaConjugateGradient, bool);\n  itkGetMacro(CudaConjugateGradient, bool);\n\n  /** Set and Get for the UseCudaCyclicDeformation variable */\n  itkSetMacro(UseCudaCyclicDeformation, bool);\n  itkGetMacro(UseCudaCyclicDeformation, bool);\n\nprotected:\n  UnwarpSequenceImageFilter();\n  ~UnwarpSequenceImageFilter() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename ConjugateGradientFilterType::Pointer m_ConjugateGradientFilter;\n  typename CGOperatorFilterType::Pointer        m_CGOperator;\n  typename WarpForwardFilterType::Pointer       m_WarpForwardFilter;\n  typename ConstantSourceType::Pointer          m_ConstantSource;\n\n  /** Member variables */\n  float m_PhaseShift;\n\n  /** The inputs of this filter have the same type (float, 3) but not the same meaning\n   * It is normal that they do not occupy the same physical space. Therefore this check\n   * must be removed */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  GenerateOutputInformation() override;\n\n  bool m_UseNearestNeighborInterpolationInWarping; // Default is false, linear interpolation is used instead\n  bool m_CudaConjugateGradient;\n  bool m_UseCudaCyclicDeformation;\n\nprivate:\n  unsigned int m_NumberOfIterations;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkUnwarpSequenceImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkUnwarpSequenceImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkUnwarpSequenceImageFilter_hxx\n#define rtkUnwarpSequenceImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nUnwarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::UnwarpSequenceImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set the default values of member parameters\n  m_NumberOfIterations = 2;\n  m_PhaseShift = 0;\n  m_UseNearestNeighborInterpolationInWarping = false;\n  m_CudaConjugateGradient = false;\n  m_UseCudaCyclicDeformation = false;\n\n  // Create the filters\n  m_ConjugateGradientFilter = ConjugateGradientFilterType::New();\n  m_ConstantSource = ConstantSourceType::New();\n  if (m_CudaConjugateGradient)\n  {\n    if (std::is_same_v<TImageSequence, CPUImageSequence>)\n      itkGenericExceptionMacro(<< \"CudaConjugateGradient option only available with itk::CudaImage.\");\n    m_ConjugateGradientFilter = CudaConjugateGradientType::New();\n  }\n\n  m_WarpForwardFilter = WarpForwardFilterType::New();\n  m_CGOperator = CGOperatorFilterType::New();\n\n  // Set permanent connections\n  m_ConjugateGradientFilter->SetB(m_WarpForwardFilter->GetOutput());\n  m_ConjugateGradientFilter->SetX(m_ConstantSource->GetOutput());\n  m_ConjugateGradientFilter->SetA(m_CGOperator.GetPointer());\n\n  // Set permanent parameters\n  m_WarpForwardFilter->SetForwardWarp(true);\n\n  // Set memory management parameters\n  m_ConstantSource->ReleaseDataFlagOn();\n  m_WarpForwardFilter->ReleaseDataFlagOn();\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nUnwarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::SetDisplacementField(\n  const TDVFImageSequence * DVFs)\n{\n  this->SetNthInput(1, const_cast<TDVFImageSequence *>(DVFs));\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\ntypename TDVFImageSequence::Pointer\nUnwarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GetDisplacementField()\n{\n  return static_cast<TDVFImageSequence *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nUnwarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get pointers to the input and output\n  typename TImageSequence::Pointer inputPtr = const_cast<TImageSequence *>(this->GetInput(0));\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n\n  typename TDVFImageSequence::Pointer inputDVFPtr = this->GetDisplacementField();\n  inputDVFPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nUnwarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GenerateOutputInformation()\n{\n  // Set runtime connections\n  m_ConstantSource->SetInformationFromImage(this->GetInput(0));\n  m_CGOperator->SetDisplacementField(this->GetDisplacementField());\n  m_CGOperator->SetUseNearestNeighborInterpolationInWarping(m_UseNearestNeighborInterpolationInWarping);\n  m_WarpForwardFilter->SetInput(this->GetInput(0));\n  m_WarpForwardFilter->SetDisplacementField(this->GetDisplacementField());\n  m_WarpForwardFilter->SetUseNearestNeighborInterpolationInWarping(m_UseNearestNeighborInterpolationInWarping);\n  m_WarpForwardFilter->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n\n  // Set runtime parameters\n  m_ConjugateGradientFilter->SetNumberOfIterations(this->m_NumberOfIterations);\n  m_WarpForwardFilter->SetPhaseShift(this->m_PhaseShift);\n  m_CGOperator->SetPhaseShift(this->m_PhaseShift);\n  m_CGOperator->SetUseCudaCyclicDeformation(m_UseCudaCyclicDeformation);\n\n  // Have the last filter calculate its output information\n  m_ConjugateGradientFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_ConjugateGradientFilter->GetOutput());\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nUnwarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GenerateData()\n{\n  m_ConjugateGradientFilter->Update();\n\n  this->GraftOutput(m_ConjugateGradientFilter->GetOutput());\n\n  // During mini-pipeline execution, the requested region on the primary input\n  // is modified by the extract filters contained in the warp filters. This\n  typename TImageSequence::Pointer inputPtr = const_cast<TImageSequence *>(this->GetInput(0));\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n\n  typename TDVFImageSequence::Pointer inputDVFPtr = this->GetDisplacementField();\n  inputDVFPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkUpsampleImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkUpsampleImageFilter_h\n#define rtkUpsampleImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\nnamespace rtk\n{\n\n/** \\class UpsampleImageFilter\n * \\brief Upsamples an image by the given factor for each dimension.\n *\n * This filter is inspired from Dan Mueller's GIFT package\n * https://www.insight-journal.org/browse/publication/103\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT UpsampleImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(UpsampleImageFilter);\n\n  /** Standard class type alias. */\n  using Self = UpsampleImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(UpsampleImageFilter);\n\n  /** Typedef to images */\n  using OutputImageType = TOutputImage;\n  using InputImageType = TInputImage;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n  using InputImagePointer = typename InputImageType::Pointer;\n  using InputImageConstPointer = typename InputImageType::ConstPointer;\n\n  /** Typedef to describe the output image region type. */\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n\n  /** ImageDimension enumeration. */\n  static constexpr unsigned int ImageDimension = TInputImage::ImageDimension;\n\n  /** Set the shrink factors. Values are clamped to\n   * a minimum value of 1.*/\n  void\n  SetFactors(const unsigned int factors[]);\n\n  /** Sets the shrink factor for the given dimension.\n   * All other dimensions are set to 1 */\n  void\n  SetFactor(unsigned int dimension, unsigned int factor);\n\n  /** UpsampleImageFilter produces an image which is a different\n   * resolution and with a different pixel spacing than its input\n   * image.  As such, UpsampleImageFilter needs to provide an\n   * implementation for GenerateOutputInformation() in order to inform\n   * the pipeline execution model.  The original documentation of this\n   * method is below.\n   * \\sa ProcessObject::GenerateOutputInformaton() */\n  void\n  GenerateOutputInformation() override;\n\n  /** UpsampleImageFilter needs a larger input requested region than the output\n   * requested region.  As such, UpsampleImageFilter needs to provide an\n   * implementation for GenerateInputRequestedRegion() in order to inform the\n   * pipeline execution model.\n   * \\sa ProcessObject::GenerateInputRequestedRegion() */\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Set/Get the order of the wavelet filter\n   * This is required because some information about the index of the image\n   * is lost during downsampling, and the upsampling filter can't guess\n   * what the exact index should be.\n   */\n  itkSetMacro(Order, unsigned int);\n  itkGetMacro(Order, unsigned int);\n\n  /** Set/Get the size of the output image\n   * This is required because some information about the size of the image\n   * is lost during downsampling, and the upsampling filter can't guess\n   * what the exact size should be.\n   */\n  itkSetMacro(OutputSize, typename TOutputImage::SizeType);\n  itkGetMacro(OutputSize, typename TOutputImage::SizeType);\n\n  /** Set/Get the index of the output image\n   * This is required because some information about the index of the image\n   * is lost during downsampling, and the upsampling filter can't guess\n   * what the exact index should be. The output index is actually set to\n   * OutputIndex + 1.\n   */\n  itkSetMacro(OutputIndex, typename TOutputImage::IndexType);\n  itkGetMacro(OutputIndex, typename TOutputImage::IndexType);\n\nprotected:\n  UpsampleImageFilter();\n  ~UpsampleImageFilter() override = default;\n\n  /** UpsampleImageFilter can be implemented as a multithreaded filter.\n   * Therefore, this implementation provides a ThreadedGenerateData() routine\n   * which is called for each processing thread. The output image data is\n   * allocated automatically by the superclass prior to calling\n   * ThreadedGenerateData().  ThreadedGenerateData can only write to the\n   * portion of the output image specified by the parameter\n   * \"outputRegionForThread\"\n   *\n   * \\sa ImageToImageFilter::ThreadedGenerateData(),\n   *     ImageToImageFilter::GenerateData() */\n  void\n  ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,\n                       itk::ThreadIdType             itkNotUsed(threadId)) override;\n\nprivate:\n  unsigned int                     m_Factors[ImageDimension];\n  unsigned int                     m_Order;\n  typename TOutputImage::SizeType  m_OutputSize;\n  typename TOutputImage::IndexType m_OutputIndex;\n\n  const itk::ImageRegionSplitterBase *\n                                             GetImageRegionSplitter() const override;\n  itk::ImageRegionSplitterDirection::Pointer m_Splitter;\n};\n\n\n} // end namespace rtk\n\n#ifndef rtk_MANUAL_INSTANTIATION\n#  include \"rtkUpsampleImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkUpsampleImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkUpsampleImageFilter_hxx\n#define rtkUpsampleImageFilter_hxx\n\n\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n#include \"itkObjectFactory.h\"\n#include \"itkProgressReporter.h\"\n#include \"itkNumericTraits.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nUpsampleImageFilter<TInputImage, TOutputImage>::UpsampleImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n  this->SetNumberOfRequiredInputs(1);\n  this->m_Order = 0;\n  this->m_OutputSize.Fill(0);\n  this->m_OutputIndex.Fill(0);\n\n  // Set the direction along which the output requested region should NOT be split\n  m_Splitter = itk::ImageRegionSplitterDirection::New();\n  m_Splitter->SetDirection(0);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nUpsampleImageFilter<TInputImage, TOutputImage>::SetFactors(const unsigned int factors[])\n{\n  unsigned int j = 0;\n\n  this->Modified();\n  for (j = 0; j < ImageDimension; j++)\n  {\n    m_Factors[j] = factors[j];\n    if (m_Factors[j] < 1)\n    {\n      m_Factors[j] = 1;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nUpsampleImageFilter<TInputImage, TOutputImage>::SetFactor(unsigned int dimension, unsigned int factor)\n{\n  unsigned int j = 0;\n\n  this->Modified();\n  for (j = 0; j < ImageDimension; j++)\n  {\n    if (j == dimension)\n    {\n      m_Factors[j] = factor;\n    }\n    else\n    {\n      m_Factors[j] = 1;\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nUpsampleImageFilter<TInputImage, TOutputImage>::ThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread,\n  itk::ThreadIdType             itkNotUsed(threadId))\n{\n  // Get the input and output pointers\n  InputImageConstPointer inputPtr = this->GetInput();\n  OutputImagePointer     outputPtr = this->GetOutput();\n\n  // Define/declare an iterator that will walk the output region for this\n  // thread.\n  using OutputIterator = itk::ImageRegionIterator<TOutputImage>;\n  OutputIterator outIt(outputPtr, outputRegionForThread);\n\n  // Fill the output region with zeros\n  while (!outIt.IsAtEnd())\n  {\n    outIt.Set(itk::NumericTraits<typename TOutputImage::PixelType>::Zero);\n    ++outIt;\n  }\n\n  // Define a few indices that will be used to translate from an input pixel\n  // to an output pixel\n  typename TOutputImage::IndexType outputStartIndex;\n  typename TInputImage::IndexType  inputStartIndex;\n\n  typename TInputImage::OffsetType  inputOffset;\n  typename TOutputImage::OffsetType firstValidPixelOffset;\n  typename TOutputImage::OffsetType firstPixelOfLineOffset;\n\n  outputStartIndex = outputPtr->GetLargestPossibleRegion().GetIndex();\n  inputStartIndex = inputPtr->GetLargestPossibleRegion().GetIndex();\n\n  // Find the first output pixel that is copied from the input (the one with lowest indices\n  // in all dimensions)\n  firstValidPixelOffset = outputRegionForThread.GetIndex() - outputStartIndex;\n  for (unsigned int i = 0; i < TOutputImage::ImageDimension; i++)\n  {\n    while ((firstValidPixelOffset[i] - 1) % m_Factors[i])\n    {\n      firstValidPixelOffset[i] = firstValidPixelOffset[i] + 1;\n    }\n  }\n\n  // Walk the slice obtained by setting the first coordinate to zero. If the\n  // line (1D vector traversing the output region along the first dimension)\n  // contains pixels that should be copied from the input,\n  // create an iterator and perform the copies\n  OutputImageRegionType slice = outputRegionForThread;\n  slice.SetSize(0, 1);\n  slice.SetIndex(0, outputRegionForThread.GetIndex(0) + firstValidPixelOffset[0]);\n\n  OutputIterator sliceIt(outputPtr, slice);\n  while (!sliceIt.IsAtEnd())\n  {\n    // Determine the offset of the current pixel in the slice\n    firstPixelOfLineOffset = sliceIt.GetIndex() - outputStartIndex;\n\n    // Check whether the line contains pixels that should be copied from the input\n    bool copyFromInput = true;\n    for (unsigned int dim = 0; dim < TInputImage::ImageDimension; dim++)\n    {\n      if ((firstPixelOfLineOffset[dim] - 1) % m_Factors[dim])\n        copyFromInput = false;\n    }\n\n    // If it does, create an iterator along the line and copy the pixels\n    if (copyFromInput)\n    {\n      // Calculate the corresponding input index\n      for (unsigned int i = 0; i < TOutputImage::ImageDimension; i++)\n      {\n        inputOffset[i] = (firstPixelOfLineOffset[i] - 1) / m_Factors[i];\n      }\n\n      // Create the iterators\n      typename TOutputImage::RegionType outputLine = slice;\n      typename TOutputImage::SizeType   outputLineSize;\n      outputLineSize.Fill(1);\n      outputLineSize[0] = outputRegionForThread.GetSize(0) - firstPixelOfLineOffset[0];\n      outputLine.SetSize(outputLineSize);\n      outputLine.SetIndex(sliceIt.GetIndex());\n\n      typename TInputImage::RegionType inputLine = inputPtr->GetLargestPossibleRegion();\n      typename TInputImage::SizeType   inputLineSize;\n      inputLineSize.Fill(1);\n      inputLineSize[0] = (outputLineSize[0] + 1) / m_Factors[0];\n      inputLine.SetSize(inputLineSize);\n      inputLine.SetIndex(inputStartIndex + inputOffset);\n\n      OutputIterator                             outIt_local(outputPtr, outputLine);\n      itk::ImageRegionConstIterator<TInputImage> inIt(inputPtr, inputLine);\n\n      // Walk the line and copy the pixels\n      while (!inIt.IsAtEnd())\n      {\n        outIt_local.Set(inIt.Get());\n        for (unsigned int i = 0; i < m_Factors[0]; i++)\n          ++outIt_local;\n        ++inIt;\n      }\n    }\n    // Move to next pixel in the slice\n    ++sliceIt;\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nUpsampleImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get pointers to the input and output\n  InputImagePointer  inputPtr = const_cast<TInputImage *>(this->GetInput());\n  OutputImagePointer outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n  {\n    return;\n  }\n\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nUpsampleImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateOutputInformation();\n\n  // Get pointers to the input and output\n  InputImageConstPointer inputPtr = this->GetInput();\n  OutputImagePointer     outputPtr = this->GetOutput();\n\n  if (!inputPtr || !outputPtr)\n  {\n    return;\n  }\n\n  // We need to compute the output spacing, the output image size, and the\n  // output image start index\n  unsigned int                              i = 0;\n  const typename TInputImage::SpacingType & inputSpacing = inputPtr->GetSpacing();\n\n  typename TOutputImage::SpacingType outputSpacing;\n  typename TOutputImage::SizeType    outputSize;\n  typename TOutputImage::IndexType   outputStartIndex;\n\n  for (i = 0; i < TOutputImage::ImageDimension; i++)\n  {\n    outputSpacing[i] = inputSpacing[i] / (double)m_Factors[i];\n    outputSize[i] = m_OutputSize[i];\n    outputStartIndex[i] = m_OutputIndex[i] + 1;\n  }\n\n  outputPtr->SetSpacing(outputSpacing);\n\n  typename TOutputImage::RegionType outputLargestPossibleRegion;\n  outputLargestPossibleRegion.SetSize(outputSize);\n  outputLargestPossibleRegion.SetIndex(outputStartIndex);\n\n  outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);\n  outputPtr->SetOrigin(inputPtr->GetOrigin());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nconst itk::ImageRegionSplitterBase *\nUpsampleImageFilter<TInputImage, TOutputImage>::GetImageRegionSplitter() const\n{\n  return m_Splitter;\n}\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkVarianObiGeometryReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkVarianObiGeometryReader_h\n#define rtkVarianObiGeometryReader_h\n\n#include \"RTKExport.h\"\n#include <itkLightProcessObject.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class VarianObiGeometryReader\n *\n * Creates a 3D circular geometry from Varian OBI data.\n *\n * \\test rtkvariantest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT VarianObiGeometryReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(VarianObiGeometryReader);\n\n  /** Standard type alias */\n  using Self = VarianObiGeometryReader;\n  using Superclass = itk::LightProcessObject;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using FileNamesContainer = std::vector<std::string>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(VarianObiGeometryReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Get the pointer to the generated geometry object. */\n  itkGetMacro(Geometry, GeometryType::Pointer);\n\n  /** Set the path to the Varian OBI xml file containing geometric information. */\n  itkGetMacro(XMLFileName, std::string);\n  itkSetMacro(XMLFileName, std::string);\n\n  /** Set the vector of strings that contains the projection file names. Files\n   * are processed in sequential order. */\n  void\n  SetProjectionsFileNames(const FileNamesContainer & name)\n  {\n    if (m_ProjectionsFileNames != name)\n    {\n      m_ProjectionsFileNames = name;\n      this->Modified();\n    }\n  }\n  const FileNamesContainer &\n  GetProjectionsFileNames() const\n  {\n    return m_ProjectionsFileNames;\n  }\n\nprotected:\n  VarianObiGeometryReader();\n\n\nprivate:\n  void\n  GenerateData() override;\n\n  GeometryType::Pointer m_Geometry;\n  std::string           m_XMLFileName;\n  FileNamesContainer    m_ProjectionsFileNames;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkVarianObiRawImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkVarianObiRawImageFilter_h\n#define rtkVarianObiRawImageFilter_h\n\n#include <itkUnaryFunctorImageFilter.h>\n#include <itkConceptChecking.h>\n#include <itkNumericTraits.h>\n\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\nnamespace Function\n{\n\n/** \\class ObiAttenuation\n * \\brief Converts a raw value measured by the Varian OBI system to attenuation\n *\n * The user can specify I0 and IDark values. The defaults are 139000 and 0,\n * respectively.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK Functions\n */\ntemplate <class TInput, class TOutput>\nclass ITK_TEMPLATE_EXPORT ObiAttenuation\n{\npublic:\n  ObiAttenuation() = default;\n  ~ObiAttenuation() = default;\n  bool\n  operator!=(const ObiAttenuation &) const\n  {\n    return false;\n  }\n  bool\n  operator==(const ObiAttenuation & other) const\n  {\n    return !(*this != other);\n  }\n  inline TOutput\n  operator()(const TInput & A) const\n  {\n    return (!A) ? 0. : TOutput(std::log((m_I0 - m_IDark) / (A - m_IDark)));\n  }\n  void\n  SetI0(double i0)\n  {\n    m_I0 = i0;\n  }\n  void\n  SetIDark(double idark)\n  {\n    m_IDark = idark;\n  }\n\nprivate:\n  double m_I0;\n  double m_IDark;\n};\n} // namespace Function\n\n/** \\class VarianObiRawImageFilter\n * \\brief Converts raw images measured by the Varian OBI system to attenuation\n *\n * Uses ObiAttenuation.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT VarianObiRawImageFilter\n  : public itk::UnaryFunctorImageFilter<\n      TInputImage,\n      TOutputImage,\n      Function::ObiAttenuation<typename TInputImage::PixelType, typename TOutputImage::PixelType>>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(VarianObiRawImageFilter);\n\n  /** Standard class type alias. */\n  using Self = VarianObiRawImageFilter;\n  using Superclass = itk::UnaryFunctorImageFilter<\n    TInputImage,\n    TOutputImage,\n    Function::ObiAttenuation<typename TInputImage::PixelType, typename TOutputImage::PixelType>>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(VarianObiRawImageFilter);\n\n  itkGetMacro(I0, double);\n  itkSetMacro(I0, double);\n\n  itkGetMacro(IDark, double);\n  itkSetMacro(IDark, double);\n\n  void\n  BeforeThreadedGenerateData() override;\n\nprotected:\n  VarianObiRawImageFilter();\n  ~VarianObiRawImageFilter() override = default;\n\nprivate:\n  double m_I0{ 139000. };\n  double m_IDark{ 0. };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkVarianObiRawImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkVarianObiRawImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkVarianObiRawImageFilter_hxx\n#define rtkVarianObiRawImageFilter_hxx\n\n#include \"rtkI0EstimationProjectionFilter.h\"\n\nnamespace rtk\n{\n\ntemplate <typename TInputImage, typename TOutputImage>\nVarianObiRawImageFilter<TInputImage, TOutputImage>::VarianObiRawImageFilter() = default;\n\ntemplate <typename TInputImage, typename TOutputImage>\nvoid\nVarianObiRawImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  auto * i0est =\n    dynamic_cast<rtk::I0EstimationProjectionFilter<TInputImage> *>(this->GetInput()->GetSource().GetPointer());\n  if (i0est)\n  {\n    m_I0 = (double)i0est->GetI0();\n  }\n  this->GetFunctor().SetI0(m_I0);\n  this->GetFunctor().SetIDark(m_IDark);\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkVarianObiXMLFileReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkVarianObiXMLFileReader_h\n#define rtkVarianObiXMLFileReader_h\n\n#ifdef _MSC_VER\n#  pragma warning(disable : 4786)\n#endif\n\n#include <itkXMLFile.h>\n#include <itkMetaDataDictionary.h>\n#include <itkMetaDataObject.h>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class VarianObiXMLFileReader\n *\n * Reads the XML-format file written by a Varian OBI\n * machine for every acquisition\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT VarianObiXMLFileReader : public itk::XMLReader<itk::MetaDataDictionary>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(VarianObiXMLFileReader);\n\n  /** Standard type alias */\n  using Self = VarianObiXMLFileReader;\n  using Superclass = itk::XMLReader<itk::MetaDataDictionary>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(VarianObiXMLFileReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Determine if a file can be read */\n  int\n  CanReadFile(const char * name) override;\n\nprotected:\n  VarianObiXMLFileReader() { m_OutputObject = &m_Dictionary; };\n  ~VarianObiXMLFileReader() override = default;\n\n  void\n  StartElement(const char * name, const char ** atts) override;\n\n  void\n  EndElement(const char * name) override;\n\n  void\n  CharacterDataHandler(const char * inData, int inLength) override;\n\nprivate:\n  itk::MetaDataDictionary m_Dictionary;\n  std::string             m_CurCharacterData;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkVarianProBeamGeometryReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkVarianProBeamGeometryReader_h\n#define rtkVarianProBeamGeometryReader_h\n\n#include \"RTKExport.h\"\n#include <itkLightProcessObject.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\nnamespace rtk\n{\n\n/** \\class VarianProBeamGeometryReader\n *\n * Creates a 3D circular geometry from Varian ProBeam data.\n *\n * \\test rtkvariantest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT VarianProBeamGeometryReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(VarianProBeamGeometryReader);\n\n  /** Standard type alias */\n  using Self = VarianProBeamGeometryReader;\n  using Superclass = itk::LightProcessObject;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n  using FileNamesContainer = std::vector<std::string>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(VarianProBeamGeometryReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Get the pointer to the generated geometry object. */\n  itkGetMacro(Geometry, GeometryType::Pointer);\n\n  /** Set the path to the Varian ProBeam xml file containing geometric information. */\n  itkGetMacro(XMLFileName, std::string);\n  itkSetMacro(XMLFileName, std::string);\n\n  /** Set the vector of strings that contains the projection file names. Files\n   * are processed in sequential order. */\n  void\n  SetProjectionsFileNames(const FileNamesContainer & name)\n  {\n    if (m_ProjectionsFileNames != name)\n    {\n      m_ProjectionsFileNames = name;\n      this->Modified();\n    }\n  }\n  const FileNamesContainer &\n  GetProjectionsFileNames() const\n  {\n    return m_ProjectionsFileNames;\n  }\n\nprotected:\n  VarianProBeamGeometryReader();\n\n\nprivate:\n  void\n  GenerateData() override;\n\n  GeometryType::Pointer m_Geometry;\n  std::string           m_XMLFileName;\n  FileNamesContainer    m_ProjectionsFileNames;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkVarianProBeamXMLFileReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkVarianProBeamXMLFileReader_h\n#define rtkVarianProBeamXMLFileReader_h\n\n#ifdef _MSC_VER\n#  pragma warning(disable : 4786)\n#endif\n\n#include <itkXMLFile.h>\n#include <itkMetaDataDictionary.h>\n#include <itkMetaDataObject.h>\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class VarianProBeamXMLFileReader\n *\n * Reads the XML-format file written by a Varian OBI\n * machine for every acquisition\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT VarianProBeamXMLFileReader : public itk::XMLReader<itk::MetaDataDictionary>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(VarianProBeamXMLFileReader);\n\n  /** Standard type alias */\n  using Self = VarianProBeamXMLFileReader;\n  using Superclass = itk::XMLReader<itk::MetaDataDictionary>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(VarianProBeamXMLFileReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Determine if a file can be read */\n  int\n  CanReadFile(const char * name) override;\n\nprotected:\n  VarianProBeamXMLFileReader() { m_OutputObject = &m_Dictionary; };\n  ~VarianProBeamXMLFileReader() override = default;\n\n  void\n  StartElement(const char * name, const char ** atts) override;\n\n  void\n  EndElement(const char * name) override;\n\n  void\n  CharacterDataHandler(const char * inData, int inLength) override;\n\nprivate:\n  itk::MetaDataDictionary m_Dictionary;\n  std::string             m_CurCharacterData;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkVectorImageToImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkVectorImageToImageFilter_h\n#define rtkVectorImageToImageFilter_h\n\n#include \"rtkMacro.h\"\n\n#include <itkImageToImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\nnamespace rtk\n{\n/** \\class VectorImageToImageFilter\n * \\brief Re-writes a vector image as an image\n *\n * Depending on the dimensions of the input and output images, the filter\n * can have two different behaviors:\n *  - if the dimensions match, the channels of the input image are\n * concatenated in the last dimension. With an input image of size (X,Y)\n * containing N-components vectors, the output image will be of size (X, Y*N)\n *  - if the output image dimension equals to the input dimension plus one,\n * the additional dimension of the output image will contain the channels of the input.\n * With an input image of size (X,Y) containing N-components vectors,\n * the output image will be of size (X, Y, N).\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\ntemplate <typename InputImageType, typename OutputImageType>\nclass ITK_TEMPLATE_EXPORT VectorImageToImageFilter : public itk::ImageToImageFilter<InputImageType, OutputImageType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(VectorImageToImageFilter);\n\n  /** Standard class type alias. */\n  using Self = VectorImageToImageFilter;\n  using Superclass = itk::ImageToImageFilter<InputImageType, OutputImageType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  using OutputImageRegionType = typename OutputImageType::RegionType;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(VectorImageToImageFilter);\n\nprotected:\n  VectorImageToImageFilter();\n  ~VectorImageToImageFilter() override = default;\n\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** Does the real work. */\n  void\n  ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,\n                       itk::ThreadIdType             itkNotUsed(threadId)) override;\n\n  /** Splits the OutputRequestedRegion along the first direction, not the last */\n  const itk::ImageRegionSplitterBase *\n                                             GetImageRegionSplitter() const override;\n  itk::ImageRegionSplitterDirection::Pointer m_Splitter;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkVectorImageToImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkVectorImageToImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkVectorImageToImageFilter_hxx\n#define rtkVectorImageToImageFilter_hxx\n\n\n#include \"itkObjectFactory.h\"\n#include \"itkImageRegionIterator.h\"\n#include \"itkImageRegionConstIterator.h\"\n\nnamespace rtk\n{\n\ntemplate <typename InputImageType, typename OutputImageType>\nVectorImageToImageFilter<InputImageType, OutputImageType>::VectorImageToImageFilter()\n{\n  this->DynamicMultiThreadingOff();\n\n  // Set the direction along which the output requested region should NOT be split\n  m_Splitter = itk::ImageRegionSplitterDirection::New();\n  m_Splitter->SetDirection(OutputImageType::ImageDimension - 1);\n}\n\ntemplate <typename InputImageType, typename OutputImageType>\nconst itk::ImageRegionSplitterBase *\nVectorImageToImageFilter<InputImageType, OutputImageType>::GetImageRegionSplitter() const\n{\n  return m_Splitter;\n}\n\ntemplate <typename InputImageType, typename OutputImageType>\nvoid\nVectorImageToImageFilter<InputImageType, OutputImageType>::GenerateOutputInformation()\n{\n  const unsigned int InputDimension = InputImageType::ImageDimension;\n  const unsigned int OutputDimension = OutputImageType::ImageDimension;\n\n  if (!((OutputDimension == InputDimension) || (OutputDimension == (InputDimension + 1))))\n    itkGenericExceptionMacro(<< \"In VectorImageToImageFilter : input and output image dimensions are not compatible\");\n\n  typename OutputImageType::SizeType      outputSize;\n  typename OutputImageType::IndexType     outputIndex;\n  typename OutputImageType::RegionType    outputRegion;\n  typename OutputImageType::SpacingType   outputSpacing;\n  typename OutputImageType::PointType     outputOrigin;\n  typename OutputImageType::DirectionType outputDirection;\n\n  // If the output has an additional dimension, set the parameters\n  // for this new dimension. Fill() is used, but only the last\n  // dimension will not be overwritten by the next part\n  if (OutputDimension == (InputDimension + 1))\n  {\n    outputSize.Fill(this->GetInput()->GetVectorLength());\n    outputIndex.Fill(0);\n    outputSpacing.Fill(1);\n    outputOrigin.Fill(0);\n    outputDirection.SetIdentity();\n  }\n\n  // In all cases\n  for (unsigned int dim = 0; dim < InputDimension; dim++)\n  {\n    outputSize[dim] = this->GetInput()->GetLargestPossibleRegion().GetSize()[dim];\n    outputIndex[dim] = this->GetInput()->GetLargestPossibleRegion().GetIndex()[dim];\n    outputSpacing[dim] = this->GetInput()->GetSpacing()[dim];\n    outputOrigin[dim] = this->GetInput()->GetOrigin()[dim];\n    for (unsigned int j = 0; j < InputDimension; j++)\n      outputDirection[dim][j] = this->GetInput()->GetDirection()[dim][j];\n  }\n\n  // If dimensions match, overwrite the size on last dimension\n  if (OutputDimension == InputDimension)\n  {\n    outputSize[OutputDimension - 1] =\n      this->GetInput()->GetLargestPossibleRegion().GetSize()[OutputDimension - 1] * this->GetInput()->GetVectorLength();\n  }\n\n  outputRegion.SetSize(outputSize);\n  outputRegion.SetIndex(outputIndex);\n  this->GetOutput()->SetLargestPossibleRegion(outputRegion);\n  this->GetOutput()->SetSpacing(outputSpacing);\n  this->GetOutput()->SetOrigin(outputOrigin);\n  this->GetOutput()->SetDirection(outputDirection);\n}\n\ntemplate <typename InputImageType, typename OutputImageType>\nvoid\nVectorImageToImageFilter<InputImageType, OutputImageType>::GenerateInputRequestedRegion()\n{\n  typename InputImageType::Pointer inputPtr = const_cast<InputImageType *>(this->GetInput());\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename InputImageType, typename OutputImageType>\nvoid\nVectorImageToImageFilter<InputImageType, OutputImageType>::ThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread,\n  itk::ThreadIdType             itkNotUsed(threadId))\n{\n  const unsigned int InputDimension = InputImageType::ImageDimension;\n  const unsigned int OutputDimension = OutputImageType::ImageDimension;\n\n  typename InputImageType::SizeType   inputSize;\n  typename InputImageType::IndexType  inputIndex;\n  typename InputImageType::RegionType inputRegion;\n\n  for (unsigned int dim = 0; dim < InputDimension; dim++)\n  {\n    inputSize[dim] = outputRegionForThread.GetSize()[dim];\n    inputIndex[dim] = outputRegionForThread.GetIndex()[dim];\n  }\n  if (OutputDimension == InputDimension)\n  {\n    inputSize[OutputDimension - 1] = this->GetInput()->GetLargestPossibleRegion().GetSize()[OutputDimension - 1];\n    inputIndex[OutputDimension - 1] = this->GetInput()->GetLargestPossibleRegion().GetIndex()[OutputDimension - 1];\n  }\n  inputRegion.SetSize(inputSize);\n  inputRegion.SetIndex(inputIndex);\n\n  // Actual copy is the same in both cases\n  itk::ImageRegionConstIterator<InputImageType> inIt(this->GetInput(), inputRegion);\n  itk::ImageRegionIterator<OutputImageType>     outIt(this->GetOutput(), outputRegionForThread);\n  for (unsigned int channel = 0; channel < this->GetInput()->GetVectorLength(); channel++)\n  {\n    inIt.GoToBegin();\n    while (!inIt.IsAtEnd())\n    {\n      outIt.Set(inIt.Get()[channel]);\n      ++inIt;\n      ++outIt;\n    }\n  }\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkWarpFourDToProjectionStackImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkWarpFourDToProjectionStackImageFilter_h\n#define rtkWarpFourDToProjectionStackImageFilter_h\n\n#include \"rtkFourDToProjectionStackImageFilter.h\"\n#include \"rtkCyclicDeformationImageFilter.h\"\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n#include <vector>\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaWarpForwardProjectionImageFilter.h\"\n#  include \"rtkCudaCyclicDeformationImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class WarpFourDToProjectionStackImageFilter\n * \\brief Forward projection part for motion compensated iterative 4D reconstruction\n *\n * This filter is similar to FourDToProjectionStackImageFilter, except\n * that it uses a motion-compensated forward projection. A 4D displacement\n * vector field is therefore required, and its forward projection filter\n * cannot be changed.\n *\n * \\dot\n * digraph WarpFourDToProjectionStackImageFilter {\n *\n * Input0 [ label=\"Input 0 (Projections)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Input: 4D sequence of volumes)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (4D Sequence of DVFs)\"];\n * Input2 [shape=Mdiamond];\n * Output [label=\"Output (Output projections)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * FourDSource [ label=\"rtk::ConstantImageSource (4D volume)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ProjectionSource [ label=\"rtk::ConstantImageSource (projections)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * ForwardProj [ label=\"rtk::ForwardProjectionImageFilter\" URL=\"\\ref rtk::ForwardProjectionImageFilter\"];\n * Interpolation [ label=\"rtk::InterpolatorWithKnownWeightsImageFilter\"\n *                 URL=\"\\ref rtk::InterpolatorWithKnownWeightsImageFilter\"];\n * CyclicDeformation [label=\"rtk::CyclicDeformationImageFilter (for DVFs)\"\n *                    URL=\"\\ref rtk::CyclicDeformationImageFilter\"];\n * BeforePaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Paste [ label=\"itk::PasteImageFilter\" URL=\"\\ref itk::PasteImageFilter\"];\n * AfterPaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * Input2 -> CyclicDeformation;\n * ProjectionSource -> ForwardProj;\n * BeforePaste -> Paste;\n * FourDSource -> Interpolation;\n * Input1 -> Interpolation;\n * Interpolation -> ForwardProj;\n * CyclicDeformation -> ForwardProj;\n * Input0 -> BeforePaste[arrowhead=none];\n * ForwardProj -> Paste;\n * Paste -> AfterPaste[arrowhead=none];\n * AfterPaste -> Output;\n * AfterPaste -> BeforePaste [style=dashed, constraint=false];\n * }\n * \\enddot\n *\n * \\test rtkwarpfourdtoprojectionstacktest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT WarpFourDToProjectionStackImageFilter\n  : public rtk::FourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(WarpFourDToProjectionStackImageFilter);\n\n  /** Standard class type alias. */\n  using Self = WarpFourDToProjectionStackImageFilter;\n  using Superclass = rtk::FourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using VolumeType = ProjectionStackType;\n  using VectorForDVF = itk::CovariantVector<typename VolumeSeriesType::ValueType, VolumeSeriesType::ImageDimension - 1>;\n\n  using CPUVolumeSeriesType =\n    typename itk::Image<typename VolumeSeriesType::PixelType, VolumeSeriesType::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using DVFSequenceImageType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension>,\n                                itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension>>;\n  using DVFImageType = typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                                   itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension - 1>,\n                                                   itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension - 1>>;\n#else\n  using DVFSequenceImageType = typename itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = typename itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension - 1>;\n#endif\n  using CPUDVFInterpolatorType = CyclicDeformationImageFilter<DVFSequenceImageType, DVFImageType>;\n#ifdef RTK_USE_CUDA\n  using WarpForwardProjectionImageFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                JosephForwardProjectionImageFilter<ProjectionStackType, ProjectionStackType>,\n                                CudaWarpForwardProjectionImageFilter>;\n  using CudaCyclicDeformationImageFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                CPUDVFInterpolatorType,\n                                CudaCyclicDeformationImageFilter>;\n#else\n  using WarpForwardProjectionImageFilterType =\n    JosephForwardProjectionImageFilter<ProjectionStackType, ProjectionStackType>;\n  using CudaCyclicDeformationImageFilterType = CPUDVFInterpolatorType;\n#endif\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(WarpFourDToProjectionStackImageFilter);\n\n  using SignalVectorType = std::vector<double>;\n\n  /** The forward projection filter cannot be set by the user */\n  void\n  SetForwardProjectionFilter(typename Superclass::ForwardProjectionFilterType * itkNotUsed(_arg))\n  {\n    itkExceptionMacro(<< \"ForwardProjection cannot be changed\");\n  }\n\n  /** The ND + time motion vector field */\n  void\n  SetDisplacementField(const DVFSequenceImageType * DisplacementField);\n  typename DVFSequenceImageType::ConstPointer\n  GetDisplacementField();\n\n  void\n  SetSignal(const std::vector<double> signal) override;\n\n  /** Set and Get for the UseCudaCyclicDeformation variable */\n  itkSetMacro(UseCudaCyclicDeformation, bool);\n  itkGetMacro(UseCudaCyclicDeformation, bool);\n\nprotected:\n  WarpFourDToProjectionStackImageFilter();\n  ~WarpFourDToProjectionStackImageFilter() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  /** The first two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename CPUDVFInterpolatorType::Pointer m_DVFInterpolatorFilter;\n  std::vector<double>                      m_Signal;\n  bool                                     m_UseCudaCyclicDeformation{ false };\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkWarpFourDToProjectionStackImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkWarpFourDToProjectionStackImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkWarpFourDToProjectionStackImageFilter_hxx\n#define rtkWarpFourDToProjectionStackImageFilter_hxx\n\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nWarpFourDToProjectionStackImageFilter<VolumeSeriesType, ProjectionStackType>::WarpFourDToProjectionStackImageFilter()\n{\n  this->SetNumberOfRequiredInputs(3);\n\n  this->m_ForwardProjectionFilter = WarpForwardProjectionImageFilterType::New();\n  if (std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n    itkWarningMacro(\"The warp Forward project image filter exists only in CUDA. Ignoring the displacement vector field \"\n                    \"and using CPU Joseph forward projection\");\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpFourDToProjectionStackImageFilter<VolumeSeriesType, ProjectionStackType>::SetDisplacementField(\n  const DVFSequenceImageType * DisplacementField)\n{\n  this->SetNthInput(2, const_cast<DVFSequenceImageType *>(DisplacementField));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename WarpFourDToProjectionStackImageFilter<VolumeSeriesType,\n                                               ProjectionStackType>::DVFSequenceImageType::ConstPointer\nWarpFourDToProjectionStackImageFilter<VolumeSeriesType, ProjectionStackType>::GetDisplacementField()\n{\n  return static_cast<const DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(2));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpFourDToProjectionStackImageFilter<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n  this->m_Signal = signal;\n  this->Modified();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpFourDToProjectionStackImageFilter<VolumeSeriesType, ProjectionStackType>::GenerateOutputInformation()\n{\n  m_DVFInterpolatorFilter = CPUDVFInterpolatorType::New();\n  if (m_UseCudaCyclicDeformation)\n  {\n    if (std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n      itkGenericExceptionMacro(<< \"UseCudaCyclicDeformation option only available with itk::CudaImage.\");\n    m_DVFInterpolatorFilter = CudaCyclicDeformationImageFilterType::New();\n  }\n#ifdef RTK_USE_CUDA\n  if (!std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n  {\n    CudaWarpForwardProjectionImageFilter * wfp;\n    wfp = dynamic_cast<CudaWarpForwardProjectionImageFilter *>(this->m_ForwardProjectionFilter.GetPointer());\n    using CudaDVFImageType = itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension - 1>;\n    CudaDVFImageType * cudvf;\n    cudvf = dynamic_cast<CudaDVFImageType *>(m_DVFInterpolatorFilter->GetOutput());\n    wfp->SetDisplacementField(cudvf);\n  }\n#endif\n  m_DVFInterpolatorFilter->SetSignalVector(m_Signal);\n  m_DVFInterpolatorFilter->SetInput(this->GetDisplacementField());\n  m_DVFInterpolatorFilter->SetFrame(0);\n\n  Superclass::GenerateOutputInformation();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpFourDToProjectionStackImageFilter<VolumeSeriesType, ProjectionStackType>::GenerateInputRequestedRegion()\n{\n  // Input 0 is the stack of projections we update\n  typename ProjectionStackType::Pointer inputPtr0 = const_cast<ProjectionStackType *>(this->GetInput(0));\n  if (!inputPtr0)\n  {\n    return;\n  }\n  inputPtr0->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Input 1 is the volume series\n  typename VolumeSeriesType::Pointer inputPtr1 = static_cast<VolumeSeriesType *>(this->itk::ProcessObject::GetInput(1));\n  inputPtr1->SetRequestedRegionToLargestPossibleRegion();\n\n  // Input 2 is the sequence of DVFs\n  typename DVFSequenceImageType::Pointer inputPtr2 =\n    static_cast<DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(2));\n  inputPtr2->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpFourDToProjectionStackImageFilter<VolumeSeriesType, ProjectionStackType>::GenerateData()\n{\n  int ProjectionStackDimension = ProjectionStackType::ImageDimension;\n\n  int NumberProjs = this->GetInputProjectionStack()->GetRequestedRegion().GetSize(ProjectionStackDimension - 1);\n  int FirstProj = this->GetInputProjectionStack()->GetRequestedRegion().GetIndex(ProjectionStackDimension - 1);\n\n  bool firstProjectionProcessed = false;\n\n  // Process the projections in order\n  for (int proj = FirstProj; proj < FirstProj + NumberProjs; proj++)\n  {\n    // After the first update, we need to use the output as input.\n    if (firstProjectionProcessed)\n    {\n      typename ProjectionStackType::Pointer pimg = this->m_PasteFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      this->m_PasteFilter->SetDestinationImage(pimg);\n    }\n\n    // Update the paste region\n    this->m_PasteRegion.SetIndex(ProjectionStackDimension - 1, proj);\n\n    // Set the projection stack source\n    this->m_ConstantProjectionStackSource->SetIndex(this->m_PasteRegion.GetIndex());\n\n    // Set the Paste Filter. Since its output has been disconnected\n    // we need to set its RequestedRegion manually (it will never\n    // be updated by a downstream filter)\n    this->m_PasteFilter->SetSourceRegion(this->m_PasteRegion);\n    this->m_PasteFilter->SetDestinationIndex(this->m_PasteRegion.GetIndex());\n    this->m_PasteFilter->GetOutput()->SetRequestedRegion(\n      this->m_PasteFilter->GetDestinationImage()->GetLargestPossibleRegion());\n\n    // Set the Interpolation filter\n    this->m_InterpolationFilter->SetProjectionNumber(proj);\n\n    // Set the DVF interpolator\n    m_DVFInterpolatorFilter->SetFrame(proj);\n\n    // Update the last filter\n    this->m_PasteFilter->Update();\n\n    // Update condition\n    firstProjectionProcessed = true;\n  }\n\n  // Graft its output\n  this->GraftOutput(this->m_PasteFilter->GetOutput());\n\n  // Release the data in internal filters\n  this->m_DVFInterpolatorFilter->GetOutput()->ReleaseData();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkWarpProjectionStackToFourDImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkWarpProjectionStackToFourDImageFilter_h\n#define rtkWarpProjectionStackToFourDImageFilter_h\n\n#include \"rtkCyclicDeformationImageFilter.h\"\n#include \"rtkProjectionStackToFourDImageFilter.h\"\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaWarpBackProjectionImageFilter.h\"\n#  include \"rtkCudaCyclicDeformationImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class WarpProjectionStackToFourDImageFilter\n * \\brief Back projection part for motion compensated iterative 4D reconstruction\n *\n * This filter is similar to ProjectionStackToFourDImageFilter, except\n * that it uses a motion-compensated backprojection. A 4D displacement\n * vector field is therefore required, and its back projection filter\n * cannot be changed.\n *\n * \\dot\n * digraph WarpProjectionStackToFourDImageFilter {\n *\n * Input0 [label=\"Input 0 (4D sequence of volumes)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Projections)\"];\n * Input1 [shape=Mdiamond];\n * Input2 [label=\"Input 2 (4D Sequence of DVFs)\"];\n * Input2 [shape=Mdiamond];\n * Output [label=\"Output (4D sequence of volumes)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * Extract [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n * VolumeSeriesSource [ label=\"rtk::ConstantImageSource (4D)\" URL=\"\\ref rtk::ConstantImageSource\"];\n * AfterSource4D [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * Source [ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * CyclicDeformation [label=\"rtk::CyclicDeformationImageFilter (for DVFs)\"\n *                    URL=\"\\ref rtk::CyclicDeformationImageFilter\"];\n * Backproj [ label=\"rtk::CudaWarpBackProjectionImageFilter\" URL=\"\\ref rtk::CudaWarpBackProjectionImageFilter\"];\n * Splat [ label=\"rtk::SplatWithKnownWeightsImageFilter\" URL=\"\\ref rtk::SplatWithKnownWeightsImageFilter\"];\n * AfterSplat [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * Input1 -> Extract;\n * Input0 -> VolumeSeriesSource [style=invis];\n * Input2 -> CyclicDeformation;\n * VolumeSeriesSource -> AfterSource4D[arrowhead=none];\n * AfterSource4D -> Splat;\n * Extract -> Backproj;\n * CyclicDeformation -> Backproj;\n * Source -> Backproj;\n * Backproj -> Splat;\n * Splat -> AfterSplat[arrowhead=none];\n * AfterSplat -> Output;\n * AfterSplat -> AfterSource4D[style=dashed, constraint=none];\n * }\n * \\enddot\n *\n * \\test rtkfourdconjugategradienttest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nclass ITK_TEMPLATE_EXPORT WarpProjectionStackToFourDImageFilter\n  : public ProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(WarpProjectionStackToFourDImageFilter);\n\n  /** Standard class type alias. */\n  using Self = WarpProjectionStackToFourDImageFilter;\n  using Superclass = ProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using VolumeType = ProjectionStackType;\n  using VectorForDVF = itk::CovariantVector<typename VolumeSeriesType::ValueType, VolumeSeriesType::ImageDimension - 1>;\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUVolumeSeriesType =\n    typename itk::Image<typename VolumeSeriesType::PixelType, VolumeSeriesType::ImageDimension>;\n#ifdef RTK_USE_CUDA\n  using DVFSequenceImageType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension>,\n                                itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension>>;\n  using DVFImageType = typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                                   itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension - 1>,\n                                                   itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension - 1>>;\n  using WarpBackProjectionImageFilter =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                BackProjectionImageFilter<VolumeType, VolumeType>,\n                                CudaWarpBackProjectionImageFilter>;\n  using CPUDVFInterpolatorType = CyclicDeformationImageFilter<DVFSequenceImageType, DVFImageType>;\n  using CudaCyclicDeformationImageFilterType =\n    typename std::conditional_t<std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>,\n                                CPUDVFInterpolatorType,\n                                CudaCyclicDeformationImageFilter>;\n#else\n  using DVFSequenceImageType = itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension>;\n  using DVFImageType = itk::Image<VectorForDVF, VolumeSeriesType::ImageDimension - 1>;\n  using WarpBackProjectionImageFilter = BackProjectionImageFilter<VolumeType, VolumeType>;\n  using CPUDVFInterpolatorType = CyclicDeformationImageFilter<DVFSequenceImageType, DVFImageType>;\n  using CudaCyclicDeformationImageFilterType = CPUDVFInterpolatorType;\n#endif\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(WarpProjectionStackToFourDImageFilter);\n\n  using SignalVectorType = std::vector<double>;\n\n  /** The back projection filter cannot be set by the user */\n  void\n  SetBackProjectionFilter(typename Superclass::BackProjectionFilterType * itkNotUsed(_arg))\n  {\n    itkExceptionMacro(<< \"BackProjection cannot be changed\");\n  }\n\n  /** The ND + time motion vector field */\n  void\n  SetDisplacementField(const DVFSequenceImageType * DisplacementField);\n  typename DVFSequenceImageType::ConstPointer\n  GetDisplacementField();\n\n  void\n  SetSignal(const std::vector<double> signal) override;\n\n  /** Set and Get for the UseCudaCyclicDeformation variable */\n  itkSetMacro(UseCudaCyclicDeformation, bool);\n  itkGetMacro(UseCudaCyclicDeformation, bool);\n\nprotected:\n  WarpProjectionStackToFourDImageFilter();\n  ~WarpProjectionStackToFourDImageFilter() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  /** The first two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename CPUDVFInterpolatorType::Pointer m_DVFInterpolatorFilter;\n  std::vector<double>                      m_Signal;\n  bool                                     m_UseCudaCyclicDeformation;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkWarpProjectionStackToFourDImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkWarpProjectionStackToFourDImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkWarpProjectionStackToFourDImageFilter_hxx\n#define rtkWarpProjectionStackToFourDImageFilter_hxx\n\n\n#include <itkObjectFactory.h>\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n\nnamespace rtk\n{\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nWarpProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>::WarpProjectionStackToFourDImageFilter()\n{\n  this->SetNumberOfRequiredInputs(3);\n\n  this->m_UseCudaSplat = !std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>;\n  this->m_UseCudaSources = !std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>;\n  m_UseCudaCyclicDeformation = false;\n\n  this->m_BackProjectionFilter = WarpBackProjectionImageFilter::New();\n  if (std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n    itkWarningMacro(\"The warp back project image filter exists only in CUDA. Ignoring the displacement vector field \"\n                    \"and using CPU voxel-based back projection\");\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>::SetDisplacementField(\n  const DVFSequenceImageType * DisplacementField)\n{\n  this->SetNthInput(2, const_cast<DVFSequenceImageType *>(DisplacementField));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\ntypename WarpProjectionStackToFourDImageFilter<VolumeSeriesType,\n                                               ProjectionStackType>::DVFSequenceImageType::ConstPointer\nWarpProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>::GetDisplacementField()\n{\n  return static_cast<const DVFSequenceImageType *>(this->itk::ProcessObject::GetInput(2));\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>::SetSignal(\n  const std::vector<double> signal)\n{\n  this->m_Signal = signal;\n  this->Modified();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>::GenerateOutputInformation()\n{\n  m_DVFInterpolatorFilter = CPUDVFInterpolatorType::New();\n  if (m_UseCudaCyclicDeformation)\n  {\n    if (std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n      itkGenericExceptionMacro(<< \"UseCudaCyclicDeformation option only available with itk::CudaImage.\");\n    m_DVFInterpolatorFilter = CudaCyclicDeformationImageFilterType::New();\n  }\n#ifdef RTK_USE_CUDA\n  if (!std::is_same_v<VolumeSeriesType, CPUVolumeSeriesType>)\n  {\n    CudaWarpBackProjectionImageFilter * wbp;\n    wbp = dynamic_cast<CudaWarpBackProjectionImageFilter *>(this->m_BackProjectionFilter.GetPointer());\n    using CudaDVFImageType = itk::CudaImage<VectorForDVF, VolumeSeriesType::ImageDimension - 1>;\n    CudaDVFImageType * cudvf;\n    cudvf = dynamic_cast<CudaDVFImageType *>(m_DVFInterpolatorFilter->GetOutput());\n    wbp->SetDisplacementField(cudvf);\n  }\n#endif\n  m_DVFInterpolatorFilter->SetSignalVector(m_Signal);\n  m_DVFInterpolatorFilter->SetInput(this->GetDisplacementField());\n  m_DVFInterpolatorFilter->SetFrame(0);\n\n  Superclass::GenerateOutputInformation();\n}\n\ntemplate <typename VolumeSeriesType, typename ProjectionStackType>\nvoid\nWarpProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>::GenerateData()\n{\n  int Dimension = ProjectionStackType::ImageDimension;\n\n  // Set the Extract filter\n  typename ProjectionStackType::RegionType extractRegion;\n  extractRegion = this->GetInputProjectionStack()->GetLargestPossibleRegion();\n  extractRegion.SetSize(Dimension - 1, 1);\n\n  // Declare the pointer to a VolumeSeries that will be used in the pipeline\n  typename VolumeSeriesType::Pointer pimg;\n\n  int NumberProjs = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  int FirstProj = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n\n  bool firstProjectionProcessed = false;\n\n  // Process the projections in order\n  for (int proj = FirstProj; proj < FirstProj + NumberProjs; proj++)\n  {\n    // After the first update, we need to use the output as input.\n    if (firstProjectionProcessed)\n    {\n      pimg = this->m_SplatFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      this->m_SplatFilter->SetInputVolumeSeries(pimg);\n    }\n\n    // Set the Extract Filter\n    extractRegion.SetIndex(Dimension - 1, proj);\n    this->m_ExtractFilter->SetExtractionRegion(extractRegion);\n\n    // Set the DVF interpolator\n    m_DVFInterpolatorFilter->SetFrame(proj);\n\n    // Set the splat filter\n    this->m_SplatFilter->SetProjectionNumber(proj);\n\n    // Update the last filter\n    this->m_SplatFilter->Update();\n\n    // Update condition\n    firstProjectionProcessed = true;\n  }\n\n  // Graft its output\n  this->GraftOutput(this->m_SplatFilter->GetOutput());\n\n  // Release the data in internal filters\n  if (pimg.IsNotNull())\n    pimg->ReleaseData();\n\n  this->m_BackProjectionFilter->GetOutput()->ReleaseData();\n  this->m_ExtractFilter->GetOutput()->ReleaseData();\n  this->m_ConstantVolumeSource->GetOutput()->ReleaseData();\n  this->m_DVFInterpolatorFilter->GetOutput()->ReleaseData();\n}\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkWarpSequenceImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkWarpSequenceImageFilter_h\n#define rtkWarpSequenceImageFilter_h\n\n#include \"rtkConstantImageSource.h\"\n\n#include <itkExtractImageFilter.h>\n#include <itkPasteImageFilter.h>\n#include <itkCastImageFilter.h>\n#include <itkNearestNeighborInterpolateImageFunction.h>\n\n#ifdef RTK_USE_CUDA\n#  include \"rtkCudaWarpImageFilter.h\"\n#  include \"rtkCudaForwardWarpImageFilter.h\"\n#  include \"rtkCudaCyclicDeformationImageFilter.h\"\n#else\n#  include <itkWarpImageFilter.h>\n#  include \"rtkForwardWarpImageFilter.h\"\n#  include \"rtkCyclicDeformationImageFilter.h\"\n#endif\n\nnamespace rtk\n{\n/** \\class WarpSequenceImageFilter\n * \\brief Applies an N-D + time Motion Vector Field to an N-D + time sequence of images\n *\n * Most of the work in this filter is performed by the underlying itkWarpImageFilter.\n * The only difference is that this filter manages the last dimension specifically as time.\n *\n * \\dot\n * digraph WarpSequenceImageFilter {\n *\n * Input0 [ label=\"Input 0 (Sequence of images)\"];\n * Input0 [shape=Mdiamond];\n * Input1 [label=\"Input 1 (Sequence of DVFs)\"];\n * Input1 [shape=Mdiamond];\n * Output [label=\"Output (Sequence of images)\"];\n * Output [shape=Mdiamond];\n *\n * node [shape=box];\n * Extract [label=\"itk::ExtractImageFilter (for images)\" URL=\"\\ref itk::ExtractImageFilter\"];\n * CyclicDeformation [label=\"rtk::CyclicDeformationImageFilter (for DVFs)\"\n *                    URL=\"\\ref rtk::CyclicDeformationImageFilter\"];\n * Warp [ label=\"itk::WarpImageFilter\" URL=\"\\ref itk::WarpImageFilter\"];\n * Cast [ label=\"itk::CastImageFilter\" URL=\"\\ref itk::CastImageFilter\"];\n * Paste [ label=\"itk::PasteImageFilter\" URL=\"\\ref itk::PasteImageFilter\"];\n * ConstantSource [ label=\"rtk::ConstantImageSource\" URL=\"\\ref rtk::ConstantImageSource\"];\n * BeforePaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n * AfterPaste [label=\"\", fixedsize=\"false\", width=0, height=0, shape=none];\n *\n * Input0 -> Extract;\n * Input1 -> CyclicDeformation;\n * Extract -> Warp;\n * CyclicDeformation -> Warp;\n * Warp -> Cast;\n * Cast -> Paste;\n * ConstantSource -> BeforePaste [arrowhead=none];\n * BeforePaste -> Paste;\n * Paste -> AfterPaste [arrowhead=none];\n * AfterPaste -> BeforePaste [style=dashed, constraint=false];\n * AfterPaste -> Output [style=dashed];\n * }\n * \\enddot\n *\n * \\test rtkfourdroostertest.cxx\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK ReconstructionAlgorithm\n */\n\ntemplate <typename TImageSequence,\n          typename TDVFImageSequence =\n            itk::Image<itk::CovariantVector<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n                       TImageSequence::ImageDimension>,\n          typename TImage = itk::Image<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n          typename TDVFImage =\n            itk::Image<itk::CovariantVector<typename TImageSequence::ValueType, TImageSequence::ImageDimension - 1>,\n                       TImageSequence::ImageDimension - 1>>\nclass ITK_TEMPLATE_EXPORT WarpSequenceImageFilter : public itk::ImageToImageFilter<TImageSequence, TImageSequence>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(WarpSequenceImageFilter);\n\n  /** Standard class type alias. */\n  using Self = WarpSequenceImageFilter;\n  using Superclass = itk::ImageToImageFilter<TImageSequence, TImageSequence>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** SFINAE type alias, depending on whether a CUDA image is used. */\n  using CPUImageType = typename itk::Image<typename TImage::PixelType, TImage::ImageDimension>;\n  using CPUWarpFilterType = typename itk::WarpImageFilter<TImage, TImage, TDVFImage>;\n#ifdef RTK_USE_CUDA\n  using WarpFilterType =\n    typename std::conditional_t<std::is_same_v<TImage, CPUImageType>, CPUWarpFilterType, CudaWarpImageFilter>;\n  using ForwardWarpFilterType = typename std::conditional_t<std::is_same_v<TImage, CPUImageType>,\n                                                            ForwardWarpImageFilter<TImage, TImage, TDVFImage>,\n                                                            CudaForwardWarpImageFilter>;\n  using CudaCyclicDeformationImageFilterType =\n    typename std::conditional_t<std::is_same_v<TImage, CPUImageType>,\n                                CyclicDeformationImageFilter<TDVFImageSequence, TDVFImage>,\n                                CudaCyclicDeformationImageFilter>;\n#else\n  using WarpFilterType = CPUWarpFilterType;\n  using ForwardWarpFilterType = ForwardWarpImageFilter<TImage, TImage, TDVFImage>;\n  using CudaCyclicDeformationImageFilterType = CyclicDeformationImageFilter<TDVFImageSequence, TDVFImage>;\n#endif\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(WarpSequenceImageFilter);\n\n  /** Set the motion vector field used in input 1 */\n  void\n  SetDisplacementField(const TDVFImageSequence * DVFs);\n\n  /** Get the motion vector field used in input 1 */\n  typename TDVFImageSequence::Pointer\n  GetDisplacementField();\n\n  /** Set/Get for m_ForwardWarp */\n  itkGetMacro(ForwardWarp, bool);\n  itkSetMacro(ForwardWarp, bool);\n\n  /** Phase shift to simulate phase estimation errors */\n  itkSetMacro(PhaseShift, float);\n  itkGetMacro(PhaseShift, float);\n\n  /** Information for the CUDA warp filter, to avoid using RTTI */\n  itkSetMacro(UseNearestNeighborInterpolationInWarping, bool);\n  itkGetMacro(UseNearestNeighborInterpolationInWarping, bool);\n\n  /** Set and Get for the UseCudaCyclicDeformation variable */\n  itkSetMacro(UseCudaCyclicDeformation, bool);\n  itkGetMacro(UseCudaCyclicDeformation, bool);\n\n  /** Typedefs of internal filters */\n  using LinearInterpolatorType = itk::LinearInterpolateImageFunction<TImage, double>;\n  using NearestNeighborInterpolatorType = itk::NearestNeighborInterpolateImageFunction<TImage, double>;\n  using ExtractFilterType = itk::ExtractImageFilter<TImageSequence, TImage>;\n  using DVFInterpolatorType = rtk::CyclicDeformationImageFilter<TDVFImageSequence, TDVFImage>;\n  using PasteFilterType = itk::PasteImageFilter<TImageSequence, TImageSequence>;\n  using CastFilterType = itk::CastImageFilter<TImage, TImageSequence>;\n  using ConstantImageSourceType = rtk::ConstantImageSource<TImageSequence>;\n\nprotected:\n  WarpSequenceImageFilter();\n  ~WarpSequenceImageFilter() override = default;\n\n  /** Does the real work. */\n  void\n  GenerateData() override;\n\n  /** Member pointers to the filters used internally (for convenience)*/\n  typename CPUWarpFilterType::Pointer       m_WarpFilter;\n  typename ExtractFilterType::Pointer       m_ExtractFilter;\n  typename DVFInterpolatorType::Pointer     m_DVFInterpolatorFilter;\n  typename PasteFilterType::Pointer         m_PasteFilter;\n  typename CastFilterType::Pointer          m_CastFilter;\n  typename ConstantImageSourceType::Pointer m_ConstantSource;\n\n  /** Extraction regions for both extract filters */\n  typename TImageSequence::RegionType m_ExtractAndPasteRegion;\n\n  /** Perform a forward warping (using splat) instead of the standard backward warping */\n  bool  m_ForwardWarp;\n  float m_PhaseShift;\n\n  /** The inputs of this filter have the same type (float, 3) but not the same meaning\n   * It is normal that they do not occupy the same physical space. Therefore this check\n   * must be removed */\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** The volume and the projections must have different requested regions\n   */\n  void\n  GenerateOutputInformation() override;\n  void\n  GenerateInputRequestedRegion() override;\n\n  bool m_UseNearestNeighborInterpolationInWarping; // Default is false, linear interpolation is used instead\n  bool m_UseCudaCyclicDeformation;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkWarpSequenceImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkWarpSequenceImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkWarpSequenceImageFilter_hxx\n#define rtkWarpSequenceImageFilter_hxx\n\n#include \"math.h\"\n\n\n#include <itkImageFileWriter.h>\n#include <iostream>\n#include <sstream>\n#include <string>\n\nnamespace rtk\n{\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nWarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::WarpSequenceImageFilter()\n{\n  this->SetNumberOfRequiredInputs(2);\n\n  // Set default member values\n  m_ForwardWarp = false;\n  m_UseNearestNeighborInterpolationInWarping = false;\n  m_UseCudaCyclicDeformation = false;\n\n  // Create the filters\n  m_ExtractFilter = ExtractFilterType::New();\n  m_PasteFilter = PasteFilterType::New();\n  m_CastFilter = CastFilterType::New();\n  m_ConstantSource = ConstantImageSourceType::New();\n  m_PhaseShift = 0;\n\n  // Set permanent connections\n  m_PasteFilter->SetSourceImage(m_CastFilter->GetOutput());\n\n  // Set permanent parameters\n  m_ExtractFilter->SetDirectionCollapseToIdentity();\n\n  // Set memory management parameters\n  m_CastFilter->SetInPlace(false);\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nWarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::SetDisplacementField(\n  const TDVFImageSequence * DVFs)\n{\n  this->SetNthInput(1, const_cast<TDVFImageSequence *>(DVFs));\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\ntypename TDVFImageSequence::Pointer\nWarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GetDisplacementField()\n{\n  return static_cast<TDVFImageSequence *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nWarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GenerateOutputInformation()\n{\n  int Dimension = TImageSequence::ImageDimension;\n\n  m_DVFInterpolatorFilter = DVFInterpolatorType::New();\n\n  // Create the right warp filter (regular or forward)\n  if (m_ForwardWarp)\n    m_WarpFilter = ForwardWarpFilterType::New();\n  else\n    m_WarpFilter = WarpFilterType::New();\n  if (m_UseCudaCyclicDeformation)\n  {\n    if (std::is_same_v<TImage, CPUImageType>)\n      itkGenericExceptionMacro(<< \"UseCudaCyclicDeformation option only available with itk::CudaImage.\");\n    m_DVFInterpolatorFilter = CudaCyclicDeformationImageFilterType::New();\n  }\n\n  auto linearInterpolator = LinearInterpolatorType::New();\n  auto nearestNeighborInterpolator = NearestNeighborInterpolatorType::New();\n\n  if (m_UseNearestNeighborInterpolationInWarping)\n    m_WarpFilter->SetInterpolator(nearestNeighborInterpolator);\n  else\n    m_WarpFilter->SetInterpolator(linearInterpolator);\n\n  // Set runtime connections\n  m_WarpFilter->SetInput(m_ExtractFilter->GetOutput());\n  m_WarpFilter->SetDisplacementField(m_DVFInterpolatorFilter->GetOutput());\n  m_CastFilter->SetInput(m_WarpFilter->GetOutput());\n  m_ExtractFilter->SetInput(this->GetInput(0));\n  m_DVFInterpolatorFilter->SetInput(this->GetDisplacementField());\n\n  // Generate a signal and pass it to the DVFInterpolator\n  std::vector<double> signal;\n  float               temp = NAN;\n  int                 nbFrames = this->GetInput(0)->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  for (int frame = 0; frame < nbFrames; frame++)\n  {\n    temp = (float)frame / (float)nbFrames + m_PhaseShift;\n    if (temp >= 1)\n      temp = temp - 1;\n    if (temp < 0)\n      temp = temp + 1;\n    signal.push_back(temp);\n  }\n  m_DVFInterpolatorFilter->SetSignalVector(signal);\n\n  // Initialize the source\n  m_ConstantSource->SetInformationFromImage(this->GetInput(0));\n  m_ConstantSource->Update();\n  m_PasteFilter->SetDestinationImage(m_ConstantSource->GetOutput());\n\n  // Set extraction regions and indices\n  m_ExtractAndPasteRegion = this->GetInput(0)->GetLargestPossibleRegion();\n  m_ExtractAndPasteRegion.SetSize(Dimension - 1, 0);\n  m_ExtractAndPasteRegion.SetIndex(Dimension - 1, 0);\n\n  m_ExtractFilter->SetExtractionRegion(m_ExtractAndPasteRegion);\n  m_DVFInterpolatorFilter->SetFrame(0);\n\n  m_ExtractFilter->UpdateOutputInformation();\n  m_DVFInterpolatorFilter->UpdateOutputInformation();\n\n  m_WarpFilter->SetOutputParametersFromImage(m_ExtractFilter->GetOutput());\n\n  m_CastFilter->UpdateOutputInformation();\n\n  m_PasteFilter->SetSourceRegion(m_CastFilter->GetOutput()->GetLargestPossibleRegion());\n  m_PasteFilter->SetDestinationIndex(m_ExtractAndPasteRegion.GetIndex());\n\n  // Have the last filter calculate its output information\n  m_PasteFilter->UpdateOutputInformation();\n\n  // Copy it as the output information of the composite filter\n  this->GetOutput()->CopyInformation(m_PasteFilter->GetOutput());\n}\n\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nWarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get pointers to the input and output\n  typename TImageSequence::Pointer inputPtr = const_cast<TImageSequence *>(this->GetInput(0));\n  inputPtr->SetRequestedRegionToLargestPossibleRegion();\n\n  typename TDVFImageSequence::Pointer inputDVFPtr = this->GetDisplacementField();\n  inputDVFPtr->SetRequestedRegionToLargestPossibleRegion();\n}\n\ntemplate <typename TImageSequence, typename TDVFImageSequence, typename TImage, typename TDVFImage>\nvoid\nWarpSequenceImageFilter<TImageSequence, TDVFImageSequence, TImage, TDVFImage>::GenerateData()\n{\n  int Dimension = TImageSequence::ImageDimension;\n\n  // Declare an image pointer to disconnect the output of paste\n  typename TImageSequence::Pointer pimg;\n\n  for (unsigned int frame = 0; frame < this->GetInput(0)->GetLargestPossibleRegion().GetSize(Dimension - 1); frame++)\n  {\n    if (frame > 0) // After the first frame, use the output of paste as input\n    {\n      pimg = m_PasteFilter->GetOutput();\n      pimg->DisconnectPipeline();\n      m_PasteFilter->SetDestinationImage(pimg);\n    }\n\n    m_ExtractAndPasteRegion.SetIndex(Dimension - 1, frame);\n\n    // I do not understand at all why, but performing an UpdateLargestPossibleRegion\n    // on these two filters is absolutely necessary. Otherwise some unexpected\n    // motion occurs (if anyone finds out why, I'm all ears: write to cyril.mory@creatis.insa-lyon.fr)\n    m_ExtractFilter->SetExtractionRegion(m_ExtractAndPasteRegion);\n    m_ExtractFilter->UpdateLargestPossibleRegion();\n\n    m_DVFInterpolatorFilter->SetFrame(frame);\n    m_DVFInterpolatorFilter->UpdateLargestPossibleRegion();\n\n    m_CastFilter->Update();\n\n    m_PasteFilter->SetSourceRegion(m_CastFilter->GetOutput()->GetLargestPossibleRegion());\n    m_PasteFilter->SetDestinationIndex(m_ExtractAndPasteRegion.GetIndex());\n\n    m_PasteFilter->UpdateLargestPossibleRegion();\n  }\n  this->GraftOutput(m_PasteFilter->GetOutput());\n\n  m_ExtractFilter->GetOutput()->ReleaseData();\n  m_WarpFilter->GetOutput()->ReleaseData();\n  m_CastFilter->GetOutput()->ReleaseData();\n}\n\n\n} // namespace rtk\n\n\n#endif\n"
  },
  {
    "path": "include/rtkWatcherForResourceProbe.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkWatcherForResourceProbe_h\n#define rtkWatcherForResourceProbe_h\n\n#include \"RTKExport.h\"\n#include <itkCommand.h>\n#include <itkProcessObject.h>\n\nnamespace rtk\n{\n/** \\class WatcherForResourceProbe\n * \\brief Very light watcher to monitor Start and End events\n * on all filters\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n */\n\nusing namespace itk;\n\nclass RTK_EXPORT WatcherForResourceProbe\n{\npublic:\n  /** Constructor. Takes a ProcessObject to monitor and an optional\n   * comment string that is prepended to each event message. */\n  WatcherForResourceProbe(itk::ProcessObject * o);\n\n  /** Copy constructor */\n  WatcherForResourceProbe(const WatcherForResourceProbe &);\n\n  /** operator=  */\n  WatcherForResourceProbe &\n  operator=(const WatcherForResourceProbe &);\n\n  /** Destructor. */\n  virtual ~WatcherForResourceProbe();\n\n  /** Method to get the name of the class being monitored by this\n   *  WatcherForResourceProbe */\n  const char *\n  GetNameOfClass()\n  {\n    return (m_Process ? m_Process->GetNameOfClass() : \"None\");\n  }\n\n  /** Methods to access member data */\n  /** Get a pointer to the process object being watched. */\n  const ProcessObject *\n  GetProcess() const\n  {\n    return m_Process;\n  }\n\nprotected:\n  /** Callback method to show the StartEvent */\n  virtual void\n  StartFilter();\n\n  /** Callback method to show the EndEvent */\n  virtual void\n  EndFilter();\n\n  /** Callback method to show the DeleteEvent */\n  virtual void\n  DeleteFilter();\n\n\nprivate:\n  itk::ProcessObject * m_Process;\n\n  using CommandType = SimpleMemberCommand<WatcherForResourceProbe>;\n  CommandType::Pointer m_StartFilterCommand;\n  CommandType::Pointer m_EndFilterCommand;\n  CommandType::Pointer m_DeleteFilterCommand;\n\n  unsigned long m_StartTag;\n  unsigned long m_EndTag;\n  unsigned long m_DeleteTag;\n};\n\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkWaterPrecorrectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkWaterPrecorrectionImageFilter_h\n#define rtkWaterPrecorrectionImageFilter_h\n\n#include <vector>\n#include <itkInPlaceImageFilter.h>\n\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n/** \\class WaterPrecorrectionImageFilter\n * \\brief Performs the classical water precorrection for beam hardening (Kachelriess, Med. Phys. 2006)\n *\n * \\test rtkwaterprecorrectiontest.cxx\n *\n * \\author S. Brousmiche\n *\n * \\ingroup RTK ImageToImageFilter\n */\n\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT WaterPrecorrectionImageFilter : public itk::InPlaceImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(WaterPrecorrectionImageFilter);\n\n  /** Standard class type alias. */\n  using Self = WaterPrecorrectionImageFilter;\n  using Superclass = itk::InPlaceImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Convenient type alias. */\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using VectorType = std::vector<double>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(WaterPrecorrectionImageFilter);\n\n  /** Get / Set the Median window that are going to be used during the operation\n   */\n  itkGetMacro(Coefficients, VectorType);\n  virtual void\n  SetCoefficients(const VectorType _arg)\n  {\n    if (this->m_Coefficients != _arg)\n    {\n      this->m_Coefficients = _arg;\n      this->Modified();\n    }\n  }\n\nprotected:\n  WaterPrecorrectionImageFilter();\n  ~WaterPrecorrectionImageFilter() override = default;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  VectorType m_Coefficients; // Correction coefficients\n};\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkWaterPrecorrectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkWaterPrecorrectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkWaterPrecorrectionImageFilter_hxx\n#define rtkWaterPrecorrectionImageFilter_hxx\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIterator.h>\n\n\nnamespace rtk\n{\ntemplate <class TInputImage, class TOutputImage>\nWaterPrecorrectionImageFilter<TInputImage, TOutputImage>::WaterPrecorrectionImageFilter()\n{\n  m_Coefficients.push_back(0.0); // No correction by default\n  m_Coefficients.push_back(1.0);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nWaterPrecorrectionImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  const int csize = m_Coefficients.size();\n\n  typename itk::ImageRegionConstIterator<TInputImage> itIn(this->GetInput(), outputRegionForThread);\n  typename itk::ImageRegionIterator<TOutputImage>     itOut(this->GetOutput(), outputRegionForThread);\n\n  if (csize >= 3)\n  {\n    itIn.GoToBegin();\n    itOut.GoToBegin();\n\n    while (!itIn.IsAtEnd())\n    {\n      float v = itIn.Get();\n      float out = m_Coefficients[0] + m_Coefficients[1] * v;\n      float bpow = v * v;\n\n      for (int i = 2; i < csize; i++)\n      {\n        out += m_Coefficients[i] * bpow;\n        bpow = bpow * v;\n      }\n      itOut.Set(out);\n\n      ++itIn;\n      ++itOut;\n    }\n  }\n  else if ((csize == 2) && ((m_Coefficients[0] != 0) || (m_Coefficients[1] != 1)))\n  {\n    itIn.GoToBegin();\n    itOut.GoToBegin();\n    while (!itIn.IsAtEnd())\n    {\n      itOut.Set(m_Coefficients[0] + m_Coefficients[1] * itIn.Get());\n      ++itIn;\n      ++itOut;\n    }\n  }\n  else if ((csize == 1) && (m_Coefficients[0] != 0))\n  {\n    itIn.GoToBegin();\n    itOut.GoToBegin();\n    while (!itIn.IsAtEnd())\n    {\n      itOut.Set(m_Coefficients[0]);\n      ++itIn;\n      ++itOut;\n    }\n  }\n}\n} // end namespace rtk\n\n#endif // rtkWaterPrecorrectionImageFilter_hxx\n"
  },
  {
    "path": "include/rtkWeidingerForwardModelImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkWeidingerForwardModelImageFilter_h\n#define rtkWeidingerForwardModelImageFilter_h\n\n#include \"itkImageToImageFilter.h\"\n#include \"rtkMacro.h\"\n\n#ifdef RTK_USE_CUDA\n#  include <itkCudaImage.h>\n#endif\n\nnamespace rtk\n{\n/** \\class WeidingerForwardModelImageFilter\n * \\brief Performs intermediate computations in Weidinger2016\n *\n * This filter performs all computations between forward and\n * back projection in Weidinger2016\n *\n * \\author Cyril Mory\n *\n * \\ingroup RTK\n *\n */\ntemplate <class TDecomposedProjections,\n          class TMeasuredProjections,\n          class TIncidentSpectrum,\n          class TProjections =\n            itk::Image<typename TDecomposedProjections::PixelType::ValueType, TDecomposedProjections::ImageDimension>>\nclass ITK_TEMPLATE_EXPORT WeidingerForwardModelImageFilter\n  : public itk::ImageToImageFilter<TDecomposedProjections, TDecomposedProjections>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(WeidingerForwardModelImageFilter);\n\n  /** Standard class type alias. */\n  using Self = WeidingerForwardModelImageFilter;\n  using Superclass = itk::ImageToImageFilter<TDecomposedProjections, TDecomposedProjections>;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(WeidingerForwardModelImageFilter);\n\n  /** Convenient parameters extracted from template types */\n  static constexpr unsigned int nBins = TMeasuredProjections::PixelType::Dimension;\n  static constexpr unsigned int nMaterials = TDecomposedProjections::PixelType::Dimension;\n\n  /** Convenient type alias */\n  using dataType = typename TDecomposedProjections::PixelType::ValueType;\n\n  /** Define types for output images:\n   * - one n-vector per pixel\n   * - one nxn-matrix per pixel, but stored as one nxn-vector\n  to allow vector back projection */\n  using TOutputImage1 = TDecomposedProjections;\n  using TPixelOutput2 = itk::Vector<dataType, nMaterials * nMaterials>;\n#ifdef RTK_USE_CUDA\n  using TOutputImage2 = itk::CudaImage<TPixelOutput2, TDecomposedProjections::ImageDimension>;\n#else\n  using TOutputImage2 = itk::Image<TPixelOutput2, TDecomposedProjections::ImageDimension>;\n#endif\n\n  /** Define the getters for the outputs, with correct types */\n  TOutputImage1 *\n  GetOutput1();\n  TOutputImage2 *\n  GetOutput2();\n\n  /** Set methods for all inputs, since they have different types */\n  void\n  SetInputDecomposedProjections(const TDecomposedProjections * decomposedProjections);\n  void\n  SetInputMeasuredProjections(const TMeasuredProjections * measuredProjections);\n  void\n  SetInputIncidentSpectrum(const TIncidentSpectrum * incidentSpectrum);\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  void\n  SetInputMaterialProjections(const TDecomposedProjections * decomposedProjections);\n  void\n  SetInputPhotonCounts(const TMeasuredProjections * measuredProjections);\n  void\n  SetInputSpectrum(const TIncidentSpectrum * incidentSpectrum);\n#endif\n  void\n  SetInputProjectionsOfOnes(const TProjections * projectionsOfOnes);\n\n  /** Typedefs for additional input information */\n  using BinnedDetectorResponseType = vnl_matrix<dataType>;\n  using MaterialAttenuationsType = vnl_matrix<dataType>;\n\n  /** Set and Get macros for the additional input information */\n  itkGetConstReferenceMacro(BinnedDetectorResponse, BinnedDetectorResponseType);\n  itkGetConstReferenceMacro(MaterialAttenuations, MaterialAttenuationsType);\n  virtual void\n  SetBinnedDetectorResponse(const BinnedDetectorResponseType & detResp);\n  virtual void\n  SetMaterialAttenuations(const MaterialAttenuationsType & matAtt);\n\nprotected:\n  WeidingerForwardModelImageFilter();\n  ~WeidingerForwardModelImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n  void\n  VerifyInputInformation() const override\n  {}\n\n  /** Does the real work. */\n  void\n  DynamicThreadedGenerateData(const typename TOutputImage1::RegionType & outputRegionForThread) override;\n\n  /** Creates the Outputs */\n  itk::ProcessObject::DataObjectPointer\n  MakeOutput(itk::ProcessObject::DataObjectPointerArraySizeType idx) override;\n  itk::ProcessObject::DataObjectPointer\n  MakeOutput(const itk::ProcessObject::DataObjectIdentifierType &) override;\n\n  /** Getters for the inputs */\n  typename TDecomposedProjections::ConstPointer\n  GetInputDecomposedProjections();\n  typename TMeasuredProjections::ConstPointer\n  GetInputMeasuredProjections();\n  typename TIncidentSpectrum::ConstPointer\n  GetInputIncidentSpectrum();\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  typename TDecomposedProjections::ConstPointer\n  GetInputMaterialProjections();\n  typename TMeasuredProjections::ConstPointer\n  GetInputPhotonCounts();\n  typename TIncidentSpectrum::ConstPointer\n  GetInputSpectrum();\n#endif\n  typename TProjections::ConstPointer\n  GetInputProjectionsOfOnes();\n\n  /** Additional input parameters */\n  BinnedDetectorResponseType m_BinnedDetectorResponse;\n  MaterialAttenuationsType   m_MaterialAttenuations;\n  itk::SizeValueType         m_NumberOfProjectionsInIncidentSpectrum;\n};\n} // namespace rtk\n\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkWeidingerForwardModelImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkWeidingerForwardModelImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#ifndef rtkWeidingerForwardModelImageFilter_hxx\n#define rtkWeidingerForwardModelImageFilter_hxx\n\n#include \"itkImageRegionIteratorWithIndex.h\"\n#include \"itkImageRegionIterator.h\"\n\nnamespace rtk\n{\n//\n// Constructor\n//\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  WeidingerForwardModelImageFilter()\n{\n  this->SetNumberOfRequiredInputs(4);\n\n  this->SetNthOutput(0, this->MakeOutput(0));\n  this->SetNthOutput(1, this->MakeOutput(1));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetInputDecomposedProjections(const TDecomposedProjections * decomposedProjections)\n{\n  this->SetNthInput(0, const_cast<TDecomposedProjections *>(decomposedProjections));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetInputMeasuredProjections(const TMeasuredProjections * measuredProjections)\n{\n  this->SetNthInput(1, const_cast<TMeasuredProjections *>(measuredProjections));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetInputIncidentSpectrum(const TIncidentSpectrum * incidentSpectrum)\n{\n  this->SetNthInput(2, const_cast<TIncidentSpectrum *>(incidentSpectrum));\n}\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetInputMaterialProjections(const TDecomposedProjections * decomposedProjections)\n{\n  this->SetInputDecomposedProjections(decomposedProjections);\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetInputPhotonCounts(const TMeasuredProjections * measuredProjections)\n{\n  this->SetInputMeasuredProjections(measuredProjections);\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetInputSpectrum(const TIncidentSpectrum * incidentSpectrum)\n{\n  this->SetInputIncidentSpectrum(incidentSpectrum);\n}\n#endif\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetInputProjectionsOfOnes(const TProjections * projectionsOfOnes)\n{\n  this->SetNthInput(3, const_cast<TProjections *>(projectionsOfOnes));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename TDecomposedProjections::ConstPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetInputDecomposedProjections()\n{\n  return static_cast<const TDecomposedProjections *>(this->itk::ProcessObject::GetInput(0));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename TMeasuredProjections::ConstPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetInputMeasuredProjections()\n{\n  return static_cast<const TMeasuredProjections *>(this->itk::ProcessObject::GetInput(1));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename TIncidentSpectrum::ConstPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetInputIncidentSpectrum()\n{\n  return static_cast<const TIncidentSpectrum *>(this->itk::ProcessObject::GetInput(2));\n}\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename TDecomposedProjections::ConstPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetInputMaterialProjections()\n{\n  return this->GetInputDecomposedProjections();\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename TMeasuredProjections::ConstPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetInputPhotonCounts()\n{\n  return this->GetInputMeasuredProjections();\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename TIncidentSpectrum::ConstPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetInputSpectrum()\n{\n  return this->GetInputIncidentSpectrum();\n}\n#endif\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename TProjections::ConstPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetInputProjectionsOfOnes()\n{\n  return static_cast<const TProjections *>(this->itk::ProcessObject::GetInput(3));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nitk::ProcessObject::DataObjectPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  MakeOutput(itk::ProcessObject::DataObjectPointerArraySizeType idx)\n{\n  itk::DataObject::Pointer output;\n\n  switch (idx)\n  {\n    case 0:\n      output = (TOutputImage1::New()).GetPointer();\n      break;\n    case 1:\n      output = (TOutputImage2::New()).GetPointer();\n      break;\n    default:\n      std::cerr << \"No output \" << idx << std::endl;\n      output = nullptr;\n      break;\n  }\n  return output.GetPointer();\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nitk::ProcessObject::DataObjectPointer\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  MakeOutput(const itk::ProcessObject::DataObjectIdentifierType & idx)\n{\n  return Superclass::MakeOutput(idx);\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename WeidingerForwardModelImageFilter<TDecomposedProjections,\n                                          TMeasuredProjections,\n                                          TIncidentSpectrum,\n                                          TProjections>::TOutputImage1 *\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetOutput1()\n{\n  return dynamic_cast<TOutputImage1 *>(this->itk::ProcessObject::GetOutput(0));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\ntypename WeidingerForwardModelImageFilter<TDecomposedProjections,\n                                          TMeasuredProjections,\n                                          TIncidentSpectrum,\n                                          TProjections>::TOutputImage2 *\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GetOutput2()\n{\n  return dynamic_cast<TOutputImage2 *>(this->itk::ProcessObject::GetOutput(1));\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetBinnedDetectorResponse(const BinnedDetectorResponseType & detResp)\n{\n  bool modified = false;\n\n  unsigned int nEnergies = detResp.columns();\n  if (m_BinnedDetectorResponse.columns() != nEnergies)\n  {\n    modified = true;\n    m_BinnedDetectorResponse.set_size(nBins, nEnergies);\n    m_BinnedDetectorResponse.fill(0.);\n  }\n\n  for (unsigned int r = 0; r < nBins; r++)\n  {\n    for (unsigned int c = 0; c < nEnergies; c++)\n    {\n      if (itk::Math::NotExactlyEquals(m_BinnedDetectorResponse[r][c], detResp[r][c]))\n      {\n        m_BinnedDetectorResponse[r][c] = detResp[r][c];\n        modified = true;\n      }\n    }\n  }\n  if (modified)\n  {\n    this->Modified();\n  }\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  SetMaterialAttenuations(const MaterialAttenuationsType & matAtt)\n{\n  bool modified = false;\n\n  unsigned int nEnergies = matAtt.rows();\n  if (m_MaterialAttenuations.rows() != nEnergies)\n  {\n    modified = true;\n    m_MaterialAttenuations.set_size(nEnergies, nMaterials);\n    m_MaterialAttenuations.fill(0.);\n  }\n\n  for (unsigned int r = 0; r < nEnergies; r++)\n  {\n    for (unsigned int c = 0; c < nMaterials; c++)\n    {\n      if (itk::Math::NotExactlyEquals(m_MaterialAttenuations[r][c], matAtt[r][c]))\n      {\n        m_MaterialAttenuations[r][c] = matAtt[r][c];\n        modified = true;\n      }\n    }\n  }\n  if (modified)\n  {\n    this->Modified();\n  }\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  GenerateInputRequestedRegion()\n{\n  // Call the superclass' implementation of this method\n  Superclass::GenerateInputRequestedRegion();\n\n  // Get the requested regions on both outputs (should be identical)\n  typename TOutputImage1::RegionType outputRequested1 = this->GetOutput1()->GetRequestedRegion();\n  typename TOutputImage2::RegionType outputRequested2 = this->GetOutput2()->GetRequestedRegion();\n  if (outputRequested1 != outputRequested2)\n    itkGenericExceptionMacro(\n      << \"In rtkWeidingerForwardModelImageFilter: requested regions for outputs 1 and 2 should be identical\");\n\n  // Get pointers to the inputs\n  typename TDecomposedProjections::Pointer input1Ptr =\n    const_cast<TDecomposedProjections *>(this->GetInputDecomposedProjections().GetPointer());\n  typename TMeasuredProjections::Pointer input2Ptr =\n    const_cast<TMeasuredProjections *>(this->GetInputMeasuredProjections().GetPointer());\n  typename TIncidentSpectrum::Pointer input3Ptr =\n    const_cast<TIncidentSpectrum *>(this->GetInputIncidentSpectrum().GetPointer());\n  typename TProjections::Pointer input4Ptr = const_cast<TProjections *>(this->GetInputProjectionsOfOnes().GetPointer());\n\n  // The first and second input must have the same requested region as the outputs\n  input1Ptr->SetRequestedRegion(outputRequested1);\n  input2Ptr->SetRequestedRegion(outputRequested1);\n  input4Ptr->SetRequestedRegion(outputRequested1);\n\n  // The spectrum input's first dimension is the energy, and then come the\n  // spatial dimensions. The projection number is discarded but the last\n  // dimension may be an integer multiple of projections to treat, e.g., even\n  // and odd projections for fast-switching.\n  // Compute the requested region for the spectrum\n  typename TIncidentSpectrum::RegionType spectrumRegion = input3Ptr->GetLargestPossibleRegion();\n  for (unsigned int d = 0; d < TIncidentSpectrum::ImageDimension - 1; d++)\n  {\n    spectrumRegion.SetIndex(d + 1, outputRequested1.GetIndex()[d]);\n    spectrumRegion.SetSize(d + 1, outputRequested1.GetSize()[d]);\n  }\n  const itk::SizeValueType nRowsIncidentSpectrum =\n    input3Ptr->GetLargestPossibleRegion().GetSize(TIncidentSpectrum::ImageDimension - 1);\n  const itk::SizeValueType nRowsMeasuredProjections =\n    input2Ptr->GetLargestPossibleRegion().GetSize(TMeasuredProjections::ImageDimension - 2);\n  if (nRowsIncidentSpectrum % nRowsMeasuredProjections != 0)\n    itkGenericExceptionMacro(\"The number of rows of the spectrum must be equal to the number of rows of the input \"\n                             \"projections times an integer number of projections\");\n  m_NumberOfProjectionsInIncidentSpectrum = nRowsIncidentSpectrum / nRowsMeasuredProjections;\n  spectrumRegion.SetSize(TIncidentSpectrum::ImageDimension - 1,\n                         spectrumRegion.GetSize(TIncidentSpectrum::ImageDimension - 1) +\n                           nRowsMeasuredProjections * (m_NumberOfProjectionsInIncidentSpectrum - 1));\n\n  // Set the requested region for the spectrum\n  input3Ptr->SetRequestedRegion(spectrumRegion);\n}\n\ntemplate <class TDecomposedProjections, class TMeasuredProjections, class TIncidentSpectrum, class TProjections>\nvoid\nWeidingerForwardModelImageFilter<TDecomposedProjections, TMeasuredProjections, TIncidentSpectrum, TProjections>::\n  DynamicThreadedGenerateData(const typename TOutputImage1::RegionType & outputRegionForThread)\n{\n  // Create the region corresponding to outputRegionForThread for the spectrum input\n  typename TIncidentSpectrum::RegionType spectrumRegion = this->GetInputIncidentSpectrum()->GetLargestPossibleRegion();\n  for (unsigned int d = 0; d < TIncidentSpectrum::ImageDimension - 1; d++)\n  {\n    spectrumRegion.SetIndex(d + 1, outputRegionForThread.GetIndex()[d]);\n    spectrumRegion.SetSize(d + 1, outputRegionForThread.GetSize()[d]);\n  }\n  const itk::SizeValueType nRowsMeasuredProjections =\n    this->GetOutput2()->GetLargestPossibleRegion().GetSize(TMeasuredProjections::ImageDimension - 2);\n  itk::IndexValueType spectrumProjIndex = outputRegionForThread.GetIndex()[TMeasuredProjections::ImageDimension - 1] %\n                                          m_NumberOfProjectionsInIncidentSpectrum;\n  spectrumRegion.SetIndex(TIncidentSpectrum::ImageDimension - 1,\n                          spectrumRegion.GetIndex(TIncidentSpectrum::ImageDimension - 1) +\n                            nRowsMeasuredProjections * spectrumProjIndex);\n\n  unsigned int nEnergies = spectrumRegion.GetSize()[0];\n\n  // Create iterators for all inputs and outputs\n  itk::ImageRegionIterator<TOutputImage1>               out1It(this->GetOutput1(), outputRegionForThread);\n  itk::ImageRegionIterator<TOutputImage2>               out2It(this->GetOutput2(), outputRegionForThread);\n  itk::ImageRegionConstIterator<TDecomposedProjections> projIt(this->GetInputDecomposedProjections(),\n                                                               outputRegionForThread);\n  itk::ImageRegionConstIterator<TMeasuredProjections>   MeasuredProjectionsIt(this->GetInputMeasuredProjections(),\n                                                                            outputRegionForThread);\n  itk::ImageRegionConstIterator<TIncidentSpectrum>      spectrumIt(this->GetInputIncidentSpectrum(), spectrumRegion);\n  itk::ImageRegionConstIterator<TProjections> projOfOnesIt(this->GetInputProjectionsOfOnes(), outputRegionForThread);\n\n  // Declare intermediate variables\n  vnl_vector<dataType>                           spectrum(nEnergies);\n  vnl_matrix<dataType>                           efficientSpectrum(nBins, nEnergies);\n  vnl_vector<dataType>                           attenuationFactors(nEnergies);\n  vnl_vector<dataType>                           expectedCounts(nBins);\n  vnl_vector<dataType>                           oneMinusRatios(nBins);\n  vnl_matrix<dataType>                           intermForGradient(nEnergies, nMaterials);\n  vnl_matrix<dataType>                           interm2ForGradient(nBins, nMaterials);\n  itk::Vector<dataType, nMaterials>              forOutput1;\n  vnl_matrix<dataType>                           intermForHessian(nEnergies, nMaterials * nMaterials);\n  vnl_matrix<dataType>                           interm2ForHessian(nBins, nMaterials * nMaterials);\n  itk::Vector<dataType, nMaterials * nMaterials> forOutput2;\n\n  while (!out1It.IsAtEnd())\n  {\n    // After each projection, the spectrum's iterator must come back to the beginning\n    if (spectrumIt.IsAtEnd())\n    {\n      spectrumProjIndex++;\n      spectrumProjIndex %= m_NumberOfProjectionsInIncidentSpectrum;\n      spectrumRegion.SetIndex(TIncidentSpectrum::ImageDimension - 1,\n                              outputRegionForThread.GetIndex()[TMeasuredProjections::ImageDimension - 2] +\n                                nRowsMeasuredProjections * spectrumProjIndex);\n      spectrumIt.SetRegion(spectrumRegion);\n      spectrumIt.GoToBegin();\n    }\n\n    // Read the spectrum at the current pixel\n    for (unsigned int e = 0; e < nEnergies; e++)\n    {\n      spectrum[e] = spectrumIt.Get();\n      ++spectrumIt;\n    }\n\n    // Get efficient spectrum, by equivalent of element-wise product with implicit extension\n    for (unsigned int r = 0; r < nBins; r++)\n      for (unsigned int c = 0; c < nEnergies; c++)\n        efficientSpectrum[r][c] = m_BinnedDetectorResponse[r][c] * spectrum[c];\n\n    // Get attenuation factors at each energy from material projections\n    attenuationFactors = m_MaterialAttenuations * projIt.Get().GetVnlVector();\n    for (unsigned int r = 0; r < nEnergies; r++)\n      attenuationFactors[r] = std::exp(-attenuationFactors[r]);\n\n    // Get the expected photon counts through these attenuations\n    expectedCounts = efficientSpectrum * attenuationFactors;\n\n    // Get intermediate variables used in the computation of the first output\n    for (unsigned int r = 0; r < nBins; r++)\n      oneMinusRatios[r] = 1 - (MeasuredProjectionsIt.Get()[r] / expectedCounts[r]);\n\n    // Form an intermediate variable used for the gradient of the cost function,\n    // (the derivation of the exponential implies that a m_MaterialAttenuations\n    // gets out), by equivalent of element-wise product with implicit extension\n    for (unsigned int r = 0; r < nEnergies; r++)\n      for (unsigned int c = 0; c < nMaterials; c++)\n        intermForGradient[r][c] = m_MaterialAttenuations[r][c] * attenuationFactors[r];\n\n    // Multiply by the spectrum\n    interm2ForGradient = -efficientSpectrum * intermForGradient;\n\n    // Compute the product with oneMinusRatios, with implicit extension\n    for (unsigned int r = 0; r < nBins; r++)\n      for (unsigned int c = 0; c < nMaterials; c++)\n        interm2ForGradient[r][c] *= oneMinusRatios[r];\n\n    // Finally, compute the vector to be written in first output\n    // by summing on the bins\n    forOutput1.Fill(0);\n    for (unsigned int r = 0; r < nBins; r++)\n      for (unsigned int c = 0; c < nMaterials; c++)\n        forOutput1[c] += interm2ForGradient[r][c];\n\n    // Set the output1\n    out1It.Set(forOutput1);\n\n    // Now compute output2\n\n    // Form an intermediate variable used for the hessian of the cost function,\n    // (the double derivation of the exponential implies that a m_MaterialAttenuations^2\n    // gets out), by equivalent of element-wise product with implicit extension\n    for (unsigned int r = 0; r < nEnergies; r++)\n      for (unsigned int c = 0; c < nMaterials; c++)\n        for (unsigned int c2 = 0; c2 < nMaterials; c2++)\n          intermForHessian[r][c2 + nMaterials * c] =\n            m_MaterialAttenuations[r][c] * m_MaterialAttenuations[r][c2] * attenuationFactors[r];\n\n    // Multiply by the spectrum\n    interm2ForHessian = efficientSpectrum * intermForHessian;\n\n    // Sum on the bins\n    forOutput2.Fill(0);\n    for (unsigned int r = 0; r < nBins; r++)\n      for (unsigned int c = 0; c < nMaterials * nMaterials; c++)\n        forOutput2[c] += interm2ForHessian[r][c];\n\n    // Multiply by the projection of ones\n    forOutput2 *= projOfOnesIt.Get();\n\n    // Set the output2\n    out2It.Set(forOutput2);\n\n    ++out1It;\n    ++out2It;\n    ++projIt;\n    ++MeasuredProjectionsIt;\n    ++projOfOnesIt;\n  }\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkXRadGeometryReader.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkXRadGeometryReader_h\n#define rtkXRadGeometryReader_h\n\n#include <itkLightProcessObject.h>\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"RTKExport.h\"\n\nnamespace rtk\n{\n\n/** \\class XRadGeometryReader\n *\n * Creates a 3D circular geometry from an exported XRad sinogram.\n *\n * \\test rtkxradtest.cxx\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT XRadGeometryReader : public itk::LightProcessObject\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(XRadGeometryReader);\n\n  /** Standard type alias */\n  using Self = XRadGeometryReader;\n  using Superclass = itk::LightProcessObject;\n  using Pointer = itk::SmartPointer<Self>;\n\n  /** Convenient type alias */\n  using GeometryType = ThreeDCircularProjectionGeometry;\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(XRadGeometryReader);\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Get the pointer to the generated geometry object. */\n  itkGetMacro(Geometry, GeometryType::Pointer);\n\n  /** Set the path to the header file containing the sinogram information */\n  itkGetMacro(ImageFileName, std::string);\n  itkSetMacro(ImageFileName, std::string);\n\nprotected:\n  XRadGeometryReader();\n\nprivate:\n  void\n  GenerateData() override;\n\n  GeometryType::Pointer m_Geometry;\n  std::string           m_ImageFileName;\n};\n\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "include/rtkXRadImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkXRadImageIO_h\n#define rtkXRadImageIO_h\n\n#include <itkImageIOBase.h>\n#include <fstream>\n#include <cstring>\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\nnamespace rtk\n{\n\n/** \\class XRadImageIO\n * \\brief Class for reading XRad image file format. XRad is the format of\n * exported X-ray projection images on the small animal irradiator SMART.\n * http://www.pxinc.com/products/small-animal-igrt-platform/x-rad-225cx/\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT XRadImageIO : public itk::ImageIOBase\n{\npublic:\n  /** Standard class type alias. */\n  using Self = XRadImageIO;\n  using Superclass = itk::ImageIOBase;\n  using Pointer = itk::SmartPointer<Self>;\n\n  XRadImageIO()\n    : Superclass()\n  {}\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(XRadImageIO);\n\n  /*-------- This part of the interface deals with reading data. ------ */\n  void\n  ReadImageInformation() override;\n\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n\n  void\n  Read(void * buffer) override;\n\n  /*-------- This part of the interfaces deals with writing data. ----- */\n  virtual void\n  WriteImageInformation(bool keepOfStream);\n\n  void\n  WriteImageInformation() override\n  {\n    WriteImageInformation(false);\n  }\n\n  bool\n  CanWriteFile(const char * filename) override;\n\n  void\n  Write(const void * buffer) override;\n\nprotected:\n}; // end class XRadImageIO\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkXRadImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkXRadImageIOFactory_h\n#define rtkXRadImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkXRadImageIO.h\"\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class XRadImageIOFactory\n * \\brief ITK factory for XRad file I/O.\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT XRadImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(XRadImageIOFactory);\n\n  /** Standard class type alias. */\n  using Self = XRadImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"XRad ImageIO Factory, allows the loading of XRad images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(XRadImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\nprotected:\n  XRadImageIOFactory();\n  ~XRadImageIOFactory() override = default;\n\n  using myProductType = XRadImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkXRadRawToAttenuationImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkXRadRawToAttenuationImageFilter_h\n#define rtkXRadRawToAttenuationImageFilter_h\n\n#include <itkImageToImageFilter.h>\n#include \"rtkConfiguration.h\"\n\n/** \\class RawToAttenuationImageFilter\n * \\brief Convert raw XRad data to attenuation images\n *\n * \\author Simon Rit\n *\n * \\ingroup RTK ImageToImageFilter\n */\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage = TInputImage>\nclass ITK_TEMPLATE_EXPORT XRadRawToAttenuationImageFilter : public itk::ImageToImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(XRadRawToAttenuationImageFilter);\n\n  /** Standard class type alias. */\n  using Self = XRadRawToAttenuationImageFilter;\n  using Superclass = itk::ImageToImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Some convenient type alias. */\n  using InputImageType = TInputImage;\n  using OutputImageType = TOutputImage;\n  using OutputImagePointer = typename OutputImageType::Pointer;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n\n  /** Standard New method. */\n  itkNewMacro(Self);\n\n  /** Runtime information support. */\n  itkOverrideGetNameOfClassMacro(XRadRawToAttenuationImageFilter);\n\nprotected:\n  XRadRawToAttenuationImageFilter();\n  ~XRadRawToAttenuationImageFilter() override = default;\n\n  void\n  BeforeThreadedGenerateData() override;\n\n  void\n  DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;\n\nprivate:\n  OutputImagePointer m_DarkImage;\n  OutputImagePointer m_FlatImage;\n  std::string        m_DarkImageFileName;\n  std::string        m_FlatImageFileName;\n}; // end of class\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkXRadRawToAttenuationImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkXRadRawToAttenuationImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkXRadRawToAttenuationImageFilter_hxx\n#define rtkXRadRawToAttenuationImageFilter_hxx\n\n\n#include <itkImageFileReader.h>\n#include <itkImageRegionIterator.h>\n#include \"rtkConfiguration.h\"\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nXRadRawToAttenuationImageFilter<TInputImage, TOutputImage>::XRadRawToAttenuationImageFilter()\n  : m_DarkImageFileName(std::string(RTK_DATA_ROOT) + std::string(\"/Input/XRad/dark.header\"))\n  , m_FlatImageFileName(std::string(RTK_DATA_ROOT) + std::string(\"/Input/XRad/flat.header\"))\n{}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nXRadRawToAttenuationImageFilter<TInputImage, TOutputImage>::BeforeThreadedGenerateData()\n{\n  auto reader = itk::ImageFileReader<OutputImageType>::New();\n\n  reader->SetFileName(m_DarkImageFileName);\n  reader->Update();\n  m_DarkImage = reader->GetOutput();\n  m_DarkImage->DisconnectPipeline();\n\n  reader->SetFileName(m_FlatImageFileName);\n  reader->Update();\n  m_FlatImage = reader->GetOutput();\n  m_FlatImage->DisconnectPipeline();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nXRadRawToAttenuationImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateData(\n  const OutputImageRegionType & outputRegionForThread)\n{\n  // Dark and flat image iterator\n  OutputImageRegionType darkRegion = outputRegionForThread;\n  darkRegion.SetSize(2, 1);\n  darkRegion.SetIndex(2, 1);\n  itk::ImageRegionConstIterator<OutputImageType> itDark(m_DarkImage, darkRegion);\n  itk::ImageRegionConstIterator<OutputImageType> itFlat(m_FlatImage, darkRegion);\n\n  // Projection regions\n  OutputImageRegionType outputRegionSlice = outputRegionForThread;\n  outputRegionSlice.SetSize(2, 1);\n  for (int k = outputRegionForThread.GetIndex(2);\n       k < outputRegionForThread.GetIndex(2) + (int)outputRegionForThread.GetSize(2);\n       k++)\n  {\n    outputRegionSlice.SetIndex(2, k);\n\n    // Create iterators\n    itk::ImageRegionConstIterator<InputImageType> itIn(this->GetInput(), outputRegionSlice);\n    itk::ImageRegionIterator<OutputImageType>     itOut(this->GetOutput(), outputRegionSlice);\n\n    itDark.GoToBegin();\n    itFlat.GoToBegin();\n    while (!itIn.IsAtEnd())\n    {\n      double den = itFlat.Get() - (double)itDark.Get();\n      if (den == 0.)\n        itOut.Set(0.);\n      else\n      {\n        double ratio = (itIn.Get() - (double)itDark.Get()) / den;\n        if (ratio <= 0.)\n          itOut.Set(0.);\n        else\n          itOut.Set(-log(ratio));\n      }\n      ++itIn;\n      ++itOut;\n      ++itDark;\n      ++itFlat;\n    }\n  }\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkXimImageIO.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkXimImageIO_h\n#define rtkXimImageIO_h\n\n#include \"RTKExport.h\"\n#include \"rtkMacro.h\"\n\n// itk include\n#include <itkImageIOBase.h>\n\n#if defined(_MSC_VER) && (_MSC_VER < 1600)\n// SR: taken from\n// #include \"msinttypes/stdint.h\"\n#else\n#  include <cstdint>\n#endif\n\nnamespace rtk\n{\n\n/** \\class XimImageIO\n * \\brief Class for reading Xim Image file format\n *\n * Reads Xim files (file format used by Varian for Obi raw data).\n *\n * \\author Andreas Gravgaard Andersen\n *\n * \\ingroup RTK IOFilters\n */\nclass RTK_EXPORT XimImageIO : public itk::ImageIOBase\n{\npublic:\n  /** Standard class type alias. */\n  using Self = XimImageIO;\n  using Superclass = itk::ImageIOBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using PixelType = signed short int;\n  using Int4 = itk::int32_t; // int of 4 bytes as in xim docs\n\n  typedef struct xim_header\n  {\n    // Actual Header:\n    char sFileType[32];\n    Int4 FileVersion;\n    Int4 SizeX;\n    Int4 SizeY;\n    Int4 dBitsPerPixel;\n    Int4 dBytesPerPixel;\n    Int4 dCompressionIndicator;\n    Int4 lookUpTableSize;\n    Int4 compressedPixelBufferSize;\n    Int4 unCompressedPixelBufferSize;\n    // Header after pixel-data:\n    Int4         binsInHistogram;\n    Int4 *       histogramData;\n    Int4         numberOfProperties;\n    unsigned int nPixelOffset;\n    double       dCollX1;\n    double       dCollX2;\n    double       dCollY1;\n    double       dCollY2;\n    double       dCollRtn;\n    double       dCouchVrt;\n    double       dCouchLng;\n    double       dCouchLat;\n    double       dIDUResolutionX;   // MUST BE CALCULATED\n    double       dIDUResolutionY;   //\n    double       dImageResolutionX; //\n    double       dImageResolutionY; //\n    double       dEnergy;\n    double       dDoseRate;\n    double       dXRayKV;\n    double       dXRayMA;\n    double       dCTProjectionAngle; // KVSourceRtn in file\n    double       dDetectorOffsetX;   // KVDetectorLat\n    double       dDetectorOffsetY;   // KVDetectorLng\n    double       dCTNormChamber;\n    double       dGatingTimeTag;\n    double       dGating4DInfoX;\n    double       dGating4DInfoY;\n    double       dGating4DInfoZ;\n    // double dGating4DInfoTime;\n  } Xim_header;\n\n  XimImageIO()\n    : Superclass()\n  {}\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(XimImageIO);\n\n  /*-------- This part of the interface deals with reading data. ------ */\n  void\n  ReadImageInformation() override;\n\n  bool\n  CanReadFile(const char * FileNameToRead) override;\n\n  void\n  Read(void * buffer) override;\n\n  /*-------- This part of the interfaces deals with writing data. ----- */\n  virtual void\n  WriteImageInformation(bool /*keepOfStream*/)\n  {}\n\n  void\n  WriteImageInformation() override\n  {\n    WriteImageInformation(false);\n  }\n\n  bool\n  CanWriteFile(const char * filename) override;\n\n  void\n  Write(const void * buffer) override;\n\nprivate:\n  template <typename T>\n  size_t\n  SetPropertyValue(char * property_name, Int4 value_length, FILE * fp, Xim_header * xim);\n\n  int  m_ImageDataStart;\n  Int4 m_BytesPerPixel;\n\n}; // end class XimImageIO\n\n} // namespace rtk\n\n#endif /* end #define __rtkXimImageIO_h */\n"
  },
  {
    "path": "include/rtkXimImageIOFactory.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// #ifndef ITKHNDIMAGEIOFACTORY_H\n// #define ITKHNDIMAGEIOFACTORY_H\n\n#ifndef rtkXimImageIOFactory_h\n#define rtkXimImageIOFactory_h\n\n#include \"RTKExport.h\"\n#include \"rtkXimImageIO.h\"\n#include \"rtkMacro.h\"\n\n// itk include\n#include <itkImageIOBase.h>\n#include <itkObjectFactoryBase.h>\n#include <itkVersion.h>\n\nnamespace rtk\n{\n\n/** \\class XimImageIOFactory\n * \\brief ITK factory for Xim file I/O.\n *\n * \\author Simon Rit & Andreas Gravgaard Andersen\n *\n * \\ingroup RTK\n */\nclass RTK_EXPORT XimImageIOFactory : public itk::ObjectFactoryBase\n{\npublic:\n  ITK_DISALLOW_COPY_AND_MOVE(XimImageIOFactory);\n\n  /** Standard class type alias. */\n  using Self = XimImageIOFactory;\n  using Superclass = itk::ObjectFactoryBase;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n\n  /** Class methods used to interface with the registered factories. */\n  const char *\n  GetITKSourceVersion() const override\n  {\n    return ITK_SOURCE_VERSION;\n  }\n\n  const char *\n  GetDescription() const override\n  {\n    return \"Xim ImageIO Factory, allows the loading of Xim images into insight\";\n  }\n\n  /** Method for class instantiation. */\n  itkFactorylessNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(XimImageIOFactory);\n\n  /** Register one factory of this type  */\n  static void\n  RegisterOneFactory()\n  {\n    ObjectFactoryBase::RegisterFactory(Self::New());\n  }\n\nprotected:\n  XimImageIOFactory();\n  ~XimImageIOFactory() override = default;\n  using myProductType = XimImageIOFactory;\n  const myProductType * m_MyProduct;\n};\n\n} // namespace rtk\n\n#endif // __rtkXimImageIOFactory_h\n"
  },
  {
    "path": "include/rtkZengBackProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkZengBackProjectionImageFilter_h\n#define rtkZengBackProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n#include \"rtkMacro.h\"\n#include <itkPixelTraits.h>\n\n#include <itkMultiplyImageFilter.h>\n#include <itkAddImageFilter.h>\n#include <itkDiscreteGaussianImageFilter.h>\n#include <itkPasteImageFilter.h>\n#include <itkResampleImageFilter.h>\n#include <itkVector.h>\n#include <itkCenteredEuler3DTransform.h>\n#include <itkChangeInformationImageFilter.h>\n#include <itkExtractImageFilter.h>\n#include <itkRegionOfInterestImageFilter.h>\n#include <itkConstantBoundaryCondition.h>\n#include <itkUnaryGeneratorImageFilter.h>\n\n#include \"rtkConstantImageSource.h\"\n\n#include <itkVectorImage.h>\nnamespace rtk\n{\n\n/** \\class ZengBackProjectionImageFilter\n * \\brief Zeng back projection.\n *\n * Performs a rotation based backprojection, i.e. the volume is rotated so that\n * the face of the image volume is parallel to the detector and the projection\n * is done by summing the collumn. This projector is used to perform the PSF\n * correction described in [Zeng et al, 1999,\n * 10.1109/42.796285]. The back projector tests if the detector has been placed\n * after the source and the volume. If the detector is in the volume the sum is\n * performed only until that point.\n *\n * \\dot\n * digraph ZengBackProjectionImageFilter {\n *\n *  Input0 [ label=\"Input 0 (Volume)\"];\n *  Input0 [shape=Mdiamond];\n *  Input1 [label=\"Input 1 (Projections)\"];\n *  Input1 [shape=Mdiamond];\n *  Input2 [label=\"Input 2 (Attenuation)\"];\n *  Input2 [shape=Mdiamond];\n *  Output [label=\"Output (Reconstruction)\"];\n *  Output [shape=Mdiamond];\n *\n *  node [shape=box];\n *\n *  Add [ label=\"itk::AddImageFilter\" URL=\"\\ref itk::AddImageFilter\"];\n *  Paste [ label=\"itk::PasteImageFilter\" URL=\"\\ref itk::PasteImageFilter\"];\n *  Gaussian [ label=\"itk::DiscreteGaussianFilter\" URL=\"\\ref itk::DiscreteGaussianFilter\"];\n *  Resample [ label=\"itk::ResampleImageFilter\" URL=\"\\ref itk::ResampleImageFilter\"];\n *  Multiply [ label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n *  Constant [ label=\"itk::ConstantVolumeSource\" URL=\"\\ref itk::ConstantVolumeSource\"];\n *  Extract [ label=\"itk::ExtractImageFilter\" URL=\"\\ref itk::ExtractImageFilter\"];\n *  ChangeInfo [ label=\"itk::ChangeInformationImageFilter\" URL=\"\\ref itk::ChangeInformationImageFilter\"];\n *  AttMultiply [ label=\"itk::MultiplyImageFilter\" URL=\"\\ref itk::MultiplyImageFilter\"];\n *  ROI [ label=\"itk::RegionOfInterestImageFilter\" URL=\"\\ref itk::RegionOfInterestImageFilter\"];\n *  AttResample [ label=\"itk::ResampleImageFilter\" URL=\"\\ref itk::ResampleImageFilter\"];\n *  AttChangeInfo [ label=\"itk::ChangeInformationImageFilter\" URL=\"\\ref itk::ChangeInformationImageFilter\"];\n *  Unary [ label=\"itk::UnaryGeneratorImageFilter\" URL=\"\\ref itk::UnaryGeneratorImageFilter\"];\n *  Multiply -> Add;\n *  Resample -> Multiply;\n *  Extract -> ChangeInfo;\n *  Input1 -> Extract\n *  ChangeInfo -> Gaussian;\n *  Input2 -> Unary;\n *  Unary -> AttResample;\n *  AttResample -> ROI;\n *  ROI -> AttChangeInfo;\n *  ChangeInfo -> AttMultiply;\n *  AttChangeInfo -> AttMultiply;\n *  AttMultiply -> Gaussian;\n *  Gaussian -> Paste;\n *  Constant -> Paste;\n *  Paste -> Resample;\n *  Input0 -> Add;\n *  Gaussian -> AttMultiply;\n *  Add -> Output;\n *  }\n * \\enddot\n *\n * \\test rtkZengBackprojectiontest.cxx\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Projector\n */\n\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT ZengBackProjectionImageFilter : public BackProjectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  /** Standard class usings. */\n  using VectorType = itk::Vector<double, 3>;\n  using InputPixelType = typename TInputImage::PixelType;\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using InputCPUImageType = itk::Image<InputPixelType, 3>;\n  using OuputCPUImageType = itk::Image<OutputPixelType, 3>;\n  using PointType = typename OuputCPUImageType::PointType;\n\n  using Self = ZengBackProjectionImageFilter;\n  using Superclass = BackProjectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using AddImageFilterType = itk::AddImageFilter<InputCPUImageType, InputCPUImageType>;\n  using AddImageFilterPointerType = typename AddImageFilterType::Pointer;\n  using PasteImageFilterType = itk::PasteImageFilter<InputCPUImageType, OuputCPUImageType>;\n  using PasteImageFilterPointerType = typename PasteImageFilterType::Pointer;\n  using DiscreteGaussianFilterType = itk::DiscreteGaussianImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using DiscreteGaussianFilterPointeurType = typename DiscreteGaussianFilterType::Pointer;\n  using ResampleImageFilterType = itk::ResampleImageFilter<InputCPUImageType, InputCPUImageType>;\n  using ResampleImageFilterPointerType = typename ResampleImageFilterType::Pointer;\n  using TransformType = itk::CenteredEuler3DTransform<double>;\n  using TransformPointerType = typename TransformType::Pointer;\n  using ChangeInformationFilterType = itk::ChangeInformationImageFilter<OuputCPUImageType>;\n  using ChangeInformationPointerType = typename ChangeInformationFilterType::Pointer;\n  using MultiplyImageFilterType = itk::MultiplyImageFilter<InputCPUImageType, InputCPUImageType>;\n  using MultiplyImageFilterPointerType = typename MultiplyImageFilterType::Pointer;\n  using ConstantVolumeSourceType = rtk::ConstantImageSource<InputCPUImageType>;\n  using ConstantVolumeSourcePointerType = typename ConstantVolumeSourceType::Pointer;\n  using ExtractImageFilterType = itk::ExtractImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using ExtractImageFilterPointerType = typename ExtractImageFilterType::Pointer;\n  using RegionOfInterestFilterType = itk::RegionOfInterestImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using RegionOfInterestPointerType = typename RegionOfInterestFilterType::Pointer;\n  using CustomUnaryFilterType = itk::UnaryGeneratorImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using CustomUnaryFilterPointerType = typename CustomUnaryFilterType::Pointer;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;\n\n  /** Typedef for the boundary condition */\n  using BoundaryCondition = itk::ConstantBoundaryCondition<OuputCPUImageType>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ZengBackProjectionImageFilter);\n\n  /** Get / Set the sigma zero of the PSF. Default is 1.5417233052142099 */\n  itkGetMacro(SigmaZero, double);\n  itkSetMacro(SigmaZero, double);\n\n  /** Get / Set the alpha of the PSF. Default is 0.016241189545787734 */\n  itkGetMacro(Alpha, double);\n  itkSetMacro(Alpha, double);\n\n\nprotected:\n  ZengBackProjectionImageFilter();\n  ~ZengBackProjectionImageFilter() override = default;\n\n  /** Apply changes to the input image requested region. */\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override;\n\n  AddImageFilterPointerType          m_AddImageFilter;\n  PasteImageFilterPointerType        m_PasteImageFilter;\n  DiscreteGaussianFilterPointeurType m_DiscreteGaussianFilter;\n  ResampleImageFilterPointerType     m_ResampleImageFilter;\n  TransformPointerType               m_Transform;\n  MultiplyImageFilterPointerType     m_MultiplyImageFilter;\n  ConstantVolumeSourcePointerType    m_ConstantVolumeSource;\n  ExtractImageFilterPointerType      m_ExtractImageFilter;\n  ChangeInformationPointerType       m_ChangeInformation;\n  MultiplyImageFilterPointerType     m_AttenuationMapMultiplyImageFilter;\n  RegionOfInterestPointerType        m_AttenuationMapRegionOfInterest;\n  ResampleImageFilterPointerType     m_AttenuationMapResampleImageFilter;\n  ChangeInformationPointerType       m_AttenuationMapChangeInformation;\n  BoundaryCondition                  m_BoundsCondition;\n  CustomUnaryFilterPointerType       m_CustomUnaryFilter;\n\nprivate:\n  ZengBackProjectionImageFilter(const Self &) = delete; // purposely not implemented\n  void\n  operator=(const Self &) = delete; // purposely not implemented\n\n  double     m_SigmaZero{ 1.5417233052142099 };\n  double     m_Alpha{ 0.016241189545787734 };\n  VectorType m_VectorOrthogonalDetector{ 0. };\n  PointType  m_centerVolume{ 0 };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkZengBackProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkZengBackProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkZengBackProjectionImageFilter_hxx\n#define rtkZengBackProjectionImageFilter_hxx\n\n#include <math.h>\n\n#include \"math.h\"\n\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkBoxShape.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkInputDataObjectConstIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nZengBackProjectionImageFilter<TInputImage, TOutputImage>::ZengBackProjectionImageFilter()\n{\n  // Set default parameters\n  m_VectorOrthogonalDetector[2] = 1;\n\n  // Create each filter of the composite filter\n  m_AddImageFilter = AddImageFilterType::New();\n  m_PasteImageFilter = PasteImageFilterType::New();\n  m_DiscreteGaussianFilter = DiscreteGaussianFilterType::New();\n  m_ResampleImageFilter = ResampleImageFilterType::New();\n  m_Transform = TransformType::New();\n  m_MultiplyImageFilter = MultiplyImageFilterType::New();\n  m_ExtractImageFilter = ExtractImageFilterType::New();\n  m_ConstantVolumeSource = ConstantVolumeSourceType::New();\n  m_ChangeInformation = ChangeInformationFilterType::New();\n  m_AttenuationMapMultiplyImageFilter = nullptr;\n  m_AttenuationMapRegionOfInterest = nullptr;\n  m_AttenuationMapResampleImageFilter = nullptr;\n  m_AttenuationMapChangeInformation = nullptr;\n  m_CustomUnaryFilter = nullptr;\n\n  // Permanent internal connections\n  m_AddImageFilter->SetInput2(m_MultiplyImageFilter->GetOutput());\n  m_MultiplyImageFilter->SetInput(m_ResampleImageFilter->GetOutput());\n  m_ChangeInformation->SetInput(m_ExtractImageFilter->GetOutput());\n  m_ChangeInformation->ChangeSpacingOn();\n\n  // Default parameters\n  m_DiscreteGaussianFilter->SetMaximumError(0.00001);\n  m_DiscreteGaussianFilter->SetFilterDimensionality(2);\n  m_DiscreteGaussianFilter->SetInputBoundaryCondition(&m_BoundsCondition);\n  m_DiscreteGaussianFilter->SetRealBoundaryCondition(&m_BoundsCondition);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nZengBackProjectionImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n  // Input 2 is the attenuation map relative to the volume\n  typename Superclass::InputImagePointer inputPtr2 = const_cast<TInputImage *>(this->GetInput(2));\n  if (!inputPtr2)\n    return;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nZengBackProjectionImageFilter<TInputImage, TOutputImage>::VerifyInputInformation() const\n{\n  using ImageBaseType = const itk::ImageBase<InputImageDimension>;\n\n  ImageBaseType * inputPtr1 = nullptr;\n\n  itk::InputDataObjectConstIterator it(this);\n  for (; !it.IsAtEnd(); ++it)\n  {\n    // Check whether the output is an image of the appropriate\n    // dimension (use ProcessObject's version of the GetInput()\n    // method since it returns the input as a pointer to a\n    // DataObject as opposed to the subclass version which\n    // static_casts the input to an TInputImage).\n    if (it.GetName() != \"_1\")\n    {\n      inputPtr1 = dynamic_cast<ImageBaseType *>(it.GetInput());\n    }\n    if (inputPtr1)\n    {\n      break;\n    }\n  }\n\n  for (; !it.IsAtEnd(); ++it)\n  {\n    if (it.GetName() != \"_1\")\n    {\n      auto * inputPtrN = dynamic_cast<ImageBaseType *>(it.GetInput());\n      // Physical space computation only matters if we're using two\n      // images, and not an image and a constant.\n      if (inputPtrN)\n      {\n        // check that the image occupy the same physical space, and that\n        // each index is at the same physical location\n\n        // tolerance for origin and spacing depends on the size of pixel\n        // tolerance for directions a fraction of the unit cube.\n        const double coordinateTol = itk::Math::abs(Self::GetGlobalDefaultCoordinateTolerance() *\n                                                    inputPtr1->GetSpacing()[0]); // use first dimension spacing\n\n        if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n              inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n        {\n          std::ostringstream originString, spacingString, directionString;\n          if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol))\n          {\n            originString.setf(std::ios::scientific);\n            originString.precision(7);\n            originString << \"InputImage Origin: \" << inputPtr1->GetOrigin() << \", InputImage\" << it.GetName()\n                         << \" Origin: \" << inputPtrN->GetOrigin() << std::endl;\n            originString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol))\n          {\n            spacingString.setf(std::ios::scientific);\n            spacingString.precision(7);\n            spacingString << \"InputImage Spacing: \" << inputPtr1->GetSpacing() << \", InputImage\" << it.GetName()\n                          << \" Spacing: \" << inputPtrN->GetSpacing() << std::endl;\n            spacingString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n                inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n          {\n            directionString.setf(std::ios::scientific);\n            directionString.precision(7);\n            directionString << \"InputImage Direction: \" << inputPtr1->GetDirection() << \", InputImage\" << it.GetName()\n                            << \" Direction: \" << inputPtrN->GetDirection() << std::endl;\n            directionString << \"\\tTolerance: \" << Self::GetGlobalDefaultDirectionTolerance() << std::endl;\n          }\n          itkExceptionMacro(<< \"Inputs do not occupy the same physical space! \" << std::endl\n                            << originString.str() << spacingString.str() << directionString.str());\n        }\n      }\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nZengBackProjectionImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n\n  // Info of the input volume\n  const typename InputCPUImageType::SpacingType spacingVolume = this->GetInput(0)->GetSpacing();\n  const typename InputCPUImageType::SizeType    sizeVolume = this->GetInput(0)->GetLargestPossibleRegion().GetSize();\n  const typename InputCPUImageType::IndexType   indexVolume = this->GetInput(0)->GetLargestPossibleRegion().GetIndex();\n\n  // Info of the input stack of projections\n  const typename OuputCPUImageType::SpacingType spacingProjections = this->GetInput(1)->GetSpacing();\n  const typename OuputCPUImageType::SizeType  sizeProjection = this->GetInput(1)->GetLargestPossibleRegion().GetSize();\n  const typename OuputCPUImageType::PointType originProjection = this->GetInput(1)->GetOrigin();\n\n  // Find the center of the volume\n  using CoordinateType = typename PointType ::ValueType;\n  using ContinuousIndexType = itk::ContinuousIndex<CoordinateType, InputImageDimension>;\n  using ContinuousIndexValueType = typename ContinuousIndexType::ValueType;\n  ContinuousIndexType centerIndex;\n\n  for (unsigned int k = 0; k < InputImageDimension; k++)\n  {\n    centerIndex[k] = static_cast<ContinuousIndexValueType>(indexVolume[k]) +\n                     static_cast<ContinuousIndexValueType>(sizeVolume[k] - 1) / 2.0;\n  }\n\n  using ValueType = typename PointType::ValueType;\n  m_centerVolume =\n    this->GetInput(0)->template TransformContinuousIndexToPhysicalPoint<CoordinateType, ValueType>(centerIndex);\n\n  PointType centerRotation;\n  centerRotation.Fill(0);\n  m_Transform->SetCenter(centerRotation);\n  m_ResampleImageFilter->SetOutputParametersFromImage(this->GetInput(0));\n\n  // Set the output size of volume\n  typename InputCPUImageType::SizeType outputSize;\n  outputSize[0] = sizeProjection[0];\n  outputSize[1] = sizeProjection[1];\n  outputSize[2] = sizeVolume[2] * std::sqrt(2);\n\n  // Set the new origin of the volume\n  typename InputCPUImageType::PointType outputOrigin;\n  outputOrigin[0] = originProjection[0];\n  outputOrigin[1] = originProjection[1];\n  outputOrigin[2] = m_centerVolume[2] - spacingVolume[2] * (double)(outputSize[2] - 1) / 2.0;\n\n  // Set the output spacing of the volume\n  typename InputCPUImageType::SpacingType outputSpacing;\n  outputSpacing[0] = spacingProjections[0];\n  outputSpacing[1] = spacingProjections[1];\n  outputSpacing[2] = spacingVolume[2];\n\n  // We only set the first sub-stack at that point, the rest will be\n  // requested in the GenerateData function\n  typename ExtractImageFilterType::InputImageRegionType projRegion;\n  const unsigned int                                    Dimension = this->InputImageDimension;\n  projRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  m_ExtractImageFilter->SetExtractionRegion(projRegion);\n  m_ExtractImageFilter->SetInput(this->GetInput(1));\n  m_ExtractImageFilter->UpdateOutputInformation();\n  m_ChangeInformation->SetOutputSpacing(outputSpacing);\n  m_ChangeInformation->UpdateOutputInformation();\n\n  m_DiscreteGaussianFilter->SetVariance(pow(m_SigmaZero, 2.0));\n\n  if (!(this->GetInput(2)))\n  {\n    m_DiscreteGaussianFilter->SetInput(m_ChangeInformation->GetOutput());\n  }\n  else\n  {\n    m_AttenuationMapMultiplyImageFilter = MultiplyImageFilterType::New();\n    m_AttenuationMapRegionOfInterest = RegionOfInterestFilterType::New();\n    m_AttenuationMapResampleImageFilter = ResampleImageFilterType::New();\n    m_AttenuationMapChangeInformation = ChangeInformationFilterType::New();\n    m_CustomUnaryFilter = CustomUnaryFilterType::New();\n    m_AttenuationMapChangeInformation->ChangeOriginOn();\n    m_AttenuationMapChangeInformation->ChangeRegionOn();\n    m_AttenuationMapChangeInformation->SetReferenceImage(m_ChangeInformation->GetOutput());\n    m_AttenuationMapChangeInformation->SetUseReferenceImage(true);\n\n    // Set Lambda function\n    auto customLambda = [spacingVolume](const typename OuputCPUImageType::PixelType & input1) ->\n      typename OuputCPUImageType::PixelType {\n        return static_cast<typename OuputCPUImageType::PixelType>(std::exp(-spacingVolume[2] * input1));\n      };\n    m_CustomUnaryFilter->SetFunctor(customLambda);\n    m_CustomUnaryFilter->SetInput(this->GetInput(2));\n\n    m_AttenuationMapResampleImageFilter->SetTransform(m_Transform);\n    m_AttenuationMapResampleImageFilter->SetOutputParametersFromImage(this->GetInput(0));\n    m_AttenuationMapResampleImageFilter->SetSize(outputSize);\n    m_AttenuationMapResampleImageFilter->SetOutputOrigin(outputOrigin);\n    m_AttenuationMapResampleImageFilter->SetOutputSpacing(outputSpacing);\n    m_AttenuationMapResampleImageFilter->SetOutputDirection(this->GetInput(1)->GetDirection());\n    m_AttenuationMapResampleImageFilter->SetInput(m_CustomUnaryFilter->GetOutput());\n    m_AttenuationMapResampleImageFilter->SetDefaultPixelValue(1.);\n    m_AttenuationMapResampleImageFilter->UpdateOutputInformation();\n\n    typename RegionOfInterestFilterType::InputImageRegionType attRegion;\n    attRegion = m_AttenuationMapResampleImageFilter->GetOutput()->GetLargestPossibleRegion();\n    attRegion.SetSize(Dimension - 1, 1);\n    m_AttenuationMapRegionOfInterest->SetRegionOfInterest(attRegion);\n    m_AttenuationMapRegionOfInterest->SetInput(m_AttenuationMapResampleImageFilter->GetOutput());\n    m_AttenuationMapRegionOfInterest->UpdateOutputInformation();\n\n    m_AttenuationMapChangeInformation->SetInput(m_AttenuationMapRegionOfInterest->GetOutput());\n    m_AttenuationMapMultiplyImageFilter->SetInput1(m_ChangeInformation->GetOutput());\n    m_AttenuationMapMultiplyImageFilter->SetInput2(m_AttenuationMapChangeInformation->GetOutput());\n    m_DiscreteGaussianFilter->SetInput(m_AttenuationMapMultiplyImageFilter->GetOutput());\n  }\n\n  m_MultiplyImageFilter->SetConstant(spacingVolume[2]);\n\n  m_ConstantVolumeSource->SetInformationFromImage(const_cast<TInputImage *>(this->GetInput(0)));\n  m_ConstantVolumeSource->SetSpacing(outputSpacing);\n  m_ConstantVolumeSource->SetOrigin(outputOrigin);\n  m_ConstantVolumeSource->SetSize(outputSize);\n  m_ConstantVolumeSource->SetDirection(this->GetInput(1)->GetDirection());\n  m_ConstantVolumeSource->SetConstant(0);\n\n  m_PasteImageFilter->SetSourceImage(m_DiscreteGaussianFilter->GetOutput());\n  m_PasteImageFilter->SetDestinationImage(m_ConstantVolumeSource->GetOutput());\n  m_PasteImageFilter->SetSourceRegion(m_DiscreteGaussianFilter->GetOutput()->GetLargestPossibleRegion());\n\n  m_ResampleImageFilter->SetInput(m_PasteImageFilter->GetOutput());\n  m_AddImageFilter->SetInput1(this->GetInput(0));\n\n  // Update output information\n  m_AddImageFilter->UpdateOutputInformation();\n  this->GetOutput()->SetOrigin(m_AddImageFilter->GetOutput()->GetOrigin());\n  this->GetOutput()->SetSpacing(m_AddImageFilter->GetOutput()->GetSpacing());\n  this->GetOutput()->SetDirection(m_AddImageFilter->GetOutput()->GetDirection());\n  this->GetOutput()->SetLargestPossibleRegion(m_AddImageFilter->GetOutput()->GetLargestPossibleRegion());\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nZengBackProjectionImageFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  const typename Superclass::GeometryType::ConstPointer geometry = this->GetGeometry();\n  const unsigned int                                    Dimension = this->InputImageDimension;\n\n  typename ExtractImageFilterType::InputImageRegionType projRegion;\n  projRegion = this->GetInput(1)->GetLargestPossibleRegion();\n  int                 indexProj = 0;\n  std::vector<double> list_angle;\n  if (geometry->GetGantryAngles().size() != projRegion.GetSize(Dimension - 1))\n  {\n    indexProj = projRegion.GetIndex(Dimension - 1);\n    list_angle.push_back(geometry->GetGantryAngles()[indexProj]);\n  }\n  else\n  {\n    list_angle = geometry->GetGantryAngles();\n  }\n\n  projRegion.SetSize(Dimension - 1, 1);\n\n  typename OuputCPUImageType::Pointer                       currentSlice;\n  typename OuputCPUImageType::Pointer                       pimg;\n  typename OuputCPUImageType::Pointer                       currentVolume;\n  typename OuputCPUImageType::PointType                     pointSlice;\n  typename OuputCPUImageType::IndexType                     indexSlice;\n  typename OuputCPUImageType::Pointer                       rotatedAttenuation;\n  typename RegionOfInterestFilterType::InputImageRegionType desiredRegion;\n  PointType                                                 centerRotatedVolume;\n  PointType                                                 originRotatedVolume;\n\n  indexSlice.Fill(0);\n  double dist = NAN, sigmaSlice = NAN;\n  double thicknessSlice = this->GetInput(0)->GetSpacing()[2];\n  int    nbProjections = indexProj;\n  int    startSlice = -1;\n  for (auto & angle : list_angle)\n  {\n    // Get the center of the rotated volume\n    m_Transform->SetRotation(0., angle, 0.);\n    m_Transform->SetTranslation(itk::MakeVector(geometry->GetProjectionOffsetsX()[nbProjections] * cos(-angle),\n                                                geometry->GetProjectionOffsetsY()[nbProjections],\n                                                geometry->GetProjectionOffsetsX()[nbProjections] * sin(-angle)));\n    centerRotatedVolume = m_Transform->GetMatrix() * m_centerVolume;\n\n    // Set the new origin of the rotate volume according to the center\n    originRotatedVolume = m_ConstantVolumeSource->GetOrigin();\n    originRotatedVolume[2] = centerRotatedVolume[2] - m_ConstantVolumeSource->GetSpacing()[2] *\n                                                        (double)(m_ConstantVolumeSource->GetSize()[2] - 1) / 2.0;\n    m_ConstantVolumeSource->SetOrigin(originRotatedVolume);\n\n    // Set the rotation angle.\n    m_ResampleImageFilter->SetTransform(m_Transform->GetInverseTransform());\n\n    // Extract the projection corresponding to the current angle from the projection stack\n    projRegion.SetIndex(Dimension - 1, nbProjections);\n    m_ExtractImageFilter->SetExtractionRegion(projRegion);\n    m_ExtractImageFilter->UpdateOutputInformation();\n\n    // Find the first positive distance between the volume and the detector\n    m_ConstantVolumeSource->Update();\n    int nbSlice = m_ConstantVolumeSource->GetOutput()->GetLargestPossibleRegion().GetSize()[2];\n    dist = -1;\n    startSlice = -1;\n    while (dist < 0)\n    {\n      startSlice += 1;\n      indexSlice[Dimension - 1] = startSlice;\n      m_ConstantVolumeSource->GetOutput()->TransformIndexToPhysicalPoint(indexSlice, pointSlice);\n      dist = geometry->GetSourceToIsocenterDistances()[nbProjections] +\n             pointSlice.GetVectorFromOrigin() * m_VectorOrthogonalDetector;\n    }\n    if (this->GetInput(2))\n    {\n      m_AttenuationMapResampleImageFilter->SetOutputOrigin(originRotatedVolume);\n      m_AttenuationMapResampleImageFilter->Update();\n      rotatedAttenuation = m_AttenuationMapResampleImageFilter->GetOutput();\n      rotatedAttenuation->DisconnectPipeline();\n      desiredRegion = rotatedAttenuation->GetLargestPossibleRegion();\n      desiredRegion.SetSize(Dimension - 1, 1);\n      desiredRegion.SetIndex(Dimension - 1, startSlice);\n      m_AttenuationMapRegionOfInterest->SetInput(rotatedAttenuation);\n      m_AttenuationMapRegionOfInterest->SetRegionOfInterest(desiredRegion);\n      m_AttenuationMapRegionOfInterest->UpdateOutputInformation();\n    }\n    // Compute the variance of the PSF for the first slice\n    sigmaSlice = pow(m_Alpha * dist + m_SigmaZero, 2.0);\n    m_DiscreteGaussianFilter->SetVariance(sigmaSlice);\n    m_DiscreteGaussianFilter->UpdateLargestPossibleRegion();\n    currentSlice = m_DiscreteGaussianFilter->GetOutput();\n    currentSlice->DisconnectPipeline();\n\n    // Paste the blur slice into the output volume\n    m_PasteImageFilter->SetDestinationImage(m_ConstantVolumeSource->GetOutput());\n    m_PasteImageFilter->SetSourceImage(currentSlice);\n    m_PasteImageFilter->SetSourceRegion(currentSlice->GetLargestPossibleRegion());\n    m_PasteImageFilter->SetDestinationIndex(indexSlice);\n    m_PasteImageFilter->Update();\n    currentVolume = m_PasteImageFilter->GetOutput();\n    currentVolume->DisconnectPipeline();\n    m_PasteImageFilter->SetDestinationImage(currentVolume);\n    int index = 0;\n    for (index = startSlice; index < nbSlice - 1; index++)\n    {\n      if (!this->GetInput(2))\n      {\n        m_DiscreteGaussianFilter->SetInput(currentSlice);\n      }\n      else\n      {\n        desiredRegion.SetIndex(Dimension - 1, index + 1);\n        m_AttenuationMapRegionOfInterest->SetRegionOfInterest(desiredRegion);\n        m_AttenuationMapRegionOfInterest->UpdateOutputInformation();\n        m_AttenuationMapMultiplyImageFilter->SetInput1(currentSlice);\n        m_DiscreteGaussianFilter->SetInput(m_AttenuationMapMultiplyImageFilter->GetOutput());\n      }\n      // Compute the distance between the current slice and the detector\n      indexSlice[Dimension - 1] = index + 1;\n      dist += m_ConstantVolumeSource->GetSpacing()[2];\n      // Compute the variance of the PSF for the current slice\n      sigmaSlice = dist * 2. * thicknessSlice * pow(m_Alpha, 2.0) + 2. * thicknessSlice * m_Alpha * m_SigmaZero -\n                   pow(m_Alpha, 2.0) * pow(thicknessSlice, 2.0);\n      m_DiscreteGaussianFilter->SetVariance(sigmaSlice);\n      m_DiscreteGaussianFilter->Update();\n      currentSlice = m_DiscreteGaussianFilter->GetOutput();\n      currentSlice->DisconnectPipeline();\n\n      // Paste the blur slice into the output volume\n      m_PasteImageFilter->SetSourceImage(currentSlice);\n      m_PasteImageFilter->SetSourceRegion(currentSlice->GetLargestPossibleRegion());\n      m_PasteImageFilter->SetDestinationIndex(indexSlice);\n      m_PasteImageFilter->Update();\n      currentVolume = m_PasteImageFilter->GetOutput();\n      currentVolume->DisconnectPipeline();\n      m_PasteImageFilter->SetDestinationImage(currentVolume);\n    }\n    // Rotate the volume\n    m_ResampleImageFilter->SetInput(currentVolume);\n    m_AddImageFilter->Update();\n    pimg = m_AddImageFilter->GetOutput();\n    pimg->DisconnectPipeline();\n    m_AddImageFilter->SetInput1(pimg);\n    if (!this->GetInput(2))\n    {\n      m_DiscreteGaussianFilter->SetInput(m_ChangeInformation->GetOutput());\n    }\n    else\n    {\n      m_AttenuationMapMultiplyImageFilter->SetInput1(m_ChangeInformation->GetOutput());\n      m_DiscreteGaussianFilter->SetInput(m_AttenuationMapMultiplyImageFilter->GetOutput());\n    }\n    nbProjections++;\n  }\n  this->GetOutput()->SetPixelContainer(pimg->GetPixelContainer());\n  this->GetOutput()->CopyInformation(pimg);\n  this->GetOutput()->SetBufferedRegion(pimg->GetBufferedRegion());\n  this->GetOutput()->SetRequestedRegion(pimg->GetRequestedRegion());\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "include/rtkZengForwardProjectionImageFilter.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkZengForwardProjectionImageFilter_h\n#define rtkZengForwardProjectionImageFilter_h\n\n#include \"rtkConfiguration.h\"\n#include \"rtkForwardProjectionImageFilter.h\"\n#include \"rtkMacro.h\"\n#include <itkPixelTraits.h>\n\n#include <itkMultiplyImageFilter.h>\n#include <itkAddImageFilter.h>\n#include <itkDiscreteGaussianImageFilter.h>\n#include <itkPasteImageFilter.h>\n#include <itkResampleImageFilter.h>\n#include <itkVector.h>\n#include <itkCenteredEuler3DTransform.h>\n#include <itkChangeInformationImageFilter.h>\n#include <itkRegionOfInterestImageFilter.h>\n#include <itkConstantBoundaryCondition.h>\n#include <itkUnaryGeneratorImageFilter.h>\n\n#include <itkVectorImage.h>\nnamespace rtk\n{\n\n/** \\class ZengForwardProjectionImageFilter\n * \\brief Zeng forward projection.\n *\n * Performs a rotation based forward projection, i.e. the volume is rotated so\n * that the face of the image volume is parallel to the detector and the\n * projection is done by summing the collumn. This projector is used to perform\n * the PSF correction described in [Zeng et al, 1999,\n * 10.1109/42.796285]. The forward projector tests if the detector has been\n * placed after the source and the volume. If the detector is in the volume the\n * sum is performed only until that point.\n *\n * \\test rtkZengforwardprojectiontest.cxx\n *\n * \\author Antoine Robert\n *\n * \\ingroup RTK Projector\n */\n\ntemplate <class TInputImage, class TOutputImage>\nclass ITK_TEMPLATE_EXPORT ZengForwardProjectionImageFilter\n  : public ForwardProjectionImageFilter<TInputImage, TOutputImage>\n{\npublic:\n  /** Standard class usings. */\n  using VectorType = itk::Vector<double, 3>;\n  using InputPixelType = typename TInputImage::PixelType;\n  using OutputPixelType = typename TOutputImage::PixelType;\n  using OutputImageRegionType = typename TOutputImage::RegionType;\n  using InputCPUImageType = itk::Image<InputPixelType, 3>;\n  using OuputCPUImageType = itk::Image<OutputPixelType, 3>;\n  using PointType = typename InputCPUImageType::PointType;\n\n  using Self = ZengForwardProjectionImageFilter;\n  using Superclass = ForwardProjectionImageFilter<TInputImage, TOutputImage>;\n  using Pointer = itk::SmartPointer<Self>;\n  using ConstPointer = itk::SmartPointer<const Self>;\n  using AddImageFilterType = itk::AddImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using AddImageFilterPointerType = typename AddImageFilterType::Pointer;\n  using PasteImageFilterType = itk::PasteImageFilter<OuputCPUImageType, InputCPUImageType>;\n  using PasteImageFilterPointerType = typename PasteImageFilterType::Pointer;\n  using DiscreteGaussianFilterType = itk::DiscreteGaussianImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using DiscreteGaussianFilterPointeurType = typename DiscreteGaussianFilterType::Pointer;\n  using ResampleImageFilterType = itk::ResampleImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using ResampleImageFilterPointerType = typename ResampleImageFilterType::Pointer;\n  using TransformType = itk::CenteredEuler3DTransform<double>;\n  using TransformPointerType = typename TransformType::Pointer;\n  using ChangeInformationFilterType = itk::ChangeInformationImageFilter<OuputCPUImageType>;\n  using ChangeInformationPointerType = typename ChangeInformationFilterType::Pointer;\n  using RegionOfInterestFilterType = itk::RegionOfInterestImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using RegionOfInterestPointerType = typename RegionOfInterestFilterType::Pointer;\n  using MultiplyImageFilterType = itk::MultiplyImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using MultpiplyImageFilterPointerType = typename MultiplyImageFilterType::Pointer;\n  using CustomUnaryFilterType = itk::UnaryGeneratorImageFilter<OuputCPUImageType, OuputCPUImageType>;\n  using CustomUnaryFilterPointerType = typename CustomUnaryFilterType::Pointer;\n\n  /** ImageDimension constants */\n  static constexpr unsigned int InputImageDimension = TOutputImage::ImageDimension;\n\n  /** Typedef for the boundary condition */\n  using BoundaryCondition = itk::ConstantBoundaryCondition<OuputCPUImageType>;\n\n  /** Method for creation through the object factory. */\n  itkNewMacro(Self);\n\n  /** Run-time type information (and related methods). */\n  itkOverrideGetNameOfClassMacro(ZengForwardProjectionImageFilter);\n\n  /** Get / Set the sigma zero of the PSF. Default is 1.5417233052142099 */\n  itkGetMacro(SigmaZero, double);\n  itkSetMacro(SigmaZero, double);\n\n  /** Get / Set the alpha of the PSF. Default is 0.016241189545787734 */\n  itkGetMacro(Alpha, double);\n  itkSetMacro(Alpha, double);\n\nprotected:\n  ZengForwardProjectionImageFilter();\n  ~ZengForwardProjectionImageFilter() override = default;\n\n  void\n  GenerateInputRequestedRegion() override;\n\n  void\n  GenerateOutputInformation() override;\n\n  void\n  GenerateData() override;\n\n  /** The two inputs should not be in the same space so there is nothing\n   * to verify. */\n  void\n  VerifyInputInformation() const override;\n\n  RegionOfInterestPointerType        m_RegionOfInterest;\n  AddImageFilterPointerType          m_AddImageFilter;\n  PasteImageFilterPointerType        m_PasteImageFilter;\n  DiscreteGaussianFilterPointeurType m_DiscreteGaussianFilter;\n  ResampleImageFilterPointerType     m_ResampleImageFilter;\n  TransformPointerType               m_Transform;\n  ChangeInformationPointerType       m_ChangeInformation;\n  MultpiplyImageFilterPointerType    m_MultiplyImageFilter;\n  MultpiplyImageFilterPointerType    m_AttenuationMapMultiplyImageFilter;\n  RegionOfInterestPointerType        m_AttenuationMapRegionOfInterest;\n  ResampleImageFilterPointerType     m_AttenuationMapResampleImageFilter;\n  ChangeInformationPointerType       m_AttenuationMapChangeInformation;\n  BoundaryCondition                  m_BoundsCondition;\n  CustomUnaryFilterPointerType       m_CustomUnaryFilter;\n\n\nprivate:\n  ZengForwardProjectionImageFilter(const Self &) = delete; // purposely not implemented\n  void\n  operator=(const Self &) = delete; // purposely not implemented\n\n  double     m_SigmaZero{ 1.5417233052142099 };\n  double     m_Alpha{ 0.016241189545787734 };\n  VectorType m_VectorOrthogonalDetector{ 0. };\n  PointType  m_centerVolume{ 0 };\n};\n\n} // end namespace rtk\n\n#ifndef ITK_MANUAL_INSTANTIATION\n#  include \"rtkZengForwardProjectionImageFilter.hxx\"\n#endif\n\n#endif\n"
  },
  {
    "path": "include/rtkZengForwardProjectionImageFilter.hxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkZengForwardProjectionImageFilter_hxx\n#define rtkZengForwardProjectionImageFilter_hxx\n\n#include <math.h>\n\n#include \"math.h\"\n\n\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkBoxShape.h\"\n#include \"rtkProjectionsRegionConstIteratorRayBased.h\"\n\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkInputDataObjectConstIterator.h>\n\nnamespace rtk\n{\n\ntemplate <class TInputImage, class TOutputImage>\nZengForwardProjectionImageFilter<TInputImage, TOutputImage>::ZengForwardProjectionImageFilter()\n{\n  // Set default parameters\n  m_VectorOrthogonalDetector[2] = 1;\n\n  // Create each filter of the composite filter\n  m_RegionOfInterest = RegionOfInterestFilterType::New();\n  m_AddImageFilter = AddImageFilterType::New();\n  m_PasteImageFilter = PasteImageFilterType::New();\n  m_DiscreteGaussianFilter = DiscreteGaussianFilterType::New();\n  m_ResampleImageFilter = ResampleImageFilterType::New();\n  m_Transform = TransformType::New();\n  m_ChangeInformation = ChangeInformationFilterType::New();\n  m_MultiplyImageFilter = MultiplyImageFilterType::New();\n  m_AttenuationMapMultiplyImageFilter = nullptr;\n  m_AttenuationMapRegionOfInterest = nullptr;\n  m_AttenuationMapResampleImageFilter = nullptr;\n  m_AttenuationMapChangeInformation = nullptr;\n  m_CustomUnaryFilter = nullptr;\n\n  // Permanent internal connections\n  m_AddImageFilter->SetInput1(m_DiscreteGaussianFilter->GetOutput());\n  m_AddImageFilter->SetInput2(m_ChangeInformation->GetOutput());\n  m_MultiplyImageFilter->SetInput(m_PasteImageFilter->GetOutput());\n\n  // Default parameters\n  m_DiscreteGaussianFilter->SetMaximumError(0.00001);\n  m_DiscreteGaussianFilter->SetFilterDimensionality(2);\n  m_DiscreteGaussianFilter->SetInputBoundaryCondition(&m_BoundsCondition);\n  m_DiscreteGaussianFilter->SetRealBoundaryCondition(&m_BoundsCondition);\n  m_ChangeInformation->ChangeOriginOn();\n  m_ChangeInformation->SetReferenceImage(m_DiscreteGaussianFilter->GetOutput());\n  m_ChangeInformation->SetUseReferenceImage(true);\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nZengForwardProjectionImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n  // Input 2 is the attenuation map relative to the volume\n  typename Superclass::InputImagePointer inputPtr2 = const_cast<TInputImage *>(this->GetInput(2));\n  if (!inputPtr2)\n    return;\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nZengForwardProjectionImageFilter<TInputImage, TOutputImage>::VerifyInputInformation() const\n{\n  using ImageBaseType = const itk::ImageBase<InputImageDimension>;\n\n  ImageBaseType * inputPtr1 = nullptr;\n\n  itk::InputDataObjectConstIterator it(this);\n  for (; !it.IsAtEnd(); ++it)\n  {\n    // Check whether the output is an image of the appropriate\n    // dimension (use ProcessObject's version of the GetInput()\n    // method since it returns the input as a pointer to a\n    // DataObject as opposed to the subclass version which\n    // static_casts the input to an TInputImage).\n    if (it.GetName() != \"Primary\")\n    {\n      inputPtr1 = dynamic_cast<ImageBaseType *>(it.GetInput());\n    }\n    if (inputPtr1)\n    {\n      break;\n    }\n  }\n\n  for (; !it.IsAtEnd(); ++it)\n  {\n    if (it.GetName() != \"Primary\")\n    {\n      auto * inputPtrN = dynamic_cast<ImageBaseType *>(it.GetInput());\n      // Physical space computation only matters if we're using two\n      // images, and not an image and a constant.\n      if (inputPtrN)\n      {\n        // check that the image occupy the same physical space, and that\n        // each index is at the same physical location\n\n        // tolerance for origin and spacing depends on the size of pixel\n        // tolerance for directions a fraction of the unit cube.\n        const double coordinateTol = itk::Math::abs(Self::GetGlobalDefaultCoordinateTolerance() *\n                                                    inputPtr1->GetSpacing()[0]); // use first dimension spacing\n\n        if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol) ||\n            !inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n              inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n        {\n          std::ostringstream originString, spacingString, directionString;\n          if (!inputPtr1->GetOrigin().GetVnlVector().is_equal(inputPtrN->GetOrigin().GetVnlVector(), coordinateTol))\n          {\n            originString.setf(std::ios::scientific);\n            originString.precision(7);\n            originString << \"InputImage Origin: \" << inputPtr1->GetOrigin() << \", InputImage\" << it.GetName()\n                         << \" Origin: \" << inputPtrN->GetOrigin() << std::endl;\n            originString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetSpacing().GetVnlVector().is_equal(inputPtrN->GetSpacing().GetVnlVector(), coordinateTol))\n          {\n            spacingString.setf(std::ios::scientific);\n            spacingString.precision(7);\n            spacingString << \"InputImage Spacing: \" << inputPtr1->GetSpacing() << \", InputImage\" << it.GetName()\n                          << \" Spacing: \" << inputPtrN->GetSpacing() << std::endl;\n            spacingString << \"\\tTolerance: \" << coordinateTol << std::endl;\n          }\n          if (!inputPtr1->GetDirection().GetVnlMatrix().as_ref().is_equal(\n                inputPtrN->GetDirection().GetVnlMatrix().as_ref(), Self::GetGlobalDefaultDirectionTolerance()))\n          {\n            directionString.setf(std::ios::scientific);\n            directionString.precision(7);\n            directionString << \"InputImage Direction: \" << inputPtr1->GetDirection() << \", InputImage\" << it.GetName()\n                            << \" Direction: \" << inputPtrN->GetDirection() << std::endl;\n            directionString << \"\\tTolerance: \" << Self::GetGlobalDefaultDirectionTolerance() << std::endl;\n          }\n          itkExceptionMacro(<< \"Inputs do not occupy the same physical space! \" << std::endl\n                            << originString.str() << spacingString.str() << directionString.str());\n        }\n      }\n    }\n  }\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nZengForwardProjectionImageFilter<TInputImage, TOutputImage>::GenerateOutputInformation()\n{\n\n  // Info of the input volume\n  const typename OuputCPUImageType::SpacingType spacingVolume = this->GetInput(1)->GetSpacing();\n  const typename OuputCPUImageType::SizeType    sizeVolume = this->GetInput(1)->GetLargestPossibleRegion().GetSize();\n  const typename OuputCPUImageType::IndexType   indexVolume = this->GetInput(1)->GetLargestPossibleRegion().GetIndex();\n\n  // Info of the input stack of projections\n  const typename InputCPUImageType::SpacingType spacingProjections = this->GetInput(0)->GetSpacing();\n  const typename InputCPUImageType::SizeType  sizeProjection = this->GetInput(0)->GetLargestPossibleRegion().GetSize();\n  const typename OuputCPUImageType::PointType originProjection = this->GetInput(0)->GetOrigin();\n\n  // Find the center of the volume\n  using CoordinateType = typename PointType ::ValueType;\n  using ContinuousIndexType = itk::ContinuousIndex<CoordinateType, InputImageDimension>;\n  using ContinuousIndexValueType = typename ContinuousIndexType::ValueType;\n  ContinuousIndexType centerIndex;\n\n  for (unsigned int k = 0; k < InputImageDimension; k++)\n  {\n    centerIndex[k] = static_cast<ContinuousIndexValueType>(indexVolume[k]) +\n                     static_cast<ContinuousIndexValueType>(sizeVolume[k] - 1) / 2.0;\n  }\n\n  using ValueType = typename PointType::ValueType;\n  m_centerVolume =\n    this->GetInput(1)->template TransformContinuousIndexToPhysicalPoint<CoordinateType, ValueType>(centerIndex);\n\n  PointType centerRotation;\n  centerRotation.Fill(0);\n  m_Transform->SetCenter(centerRotation);\n  m_ResampleImageFilter->SetTransform(m_Transform);\n  m_ResampleImageFilter->SetOutputParametersFromImage(this->GetInput(1));\n\n  // Set the output size of the rotated volume\n  typename OuputCPUImageType::SizeType outputSize;\n  outputSize[0] = sizeProjection[0];\n  outputSize[1] = sizeProjection[1];\n  outputSize[2] = sizeVolume[2] * std::sqrt(2);\n  m_ResampleImageFilter->SetSize(outputSize);\n\n  // Set the new origin of the rotated volume\n  typename OuputCPUImageType::PointType outputOrigin;\n  outputOrigin[0] = originProjection[0];\n  outputOrigin[1] = originProjection[1];\n  outputOrigin[2] = m_centerVolume[2] - spacingVolume[2] * (double)(outputSize[2] - 1) / 2.0;\n  m_ResampleImageFilter->SetOutputOrigin(outputOrigin);\n\n  // Set the output spacing of the rotated volume\n  typename OuputCPUImageType::SpacingType outputSpacing;\n  outputSpacing[0] = spacingProjections[0];\n  outputSpacing[1] = spacingProjections[1];\n  outputSpacing[2] = spacingVolume[2];\n  m_ResampleImageFilter->SetOutputSpacing(outputSpacing);\n  m_ResampleImageFilter->SetOutputDirection(this->GetInput(0)->GetDirection());\n  m_ResampleImageFilter->SetInput(this->GetInput(1));\n  m_ResampleImageFilter->UpdateOutputInformation();\n\n  // We only set the first sub-stack at that point, the rest will be\n  // requested in the GenerateData function\n  typename RegionOfInterestFilterType::InputImageRegionType projRegion;\n  const unsigned int                                        Dimension = this->InputImageDimension;\n  projRegion = m_ResampleImageFilter->GetOutput()->GetLargestPossibleRegion();\n  projRegion.SetSize(Dimension - 1, 1);\n  m_RegionOfInterest->SetRegionOfInterest(projRegion);\n  m_RegionOfInterest->SetInput(m_ResampleImageFilter->GetOutput());\n  m_RegionOfInterest->UpdateOutputInformation();\n\n  m_DiscreteGaussianFilter->SetVariance(pow(m_SigmaZero, 2.0));\n\n  if (!(this->GetInput(2)))\n  {\n    m_DiscreteGaussianFilter->SetInput(m_RegionOfInterest->GetOutput());\n  }\n  else\n  {\n    m_AttenuationMapMultiplyImageFilter = MultiplyImageFilterType::New();\n    m_AttenuationMapRegionOfInterest = RegionOfInterestFilterType::New();\n    m_AttenuationMapResampleImageFilter = ResampleImageFilterType::New();\n    m_AttenuationMapChangeInformation = ChangeInformationFilterType::New();\n    m_AttenuationMapChangeInformation->ChangeOriginOn();\n    m_AttenuationMapChangeInformation->SetReferenceImage(m_DiscreteGaussianFilter->GetOutput());\n    m_AttenuationMapChangeInformation->SetUseReferenceImage(true);\n    m_CustomUnaryFilter = CustomUnaryFilterType::New();\n\n    // Set Lambda function\n    auto customLambda = [spacingVolume](const typename OuputCPUImageType::PixelType & input1) ->\n      typename OuputCPUImageType::PixelType {\n        return static_cast<typename OuputCPUImageType::PixelType>(std::exp(-spacingVolume[2] * input1));\n      };\n    m_CustomUnaryFilter->SetFunctor(customLambda);\n    m_CustomUnaryFilter->SetInput(this->GetInput(2));\n\n    m_AttenuationMapResampleImageFilter->SetTransform(m_Transform);\n    m_AttenuationMapResampleImageFilter->SetOutputParametersFromImage(this->GetInput(1));\n    m_AttenuationMapResampleImageFilter->SetSize(outputSize);\n    m_AttenuationMapResampleImageFilter->SetOutputOrigin(outputOrigin);\n    m_AttenuationMapResampleImageFilter->SetOutputSpacing(outputSpacing);\n    m_AttenuationMapResampleImageFilter->SetOutputDirection(this->GetInput(0)->GetDirection());\n    m_AttenuationMapResampleImageFilter->SetInput(m_CustomUnaryFilter->GetOutput());\n    m_AttenuationMapResampleImageFilter->SetDefaultPixelValue(1.);\n    m_AttenuationMapResampleImageFilter->UpdateOutputInformation();\n\n    m_AttenuationMapRegionOfInterest->SetRegionOfInterest(projRegion);\n    m_AttenuationMapRegionOfInterest->SetInput(m_AttenuationMapResampleImageFilter->GetOutput());\n    m_AttenuationMapRegionOfInterest->UpdateOutputInformation();\n\n    m_AttenuationMapMultiplyImageFilter->SetInput1(m_RegionOfInterest->GetOutput());\n    m_AttenuationMapMultiplyImageFilter->SetInput2(m_AttenuationMapRegionOfInterest->GetOutput());\n    m_DiscreteGaussianFilter->SetInput(m_AttenuationMapMultiplyImageFilter->GetOutput());\n  }\n\n  m_MultiplyImageFilter->SetConstant(spacingVolume[2]);\n\n  m_PasteImageFilter->SetSourceImage(m_DiscreteGaussianFilter->GetOutput());\n  m_PasteImageFilter->SetDestinationImage(this->GetInput(0));\n  m_PasteImageFilter->SetSourceRegion(m_DiscreteGaussianFilter->GetOutput()->GetLargestPossibleRegion());\n\n  // Update output information\n  m_PasteImageFilter->UpdateOutputInformation();\n  this->GetOutput()->SetOrigin(m_PasteImageFilter->GetOutput()->GetOrigin());\n  this->GetOutput()->SetSpacing(m_PasteImageFilter->GetOutput()->GetSpacing());\n  this->GetOutput()->SetDirection(m_PasteImageFilter->GetOutput()->GetDirection());\n  this->GetOutput()->SetLargestPossibleRegion(m_PasteImageFilter->GetOutput()->GetLargestPossibleRegion());\n\n  //  m_ResampleImageFilter->ReleaseDataFlagOn();\n}\n\ntemplate <class TInputImage, class TOutputImage>\nvoid\nZengForwardProjectionImageFilter<TInputImage, TOutputImage>::GenerateData()\n{\n  const unsigned int                                    Dimension = this->InputImageDimension;\n  const typename Superclass::GeometryType::ConstPointer geometry = this->GetGeometry();\n  typename OuputCPUImageType::RegionType                projRegion = this->GetInput(0)->GetLargestPossibleRegion();\n  std::vector<double>                                   list_angle;\n  if (geometry->GetGantryAngles().size() != projRegion.GetSize(Dimension - 1))\n  {\n    list_angle.push_back(geometry->GetGantryAngles()[projRegion.GetIndex(Dimension - 1)]);\n  }\n  else\n  {\n    list_angle = geometry->GetGantryAngles();\n  }\n\n  typename OuputCPUImageType::Pointer   currentSlice;\n  typename OuputCPUImageType::Pointer   pimg;\n  typename OuputCPUImageType::Pointer   rotatedVolume;\n  typename OuputCPUImageType::IndexType indexSlice;\n  typename OuputCPUImageType::IndexType indexProjection;\n  PointType                             pointSlice;\n  PointType                             centerRotatedVolume;\n  PointType                             originRotatedVolume;\n\n  indexSlice.Fill(0);\n  indexProjection.Fill(0);\n  double dist = NAN, sigmaSlice = NAN;\n  double thicknessSlice = NAN;\n  int    nbProjections = projRegion.GetIndex(Dimension - 1);\n  for (auto & angle : list_angle)\n  {\n    // Set the rotation angle.\n    m_Transform->SetRotation(0., angle, 0.);\n    m_Transform->SetTranslation(itk::MakeVector(geometry->GetProjectionOffsetsX()[nbProjections] * cos(-angle),\n                                                geometry->GetProjectionOffsetsY()[nbProjections],\n                                                geometry->GetProjectionOffsetsX()[nbProjections] * sin(-angle)));\n    centerRotatedVolume = m_Transform->GetMatrix() * m_centerVolume;\n\n    // Rotate the input volume\n    this->GetInput(1)->GetBufferPointer();\n    originRotatedVolume = m_ResampleImageFilter->GetOutputOrigin();\n    originRotatedVolume[2] = centerRotatedVolume[2] - m_ResampleImageFilter->GetOutputSpacing()[2] *\n                                                        (double)(m_ResampleImageFilter->GetSize()[2] - 1) / 2.0;\n    m_ResampleImageFilter->SetOutputOrigin(originRotatedVolume);\n    m_ResampleImageFilter->Update();\n    rotatedVolume = m_ResampleImageFilter->GetOutput();\n    rotatedVolume->DisconnectPipeline();\n    thicknessSlice = rotatedVolume->GetSpacing()[2];\n\n    // Extract slice from the volume starting by the farthest from the detector.\n    typename RegionOfInterestFilterType::InputImageRegionType desiredRegion = rotatedVolume->GetLargestPossibleRegion();\n    unsigned int                                              nbSlice = desiredRegion.GetSize(Dimension - 1);\n    desiredRegion.SetSize(Dimension - 1, 1);\n    desiredRegion.SetIndex(Dimension - 1, nbSlice - 1);\n    indexSlice[2] = nbSlice - 1;\n    m_RegionOfInterest->SetInput(rotatedVolume);\n    m_RegionOfInterest->SetRegionOfInterest(desiredRegion);\n    m_RegionOfInterest->UpdateOutputInformation();\n    m_RegionOfInterest->Update();\n    if (!(this->GetInput(2)))\n    {\n      currentSlice = m_RegionOfInterest->GetOutput();\n    }\n    else\n    {\n      typename OuputCPUImageType::Pointer rotatedAttenuation;\n      m_AttenuationMapResampleImageFilter->SetOutputOrigin(originRotatedVolume);\n      m_AttenuationMapResampleImageFilter->Update();\n      rotatedAttenuation = m_AttenuationMapResampleImageFilter->GetOutput();\n      rotatedAttenuation->DisconnectPipeline();\n      m_AttenuationMapRegionOfInterest->SetInput(rotatedAttenuation);\n      m_AttenuationMapRegionOfInterest->SetRegionOfInterest(desiredRegion);\n      m_AttenuationMapRegionOfInterest->UpdateOutputInformation();\n      m_AttenuationMapMultiplyImageFilter->SetInput1(m_RegionOfInterest->GetOutput());\n      m_AttenuationMapMultiplyImageFilter->SetInput2(m_AttenuationMapRegionOfInterest->GetOutput());\n      m_AttenuationMapMultiplyImageFilter->Update();\n      m_AttenuationMapChangeInformation->SetInput(m_AttenuationMapRegionOfInterest->GetOutput());\n      currentSlice = m_AttenuationMapMultiplyImageFilter->GetOutput();\n    }\n    currentSlice->DisconnectPipeline();\n    m_DiscreteGaussianFilter->SetInput(currentSlice);\n    m_ChangeInformation->SetInput(m_RegionOfInterest->GetOutput());\n\n    // Compute the distance between the current slice and the detector\n    rotatedVolume->TransformIndexToPhysicalPoint(indexSlice, pointSlice);\n    dist = geometry->GetSourceToIsocenterDistances()[nbProjections] +\n           pointSlice.GetVectorFromOrigin() * m_VectorOrthogonalDetector;\n    int index = 0;\n    for (index = nbSlice - 2; index >= 0; index--)\n    {\n      if (dist - rotatedVolume->GetSpacing()[2] < 0)\n      {\n        break;\n      }\n      // Compute the variance of the PSF for the current slice\n      sigmaSlice = dist * 2. * thicknessSlice * pow(m_Alpha, 2.0) + 2. * thicknessSlice * m_Alpha * m_SigmaZero -\n                   pow(m_Alpha, 2.0) * pow(thicknessSlice, 2.0);\n      m_DiscreteGaussianFilter->SetVariance(sigmaSlice);\n\n      // Extract the next slice\n      desiredRegion.SetIndex(Dimension - 1, index);\n      m_RegionOfInterest->SetRegionOfInterest(desiredRegion);\n      m_RegionOfInterest->UpdateOutputInformation();\n\n      // Add the current blur slice with the next\n      m_AddImageFilter->GetOutput()->UpdateOutputInformation();\n      m_AddImageFilter->GetOutput()->PropagateRequestedRegion();\n      m_AddImageFilter->Update();\n      if (!(this->GetInput(2)))\n      {\n        currentSlice = m_AddImageFilter->GetOutput();\n      }\n      else\n      {\n        m_AttenuationMapRegionOfInterest->SetRegionOfInterest(desiredRegion);\n        m_AttenuationMapRegionOfInterest->UpdateOutputInformation();\n        m_AttenuationMapMultiplyImageFilter->SetInput1(m_AddImageFilter->GetOutput());\n        m_AttenuationMapMultiplyImageFilter->SetInput2(m_AttenuationMapChangeInformation->GetOutput());\n        m_AttenuationMapMultiplyImageFilter->Update();\n        currentSlice = m_AttenuationMapMultiplyImageFilter->GetOutput();\n      }\n      currentSlice->DisconnectPipeline();\n      m_DiscreteGaussianFilter->SetInput(currentSlice);\n      dist -= rotatedVolume->GetSpacing()[2];\n    }\n    // Compute the variance of the PSF for the last slice\n    sigmaSlice = pow(m_Alpha * dist + m_SigmaZero, 2.0);\n    m_DiscreteGaussianFilter->SetVariance(sigmaSlice);\n    // Paste the projection in the output volume\n    indexProjection[Dimension - 1] = nbProjections;\n    m_PasteImageFilter->SetSourceRegion(m_DiscreteGaussianFilter->GetOutput()->GetLargestPossibleRegion());\n    m_PasteImageFilter->SetDestinationIndex(indexProjection);\n    m_PasteImageFilter->UpdateLargestPossibleRegion();\n    pimg = m_PasteImageFilter->GetOutput();\n\n    pimg->DisconnectPipeline();\n    m_PasteImageFilter->SetDestinationImage(pimg);\n    nbProjections++;\n  }\n  m_MultiplyImageFilter->SetInput(pimg);\n  m_MultiplyImageFilter->UpdateLargestPossibleRegion();\n  pimg = m_MultiplyImageFilter->GetOutput();\n  pimg->DisconnectPipeline();\n  this->GetOutput()->SetPixelContainer(pimg->GetPixelContainer());\n  this->GetOutput()->CopyInformation(pimg);\n  this->GetOutput()->SetBufferedRegion(pimg->GetBufferedRegion());\n  this->GetOutput()->SetRequestedRegion(pimg->GetRequestedRegion());\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "index.md",
    "content": "﻿The Reconstruction Toolkit (RTK)\n================================\n\nRTK is an open-source and cross-platform software for fast circular cone-beam CT reconstruction based on the Insight Toolkit (ITK). RTK is developed by the RTK consortium.\n\n[![GitHub release](https://img.shields.io/github/release/RTKConsortium/RTK.svg)](https://github.com/RTKConsortium/RTK/releases/latest)\n[![PyPI](https://img.shields.io/pypi/v/itk-rtk.svg)](https://pypi.python.org/pypi/itk-rtk)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/RTKConsortium/RTK/blob/master/LICENSE.TXT)\n\n```{toctree}\nGettingStarted\n```\n\n```{toctree}\n:maxdepth: 1\n:caption: 💾 Download\nINSTALLATION\n```\n\n```{toctree}\n:maxdepth: 1\n:caption: 📖 Learn\ndocumentation/docs/Geometry.md\ndocumentation/docs/Phantom.md\ndocumentation/docs/Projectors.md\nexamples/README.md\napplications/README.md\n```\n\n```{toctree}\n:maxdepth: 1\n:caption: 🔨 Develop\nAPI <https://www.openrtk.org/Doxygen/index.html>\nDiscussion <https://www.creatis.insa-lyon.fr/mailman/listinfo/rtk-users>\nIssue tracker <https://github.com/RTKConsortium/RTK/issues>\ndocumentation/docs/rtk_3_migration_guide.md\nCodeContribution\ndocumentation/docs/README\ndocumentation/docs/Release\n\n```\n"
  },
  {
    "path": "itk-module-init.cmake",
    "content": "#\n# Find the packages required by this module\n#\nlist(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)\n\n# Set default Cuda architecture if not provided. The first case allows for\n# backward compatibility with cmake versions before 3.20 which did not handle\n# CUDAARCHS environment variable.\nif(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)\n  if(DEFINED ENV{CUDAARCHS})\n    set(CMAKE_CUDA_ARCHITECTURES \"$ENV{CUDAARCHS}\" CACHE STRING \"CUDA architectures\")\n  else()\n    set(CMAKE_CUDA_ARCHITECTURES \"52\" CACHE STRING \"CUDA architectures\")\n  endif()\nendif()\ninclude(CheckLanguage)\ncheck_language(CUDA)\n\n# Determine default value for RTK_USE_CUDA\nset(RTK_USE_CUDA_DEFAULT OFF)\nif (CMAKE_CUDA_COMPILER)\n  set(CUDAToolkit_NVCC_EXECUTABLE ${CMAKE_CUDA_COMPILER})\n  find_package(CUDAToolkit)\n  if(NOT CUDAToolkit_FOUND)\n    message(WARNING \"CUDAToolkit not found (available since CMake v3.17). RTK_USE_CUDA set to OFF.\")\n  elseif(DEFINED CUDAToolkit_VERSION AND \"${CUDAToolkit_VERSION}\" VERSION_LESS 8.0)\n    message(WARNING \"CUDA version ${CUDAToolkit_VERSION} is not supported by RTK, version 8 is required. RTK_USE_CUDA set to OFF.\")\n  else()\n    set(RTK_USE_CUDA_DEFAULT ON)\n  endif()\nendif()\noption(RTK_USE_CUDA \"Use CUDA for RTK\" ${RTK_USE_CUDA_DEFAULT})\n\n# Configure CUDA compilation options\noption(RTK_CUDA_VERSION \"Specify the exact CUDA version that must be used for RTK\")\nif(RTK_USE_CUDA)\n  enable_language(CUDA)\n  set(CMAKE_CUDA_RUNTIME_LIBRARY Static)\n\n  include_directories(${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES})\n  if(RTK_CUDA_VERSION)\n    find_package(CUDAToolkit EXACT ${RTK_CUDA_VERSION})\n  else()\n    find_package(CUDAToolkit REQUIRED 8.0)\n  endif()\n\n  set(RTK_CUDA_PROJECTIONS_SLAB_SIZE \"16\" CACHE STRING \"Number of projections processed simultaneously in CUDA forward and back projections\")\nelseif(RTK_CUDA_VERSION)\n  message(FATAL_ERROR \"RTK_CUDA_VERSION is set but the CUDA toolkit has not been found.\")\nendif()\n"
  },
  {
    "path": "itk-module.cmake",
    "content": "set(DOCUMENTATION \"\")\n\n# -----------------------------------------\n#  Required Modules to build RTK library :\nset(RTK_IO_DEPENDS\n  ITKIOCSV\n  ITKIOGDCM\n  ITKGDCM\n  ITKIOMeta\n  ITKIORAW\n  ITKIOTIFF\n  ITKIOXML\n  )\n\nif(ITK_WRAP_PYTHON)\n  set(RTK_BRIDGE_DEPENDS\n  ITKBridgeNumPy\n  )\nendif()\n\nset(RTK_DEPENDS\n  ITKCommon\n  ITKConvolution\n  ITKFFT\n  ITKOptimizers\n  ITKRegistrationCommon\n  ITKSmoothing\n  ITKImageNoise\n  ${RTK_IO_DEPENDS}\n  ${RTK_BRIDGE_DEPENDS}\n  )\n\n# -----------------------------------------\n#  Required Modules to build RTK tests :\nset(RTK_TEST_DEPENDS\n  ITKTestKernel)\n\n# # -----------------------------------------\n# # CUDA optional dependencies\nif(${RTK_USE_CUDA})\n  list(APPEND RTK_DEPENDS CudaCommon)\nendif()\n\n#=========================================================\n# Module RTK\n#=========================================================\nitk_module(RTK\n  ENABLE_SHARED\n  EXCLUDE_FROM_DEFAULT\n  DEPENDS\n    ${RTK_DEPENDS}\n  TEST_DEPENDS\n    ${RTK_TEST_DEPENDS}\n  FACTORY_NAMES\n    ImageIO::DCMImagX\n    ImageIO::His\n    ImageIO::Hnc\n    ImageIO::Hnd\n    ImageIO::ImagX\n    ImageIO::Ora\n    ImageIO::Xim\n    ImageIO::XRad\n  DESCRIPTION\n    \"${DOCUMENTATION}\"\n  )\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [\"scikit-build-core\"]\nbuild-backend = \"scikit_build_core.build\"\n\n[project]\nname = \"itk-rtk\"\nversion = \"2.7.0.post1\"\ndescription = \"The Reconstruction Toolkit (RTK) for fast circular cone-beam CT reconstruction\"\nreadme = \"README.md\"\nlicense = {file = \"LICENSE.TXT\"}\nauthors = [\n    { name = \"RTK Consortium\", email = \"simon.rit@creatis.insa-lyon.fr\" },\n]\nkeywords = [\n    \"itk\",\n    \"rtk\",\n]\nclassifiers = [\n    \"Development Status :: 4 - Beta\",\n    \"Intended Audience :: Developers\",\n    \"Intended Audience :: Education\",\n    \"Intended Audience :: Healthcare Industry\",\n    \"Intended Audience :: Science/Research\",\n    \"License :: OSI Approved :: Apache Software License\",\n    \"Operating System :: Android\",\n    \"Operating System :: MacOS\",\n    \"Operating System :: Microsoft :: Windows\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: Unix\",\n    \"Programming Language :: C++\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Python :: 3\",\n    \"Topic :: Scientific/Engineering\",\n    \"Topic :: Scientific/Engineering :: Information Analysis\",\n    \"Topic :: Scientific/Engineering :: Medical Science Apps.\",\n    \"Topic :: Software Development :: Libraries\",\n]\nrequires-python = \">=3.8\"\ndependencies = [\n    \"itk == 5.4.*\",\n]\n\n[project.scripts]\nrtkadmmtotalvariation = \"itk.rtkadmmtotalvariation:main\"\nrtkamsterdamshroud = \"itk.rtkamsterdamshroud:main\"\nrtkbackprojections = \"itk.rtkbackprojections:main\"\nrtkbioscangeometry = \"itk.rtkbioscangeometry:main\"\nrtkcheckimagequality = \"itk.rtkcheckimagequality:main\"\nrtkconjugategradient = \"itk.rtkconjugategradient:main\"\nrtkdigisensgeometry = \"itk.rtkdigisensgeometry:main\"\nrtkdrawgeometricphantom = \"itk.rtkdrawgeometricphantom:main\"\nrtkdrawshepploganphantom = \"itk.rtkdrawshepploganphantom:main\"\nrtkdualenergyforwardmodel = \"itk.rtkdualenergyforwardmodel:main\"\nrtkdualenergysimplexdecomposition = \"itk.rtkdualenergysimplexdecomposition:main\"\nrtkelektasynergygeometry = \"itk.rtkelektasynergygeometry:main\"\nrtkextractphasesignal = \"itk.rtkextractphasesignal:main\"\nrtkfdk = \"itk.rtkfdk:main\"\nrtkfieldofview = \"itk.rtkfieldofview:main\"\nrtkforwardprojections = \"itk.rtkforwardprojections:main\"\nrtkorageometry = \"itk.rtkorageometry:main\"\nrtkprojectgeometricphantom = \"itk.rtkprojectgeometricphantom:main\"\nrtkprojections = \"itk.rtkprojections:main\"\nrtkprojectshepploganphantom= \"itk.rtkprojectshepploganphantom:main\"\nrtkshowgeometry = \"itk.rtkshowgeometry:main\"\nrtksimulatedgeometry = \"itk.rtksimulatedgeometry:main\"\nrtkvarianobigeometry = \"itk.rtkvarianobigeometry:main\"\n\n[project.urls]\nDownload = \"https://github.com/RTKConsortium/RTK\"\nHomepage = \"https://www.openrtk.org\"\n\n[tool.scikit-build]\n# The versions of CMake to allow. If CMake is not present on the system or does\n# not pass this specifier, it will be downloaded via PyPI if possible. An empty\n# string will disable this check.\ncmake.version = \">=3.16.3\"\n\n# A list of args to pass to CMake when configuring the project. Setting this in\n# config or envvar will override toml. See also ``cmake.define``.\ncmake.args = []\n\n# A table of defines to pass to CMake when configuring the project. Additive.\ncmake.define = {}\n\n# Verbose printout when building.\ncmake.verbose = true\n\n# The build type to use when building the project. Valid options are: \"Debug\",\n# \"Release\", \"RelWithDebInfo\", \"MinSizeRel\", \"\", etc.\ncmake.build-type = \"Release\"\n\n# The source directory to use when building the project. Currently only affects\n# the native builder (not the setuptools plugin).\ncmake.source-dir = \".\"\n\n# The versions of Ninja to allow. If Ninja is not present on the system or does\n# not pass this specifier, it will be downloaded via PyPI if possible. An empty\n# string will disable this check.\nninja.version = \">=1.11\"\n\n# If CMake is not present on the system or is older required, it will be\n# downloaded via PyPI if possible. An empty string will disable this check.\nninja.make-fallback = true\n\n# The logging level to display, \"DEBUG\", \"INFO\", \"WARNING\", and \"ERROR\" are\n# possible options.\nlogging.level = \"INFO\"\n\n# Files to include in the SDist even if they are skipped by default. Supports\n# gitignore syntax.\nsdist.include = []\n\n# Files to exclude from the SDist even if they are included by default. Supports\n# gitignore syntax.\nsdist.exclude = []\n\n# A list of license files to include in the wheel. Supports glob patterns.\nwheel.license-files = [\"LICEN[CS]E*\",]\n\n# Target the platlib or the purelib. If not set, the default is to target the\n# platlib if wheel.cmake is true, and the purelib otherwise.\nwheel.platlib = \"false\"\n\n# If CMake is less than this value, backport a copy of FindPython. Set to 0\n# disable this, or the empty string.\nbackport.find-python = \"3.26.1\"\n\n# Select the editable mode to use. Can be \"redirect\" (default) or \"inplace\".\neditable.mode = \"redirect\"\n\n# Rebuild the project when the package is imported. The build-directory must be\n# set.\neditable.rebuild = false\n\n# The components to install. If empty, all default components are installed.\ninstall.components = []\n\n# Whether to strip the binaries. True for scikit-build-core 0.5+.\ninstall.strip = true\n\n# If set, this will provide a method for backward compatibility.\nminimum-version = \"0.8.2\"\n\n# The build directory. Defaults to a temporary directory, but can be set.\nbuild-dir = \"build/{wheel_tag}\"\n"
  },
  {
    "path": "rtkConfiguration.h.in",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef __rtkConfiguration_h\n#define __rtkConfiguration_h\n// This file is interpreted by cmake, to define macros based on the cmake configuration options\n//\n\n#include <itkConfigure.h>\n#include <itkIntTypes.h>\nnamespace rtk\n{\nusing ThreadIdType = itk::ThreadIdType;\n}\n\n#cmakedefine RTK_PROBE_EACH_FILTER\n#cmakedefine RTK_USE_CUDA\n#cmakedefine RTK_BUILD_SHARED_LIBS 1\n#ifndef SLAB_SIZE\n#  define SLAB_SIZE @RTK_CUDA_PROJECTIONS_SLAB_SIZE@\n#endif\n\n// CudaCommon_VERSION_* and cudaCommonConfiguration.h were introduced in CudaCommon 2.0\n#cmakedefine CudaCommon_VERSION_MAJOR\n#ifdef CudaCommon_VERSION_MAJOR\n#  undef CudaCommon_VERSION_MAJOR\n#  include <cudaCommonConfiguration.h>\n#endif\n\n#define RTK_BINARY_DIR \"@RTK_BINARY_DIR@\"\n#define RTK_DATA_ROOT \"@RTK_DATA_ROOT@\"\n\n/* Fix for ITK4 */\n#if defined(ITK_USE_FFTWF) && !defined(USE_FFTWF)\n#  define USE_FFTWF\n#endif\n#if defined(ITK_USE_FFTWD) && !defined(USE_FFTWD)\n#  define USE_FFTWD\n#endif\n\n#define RTK_VERSION_MAJOR @RTK_VERSION_MAJOR@\n#define RTK_VERSION_MINOR @RTK_VERSION_MINOR@\n#define RTK_VERSION_PATCH @RTK_VERSION_PATCH@\n#define RTK_VERSION_STRING \"@RTK_VERSION_STRING@\"\n\n#endif\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "set(RTK_SRCS\n  rtkBioscanGeometryReader.cxx\n  rtkBoxShape.cxx\n  rtkConditionalMedianImageFilter.cxx\n  rtkConvexShape.cxx\n  rtkDbf.cxx\n  rtkDCMImagXImageIO.cxx\n  rtkDCMImagXImageIOFactory.cxx\n  rtkDigisensGeometryReader.cxx\n  rtkDigisensGeometryXMLFileReader.cxx\n  rtkEdfImageIO.cxx\n  rtkEdfImageIOFactory.cxx\n  rtkElektaSynergyGeometryReader.cxx\n  rtkElektaXVI5GeometryXMLFileReader.cxx\n  rtkForbildPhantomFileReader.cxx\n  rtkGeometricPhantom.cxx\n  rtkGlobalResourceProbe.cxx\n  rtkHisImageIO.cxx\n  rtkHisImageIOFactory.cxx\n  rtkHncImageIO.cxx\n  rtkHncImageIOFactory.cxx\n  rtkHndImageIO.cxx\n  rtkHndImageIOFactory.cxx\n  rtkImagXImageIO.cxx\n  rtkImagXImageIOFactory.cxx\n  rtkImagXXMLFileReader.cxx\n  rtkIntersectionOfConvexShapes.cxx\n  rtkIOFactories.cxx\n  rtkOraGeometryReader.cxx\n  rtkOraImageIO.cxx\n  rtkOraImageIOFactory.cxx\n  rtkOraXMLFileReader.cxx\n  rtkPhaseReader.cxx\n  rtkPhasesToInterpolationWeights.cxx\n  rtkQuadricShape.cxx\n  rtkReg23ProjectionGeometry.cxx\n  rtkSheppLoganPhantom.cxx\n  rtkSignalToInterpolationWeights.cxx\n  rtkThreeDCircularProjectionGeometry.cxx\n  rtkThreeDCircularProjectionGeometryXMLFileReader.cxx\n  rtkThreeDCircularProjectionGeometryXMLFileWriter.cxx\n  rtkResourceProbesCollector.cxx\n  rtkVarianObiGeometryReader.cxx\n  rtkVarianObiXMLFileReader.cxx\n  rtkVarianProBeamGeometryReader.cxx\n  rtkVarianProBeamXMLFileReader.cxx\n  rtkWatcherForResourceProbe.cxx\n  rtkXimImageIO.cxx\n  rtkXimImageIOFactory.cxx\n  rtkXRadGeometryReader.cxx\n  rtkXRadImageIO.cxx\n  rtkXRadImageIOFactory.cxx\n  )\n\n#=========================================================\n# This is a fix for when using Module_ITKVtkGlue\n# (https://gitlab.kitware.com/vtk/vtk/issues/15895)\nget_directory_property(defCom COMPILE_DEFINITIONS)\nset(defComSansVTK)\nforeach(def ${defCom})\n  if(NOT def MATCHES \"^vtk.*\")\n    list(APPEND defComSansVTK ${def})\n  endif()\nendforeach()\nset_directory_properties(PROPERTIES COMPILE_DEFINITIONS \"${defComSansVTK}\")\n\n#=========================================================\n# CUDA library\n#=========================================================\nif (RTK_USE_CUDA)\n  set(RTK_SRCS ${RTK_SRCS}\n    rtkCudaAverageOutOfROIImageFilter.cxx\n    rtkCudaConstantVolumeSeriesSource.cxx\n    rtkCudaConstantVolumeSource.cxx\n    rtkCudaCropImageFilter.cxx\n    rtkCudaCyclicDeformationImageFilter.cxx\n    rtkCudaDisplacedDetectorImageFilter.cxx\n    rtkCudaFDKBackProjectionImageFilter.cxx\n    rtkCudaFDKConeBeamReconstructionFilter.cxx\n    rtkCudaFDKWeightProjectionFilter.cxx\n    rtkCudaForwardWarpImageFilter.cxx\n    rtkCudaInterpolateImageFilter.cxx\n    rtkCudaIterativeFDKConeBeamReconstructionFilter.cxx\n    rtkCudaLagCorrectionImageFilter.cxx\n    rtkCudaLaplacianImageFilter.cxx\n    rtkCudaLastDimensionTVDenoisingImageFilter.cxx\n    rtkCudaParkerShortScanImageFilter.cxx\n    rtkCudaPolynomialGainCorrectionImageFilter.cxx\n    rtkCudaRayCastBackProjectionImageFilter.cxx\n    rtkCudaSplatImageFilter.cxx\n    rtkCudaTotalVariationDenoisingBPDQImageFilter.cxx\n    rtkCudaWarpBackProjectionImageFilter.cxx\n    rtkCudaWarpForwardProjectionImageFilter.cxx\n    rtkCudaWarpImageFilter.cxx)\n\n  set(RTK_SRCS ${RTK_SRCS}\n    rtkCudaAverageOutOfROIImageFilter.cu\n    rtkCudaBackProjectionImageFilter.cu\n    rtkCudaConjugateGradientImageFilter.cu\n    rtkCudaConstantVolumeSeriesSource.cu\n    rtkCudaConstantVolumeSource.cu\n    rtkCudaCropImageFilter.cu\n    rtkCudaCyclicDeformationImageFilter.cu\n    rtkCudaDisplacedDetectorImageFilter.cu\n    rtkCudaFDKBackProjectionImageFilter.cu\n    rtkCudaFDKWeightProjectionFilter.cu\n    rtkCudaFFTProjectionsConvolutionImageFilter.cu\n    rtkCudaFirstOrderKernels.cu\n    rtkCudaForwardProjectionImageFilter.cu\n    rtkCudaForwardWarpImageFilter.cu\n    rtkCudaInterpolateImageFilter.cu\n    rtkCudaLagCorrectionImageFilter.cu\n    rtkCudaLaplacianImageFilter.cu\n    rtkCudaLastDimensionTVDenoisingImageFilter.cu\n    rtkCudaParkerShortScanImageFilter.cu\n    rtkCudaPolynomialGainCorrectionImageFilter.cu\n    rtkCudaRayCastBackProjectionImageFilter.cu\n    rtkCudaSplatImageFilter.cu\n    rtkCudaTotalVariationDenoisingBPDQImageFilter.cu\n    rtkCudaUtilities.cu\n    rtkCudaWarpBackProjectionImageFilter.cu\n    rtkCudaWarpForwardProjectionImageFilter.cu\n    rtkCudaWarpImageFilter.cu\n    rtkCudaWeidingerForwardModelImageFilter.cu\n    )\nendif()\n#=========================================================\n\nitk_module_add_library(RTK ${RTK_SRCS})\ntarget_link_libraries(RTK PUBLIC lpsolve55)\n\nif (RTK_USE_CUDA)\n  target_link_libraries(RTK PUBLIC CUDA::cufft CUDA::cublas)\n  set_property(TARGET RTK PROPERTY CUDA_STANDARD ${CMAKE_CXX_STANDARD})\nendif ()\n"
  },
  {
    "path": "src/rtkBioscanGeometryReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkBioscanGeometryReader_hxx\n#define rtkBioscanGeometryReader_hxx\n\n#include \"rtkMacro.h\"\n#include \"rtkBioscanGeometryReader.h\"\n#include \"rtkIOFactories.h\"\n\n#include <gdcmImageReader.h>\n#include <gdcmAttribute.h>\n#include <gdcmDataSet.h>\n\nnamespace rtk\n{\n\nstd::vector<float>\nBioscanGeometryReader::GetVectorTagValue(const gdcm::DataSet & ds, itk::uint16_t group, itk::uint16_t element) const\n{\n  const gdcm::Tag tag(group, element);\n  if (!ds.FindDataElement(tag))\n  {\n    itkExceptionMacro(<< \"Cannot find tag \" << group << \"|\" << element);\n  }\n  const gdcm::DataElement &                    de = ds.GetDataElement(tag);\n  gdcm::Element<gdcm::VR::FL, gdcm::VM::VM1_n> el;\n  el.Set(de.GetValue());\n  std::vector<float> val;\n  for (unsigned int i = 0; i < el.GetLength(); i++)\n  {\n    val.push_back(el.GetValue(i));\n  }\n  return val;\n}\n\nstd::string\nBioscanGeometryReader::GetStringTagValue(const gdcm::DataSet & ds, itk::uint16_t group, itk::uint16_t element) const\n{\n  const gdcm::Tag tag(group, element);\n  if (!ds.FindDataElement(tag))\n  {\n    itkExceptionMacro(<< \"Cannot find tag \" << group << \"|\" << element);\n  }\n  const gdcm::DataElement & de = ds.GetDataElement(tag);\n  const gdcm::ByteValue *   bv = de.GetByteValue();\n  return std::string(bv->GetPointer(), bv->GetLength());\n}\n\ndouble\nBioscanGeometryReader::GetFloatTagValue(const gdcm::DataSet & ds, itk::uint16_t group, itk::uint16_t element) const\n{\n  const gdcm::Tag tag(group, element);\n  if (!ds.FindDataElement(tag))\n  {\n    itkExceptionMacro(<< \"Cannot find tag \" << group << \"|\" << element);\n  }\n  const gdcm::DataElement &                  de = ds.GetDataElement(tag);\n  gdcm::Element<gdcm::VR::FD, gdcm::VM::VM1> el;\n  el.SetFromDataElement(de);\n  return el.GetValue();\n}\n\nvoid\nBioscanGeometryReader::GenerateData()\n{\n  m_Geometry = GeometryType::New();\n  for (const std::string & m_ProjectionsFileName : m_ProjectionsFileNames)\n  {\n    gdcm::Reader reader;\n    reader.SetFileName(m_ProjectionsFileName.c_str());\n    if (!reader.Read())\n    {\n      itkExceptionMacro(<< \"Cannot read requested file: \" << m_ProjectionsFileName);\n    }\n    const gdcm::DataSet & ds = reader.GetFile().GetDataSet();\n\n    // See https://github.com/JStrydhorst/win-cone-ct/blob/master/ct_recon_win.h#L111\n    const std::vector<float> zOffsets = GetVectorTagValue(ds, 0x0009, 0x1046);\n    const std::vector<float> yOffsets = GetVectorTagValue(ds, 0x0009, 0x1047);\n    const double             sdd = std::stod(GetStringTagValue(ds, 0x0018, 0x1110).c_str());\n    const double             sid = std::stod(GetStringTagValue(ds, 0x0018, 0x1111).c_str());\n    // const double spacing = GetFloatTagValue(ds, 0x0018, 0x9306);\n    const double angle = GetFloatTagValue(ds, 0x0009, 0x1036);\n\n    // See https://github.com/JStrydhorst/win-cone-ct/blob/master/ct_recon_win.h#L222\n    const float yOffset = yOffsets[(itk::Math::Round<int>(angle) + 180) % 360];\n    const float zOffset = zOffsets[(itk::Math::Round<int>(angle) + 180) % 360];\n    if (std::string(\"BLANK SCAN\") != GetStringTagValue(ds, 0x0008, 0x0008))\n      m_Geometry->AddProjection(sid, sdd, angle, yOffset, zOffset);\n  }\n}\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "src/rtkBoxShape.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"math.h\"\n\n#include \"rtkBoxShape.h\"\n\nnamespace rtk\n{\n\nBoxShape ::BoxShape()\n  : m_BoxMin(0.)\n  , m_BoxMax(0.)\n{\n  m_Direction.SetIdentity();\n}\n\nbool\nBoxShape ::IsInside(const PointType & point) const\n{\n  RotationMatrixType dirt;\n  dirt = m_Direction.GetTranspose();\n  PointType t = dirt * point;\n  PointType min = dirt * m_BoxMin;\n  PointType max = dirt * m_BoxMax;\n  if (t[0] < min[0] || t[0] > max[0] || t[1] < min[1] || t[1] > max[1] || t[2] < min[2] || t[2] > max[2])\n    return false;\n  return ApplyClipPlanes(point);\n}\n\nbool\nBoxShape ::IsIntersectedByRay(const PointType &  rayOrigin,\n                              const VectorType & rayDirection,\n                              double &           nearDist,\n                              double &           farDist) const\n{\n  // Apply transform\n  RotationMatrixType dirt;\n  dirt = m_Direction.GetTranspose();\n  PointType  org = dirt * rayOrigin;\n  VectorType dir = dirt * rayDirection;\n  PointType  min = dirt * m_BoxMin;\n  PointType  max = dirt * m_BoxMax;\n  for (unsigned int i = 0; i < Dimension; i++)\n    if (min[i] > max[i])\n      std::swap(min[i], max[i]);\n\n  // To account for m_Direction, everything (ray source and direction + boxmin/boxmax)\n  // is rotated with its inverse, m_DirectionT. Then, the box is aligned with the\n  // axes of the coordinate system and the algorithm at this hyperlink used:\n  // https://education.siggraph.org/static/HyperGraph/raytrace/rtinter3.htm\n  // Note that the variables at this page have been renamed:\n  // BI <-> min\n  // Bh <-> max\n  // Ro <-> org\n  // Rd <-> dir\n  // Tnear <-> nearDist\n  // Tfar <-> farDist\n  nearDist = itk::NumericTraits<ScalarType>::NonpositiveMin();\n  farDist = itk::NumericTraits<ScalarType>::max();\n  ScalarType T1 = NAN, T2 = NAN, invRayDir = NAN;\n  for (unsigned int i = 0; i < Dimension; i++)\n  {\n    if (dir[i] == itk::NumericTraits<ScalarType>::ZeroValue() && (org[i] < min[i] || org[i] > max[i]))\n      return false;\n\n    invRayDir = 1 / dir[i];\n    T1 = (min[i] - org[i]) * invRayDir;\n    T2 = (max[i] - org[i]) * invRayDir;\n    if (T1 > T2)\n      std::swap(T1, T2);\n    if (T1 > nearDist)\n      nearDist = T1;\n    if (T2 < farDist)\n      farDist = T2;\n    if (nearDist > farDist)\n      return false;\n    if (farDist < 0)\n      return false;\n  }\n\n  return ApplyClipPlanes(rayOrigin, rayDirection, nearDist, farDist);\n}\n\nvoid\nBoxShape ::Rescale(const VectorType & r)\n{\n  Superclass::Rescale(r);\n  for (unsigned int i = 0; i < Dimension; i++)\n  {\n    m_BoxMin[i] *= r[i];\n    m_BoxMax[i] *= r[i];\n  }\n}\n\nvoid\nBoxShape ::Translate(const VectorType & t)\n{\n  Superclass::Translate(t);\n  m_BoxMin += t;\n  m_BoxMax += t;\n}\n\nvoid\nBoxShape ::Rotate(const RotationMatrixType & r)\n{\n  Superclass::Rotate(r);\n  m_Direction = m_Direction * r;\n  m_BoxMin = m_Direction * m_BoxMin;\n  m_BoxMax = m_Direction * m_BoxMax;\n}\n\nitk::LightObject::Pointer\nBoxShape ::InternalClone() const\n{\n  LightObject::Pointer loPtr = Superclass::InternalClone();\n  Self::Pointer        clone = dynamic_cast<Self *>(loPtr.GetPointer());\n\n  clone->SetBoxMin(this->GetBoxMin());\n  clone->SetBoxMax(this->GetBoxMax());\n  clone->SetDirection(this->GetDirection());\n\n  return loPtr;\n}\n\nvoid\nBoxShape ::SetBoxFromImage(const ImageBaseType * img, bool bWithExternalHalfPixelBorder)\n{\n  if (Dimension != img->GetImageDimension())\n    itkGenericExceptionMacro(<< \"BoxShape and image dimensions must agree\");\n\n  // BoxShape corner 1\n  m_BoxMin = img->GetOrigin().GetVectorFromOrigin();\n  if (bWithExternalHalfPixelBorder)\n    m_BoxMin -= img->GetDirection() * img->GetSpacing() * 0.5;\n\n  // BoxShape corner 2\n  for (unsigned int i = 0; i < Dimension; i++)\n    if (bWithExternalHalfPixelBorder)\n      m_BoxMax[i] = img->GetSpacing()[i] * img->GetLargestPossibleRegion().GetSize()[i];\n    else\n      m_BoxMax[i] = img->GetSpacing()[i] * (img->GetLargestPossibleRegion().GetSize()[i] - 1);\n  m_BoxMax = m_BoxMin + img->GetDirection() * m_BoxMax;\n\n  SetDirection(img->GetDirection());\n}\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkConditionalMedianImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkConditionalMedianImageFilter.h\"\n\ntemplate <>\nvoid\nrtk::ConditionalMedianImageFilter<itk::VectorImage<float, 3>>::DynamicThreadedGenerateData(\n  const itk::VectorImage<float, 3>::RegionType & outputRegionForThread)\n{\n  using TInputImage = itk::VectorImage<float, 3>;\n\n  // Compute the centered difference with the previous and next frames, store it into the intermediate image\n  itk::ConstNeighborhoodIterator<TInputImage> nIt(m_Radius, this->GetInput(), outputRegionForThread);\n  itk::ImageRegionIterator<TInputImage>       outIt(this->GetOutput(), outputRegionForThread);\n\n  // Build a vector in which all pixel of the neighborhood will be temporarily stored\n  std::vector<std::vector<TInputImage::InternalPixelType>> pixels;\n  pixels.resize(this->GetInput()->GetVectorLength());\n  for (auto & pixel : pixels)\n    pixel.resize(nIt.Size());\n\n  itk::VariableLengthVector<float> vlv;\n  vlv.SetSize(this->GetInput()->GetVectorLength());\n\n  // Walk the output image\n  while (!outIt.IsAtEnd())\n  {\n    // Walk the neighborhood in the input image, store the pixels into a vector\n    for (unsigned int i = 0; i < nIt.Size(); i++)\n    {\n      for (unsigned int mat = 0; mat < pixels.size(); mat++)\n        pixels[mat][i] = nIt.GetPixel(i)[mat];\n    }\n\n    for (unsigned int mat = 0; mat < pixels.size(); mat++)\n    {\n      // Compute the standard deviation\n      double sum = std::accumulate(pixels[mat].begin(), pixels[mat].end(), 0.0);\n      double mean = sum / pixels[mat].size();\n      double sq_sum = std::inner_product(pixels[mat].begin(), pixels[mat].end(), pixels[mat].begin(), 0.0);\n      double stdev = std::sqrt(sq_sum / pixels[mat].size() - mean * mean);\n\n      // Compute the median of the neighborhood\n      std::nth_element(pixels[mat].begin(), pixels[mat].begin() + pixels[mat].size() / 2, pixels[mat].end());\n\n      // If the pixel value is too far from the median, replace it by the median\n      if (itk::Math::abs(pixels[mat][pixels[mat].size() / 2] - nIt.GetCenterPixel()[mat]) >\n          (m_ThresholdMultiplier * stdev))\n        vlv[mat] = pixels[mat][pixels[mat].size() / 2];\n      else // Otherwise, leave it as is\n        vlv[mat] = nIt.GetCenterPixel()[mat];\n    }\n    outIt.Set(vlv);\n\n    ++nIt;\n    ++outIt;\n  }\n}\n"
  },
  {
    "path": "src/rtkConvexShape.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkConvexShape.h\"\n\nnamespace rtk\n{\n\nConvexShape ::ConvexShape() = default;\n\nbool\nConvexShape ::IsInside(const PointType & /*point*/) const\n{\n  itkExceptionMacro(<< \"This method should have been reimplemented in base classe\");\n  return false;\n}\n\nbool\nConvexShape ::IsIntersectedByRay(const PointType & /*rayOrigin*/,\n                                 const VectorType & /*rayDirection*/,\n                                 ScalarType & /*nearDist*/,\n                                 ScalarType & /*farDist*/) const\n{\n  itkExceptionMacro(<< \"This method should have been reimplemented in base classe\");\n  return false;\n}\n\nvoid\nConvexShape ::Rescale(const VectorType & r)\n{\n  for (VectorType & m_PlaneDirection : m_PlaneDirections)\n  {\n    for (unsigned int j = 0; j < Dimension; j++)\n    {\n      m_PlaneDirection[j] /= r[j];\n    }\n  }\n}\n\nvoid\nConvexShape ::Translate(const VectorType & t)\n{\n  for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n  {\n    m_PlanePositions[i] += m_PlaneDirections[i] * t;\n  }\n}\n\nvoid\nConvexShape ::Rotate(const RotationMatrixType & r)\n{\n  for (VectorType & m_PlaneDirection : m_PlaneDirections)\n  {\n    m_PlaneDirection = r * m_PlaneDirection;\n  }\n}\n\nitk::LightObject::Pointer\nConvexShape ::InternalClone() const\n{\n  LightObject::Pointer loPtr = Superclass::InternalClone();\n  Self::Pointer        clone = dynamic_cast<Self *>(loPtr.GetPointer());\n\n  clone->SetDensity(this->GetDensity());\n  clone->SetClipPlanes(this->GetPlaneDirections(), this->GetPlanePositions());\n\n  return loPtr;\n}\n\nvoid\nConvexShape ::AddClipPlane(const VectorType & dir, const ScalarType & pos)\n{\n  for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n  {\n    if (dir == m_PlaneDirections[i] && pos == m_PlanePositions[i])\n      return;\n  }\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n}\n\nvoid\nConvexShape ::SetClipPlanes(const std::vector<VectorType> & dir, const std::vector<ScalarType> & pos)\n{\n  m_PlaneDirections = dir;\n  m_PlanePositions = pos;\n}\n\nbool\nConvexShape ::ApplyClipPlanes(const PointType &  rayOrigin,\n                              const VectorType & rayDirection,\n                              double &           nearDist,\n                              double &           farDist) const\n{\n  for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n  {\n    ScalarType rayDirPlaneDir = rayDirection * m_PlaneDirections[i];\n\n    // Ray parallel to plane\n    if (rayDirPlaneDir == itk::NumericTraits<ScalarType>::ZeroValue())\n    {\n      if (rayOrigin * m_PlaneDirections[i] < m_PlanePositions[i])\n        continue;\n      else\n        return false;\n    }\n\n    // Compute plane distance in ray direction\n    ScalarType planeDist = (m_PlanePositions[i] - rayOrigin * m_PlaneDirections[i]) / rayDirPlaneDir;\n\n    // If plane is pointing in the same direction as the ray\n    if (rayDirPlaneDir >= 0)\n    {\n      if (planeDist <= nearDist)\n        return false;\n      farDist = std::min(farDist, planeDist);\n    }\n    else\n    {\n      if (planeDist >= farDist)\n        return false;\n      nearDist = std::max(nearDist, planeDist);\n    }\n  }\n  return true;\n}\n\nbool\nConvexShape ::ApplyClipPlanes(const PointType & point) const\n{\n  for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n  {\n    if (point * m_PlaneDirections[i] >= m_PlanePositions[i])\n      return false;\n  }\n  return true;\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkCudaAverageOutOfROIImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaAverageOutOfROIImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n// TEXTURES AND CONSTANTS //\n\n__constant__ int4 c_Size;\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n\n__global__ void\naverage_along_dim_4(float * in, float * out, float * roi, unsigned int strideInFloats)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z)\n    return;\n\n  // Compute the index of the initial voxel\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n  long int strided_id = id; // strided_id will run along the 4th dimension\n\n  // Compute the average along last dimension\n  float avg = 0;\n  for (unsigned int l = 0; l < c_Size.w; l++)\n  {\n    avg += in[strided_id];\n    strided_id += strideInFloats;\n  }\n  avg /= c_Size.w;\n\n  // Write to the output. If the ROI is 0, replace by the average. If it is 1,\n  // do nothing. Since I do not trust CUDA's comparisons between floats,\n  // I wrote it without ifs. It has the side effect that the ROI can be non-binary\n  // without any problem\n  strided_id = id;\n  for (unsigned int l = 0; l < c_Size.w; l++)\n  {\n    out[strided_id] = in[strided_id] * roi[id] + avg * (1 - roi[id]);\n    strided_id += strideInFloats;\n  }\n}\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\nvoid\nCUDA_average_out_of_ROI(int size[4], float * input, float * output, float * roi)\n{\n  int4 dev_Size = make_int4(size[0], size[1], size[2], size[3]);\n  cudaMemcpyToSymbol(c_Size, &dev_Size, sizeof(int4));\n\n  // Compute the stride (in floats, not Bytes) to jump from one voxel\n  // to the next one along 4th dimension\n  unsigned int strideInFloats = size[0] * size[1] * size[2];\n\n  // Thread Block Dimensions\n  dim3 dimBlock = dim3(8, 8, 8);\n\n  int blocksInX = iDivUp(size[0], dimBlock.x);\n  int blocksInY = iDivUp(size[1], dimBlock.y);\n  int blocksInZ = iDivUp(size[2], dimBlock.z);\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n\n  average_along_dim_4<<<dimGrid, dimBlock>>>(input, output, roi, strideInFloats);\n}\n"
  },
  {
    "path": "src/rtkCudaAverageOutOfROIImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaAverageOutOfROIImageFilter.h\"\n#include \"rtkCudaAverageOutOfROIImageFilter.hcu\"\n\n#include <itkMacro.h>\n\nrtk::CudaAverageOutOfROIImageFilter ::CudaAverageOutOfROIImageFilter() {}\n\nvoid\nrtk::CudaAverageOutOfROIImageFilter ::GPUGenerateData()\n{\n  int size[4];\n\n  for (int i = 0; i < 4; i++)\n  {\n    size[i] = this->GetOutput()->GetBufferedRegion().GetSize()[i];\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * proi = (float *)(this->GetROI()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * proi = *(float **)(this->GetROI()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_average_out_of_ROI(size, pin, pout, proi);\n\n  // Transfer the ROI volume back to the CPU memory to save space on the GPU\n  this->GetROI()->GetCudaDataManager()->GetCPUBufferPointer();\n}\n"
  },
  {
    "path": "src/rtkCudaBackProjectionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/* -----------------------------------------------------------------------\n   See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information\n   ----------------------------------------------------------------------- */\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaBackProjectionImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n\n// Constant memory\n__constant__ float c_matrices[SLAB_SIZE * 12]; // Can process stacks of at most SLAB_SIZE projections\n__constant__ float c_volIndexToProjPP[SLAB_SIZE * 12];\n__constant__ float c_projPPToProjIndex[9];\n__constant__ int3  c_projSize;\n__constant__ int3  c_volSize;\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\ntemplate <unsigned int VVectorLength, bool VIsCylindrical>\n__global__ void\nkernel_backProject(float * dev_vol_in, float * dev_vol_out, float radius, cudaTextureObject_t * dev_tex_proj)\n{\n  itk::SizeValueType i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  itk::SizeValueType j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  itk::SizeValueType k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= c_volSize.x || j >= c_volSize.y || k >= c_volSize.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  itk::SizeValueType vol_idx = i + (j + k * c_volSize.y) * (c_volSize.x);\n\n  float3 ip, pp;\n  float  voxel_data[VVectorLength];\n  for (unsigned int c = 0; c < VVectorLength; c++)\n    voxel_data[c] = 0.0f;\n\n  for (unsigned int proj = 0; proj < c_projSize.z; proj++)\n  {\n    if (VIsCylindrical)\n    {\n      // matrix multiply\n      pp = matrix_multiply(make_float3(i, j, k), &(c_volIndexToProjPP[12 * proj]));\n\n      // Change coordinate systems\n      pp.z = 1 / pp.z;\n      pp.x = pp.x * pp.z;\n      pp.y = pp.y * pp.z;\n\n      // Apply correction for cylindrical detector\n      const float u = pp.x;\n      pp.x = radius * atan2(u, radius);\n      pp.y = pp.y * radius / sqrt(radius * radius + u * u);\n\n      // Get projection index\n      ip.x = c_projPPToProjIndex[0] * pp.x + c_projPPToProjIndex[1] * pp.y + c_projPPToProjIndex[2];\n      ip.y = c_projPPToProjIndex[3] * pp.x + c_projPPToProjIndex[4] * pp.y + c_projPPToProjIndex[5];\n    }\n    else\n    {\n      // matrix multiply\n      ip = matrix_multiply(make_float3(i, j, k), &(c_matrices[12 * proj]));\n\n      // Change coordinate systems\n      ip.z = 1 / ip.z;\n      ip.x = ip.x * ip.z;\n      ip.y = ip.y * ip.z;\n    }\n\n    // Get texture point, clip left to GPU, and accumulate in voxel_data\n    for (unsigned int c = 0; c < VVectorLength; c++)\n      voxel_data[c] += tex2DLayered<float>(dev_tex_proj[c], ip.x, ip.y, proj);\n  }\n\n  // Place it into the volume\n  for (unsigned int c = 0; c < VVectorLength; c++)\n    dev_vol_out[vol_idx * VVectorLength + c] = dev_vol_in[vol_idx * VVectorLength + c] + voxel_data[c];\n}\n\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_back_project /////////////////////////////\nvoid\nCUDA_back_project(int          projSize[3],\n                  int          volSize[3],\n                  float *      matrices,\n                  float *      volIndexToProjPPs,\n                  float *      projPPToProjIndex,\n                  float *      dev_vol_in,\n                  float *      dev_vol_out,\n                  float *      dev_proj,\n                  double       radiusCylindricalDetector,\n                  unsigned int vectorLength)\n{\n  // Copy the size of inputs into constant memory\n  cudaMemcpyToSymbol(c_projSize, projSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_volSize, volSize, sizeof(int3));\n\n  // Copy the projection matrices into constant memory\n  cudaMemcpyToSymbol(c_matrices, &(matrices[0]), 12 * sizeof(float) * projSize[2]);\n  cudaMemcpyToSymbol(c_volIndexToProjPP, &(volIndexToProjPPs[0]), 12 * sizeof(float) * projSize[2]);\n  cudaMemcpyToSymbol(c_projPPToProjIndex, &(projPPToProjIndex[0]), 9 * sizeof(float));\n\n  // Thread Block Dimensions\n  constexpr int tBlock_x = 16;\n  constexpr int tBlock_y = 4;\n  constexpr int tBlock_z = 4;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (volSize[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (volSize[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (volSize[2] - 1) / tBlock_z + 1;\n\n  // Run kernels. Note: Projection data is passed via texture memory,\n  // transform matrix is passed via constant memory\n\n  // Compute block and grid sizes\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n  CUDA_CHECK_ERROR;\n\n  // Prepare texture objects (needs an array of cudaTextureObjects on the host as \"tex_proj\" argument)\n  std::vector<cudaArray *>         projComponentArrays;\n  std::vector<cudaTextureObject_t> tex_proj;\n  prepareVectorTextureObject(projSize, dev_proj, projComponentArrays, vectorLength, tex_proj, true);\n\n  // Copy them to a device pointer, since it will have to be de-referenced in the kernels\n  cudaTextureObject_t * dev_tex_proj;\n  cudaMalloc(&dev_tex_proj, vectorLength * sizeof(cudaTextureObject_t));\n  cudaMemcpy(dev_tex_proj, tex_proj.data(), vectorLength * sizeof(cudaTextureObject_t), cudaMemcpyHostToDevice);\n\n  // Run the kernel. Since \"vectorLength\" is passed as a function argument, not as a template argument,\n  // the compiler can't assume it's constant, and a dirty trick has to be used.\n  // I did not manage to make CUDA_forward_project templated over vectorLength,\n  // which would be the best solution\n  // Since the list of arguments is long, and is the same in all cases (only the template parameters\n  // change), it is passed by a macro\n  switch (vectorLength)\n  {\n    case 1:\n      if (radiusCylindricalDetector == 0)\n        kernel_backProject<1, false>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      else\n        kernel_backProject<1, true>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      break;\n\n    case 2:\n      if (radiusCylindricalDetector == 0)\n        kernel_backProject<2, false>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      else\n        kernel_backProject<2, true>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      break;\n\n    case 3:\n      if (radiusCylindricalDetector == 0)\n        kernel_backProject<3, false>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      else\n        kernel_backProject<3, true>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      break;\n\n    case 4:\n      if (radiusCylindricalDetector == 0)\n        kernel_backProject<4, false>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      else\n        kernel_backProject<4, true>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      break;\n\n    case 9:\n      if (radiusCylindricalDetector == 0)\n        kernel_backProject<9, false>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      else\n        kernel_backProject<9, true>\n          <<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, dev_tex_proj);\n      break;\n\n    default:\n    {\n      itkGenericExceptionMacro(\"Vector length \" << vectorLength << \" is not supported.\");\n    }\n  }\n  CUDA_CHECK_ERROR;\n\n  // Cleanup\n  for (unsigned int c = 0; c < vectorLength; c++)\n  {\n    cudaFreeArray(projComponentArrays[c]);\n    CUDA_CHECK_ERROR;\n    cudaDestroyTextureObject(tex_proj[c]);\n    CUDA_CHECK_ERROR;\n  }\n  cudaFree(dev_tex_proj);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaConjugateGradientImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaConjugateGradientImageFilter.hcu\"\n\n// cuda includes\n#include <cuda.h>\n#include <cublas_v2.h>\n#include <cuda_runtime.h>\n\n// TEXTURES AND CONSTANTS //\n\nvoid\nCUDA_copy(size_t numberOfElements, float * in, float * out)\n{\n  // Copy input volume to output\n  size_t memorySizeOutput = numberOfElements * sizeof(float);\n  cudaMemcpy(out, in, memorySizeOutput, cudaMemcpyDeviceToDevice);\n}\n\nvoid\nCUDA_copy(size_t numberOfElements, double * in, double * out)\n{\n  // Copy input volume to output\n  size_t memorySizeOutput = numberOfElements * sizeof(double);\n  cudaMemcpy(out, in, memorySizeOutput, cudaMemcpyDeviceToDevice);\n}\n\nvoid\nCUDA_subtract(size_t numberOfElements, float * out, float * toBeSubtracted)\n{\n  cublasHandle_t handle;\n  cublasCreate(&handle);\n\n  const float alpha = -1.0;\n#if CUDA_VERSION < 12000\n  cublasSaxpy(handle, (int)numberOfElements, &alpha, toBeSubtracted, 1, out, 1);\n#else\n  cublasSaxpy_64(handle, numberOfElements, &alpha, toBeSubtracted, 1, out, 1);\n#endif\n\n  // Destroy Cublas context\n  cublasDestroy(handle);\n\n  CUDA_CHECK_ERROR;\n}\n\nvoid\nCUDA_subtract(size_t numberOfElements, double * out, double * toBeSubtracted)\n{\n  cublasHandle_t handle;\n  cublasCreate(&handle);\n\n  const double alpha = -1.0;\n  cublasDaxpy(handle, (int)numberOfElements, &alpha, toBeSubtracted, 1, out, 1);\n\n  // Destroy Cublas context\n  cublasDestroy(handle);\n\n  CUDA_CHECK_ERROR;\n}\n\nvoid\nCUDA_conjugate_gradient(size_t numberOfElements, float * Xk, float * Rk, float * Pk, float * APk)\n{\n  cublasHandle_t handle;\n  cublasCreate(&handle);\n\n  float eps = 1e-30;\n\n  // Compute Rk_square = sum(Rk(:).^2) by cublas\n  float Rk_square = 0;\n  cublasSdot(handle, (int)numberOfElements, Rk, 1, Rk, 1, &Rk_square);\n\n  // Compute alpha_k = Rk_square / sum(Pk(:) .* APk(:))\n  float Pk_APk = 0;\n  cublasSdot(handle, (int)numberOfElements, Pk, 1, APk, 1, &Pk_APk);\n\n  const float alpha_k = Rk_square / (Pk_APk + eps);\n  const float minus_alpha_k = -alpha_k;\n\n  // Compute Xk+1 = Xk + alpha_k * Pk\n  cublasSaxpy(handle, (int)numberOfElements, &alpha_k, Pk, 1, Xk, 1);\n\n  // Compute Rk+1 = Rk - alpha_k * APk\n  cublasSaxpy(handle, (int)numberOfElements, &minus_alpha_k, APk, 1, Rk, 1);\n\n  // Compute beta_k = sum(Rk+1(:).^2) / Rk_square\n  float Rkplusone_square = 0;\n  cublasSdot(handle, (int)numberOfElements, Rk, 1, Rk, 1, &Rkplusone_square);\n\n  float beta_k = Rkplusone_square / (Rk_square + eps);\n  float one = 1.0;\n\n  // Compute Pk+1 = Rk+1 + beta_k * Pk\n  // This requires two cublas functions,\n  // since axpy would store the result in the wrong array\n  cublasSscal(handle, (int)numberOfElements, &beta_k, Pk, 1);\n  cublasSaxpy(handle, (int)numberOfElements, &one, Rk, 1, Pk, 1);\n\n  // Destroy Cublas context\n  cublasDestroy(handle);\n\n  CUDA_CHECK_ERROR;\n}\n\nvoid\nCUDA_conjugate_gradient(size_t numberOfElements, double * Xk, double * Rk, double * Pk, double * APk)\n{\n  cublasHandle_t handle;\n  cublasCreate(&handle);\n\n  double eps = 1e-30;\n\n  // Compute Rk_square = sum(Rk(:).^2) by cublas\n  double Rk_square = 0;\n  cublasDdot(handle, (int)numberOfElements, Rk, 1, Rk, 1, &Rk_square);\n\n  // Compute alpha_k = Rk_square / sum(Pk(:) .* APk(:))\n  double Pk_APk = 0;\n  cublasDdot(handle, (int)numberOfElements, Pk, 1, APk, 1, &Pk_APk);\n\n  const double alpha_k = Rk_square / (Pk_APk + eps);\n  const double minus_alpha_k = -alpha_k;\n\n  // Compute Xk+1 = Xk + alpha_k * Pk\n  cublasDaxpy(handle, (int)numberOfElements, &alpha_k, Pk, 1, Xk, 1);\n\n  // Compute Rk+1 = Rk - alpha_k * APk\n  cublasDaxpy(handle, (int)numberOfElements, &minus_alpha_k, APk, 1, Rk, 1);\n\n  // Compute beta_k = sum(Rk+1(:).^2) / Rk_square\n  double Rkplusone_square = 0;\n  cublasDdot(handle, (int)numberOfElements, Rk, 1, Rk, 1, &Rkplusone_square);\n\n  double beta_k = Rkplusone_square / (Rk_square + eps);\n  double one = 1.0;\n\n  // Compute Pk+1 = Rk+1 + beta_k * Pk\n  // This requires two cublas functions,\n  // since axpy would store the result in the wrong array\n  cublasDscal(handle, (int)numberOfElements, &beta_k, Pk, 1);\n  cublasDaxpy(handle, (int)numberOfElements, &one, Rk, 1, Pk, 1);\n\n  // Destroy Cublas context\n  cublasDestroy(handle);\n\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaConstantVolumeSeriesSource.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaConstantVolumeSeriesSource.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n\n// TEXTURES AND CONSTANTS //\n\n__constant__ int4 c_Size;\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n\n__global__ void\nset_volume_series_to_constant(float * out, float value)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z * c_Size.w)\n    return;\n\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n\n  out[id] = value;\n}\n\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\nvoid\nCUDA_generate_constant_volume_series(int size[4], float * dev_out, float constantValue)\n{\n  int4 dev_Size = make_int4(size[0], size[1], size[2], size[3]);\n  cudaMemcpyToSymbol(c_Size, &dev_Size, sizeof(int4));\n\n  // NOTE : memset sets every BYTE of the memory to the value given in\n  // argument (here, 0). With 0, it's fine, as all number formats seem\n  // to represent 0 by bytes containing only zeros.\n  // But running memset with argument 1, for example, will set all bytes\n  // of the memory chunk to 00000001. And so reading a float from this memory\n  // chunk means reading \"00000001 00000001 00000001 00000001\" and\n  // interpreting it as a float, which certainly doesn't give 1.0\n  // Therefore we use memset to set the image to zero quickly (most of the\n  // time, that's what rtkConstantImageSource is used for) and if necessary,\n  // run a kernel to replace the zeros with constantValue.\n\n  // Reset output volume\n  size_t memorySizeOutput = size[0] * size[1] * size[2] * size[3] * sizeof(float);\n  cudaMemset((void *)dev_out, 0, memorySizeOutput);\n\n  if (!(constantValue == 0))\n  {\n    // Thread Block Dimensions\n    dim3 dimBlock = dim3(4, 4, 16);\n\n    int blocksInX = iDivUp(size[0], dimBlock.x);\n    int blocksInY = iDivUp(size[1], dimBlock.y);\n    int blocksInZ = iDivUp(size[2] * size[3], dimBlock.z);\n\n    dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n\n    set_volume_series_to_constant<<<dimGrid, dimBlock>>>(dev_out, constantValue);\n  }\n\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaConstantVolumeSeriesSource.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaConstantVolumeSeriesSource.h\"\n#include \"rtkCudaConstantVolumeSeriesSource.hcu\"\n\n#include <itkMacro.h>\n\nrtk::CudaConstantVolumeSeriesSource ::CudaConstantVolumeSeriesSource() {}\n\nvoid\nrtk::CudaConstantVolumeSeriesSource ::GPUGenerateData()\n{\n  int outputSize[4];\n\n  for (int i = 0; i < 4; i++)\n  {\n    outputSize[i] = this->GetOutput()->GetRequestedRegion().GetSize()[i];\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_generate_constant_volume_series(outputSize, pout, m_Constant);\n}\n"
  },
  {
    "path": "src/rtkCudaConstantVolumeSource.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaConstantVolumeSource.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n\n// TEXTURES AND CONSTANTS //\n\n__constant__ int3 c_Size;\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n\n__global__ void\nset_volume_to_constant(float * out, float value)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z)\n    return;\n\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n\n  out[id] = value;\n}\n\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\nvoid\nCUDA_generate_constant_volume(int size[3], float * dev_out, float constantValue)\n{\n  int3 dev_Size = make_int3(size[0], size[1], size[2]);\n  cudaMemcpyToSymbol(c_Size, &dev_Size, sizeof(int3));\n\n  // NOTE : memset sets every BYTE of the memory to the value given in\n  // argument (here, 0). With 0, it's fine, as all number formats seem\n  // to represent 0 by bytes containing only zeros.\n  // But running memset with argument 1, for example, will set all bytes\n  // of the memory chunk to 00000001. And so reading a float from this memory\n  // chunk means reading \"00000001 00000001 00000001 00000001\" and\n  // interpreting it as a float, which certainly doesn't give 1.0\n  // Therefore we use memset to set the image to zero quickly (most of the\n  // time, that's what rtkConstantImageSource is used for) and if necessary,\n  // run a kernel to replace the zeros with constantValue.\n\n  // Reset output volume\n  size_t memorySizeOutput = size[0] * size[1] * size[2] * sizeof(float);\n  cudaMemset((void *)dev_out, 0, memorySizeOutput);\n\n  if (!(constantValue == 0))\n  {\n    // Thread Block Dimensions\n    dim3 dimBlock = dim3(16, 4, 4);\n\n    int blocksInX = iDivUp(size[0], dimBlock.x);\n    int blocksInY = iDivUp(size[1], dimBlock.y);\n    int blocksInZ = iDivUp(size[2], dimBlock.z);\n\n    dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n\n    set_volume_to_constant<<<dimGrid, dimBlock>>>(dev_out, constantValue);\n  }\n\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaConstantVolumeSource.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaConstantVolumeSource.h\"\n#include \"rtkCudaConstantVolumeSource.hcu\"\n\n#include <itkMacro.h>\n\nrtk::CudaConstantVolumeSource ::CudaConstantVolumeSource() {}\n\nvoid\nrtk::CudaConstantVolumeSource ::GPUGenerateData()\n{\n  int outputSize[3];\n\n  for (int i = 0; i < 3; i++)\n  {\n    outputSize[i] = this->GetOutput()->GetRequestedRegion().GetSize()[i];\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_generate_constant_volume(outputSize, pout, m_Constant);\n}\n"
  },
  {
    "path": "src/rtkCudaCropImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaCropImageFilter.hcu\"\n\n// cuda includes\n#include <cuda.h>\n#include <cufft.h>\n\n__global__ void\ncrop_kernel(float *            input,\n            float *            output,\n            const long3        cropIdx,\n            const uint3        cropDim,\n            const uint3        inputDim,\n            const unsigned int Blocks_Y)\n{\n  unsigned int blockIdx_z = blockIdx.y / Blocks_Y;\n  unsigned int blockIdx_y = blockIdx.y - __umul24(blockIdx_z, Blocks_Y);\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx_y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx_z, blockDim.z) + threadIdx.z;\n\n  if (i >= cropDim.x || j >= cropDim.y || k >= cropDim.z)\n    return;\n\n  unsigned long int out_idx = i + j * cropDim.x + k * cropDim.y * cropDim.x;\n  unsigned long int in_idx = (cropIdx.x + i) + (cropIdx.y + j) * inputDim.x + (cropIdx.z + k) * inputDim.y * inputDim.x;\n\n  output[out_idx] = input[in_idx];\n}\n\nvoid\nCUDA_crop(const long3 & cropIndex, const uint3 & cropSize, const uint3 & inputSize, float * input, float * output)\n{\n  // Thread Block Dimensions\n  unsigned int tBlock_x = 4;\n  unsigned int tBlock_y = 4;\n  unsigned int tBlock_z = 4;\n  unsigned int blocksInX = ((cropSize.x - 1) / tBlock_x) + 1;\n  unsigned int blocksInY = ((cropSize.y - 1) / tBlock_y) + 1;\n  unsigned int blocksInZ = ((cropSize.z - 1) / tBlock_z) + 1;\n  dim3         dimGrid = dim3(blocksInX, blocksInY * blocksInZ);\n  dim3         dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n\n  // Call to kernel\n  crop_kernel<<<dimGrid, dimBlock>>>(input, output, cropIndex, cropSize, inputSize, blocksInY);\n  CUDA_CHECK_ERROR;\n\n  // Release memory\n  // cudaFree(deviceVolume);\n}\n"
  },
  {
    "path": "src/rtkCudaCropImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaCropImageFilter.h\"\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaCropImageFilter.hcu\"\n\n#include <itkMacro.h>\n\nnamespace rtk\n{\n\nCudaCropImageFilter ::CudaCropImageFilter() {}\n\n// CUDA cropping call\nvoid\nCudaCropImageFilter ::GPUGenerateData()\n{\n  OutputImageRegionType croppedRegion = this->GetExtractionRegion();\n  uint3                 sz, input_sz;\n  long3                 idx;\n\n  idx.x = croppedRegion.GetIndex()[0] - this->GetInput()->GetBufferedRegion().GetIndex()[0];\n  idx.y = croppedRegion.GetIndex()[1] - this->GetInput()->GetBufferedRegion().GetIndex()[1];\n  idx.z = croppedRegion.GetIndex()[2] - this->GetInput()->GetBufferedRegion().GetIndex()[2];\n  sz.x = croppedRegion.GetSize()[0];\n  sz.y = croppedRegion.GetSize()[1];\n  sz.z = croppedRegion.GetSize()[2];\n  input_sz.x = this->GetInput()->GetBufferedRegion().GetSize()[0];\n  input_sz.y = this->GetInput()->GetBufferedRegion().GetSize()[1];\n  input_sz.z = this->GetInput()->GetBufferedRegion().GetSize()[2];\n\n  if (this->GetOutput()->GetBufferedRegion() != this->GetOutput()->GetRequestedRegion())\n  {\n    itkExceptionMacro(<< \"CudaCropImageFilter assumes that requested and buffered regions are equal.\");\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_crop(idx, sz, input_sz, pin, pout);\n}\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkCudaCyclicDeformationImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaCyclicDeformationImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n#include <cublas_v2.h>\n#include <cuda_runtime.h>\n\n// TEXTURES AND CONSTANTS //\n\n__constant__ int4 c_inputSize;\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\nvoid\nCUDA_linear_interpolate_along_fourth_dimension(unsigned int inputSize[4],\n                                               float *      input,\n                                               float *      output,\n                                               unsigned int frameInf,\n                                               unsigned int frameSup,\n                                               double       weightInf,\n                                               double       weightSup)\n{\n  cublasHandle_t handle;\n  cublasCreate(&handle);\n\n  float wInf = (float)weightInf;\n  float wSup = (float)weightSup;\n\n  size_t numel = inputSize[0] * inputSize[1] * inputSize[2] * 3;\n\n  cudaMemset((void *)output, 0, numel * sizeof(float));\n\n  // Add it weightInf times the frameInf to the output\n  float * pinf = input + frameInf * numel;\n#if CUDA_VERSION < 12000\n  cublasSaxpy(handle, (int)numel, &wInf, pinf, 1, output, 1);\n#else\n  cublasSaxpy_64(handle, numel, &wInf, pinf, 1, output, 1);\n#endif\n\n  // Add it weightSup times the frameSup to the output\n  float * psup = input + frameSup * numel;\n#if CUDA_VERSION < 12000\n  cublasSaxpy(handle, (int)numel, &wSup, psup, 1, output, 1);\n#else\n  cublasSaxpy_64(handle, numel, &wSup, psup, 1, output, 1);\n#endif\n\n  // Destroy Cublas context\n  cublasDestroy(handle);\n\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaCyclicDeformationImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaCyclicDeformationImageFilter.h\"\n#include \"rtkCudaCyclicDeformationImageFilter.hcu\"\n#include \"rtkCudaConstantVolumeSeriesSource.h\"\n\n#include <itkMacro.h>\n\nrtk::CudaCyclicDeformationImageFilter ::CudaCyclicDeformationImageFilter() {}\n\nvoid\nrtk::CudaCyclicDeformationImageFilter ::GPUGenerateData()\n{\n  // Run the superclass method that updates all member variables\n  this->Superclass::BeforeThreadedGenerateData();\n\n  // Prepare the data to perform the linear interpolation on GPU\n  unsigned int inputSize[4];\n\n  for (unsigned int i = 0; i < 4; i++)\n    inputSize[i] = this->GetInput()->GetBufferedRegion().GetSize()[i];\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    if (this->GetOutput()->GetRequestedRegion().GetSize()[i] != inputSize[i])\n    {\n      itkExceptionMacro(\"In rtk::CudaCyclicDeformationImageFilter: the output's requested region must have the same \"\n                        \"size as the input's buffered region on the first 3 dimensions\");\n    }\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_linear_interpolate_along_fourth_dimension(\n    inputSize, pin, pout, this->m_FrameInf, this->m_FrameSup, this->m_WeightInf, this->m_WeightSup);\n}\n"
  },
  {
    "path": "src/rtkCudaDisplacedDetectorImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaDisplacedDetectorImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math_constants.h>\n\ninline __device__ float\nTransformIndexToPhysicalPoint(int2 idx, float origin, float row, float column)\n{\n  return origin + row * idx.x + column * idx.y;\n}\n\ninline __device__ float\nToUntiltedCoordinateAtIsocenter(float tiltedCoord, float sdd, float sid, float sx, float px, float sidu)\n{\n  // sidu is the distance between the source and the virtual untilted detector\n  // l is the coordinate on the virtual detector parallel to the real detector\n  // and passing at the isocenter\n  const float l = (tiltedCoord + px - sx) * sid / sdd + sx;\n  // a is the angle between the virtual detector and the real detector\n  const float cosa = sx / sidu;\n  // the following relation refers to a note by R. Clackdoyle, title\n  // \"Samping a tilted detector\"\n  return l * abs(sid) / (sidu - l * cosa);\n}\n\n__global__ void\nkernel_displaced_weight(int3                proj_idx_in,\n                        int3                proj_size_in,\n                        int2                proj_size_in_buf,\n                        int3                proj_idx_out,\n                        int3                proj_size_out,\n                        int2                proj_size_out_buf,\n                        float *             dev_proj_in,\n                        float *             dev_proj_out,\n                        float               theta,\n                        bool                isPositiveCase,\n                        float               proj_orig, // projection origin\n                        float               proj_row,  // projection row direction & spacing\n                        float               proj_col,  // projection col direction & spacing\n                        cudaTextureObject_t tex_geom   // geometry texture object\n)\n{\n  // compute thread index\n  int3 tIdx;\n  tIdx.x = blockIdx.x * blockDim.x + threadIdx.x;\n  tIdx.y = blockIdx.y * blockDim.y + threadIdx.y;\n  tIdx.z = blockIdx.z * blockDim.z + threadIdx.z;\n  long int tIdx_comp = tIdx.x + tIdx.y * proj_size_out.x + tIdx.z * proj_size_out_buf.x * proj_size_out_buf.y;\n\n  // check if outside of projection grid\n  if (tIdx.x >= proj_size_out.x || tIdx.y >= proj_size_out.y || tIdx.z >= proj_size_out.z)\n    return;\n\n  // compute projection index from thread index\n  int3 pIdx = make_int3(tIdx.x + proj_idx_out.x, tIdx.y + proj_idx_out.y, tIdx.z + proj_idx_out.z);\n  // combined proj. index -> use thread index in z because accessing memory only with this index\n  long int pIdx_comp = (pIdx.x - proj_idx_in.x) + (pIdx.y - proj_idx_in.y) * proj_size_in_buf.x +\n                       (pIdx.z - proj_idx_in.z) * proj_size_in_buf.x * proj_size_in_buf.y;\n\n  // check if outside overlapping region\n  if (pIdx.x < proj_idx_in.x || pIdx.x >= (proj_idx_in.x + proj_size_in.x) || pIdx.y < proj_idx_in.y ||\n      pIdx.y >= (proj_idx_in.y + proj_size_in.y) || pIdx.z < proj_idx_in.z ||\n      pIdx.z >= (proj_idx_in.z + proj_size_in.z))\n  {\n    // set areas outside overlapping region to zero\n    dev_proj_out[tIdx_comp] = 0.f;\n    return;\n  }\n  else\n  {\n    float pPoint = TransformIndexToPhysicalPoint(make_int2(pIdx.x, pIdx.y), proj_orig, proj_row, proj_col);\n\n    float sdd = tex1Dfetch<float>(tex_geom, tIdx.z * 4 + 0);\n    float sx = tex1Dfetch<float>(tex_geom, tIdx.z * 4 + 1);\n    float px = tex1Dfetch<float>(tex_geom, tIdx.z * 4 + 2);\n    float sid = tex1Dfetch<float>(tex_geom, tIdx.z * 4 + 3);\n\n    float hyp = sqrtf(sid * sid + sx * sx); // to untilted situation\n    float l = ToUntiltedCoordinateAtIsocenter(pPoint, sdd, sid, sx, px, hyp);\n    float invsdd = 0.f;\n    float invden = 0.f;\n    if (hyp != 0.f)\n    {\n      invsdd = 1.f / hyp;\n      invden = 1.f / (2.f * atanf(theta * invsdd));\n    }\n\n    // compute weights here\n    float weight = 0.f;\n    if (isPositiveCase)\n    {\n      if (l <= -1.f * theta)\n        weight = 0.f;\n      else if (l >= theta)\n        weight = 2.f;\n      else\n        weight = sinf(CUDART_PI_F * atanf(l * invsdd) * invden) + 1.f;\n    }\n    else\n    {\n      if (l <= -1.f * theta)\n        weight = 2.f;\n      else if (l >= theta)\n        weight = 0.f;\n      else\n        weight = 1.f - sinf(CUDART_PI_F * atanf(l * invsdd) * invden);\n    }\n\n    dev_proj_out[tIdx_comp] = dev_proj_in[pIdx_comp] * weight;\n  }\n}\n\nvoid\nCUDA_displaced_weight(int     proj_idx_in[3],      // overlapping input region index\n                      int     proj_dim_in[3],      // overlapping input region size\n                      int     proj_dim_in_buf[2],  // input size of buffered region\n                      int     proj_idx_out[3],     // output region index\n                      int     proj_dim_out[3],     // output region size\n                      int     proj_dim_out_buf[2], // output size of buffered region\n                      float * dev_proj_in,\n                      float * dev_proj_out,\n                      float * geometry,\n                      float   theta,\n                      bool    isPositiveCase,\n                      float   proj_orig,\n                      float   proj_row,\n                      float   proj_col)\n{\n  // copy geometry matrix to device, bind the matrix to the texture\n  float *             dev_geom;\n  cudaTextureObject_t tex_geom;\n  prepareGeometryTextureObject(proj_dim_out[2], geometry, dev_geom, tex_geom, 4);\n\n  // Thread Block Dimensions\n  int tBlock_x = 16;\n  int tBlock_y = 16;\n  int tBlock_z = 2;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (proj_dim_out[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (proj_dim_out[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (proj_dim_out[2] - 1) / tBlock_z + 1;\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n  kernel_displaced_weight<<<dimGrid, dimBlock>>>(make_int3(proj_idx_in[0], proj_idx_in[1], proj_idx_in[2]),\n                                                 make_int3(proj_dim_in[0], proj_dim_in[1], proj_dim_in[2]),\n                                                 make_int2(proj_dim_in_buf[0], proj_dim_in_buf[1]),\n                                                 make_int3(proj_idx_out[0], proj_idx_out[1], proj_idx_out[2]),\n                                                 make_int3(proj_dim_out[0], proj_dim_out[1], proj_dim_out[2]),\n                                                 make_int2(proj_dim_out_buf[0], proj_dim_out_buf[1]),\n                                                 dev_proj_in,\n                                                 dev_proj_out,\n                                                 theta,\n                                                 isPositiveCase,\n                                                 proj_orig,\n                                                 proj_row,\n                                                 proj_col,\n                                                 tex_geom);\n\n  // Unbind matrix texture\n  cudaDestroyTextureObject(tex_geom);\n  CUDA_CHECK_ERROR;\n  cudaFree(dev_geom);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaDisplacedDetectorImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaDisplacedDetectorImageFilter.h\"\n#include \"rtkCudaDisplacedDetectorImageFilter.hcu\"\n\nnamespace rtk\n{\n\nCudaDisplacedDetectorImageFilter ::CudaDisplacedDetectorImageFilter() {}\n\nCudaDisplacedDetectorImageFilter ::~CudaDisplacedDetectorImageFilter() {}\n\nvoid\nCudaDisplacedDetectorImageFilter ::GPUGenerateData()\n{\n  // compute overlap region by cropping output region with input buffer\n  OutputImageRegionType overlapRegion = this->GetOutput()->GetRequestedRegion();\n  overlapRegion.Crop(this->GetInput()->GetBufferedRegion());\n\n  // Put the two data pointers at the same location\n#ifdef CudaCommon_VERSION_MAJOR\n  float * inBuffer = static_cast<float *>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * inBuffer = *static_cast<float **>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  inBuffer += this->GetInput()->ComputeOffset(overlapRegion.GetIndex());\n#ifdef CudaCommon_VERSION_MAJOR\n  float * outBuffer = static_cast<float *>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * outBuffer = *static_cast<float **>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  outBuffer += this->GetOutput()->ComputeOffset(this->GetOutput()->GetRequestedRegion().GetIndex());\n\n  // nothing to do\n  if ((itk::Math::abs(this->GetInferiorCorner() + this->GetSuperiorCorner()) <\n       0.1 * itk::Math::abs(this->GetSuperiorCorner() - this->GetInferiorCorner())) ||\n      this->GetDisable())\n  {\n    if (outBuffer != inBuffer)\n    {\n      size_t count = this->GetOutput()->GetRequestedRegion().GetSize(0);\n      count *= sizeof(ImageType::PixelType);\n      for (unsigned int k = 0; k < this->GetOutput()->GetRequestedRegion().GetSize(2); k++)\n      {\n        for (unsigned int j = 0; j < this->GetOutput()->GetRequestedRegion().GetSize(1); j++)\n        {\n          cudaMemcpy(outBuffer, inBuffer, count, cudaMemcpyDeviceToDevice);\n          inBuffer += this->GetInput()->GetBufferedRegion().GetSize(0);\n          outBuffer += this->GetOutput()->GetBufferedRegion().GetSize(0);\n        }\n        inBuffer +=\n          (this->GetInput()->GetBufferedRegion().GetSize(1) - this->GetInput()->GetRequestedRegion().GetSize(1)) *\n          this->GetInput()->GetBufferedRegion().GetSize(0);\n        outBuffer +=\n          (this->GetOutput()->GetBufferedRegion().GetSize(1) - this->GetOutput()->GetRequestedRegion().GetSize(1)) *\n          this->GetOutput()->GetBufferedRegion().GetSize(0);\n      }\n    }\n    return;\n  }\n\n  float proj_orig = this->GetOutput()->GetOrigin()[0];\n\n  float proj_row = this->GetOutput()->GetDirection()[0][0] * this->GetOutput()->GetSpacing()[0];\n\n  float proj_col = this->GetOutput()->GetDirection()[0][1] * this->GetOutput()->GetSpacing()[1];\n\n  int proj_idx_in[3];\n  proj_idx_in[0] = overlapRegion.GetIndex()[0];\n  proj_idx_in[1] = overlapRegion.GetIndex()[1];\n  proj_idx_in[2] = overlapRegion.GetIndex()[2];\n\n  int proj_size_in[3];\n  proj_size_in[0] = overlapRegion.GetSize()[0];\n  proj_size_in[1] = overlapRegion.GetSize()[1];\n  proj_size_in[2] = overlapRegion.GetSize()[2];\n\n  int proj_size_in_buf[2];\n  proj_size_in_buf[0] = this->GetInput()->GetBufferedRegion().GetSize()[0];\n  proj_size_in_buf[1] = this->GetInput()->GetBufferedRegion().GetSize()[1];\n\n  int proj_idx_out[3];\n  proj_idx_out[0] = this->GetOutput()->GetRequestedRegion().GetIndex()[0];\n  proj_idx_out[1] = this->GetOutput()->GetRequestedRegion().GetIndex()[1];\n  proj_idx_out[2] = this->GetOutput()->GetRequestedRegion().GetIndex()[2];\n\n  int proj_size_out_buf[2];\n  proj_size_out_buf[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  proj_size_out_buf[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n\n  int proj_size_out[3];\n  proj_size_out[0] = this->GetOutput()->GetRequestedRegion().GetSize()[0];\n  proj_size_out[1] = this->GetOutput()->GetRequestedRegion().GetSize()[1];\n  proj_size_out[2] = this->GetOutput()->GetRequestedRegion().GetSize()[2];\n\n  double theta = std::min(-1. * this->GetInferiorCorner(), this->GetSuperiorCorner());\n  bool   isPositiveCase = (this->GetSuperiorCorner() + this->GetInferiorCorner() > 0.) ? true : false;\n\n  // 2D matrix (numgeom * 4 values) in one block for memcpy!\n  // for each geometry, the following structure is used:\n  // 0: sdd\n  // 1: source offset x\n  // 2: projection offset x\n  // 3: sid\n  int     geomIdx = proj_idx_out[2];\n  float * geomMatrix = new float[proj_size_out[2] * 4];\n  if (geomMatrix == nullptr)\n    itkExceptionMacro(<< \"Couldn't allocate geomMatrix\");\n  for (int g = 0; g < proj_size_out[2]; ++g)\n  {\n    geomMatrix[g * 4 + 0] = this->GetGeometry()->GetSourceToDetectorDistances()[g + geomIdx];\n    geomMatrix[g * 4 + 1] = this->GetGeometry()->GetSourceOffsetsX()[g + geomIdx];\n    geomMatrix[g * 4 + 2] = this->GetGeometry()->GetProjectionOffsetsX()[g + geomIdx];\n    geomMatrix[g * 4 + 3] = this->GetGeometry()->GetSourceToIsocenterDistances()[g + geomIdx];\n  }\n\n\n  CUDA_displaced_weight(proj_idx_in,\n                        proj_size_in,\n                        proj_size_in_buf,\n                        proj_idx_out,\n                        proj_size_out,\n                        proj_size_out_buf,\n                        inBuffer,\n                        outBuffer,\n                        geomMatrix,\n                        theta,\n                        isPositiveCase,\n                        proj_orig,\n                        proj_row,\n                        proj_col);\n\n  delete[] geomMatrix;\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkCudaFDKBackProjectionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/* -----------------------------------------------------------------------\n   See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information\n   ----------------------------------------------------------------------- */\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaFDKBackProjectionImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n\n// Constant memory\n__constant__ float c_matrices[SLAB_SIZE * 12]; // Can process stacks of at most SLAB_SIZE projections\n__constant__ int3  c_projSize;\n__constant__ int3  c_vol_size;\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n__global__ void\nkernel_fdk_3Dgrid(float * dev_vol_in, float * dev_vol_out, cudaTextureObject_t tex_proj)\n{\n  itk::SizeValueType i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  itk::SizeValueType j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  itk::SizeValueType k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= c_vol_size.x || j >= c_vol_size.y || k >= c_vol_size.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  itk::SizeValueType vol_idx = i + (j + k * c_vol_size.y) * (c_vol_size.x);\n\n  float3 ip;\n  float  voxel_data = 0;\n\n  for (unsigned int proj = 0; proj < c_projSize.z; proj++)\n  {\n    // matrix multiply\n    ip = matrix_multiply(make_float3(i, j, k), &(c_matrices[12 * proj]));\n\n    // Change coordinate systems\n    ip.z = 1 / ip.z;\n    ip.x = ip.x * ip.z;\n    ip.y = ip.y * ip.z;\n\n    // Get texture point, clip left to GPU, and accumulate in voxel_data\n    voxel_data += tex2DLayered<float>(tex_proj, ip.x, ip.y, proj) * ip.z * ip.z;\n  }\n\n  // Place it into the volume\n  dev_vol_out[vol_idx] = dev_vol_in[vol_idx] + voxel_data;\n}\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_back_project /////////////////////////////\nvoid\nCUDA_reconstruct_conebeam(int     proj_size[3],\n                          int     vol_size[3],\n                          float * matrices,\n                          float * dev_vol_in,\n                          float * dev_vol_out,\n                          float * dev_proj)\n{\n  // Copy the size of inputs into constant memory\n  cudaMemcpyToSymbol(c_projSize, proj_size, sizeof(int3));\n  cudaMemcpyToSymbol(c_vol_size, vol_size, sizeof(int3));\n\n  // Copy the projection matrices into constant memory\n  cudaMemcpyToSymbol(c_matrices, &(matrices[0]), 12 * sizeof(float) * proj_size[2]);\n\n  // Thread Block Dimensions\n  constexpr int tBlock_x = 16;\n  constexpr int tBlock_y = 4;\n  constexpr int tBlock_z = 4;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (vol_size[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (vol_size[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (vol_size[2] - 1) / tBlock_z + 1;\n\n  // Run kernels. Note: Projection data is passed via texture memory,\n  // transform matrix is passed via constant memory\n\n  // Compute block and grid sizes\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n\n  cudaArray *         array_proj;\n  cudaTextureObject_t tex_proj;\n  prepareScalarTextureObject(proj_size, dev_proj, array_proj, tex_proj, true);\n  kernel_fdk_3Dgrid<<<dimGrid, dimBlock>>>(dev_vol_in, dev_vol_out, tex_proj);\n\n  // Cleanup\n  cudaFreeArray((cudaArray *)array_proj);\n  CUDA_CHECK_ERROR;\n  cudaDestroyTextureObject(tex_proj);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaFDKBackProjectionImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaFDKBackProjectionImageFilter.h\"\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaFDKBackProjectionImageFilter.hcu\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkLinearInterpolateImageFunction.h>\n#include <itkMacro.h>\n#include <itkProgressReporter.h>\n\nnamespace rtk\n{\n\nCudaFDKBackProjectionImageFilter ::CudaFDKBackProjectionImageFilter() {}\n\nvoid\nCudaFDKBackProjectionImageFilter ::GPUGenerateData()\n{\n  const unsigned int Dimension = ImageType::ImageDimension;\n  const unsigned int nProj = this->GetInput(1)->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  const unsigned int iFirstProj = this->GetInput(1)->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n  if (nProj > 1024)\n  {\n    itkGenericExceptionMacro(\n      \"The CUDA voxel based back projection image filter can only handle stacks of at most 1024 projections\");\n  }\n\n  // Rotation center (assumed to be at 0 yet)\n  ImageType::PointType rotCenterPoint;\n  rotCenterPoint.Fill(0.0);\n  itk::ContinuousIndex<double, Dimension> rotCenterIndex =\n    this->GetInput(0)->TransformPhysicalPointToContinuousIndex<ImageType::PointType::ValueType, double>(rotCenterPoint);\n\n  // Include non-zero index in matrix\n  itk::Matrix<double, 4, 4> matrixIdxVol;\n  matrixIdxVol.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    matrixIdxVol[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n    rotCenterIndex[i] -= this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n  }\n\n  // Cuda convenient format for dimensions\n  int projectionSize[3];\n  projectionSize[0] = this->GetInput(1)->GetBufferedRegion().GetSize()[0];\n  projectionSize[1] = this->GetInput(1)->GetBufferedRegion().GetSize()[1];\n\n  int volumeSize[3];\n  volumeSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  volumeSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n  volumeSize[2] = this->GetOutput()->GetBufferedRegion().GetSize()[2];\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * stackGPUPointer = (float *)(this->GetInput(1)->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * stackGPUPointer = *(float **)(this->GetInput(1)->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  ptrdiff_t projSize =\n    this->GetInput(1)->GetBufferedRegion().GetSize()[0] * this->GetInput(1)->GetBufferedRegion().GetSize()[1];\n  stackGPUPointer += projSize * (iFirstProj - this->GetInput(1)->GetBufferedRegion().GetIndex()[2]);\n\n  // Allocate a large matrix to hold the matrix of all projections\n  float * fMatrix = new float[12 * nProj];\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    // Index to index matrix normalized to have a correct backprojection weight\n    // (1 at the isocenter)\n    ProjectionMatrixType matrix = GetIndexToIndexProjectionMatrix(iProj);\n\n    // We correct the matrix for non zero indexes\n    itk::Matrix<double, 3, 3> matrixIdxProj;\n    matrixIdxProj.SetIdentity();\n    for (unsigned int i = 0; i < 2; i++)\n      // SR: 0.5 for 2D texture\n      matrixIdxProj[i][2] = -1 * (this->GetInput(1)->GetBufferedRegion().GetIndex()[i]) + 0.5;\n\n    matrix = matrixIdxProj.GetVnlMatrix() * matrix.GetVnlMatrix() * matrixIdxVol.GetVnlMatrix();\n\n    double perspFactor = matrix[Dimension - 1][Dimension];\n    for (unsigned int j = 0; j < Dimension; j++)\n      perspFactor += matrix[Dimension - 1][j] * rotCenterIndex[j];\n    matrix /= perspFactor;\n\n    for (int j = 0; j < 12; j++)\n      fMatrix[j + (iProj - iFirstProj) * 12] = matrix[j / 4][j % 4];\n  }\n\n  // Slab-wise progress reporting\n  itk::ProgressReporter progress(this, 0, itk::Math::ceil(double(nProj) / SLAB_SIZE));\n\n  for (unsigned int i = 0; i < nProj; i += SLAB_SIZE)\n  {\n    // If nProj is not a multiple of SLAB_SIZE, the last slab will contain less than SLAB_SIZE projections\n    projectionSize[2] = std::min(nProj - i, (unsigned int)SLAB_SIZE);\n\n    // Run the back projection with a slab of SLAB_SIZE or less projections\n    CUDA_reconstruct_conebeam(projectionSize, volumeSize, fMatrix + 12 * i, pin, pout, stackGPUPointer + projSize * i);\n\n    // Re-use the output as input\n    pin = pout;\n\n    progress.CompletedPixel();\n  }\n\n  delete[] fMatrix;\n}\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkCudaFDKConeBeamReconstructionFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaFDKConeBeamReconstructionFilter.h\"\n\nrtk::CudaFDKConeBeamReconstructionFilter ::CudaFDKConeBeamReconstructionFilter()\n{\n  // Create each filter which are specific for cuda\n  m_WeightFilter = WeightFilterType::New();\n  m_RampFilter = RampFilterType::New();\n  m_BackProjectionFilter = BackProjectionFilterType::New();\n\n  // Permanent internal connections\n  m_WeightFilter->SetInput(m_ExtractFilter->GetOutput());\n  m_RampFilter->SetInput(m_WeightFilter->GetOutput());\n  m_BackProjectionFilter->SetInput(1, m_RampFilter->GetOutput());\n\n  // Default parameters\n  m_BackProjectionFilter->InPlaceOn();\n  m_BackProjectionFilter->SetTranspose(false);\n\n  // Overwrite subset size of CPU version with GPU default\n  CPUSuperclass::SetProjectionSubsetSize(SLAB_SIZE);\n}\n\nvoid\nrtk::CudaFDKConeBeamReconstructionFilter ::GPUGenerateData()\n{\n  CPUSuperclass::GenerateData();\n}\n"
  },
  {
    "path": "src/rtkCudaFDKWeightProjectionFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaFDKWeightProjectionFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n#include <cuda.h>\n#include <cuda_runtime.h>\n\ninline __device__ float2\nTransformIndexToPhysicalPoint(int2 idx, float2 origin, float2 row, float2 column)\n{\n  return make_float2(origin.x + row.x * idx.x + column.x * idx.y, origin.y + row.y * idx.x + column.y * idx.y);\n}\n\n__global__ void\nkernel_weight_projection(int2                proj_idx,\n                         int3                proj_size,\n                         int2                proj_size_buf_in,\n                         int2                proj_size_buf_out,\n                         float *             dev_proj_in,\n                         float *             dev_proj_out,\n                         float2              proj_orig, // projection origin\n                         float2              proj_row,  // projection row direction & spacing\n                         float2              proj_col,  // projection col direction & spacing\n                         cudaTextureObject_t tex_geom   // geometry texture object\n)\n{\n  // compute projection index (== thread index)\n  int3 pIdx;\n  pIdx.x = blockIdx.x * blockDim.x + threadIdx.x;\n  pIdx.y = blockIdx.y * blockDim.y + threadIdx.y;\n  pIdx.z = blockIdx.z * blockDim.z + threadIdx.z;\n  long int pIdx_comp_in = pIdx.x + (pIdx.y + pIdx.z * proj_size_buf_in.y) * (proj_size_buf_in.x);\n  long int pIdx_comp_out = pIdx.x + (pIdx.y + pIdx.z * proj_size_buf_out.y) * (proj_size_buf_out.x);\n\n  // check if outside of projection grid\n  if (pIdx.x >= proj_size.x || pIdx.y >= proj_size.y || pIdx.z >= proj_size.z)\n    return;\n\n  const float sdd = tex1Dfetch<float>(tex_geom, pIdx.z * 7);\n  const float sid = tex1Dfetch<float>(tex_geom, pIdx.z * 7 + 1);\n  const float wFac = tex1Dfetch<float>(tex_geom, pIdx.z * 7 + 5);\n  if (sdd == 0) // parallel\n  {\n    dev_proj_out[pIdx_comp_out] = dev_proj_in[pIdx_comp_in] * wFac;\n  }\n  else // divergent\n  {\n    const float pOffX = tex1Dfetch<float>(tex_geom, pIdx.z * 7 + 2);\n    const float pOffY = tex1Dfetch<float>(tex_geom, pIdx.z * 7 + 3);\n    const float sOffY = tex1Dfetch<float>(tex_geom, pIdx.z * 7 + 4);\n    const float tAngle = tex1Dfetch<float>(tex_geom, pIdx.z * 7 + 6);\n    const float sina = sin(tAngle);\n    const float cosa = cos(tAngle);\n    const float tana = tan(tAngle);\n\n    // compute projection point from index\n    float2 pPoint =\n      TransformIndexToPhysicalPoint(make_int2(pIdx.x + proj_idx.x, pIdx.y + proj_idx.y), proj_orig, proj_row, proj_col);\n    pPoint.x = pPoint.x + pOffX + tana * (sdd - sid);\n    pPoint.y = pPoint.y + pOffY - sOffY;\n\n    const float numpart1 = sdd * (cosa + tana * sina);\n    const float denom = sqrt((sdd * sdd + pPoint.y * pPoint.y) + ((pPoint.x - sdd * tana) * (pPoint.x - sdd * tana)));\n    const float cosGamma = (numpart1 - pPoint.x * sina) / denom;\n    dev_proj_out[pIdx_comp_out] = dev_proj_in[pIdx_comp_in] * wFac * cosGamma;\n  }\n}\n\nvoid\nCUDA_weight_projection(int     proj_idx[2],\n                       int     proj_dim[3],\n                       int     proj_dim_buf_in[2],\n                       int     proj_dim_buf_out[2],\n                       float * dev_proj_in,\n                       float * dev_proj_out,\n                       float * geometry,\n                       float   proj_orig[2],\n                       float   proj_row[2],\n                       float   proj_col[2])\n{\n  float *             dev_geom;\n  cudaTextureObject_t tex_geom;\n  prepareGeometryTextureObject(proj_dim[2], geometry, dev_geom, tex_geom, 7);\n\n  // Thread Block Dimensions\n  int tBlock_x = 16;\n  int tBlock_y = 16;\n  int tBlock_z = 2;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (proj_dim[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (proj_dim[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (proj_dim[2] - 1) / tBlock_z + 1;\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n  kernel_weight_projection<<<dimGrid, dimBlock>>>(make_int2(proj_idx[0], proj_idx[1]),\n                                                  make_int3(proj_dim[0], proj_dim[1], proj_dim[2]),\n                                                  make_int2(proj_dim_buf_in[0], proj_dim_buf_in[1]),\n                                                  make_int2(proj_dim_buf_out[0], proj_dim_buf_out[1]),\n                                                  dev_proj_in,\n                                                  dev_proj_out,\n                                                  make_float2(proj_orig[0], proj_orig[1]),\n                                                  make_float2(proj_row[0], proj_row[1]),\n                                                  make_float2(proj_col[0], proj_col[1]),\n                                                  tex_geom);\n\n  // destroy texture object\n  cudaDestroyTextureObject(tex_geom);\n  CUDA_CHECK_ERROR;\n  cudaFree(dev_geom);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaFDKWeightProjectionFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaFDKWeightProjectionFilter.h\"\n#include \"rtkCudaFDKWeightProjectionFilter.hcu\"\n#include <itkProgressReporter.h>\n\nnamespace rtk\n{\n\nCudaFDKWeightProjectionFilter ::CudaFDKWeightProjectionFilter() {}\n\nCudaFDKWeightProjectionFilter ::~CudaFDKWeightProjectionFilter() {}\n\nvoid\nCudaFDKWeightProjectionFilter ::GPUGenerateData()\n{\n  // Get angular weights from geometry\n  std::vector<double> constantProjectionFactor =\n    this->GetGeometry()->GetAngularGaps(this->GetGeometry()->GetSourceAngles());\n  std::vector<double> tiltAngles = this->GetGeometry()->GetTiltAngles();\n\n  for (unsigned int g = 0; g < constantProjectionFactor.size(); g++)\n  {\n    // Add correction factor for ramp filter\n    const double sdd = this->GetGeometry()->GetSourceToDetectorDistances()[g];\n    if (sdd == 0.) // Parallel\n      constantProjectionFactor[g] *= 0.5;\n    else // Divergent\n    {\n      // See [Rit and Clackdoyle, CT meeting, 2014]\n      ThreeDCircularProjectionGeometry::HomogeneousVectorType sp;\n      sp = this->GetGeometry()->GetSourcePosition(g);\n      sp[3] = 0.;\n      const double sid = this->GetGeometry()->GetSourceToIsocenterDistances()[g];\n      constantProjectionFactor[g] *= itk::Math::abs(sdd) / (2. * sid * sid);\n      constantProjectionFactor[g] *= sp.GetNorm();\n    }\n  }\n\n  float proj_orig[2];\n  proj_orig[0] = this->GetInput()->GetOrigin()[0];\n  proj_orig[1] = this->GetInput()->GetOrigin()[1];\n\n  float proj_row[2];\n  proj_row[0] = this->GetInput()->GetDirection()[0][0] * this->GetInput()->GetSpacing()[0];\n  proj_row[1] = this->GetInput()->GetDirection()[1][0] * this->GetInput()->GetSpacing()[0];\n\n  float proj_col[2];\n  proj_col[0] = this->GetInput()->GetDirection()[0][1] * this->GetInput()->GetSpacing()[1];\n  proj_col[1] = this->GetInput()->GetDirection()[1][1] * this->GetInput()->GetSpacing()[1];\n\n  int proj_idx[2];\n  proj_idx[0] = this->GetInput()->GetRequestedRegion().GetIndex()[0];\n  proj_idx[1] = this->GetInput()->GetRequestedRegion().GetIndex()[1];\n\n  int proj_size[3];\n  proj_size[0] = this->GetInput()->GetRequestedRegion().GetSize()[0];\n  proj_size[1] = this->GetInput()->GetRequestedRegion().GetSize()[1];\n  proj_size[2] = this->GetInput()->GetRequestedRegion().GetSize()[2];\n\n  int proj_size_buf_in[2];\n  proj_size_buf_in[0] = this->GetInput()->GetBufferedRegion().GetSize()[0];\n  proj_size_buf_in[1] = this->GetInput()->GetBufferedRegion().GetSize()[1];\n\n  int proj_size_buf_out[2];\n  proj_size_buf_out[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  proj_size_buf_out[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n\n  // 2D matrix (numgeom * 7 values) in one block for memcpy!\n  // for each geometry, the following structure is used:\n  // 0: sdd\n  // 1: sid\n  // 2: projection offset x\n  // 3: projection offset y\n  // 4: source offset x\n  // 5: source offset y\n  // 6: weight factor\n  int     geomIdx = this->GetInput()->GetRequestedRegion().GetIndex()[2];\n  float * geomMatrix = new float[proj_size[2] * 7];\n  if (geomMatrix == nullptr)\n    itkExceptionMacro(<< \"Couldn't allocate geomMatrix\");\n  for (int g = 0; g < proj_size[2]; ++g)\n  {\n    geomMatrix[g * 7 + 0] = this->GetGeometry()->GetSourceToDetectorDistances()[g + geomIdx];\n    geomMatrix[g * 7 + 1] = this->GetGeometry()->GetSourceToIsocenterDistances()[g + geomIdx];\n    geomMatrix[g * 7 + 2] = this->GetGeometry()->GetProjectionOffsetsX()[g + geomIdx];\n    geomMatrix[g * 7 + 3] = this->GetGeometry()->GetProjectionOffsetsY()[g + geomIdx];\n    geomMatrix[g * 7 + 4] = this->GetGeometry()->GetSourceOffsetsY()[g + geomIdx];\n    geomMatrix[g * 7 + 5] = constantProjectionFactor[g + geomIdx];\n    geomMatrix[g * 7 + 6] = tiltAngles[g + geomIdx];\n  }\n\n  // Put the two data pointers at the same location\n#ifdef CudaCommon_VERSION_MAJOR\n  float * inBuffer = static_cast<float *>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * inBuffer = *static_cast<float **>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  inBuffer += this->GetInput()->ComputeOffset(this->GetInput()->GetRequestedRegion().GetIndex());\n#ifdef CudaCommon_VERSION_MAJOR\n  float * outBuffer = static_cast<float *>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * outBuffer = *static_cast<float **>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  outBuffer += this->GetOutput()->ComputeOffset(this->GetOutput()->GetRequestedRegion().GetIndex());\n\n  CUDA_weight_projection(proj_idx,\n                         proj_size,\n                         proj_size_buf_in,\n                         proj_size_buf_out,\n                         inBuffer,\n                         outBuffer,\n                         geomMatrix,\n                         proj_orig,\n                         proj_row,\n                         proj_col);\n\n  /* Impossible to get a pixel-wise progress reporting with CUDA\n   * so this filter only reports 0 and 100% completion. */\n  itk::ProgressReporter progress(this, 0, 1);\n  progress.CompletedPixel();\n\n  delete[] geomMatrix;\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkCudaFFTProjectionsConvolutionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaFFTProjectionsConvolutionImageFilter.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n#include <cufft.h>\n\n__global__ void\nmultiply_kernel(cufftComplex * projFFT, int3 fftDimension, cufftComplex * kernelFFT, unsigned int Blocks_Y)\n{\n  unsigned int blockIdx_z = blockIdx.y / Blocks_Y;\n  unsigned int blockIdx_y = blockIdx.y - __umul24(blockIdx_z, Blocks_Y);\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx_y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx_z, blockDim.z) + threadIdx.z;\n\n  if (i >= fftDimension.x || j >= fftDimension.y || k >= fftDimension.z)\n    return;\n\n  long int proj_idx = i + (j + k * fftDimension.y) * fftDimension.x;\n\n  cufftComplex result;\n  result.x = projFFT[proj_idx].x * kernelFFT[i].x - projFFT[proj_idx].y * kernelFFT[i].y;\n  result.y = projFFT[proj_idx].y * kernelFFT[i].x + projFFT[proj_idx].x * kernelFFT[i].y;\n  projFFT[proj_idx] = result;\n}\n\n__global__ void\nmultiply_kernel2D(cufftComplex * projFFT, int3 fftDimension, cufftComplex * kernelFFT, unsigned int Blocks_Y)\n{\n  unsigned int blockIdx_z = blockIdx.y / Blocks_Y;\n  unsigned int blockIdx_y = blockIdx.y - __umul24(blockIdx_z, Blocks_Y);\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx_y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx_z, blockDim.z) + threadIdx.z;\n\n  if (i >= fftDimension.x || j >= fftDimension.y || k >= fftDimension.z)\n    return;\n\n  long int kernel_idx = i + j * fftDimension.x;\n  long int proj_idx = kernel_idx + k * fftDimension.y * fftDimension.x;\n\n  cufftComplex result;\n  result.x = projFFT[proj_idx].x * kernelFFT[kernel_idx].x - projFFT[proj_idx].y * kernelFFT[kernel_idx].y;\n  result.y = projFFT[proj_idx].y * kernelFFT[kernel_idx].x + projFFT[proj_idx].x * kernelFFT[kernel_idx].y;\n  projFFT[proj_idx] = result;\n}\n\nvoid\nCUDA_fft_convolution(const int3 &   inputDimension,\n                     const int2 &   kernelDimension,\n                     float *        deviceProjection,\n                     cufftComplex * deviceKernelFFT)\n{\n  // CUDA device pointers\n  cufftComplex * deviceProjectionFFT;\n  int3           fftDimension = inputDimension;\n  fftDimension.x = inputDimension.x / 2 + 1;\n\n  size_t memorySizeProjectionFFT = sizeof(cufftComplex) * fftDimension.x * fftDimension.y * fftDimension.z;\n  cudaMalloc((void **)&deviceProjectionFFT, memorySizeProjectionFFT);\n  CUDA_CHECK_ERROR;\n\n  // 3D FFT\n  cufftHandle fftFwd;\n  cufftResult result;\n  if (fftDimension.z == 1)\n    result = cufftPlan2d(&fftFwd, inputDimension.y, inputDimension.x, CUFFT_R2C);\n  else\n    result = cufftPlan3d(&fftFwd, inputDimension.z, inputDimension.y, inputDimension.x, CUFFT_R2C);\n  CUFFT_CHECK_ERROR(result);\n  result = cufftExecR2C(fftFwd, deviceProjection, deviceProjectionFFT);\n  CUFFT_CHECK_ERROR(result);\n  cufftDestroy(fftFwd);\n\n  // Thread Block Dimensions\n  int  tBlock_x = 16;\n  int  tBlock_y = 4;\n  int  tBlock_z = 4;\n  int  blocksInX = (fftDimension.x - 1) / tBlock_x + 1;\n  int  blocksInY = (fftDimension.y - 1) / tBlock_y + 1;\n  int  blocksInZ = (fftDimension.z - 1) / tBlock_z + 1;\n  dim3 dimGrid = dim3(blocksInX, blocksInY * blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n  if (kernelDimension.y == 1)\n    multiply_kernel<<<dimGrid, dimBlock>>>(deviceProjectionFFT, fftDimension, deviceKernelFFT, blocksInY);\n  else\n    multiply_kernel2D<<<dimGrid, dimBlock>>>(deviceProjectionFFT, fftDimension, deviceKernelFFT, blocksInY);\n  CUDA_CHECK_ERROR;\n\n  // 3D inverse FFT\n  cufftHandle fftInv;\n  if (fftDimension.z == 1)\n    result = cufftPlan2d(&fftInv, inputDimension.y, inputDimension.x, CUFFT_C2R);\n  else\n    result = cufftPlan3d(&fftInv, inputDimension.z, inputDimension.y, inputDimension.x, CUFFT_C2R);\n  CUFFT_CHECK_ERROR(result);\n  result = cufftExecC2R(fftInv, deviceProjectionFFT, deviceProjection);\n  CUFFT_CHECK_ERROR(result);\n\n  // Release memory\n  cufftDestroy(fftInv);\n  cudaFree(deviceProjectionFFT);\n}\n\n__global__ void\npadding_kernel(float *            input,\n               float *            output,\n               const int3         paddingIdx,\n               const uint3        paddingDim,\n               const uint3        inputDim,\n               const unsigned int Blocks_Y,\n               float *            truncationWeights,\n               size_t             sizeWeights)\n{\n  unsigned int blockIdx_z = blockIdx.y / Blocks_Y;\n  unsigned int blockIdx_y = blockIdx.y - __umul24(blockIdx_z, Blocks_Y);\n  int          i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  int          j = __umul24(blockIdx_y, blockDim.y) + threadIdx.y;\n  int          k = __umul24(blockIdx_z, blockDim.z) + threadIdx.z;\n\n  if (i >= paddingDim.x || j >= paddingDim.y || k >= paddingDim.z)\n    return;\n\n  unsigned long int out_idx = i + (j + k * paddingDim.y) * paddingDim.x;\n  i -= paddingIdx.x;\n  j -= paddingIdx.y;\n  k -= paddingIdx.z;\n\n  // out of input y/z dimensions\n  if (j < 0 || j >= inputDim.y || k < 0 || k >= inputDim.z)\n    output[out_idx] = 0.0f;\n  // central part in CPU code\n  else if (i >= 0 && i < inputDim.x)\n    output[out_idx] = input[i + (j + k * inputDim.y) * inputDim.x];\n  // left mirroring (equation 3a in [Ohnesorge et al, Med Phys, 2000])\n  else if (i < 0 && -i < sizeWeights)\n  {\n    int begRow = (j + k * inputDim.y) * inputDim.x;\n    output[out_idx] = (2 * input[begRow + 1] - input[-i + begRow]) * truncationWeights[-i];\n  }\n  // right mirroring (equation 3b in [Ohnesorge et al, Med Phys, 2000])\n  else if ((i >= inputDim.x) && (i - inputDim.x + 1) < sizeWeights)\n  {\n    unsigned int borderDist = i - inputDim.x + 1;\n    int          endRow = inputDim.x - 1 + (j + k * inputDim.y) * inputDim.x;\n    output[out_idx] = (2 * input[endRow] - input[endRow - borderDist]) * truncationWeights[borderDist];\n  }\n  // zero padding\n  else\n    output[out_idx] = 0.0f;\n}\n\nvoid\nCUDA_padding(const int3 &               paddingIndex,\n             const uint3 &              paddingSize,\n             const uint3 &              inputSize,\n             float *                    deviceVolume,\n             float *                    devicePaddedVolume,\n             const std::vector<float> & mirrorWeights)\n{\n  // Thread Block Dimensions\n  unsigned int tBlock_x = 4;\n  unsigned int tBlock_y = 4;\n  unsigned int tBlock_z = 4;\n  unsigned int blocksInX = ((paddingSize.x - 1) / tBlock_x) + 1;\n  unsigned int blocksInY = ((paddingSize.y - 1) / tBlock_y) + 1;\n  unsigned int blocksInZ = ((paddingSize.z - 1) / tBlock_z) + 1;\n  dim3         dimGrid = dim3(blocksInX, blocksInY * blocksInZ);\n  dim3         dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n\n  // Transfer weights if required\n  float * weights_d = NULL;\n  if (mirrorWeights.size())\n  {\n    size_t size = mirrorWeights.size() * sizeof(float);\n    cudaMalloc((void **)&weights_d, size);\n    cudaMemcpy(weights_d, &(mirrorWeights[0]), size, cudaMemcpyHostToDevice);\n  }\n\n  // Call to kernel\n  padding_kernel<<<dimGrid, dimBlock>>>(\n    deviceVolume, devicePaddedVolume, paddingIndex, paddingSize, inputSize, blocksInY, weights_d, mirrorWeights.size());\n  CUDA_CHECK_ERROR;\n  // Release memory\n  cudaFree(weights_d);\n}\n"
  },
  {
    "path": "src/rtkCudaFirstOrderKernels.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaFirstOrderKernels.hcu\"\n\n__global__ void\ndivergence_kernel(float * grad_x, float * grad_y, float * grad_z, float * out, int3 c_Size, float3 c_Spacing)\n{\n  int i = blockIdx.x * blockDim.x + threadIdx.x;\n  int j = blockIdx.y * blockDim.y + threadIdx.y;\n  int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z)\n    return;\n\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n  long int id_x = (k * c_Size.y + j) * c_Size.x + i - 1;\n  long int id_y = (k * c_Size.y + j - 1) * c_Size.x + i;\n  long int id_z = ((k - 1) * c_Size.y + j) * c_Size.x + i;\n\n  float3 A;\n  float3 B;\n\n  if (i == 0)\n    B.x = 0;\n  else\n    B.x = grad_x[id_x];\n  if (i == (c_Size.x - 1))\n    A.x = 0;\n  else\n    A.x = grad_x[id];\n\n  if (j == 0)\n    B.y = 0;\n  else\n    B.y = grad_y[id_y];\n  if (j == (c_Size.y - 1))\n    A.y = 0;\n  else\n    A.y = grad_y[id];\n\n  if (k == 0)\n    B.z = 0;\n  else\n    B.z = grad_z[id_z];\n  if (k == (c_Size.z - 1))\n    A.z = 0;\n  else\n    A.z = grad_z[id];\n\n  out[id] = (A.x - B.x) / c_Spacing.x + (A.y - B.y) / c_Spacing.y + (A.z - B.z) / c_Spacing.z;\n}\n\n__global__ void\ngradient_kernel(float * in, float * grad_x, float * grad_y, float * grad_z, int3 c_Size, float3 c_Spacing)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z)\n    return;\n\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n  long int id_x = (k * c_Size.y + j) * c_Size.x + i + 1;\n  long int id_y = (k * c_Size.y + j + 1) * c_Size.x + i;\n  long int id_z = ((k + 1) * c_Size.y + j) * c_Size.x + i;\n\n  if (i == (c_Size.x - 1))\n    grad_x[id] = 0;\n  else\n    grad_x[id] = (in[id_x] - in[id]) / c_Spacing.x;\n\n  if (j == (c_Size.y - 1))\n    grad_y[id] = 0;\n  else\n    grad_y[id] = (in[id_y] - in[id]) / c_Spacing.y;\n\n  if (k == (c_Size.z - 1))\n    grad_z[id] = 0;\n  else\n    grad_z[id] = (in[id_z] - in[id]) / c_Spacing.z;\n}\n"
  },
  {
    "path": "src/rtkCudaForwardProjectionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaIntersectBox.hcu\"\n#include \"rtkCudaForwardProjectionImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n// CONSTANTS //\n__constant__ int3   c_projSize;\n__constant__ float3 c_boxMin;\n__constant__ float3 c_boxMax;\n__constant__ float3 c_spacing;\n__constant__ int3   c_volSize;\n__constant__ float  c_tStep;\n__constant__ float  c_radius;\n__constant__ float\n  c_translatedProjectionIndexTransformMatrices[SLAB_SIZE * 12]; // Can process stacks of at most SLAB_SIZE projections\n__constant__ float\n  c_translatedVolumeTransformMatrices[SLAB_SIZE * 12]; // Can process stacks of at most SLAB_SIZE projections\n__constant__ float c_sourcePos[SLAB_SIZE * 3];         // Can process stacks of at most SLAB_SIZE projections\n\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n// KERNEL kernel_forwardProject\ntemplate <unsigned int VVectorLength>\n__global__ void\nkernel_forwardProject(float * dev_proj_in, float * dev_proj_out, cudaTextureObject_t * dev_tex_vol)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int numThread = j * c_projSize.x + i;\n\n  if (i >= c_projSize.x || j >= c_projSize.y)\n    return;\n\n  // Declare variables used in the loop\n  Ray    ray;\n  float3 pixelPos;\n  float  tnear, tfar;\n\n  for (unsigned int proj = 0; proj < c_projSize.z; proj++)\n  {\n    // Setting ray origin\n    ray.o = make_float3(c_sourcePos[3 * proj], c_sourcePos[3 * proj + 1], c_sourcePos[3 * proj + 2]);\n\n    if (c_radius == 0)\n    {\n      pixelPos = matrix_multiply(make_float3(i, j, 0), &(c_translatedProjectionIndexTransformMatrices[12 * proj]));\n    }\n    else\n    {\n      float3 posProj;\n      posProj = matrix_multiply(make_float3(i, j, 0), &(c_translatedProjectionIndexTransformMatrices[12 * proj]));\n      double a = posProj.x / c_radius;\n      posProj.x = sin(a) * c_radius;\n      posProj.z += (1. - cos(a)) * c_radius;\n      pixelPos = matrix_multiply(posProj, &(c_translatedVolumeTransformMatrices[12 * proj]));\n    }\n\n    ray.d = pixelPos - ray.o;\n    ray.d = ray.d / sqrtf(dot(ray.d, ray.d));\n\n    int projOffset = numThread + proj * c_projSize.x * c_projSize.y;\n\n    // Detect intersection with box\n    if (!intersectBox(ray, &tnear, &tfar, c_boxMin, c_boxMax) || tfar < 0.f)\n    {\n      for (unsigned int c = 0; c < VVectorLength; c++)\n        dev_proj_out[projOffset * VVectorLength + c] = dev_proj_in[projOffset * VVectorLength + c];\n    }\n    else\n    {\n      if (tnear < 0.f)\n        tnear = 0.f; // clamp to near plane\n\n      // Step length in mm\n      float3 dirInMM = c_spacing * ray.d;\n      float  vStep = c_tStep / sqrtf(dot(dirInMM, dirInMM));\n      float3 step = vStep * ray.d;\n\n      // First position in the box\n      float3 pos;\n      float  halfVStep = 0.5f * vStep;\n      tnear = tnear + halfVStep;\n      pos = ray.o + tnear * ray.d;\n\n      float t;\n      float sample[VVectorLength];\n      float sum[VVectorLength];\n      for (unsigned int c = 0; c < VVectorLength; c++)\n      {\n        sample[c] = 0.0f;\n        sum[c] = 0.0f;\n      }\n\n      for (t = tnear; t <= tfar; t += vStep)\n      {\n        // Read from 3D texture from volume(s)\n        for (unsigned int c = 0; c < VVectorLength; c++)\n          sample[c] = tex3D<float>(dev_tex_vol[c], pos.x, pos.y, pos.z);\n\n        // Accumulate\n        for (unsigned int c = 0; c < VVectorLength; c++)\n          sum[c] += sample[c];\n\n        // Step forward\n        pos += step;\n      }\n\n      // Update the output projection pixels\n      for (unsigned int c = 0; c < VVectorLength; c++)\n        dev_proj_out[projOffset * VVectorLength + c] =\n          dev_proj_in[projOffset * VVectorLength + c] + (sum[c] + (tfar - t + halfVStep) / vStep * sample[c]) * c_tStep;\n    }\n  }\n}\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_forward_project() //////////////////////////////////\nvoid\nCUDA_forward_project(int          projSize[3],\n                     int          volSize[3],\n                     float *      translatedProjectionIndexTransformMatrices,\n                     float *      translatedVolumeTransformMatrices,\n                     float *      dev_proj_in,\n                     float *      dev_proj_out,\n                     float *      dev_vol,\n                     float        t_step,\n                     float *      source_positions,\n                     float        radiusCylindricalDetector,\n                     float        box_min[3],\n                     float        box_max[3],\n                     float        spacing[3],\n                     unsigned int vectorLength)\n{\n  // Constant memory\n  cudaMemcpyToSymbol(c_projSize, projSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_boxMin, box_min, sizeof(float3));\n  cudaMemcpyToSymbol(c_boxMax, box_max, sizeof(float3));\n  cudaMemcpyToSymbol(c_spacing, spacing, sizeof(float3));\n  cudaMemcpyToSymbol(c_volSize, volSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_tStep, &t_step, sizeof(float));\n  cudaMemcpyToSymbol(c_radius, &radiusCylindricalDetector, sizeof(float));\n\n  dim3 dimBlock = dim3(16, 16, 1);\n  dim3 dimGrid = dim3(iDivUp(projSize[0], dimBlock.x), iDivUp(projSize[1], dimBlock.x));\n\n  // Copy the source position matrix into a float3 in constant memory\n  cudaMemcpyToSymbol(c_sourcePos, &(source_positions[0]), 3 * sizeof(float) * projSize[2]);\n\n  // Copy the projection matrices into constant memory\n  cudaMemcpyToSymbol(c_translatedProjectionIndexTransformMatrices,\n                     &(translatedProjectionIndexTransformMatrices[0]),\n                     12 * sizeof(float) * projSize[2]);\n  cudaMemcpyToSymbol(\n    c_translatedVolumeTransformMatrices, &(translatedVolumeTransformMatrices[0]), 12 * sizeof(float) * projSize[2]);\n\n  // Prepare texture objects\n  std::vector<cudaArray *>         volComponentArrays;\n  std::vector<cudaTextureObject_t> tex_vol;\n  prepareVectorTextureObject(volSize, dev_vol, volComponentArrays, vectorLength, tex_vol, false, cudaAddressModeClamp);\n\n  // Copy them to a device pointer, since it will have to be de-referenced in the kernels\n  cudaTextureObject_t * dev_tex_vol;\n  cudaMalloc(&dev_tex_vol, vectorLength * sizeof(cudaTextureObject_t));\n  cudaMemcpy(dev_tex_vol, tex_vol.data(), vectorLength * sizeof(cudaTextureObject_t), cudaMemcpyHostToDevice);\n\n  // Run the kernel. Since \"vectorLength\" is passed as a function argument, not as a template argument,\n  // the compiler can't assume it's constant, and a dirty trick has to be used.\n  // I did not manage to make CUDA_forward_project templated over vectorLength,\n  // which would be the best solution\n  switch (vectorLength)\n  {\n    case 1:\n      kernel_forwardProject<1><<<dimGrid, dimBlock>>>(dev_proj_in, dev_proj_out, dev_tex_vol);\n      break;\n\n    case 2:\n      kernel_forwardProject<2><<<dimGrid, dimBlock>>>(dev_proj_in, dev_proj_out, dev_tex_vol);\n      break;\n\n    case 3:\n      kernel_forwardProject<3><<<dimGrid, dimBlock>>>(dev_proj_in, dev_proj_out, dev_tex_vol);\n      break;\n\n    default:\n    {\n      itkGenericExceptionMacro(\"Vector length \" << vectorLength << \" is not supported.\");\n    }\n  }\n  CUDA_CHECK_ERROR;\n\n  // Cleanup\n  for (unsigned int c = 0; c < vectorLength; c++)\n  {\n    cudaFreeArray((cudaArray *)volComponentArrays[c]);\n    CUDA_CHECK_ERROR;\n    cudaDestroyTextureObject(tex_vol[c]);\n    CUDA_CHECK_ERROR;\n  }\n  cudaFree(dev_tex_vol);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaForwardWarpImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/* -----------------------------------------------------------------------\n   See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information\n   ----------------------------------------------------------------------- */\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaForwardWarpImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n\n// CONSTANTS //////////////////////////////////////////////////////////////\n__constant__ float c_IndexInputToPPInputMatrix[12];\n__constant__ float c_IndexInputToIndexDVFMatrix[12];\n__constant__ float c_PPOutputToIndexOutputMatrix[12];\n////////////////////////////////////////////////////////////////////////////\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n__global__ void\nfillHoles_3Dgrid(float * dev_vol_out, float * dev_accumulate_weights, int3 out_dim)\n{\n  int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= out_dim.x || j >= out_dim.y || k >= out_dim.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  long int out_idx = i + (j + k * out_dim.y) * (out_dim.x);\n  long int current_idx;\n  int      radius = 3;\n\n  float eps = 1e-6;\n\n  // If there is a hole in splat at this point\n  if (abs(dev_accumulate_weights[out_idx]) < eps)\n  {\n    // Replace it with the weighted mean of the neighbours\n    // (with dev_accumulate_weights as weights, so as to\n    // negate the contribution of neighbouring holes)\n    float sum = 0;\n    float sum_weights = 0;\n\n    for (int delta_i = -radius; delta_i <= radius; delta_i++)\n    {\n      for (int delta_j = -radius; delta_j <= radius; delta_j++)\n      {\n        for (int delta_k = -radius; delta_k <= radius; delta_k++)\n        {\n          if ((i + delta_i >= 0) && (i + delta_i < out_dim.x) && (j + delta_j >= 0) && (j + delta_j < out_dim.y) &&\n              (k + delta_k >= 0) && (k + delta_k < out_dim.z))\n          {\n            current_idx = i + delta_i + (j + delta_j + (k + delta_k) * out_dim.y) * (out_dim.x);\n            sum += dev_vol_out[current_idx] * dev_accumulate_weights[current_idx];\n            sum_weights += dev_accumulate_weights[current_idx];\n          }\n        }\n      }\n    }\n    if (abs(sum_weights) > eps)\n      dev_vol_out[out_idx] = sum / sum_weights;\n    else\n      dev_vol_out[out_idx] = 0;\n  }\n}\n\n__global__ void\nnormalize_3Dgrid(float * dev_vol_out, float * dev_accumulate_weights, int3 out_dim)\n{\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= out_dim.x || j >= out_dim.y || k >= out_dim.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  long int out_idx = i + (j + k * out_dim.y) * (out_dim.x);\n\n  float eps = 1e-6;\n\n  if (abs(dev_accumulate_weights[out_idx]) > eps)\n    dev_vol_out[out_idx] /= dev_accumulate_weights[out_idx];\n  else\n    dev_vol_out[out_idx] = 0;\n}\n\n__global__ void\nlinearSplat_3Dgrid(float *             dev_vol_in,\n                   float *             dev_vol_out,\n                   float *             dev_accumulate_weights,\n                   int3                in_dim,\n                   int3                out_dim,\n                   cudaTextureObject_t tex_xdvf,\n                   cudaTextureObject_t tex_ydvf,\n                   cudaTextureObject_t tex_zdvf)\n{\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= in_dim.x || j >= in_dim.y || k >= in_dim.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  float3   idx = make_float3(i, j, k);\n  long int in_idx = i + (j + k * in_dim.y) * (in_dim.x);\n\n  // Matrix multiply to get the index in the DVF texture of the current point in the output volume\n  float3 IndexInDVF = matrix_multiply(idx, c_IndexInputToIndexDVFMatrix);\n\n  // Get each component of the displacement vector by\n  // interpolation in the dvf\n  float3 Displacement;\n  Displacement.x = tex3D<float>(tex_xdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n  Displacement.y = tex3D<float>(tex_ydvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n  Displacement.z = tex3D<float>(tex_zdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n\n  // Matrix multiply to get the physical coordinates of the current point in the input volume\n  float3 PPinInput = matrix_multiply(idx, c_IndexInputToPPInputMatrix);\n\n  // Get the index corresponding to the current physical point in output displaced by the displacement vector\n  float3 PPDisplaced;\n  PPDisplaced.x = PPinInput.x + Displacement.x;\n  PPDisplaced.y = PPinInput.y + Displacement.y;\n  PPDisplaced.z = PPinInput.z + Displacement.z;\n\n  float3 IndexInOutput = matrix_multiply(PPDisplaced, c_PPOutputToIndexOutputMatrix);\n\n  // Compute the splat weights\n  int3 BaseIndexInOutput;\n  BaseIndexInOutput.x = floorf(IndexInOutput.x);\n  BaseIndexInOutput.y = floorf(IndexInOutput.y);\n  BaseIndexInOutput.z = floorf(IndexInOutput.z);\n\n  float3 Distance;\n  Distance.x = IndexInOutput.x - BaseIndexInOutput.x;\n  Distance.y = IndexInOutput.y - BaseIndexInOutput.y;\n  Distance.z = IndexInOutput.z - BaseIndexInOutput.z;\n\n  float weight000 = (1 - Distance.x) * (1 - Distance.y) * (1 - Distance.z);\n  float weight001 = (1 - Distance.x) * (1 - Distance.y) * Distance.z;\n  float weight010 = (1 - Distance.x) * Distance.y * (1 - Distance.z);\n  float weight011 = (1 - Distance.x) * Distance.y * Distance.z;\n  float weight100 = Distance.x * (1 - Distance.y) * (1 - Distance.z);\n  float weight101 = Distance.x * (1 - Distance.y) * Distance.z;\n  float weight110 = Distance.x * Distance.y * (1 - Distance.z);\n  float weight111 = Distance.x * Distance.y * Distance.z;\n\n  // Compute indices in the volume\n  long int out_idx000 = (BaseIndexInOutput.x + 0) + (BaseIndexInOutput.y + 0) * out_dim.x +\n                        (BaseIndexInOutput.z + 0) * out_dim.x * out_dim.y;\n  long int out_idx001 = (BaseIndexInOutput.x + 0) + (BaseIndexInOutput.y + 0) * out_dim.x +\n                        (BaseIndexInOutput.z + 1) * out_dim.x * out_dim.y;\n  long int out_idx010 = (BaseIndexInOutput.x + 0) + (BaseIndexInOutput.y + 1) * out_dim.x +\n                        (BaseIndexInOutput.z + 0) * out_dim.x * out_dim.y;\n  long int out_idx011 = (BaseIndexInOutput.x + 0) + (BaseIndexInOutput.y + 1) * out_dim.x +\n                        (BaseIndexInOutput.z + 1) * out_dim.x * out_dim.y;\n  long int out_idx100 = (BaseIndexInOutput.x + 1) + (BaseIndexInOutput.y + 0) * out_dim.x +\n                        (BaseIndexInOutput.z + 0) * out_dim.x * out_dim.y;\n  long int out_idx101 = (BaseIndexInOutput.x + 1) + (BaseIndexInOutput.y + 0) * out_dim.x +\n                        (BaseIndexInOutput.z + 1) * out_dim.x * out_dim.y;\n  long int out_idx110 = (BaseIndexInOutput.x + 1) + (BaseIndexInOutput.y + 1) * out_dim.x +\n                        (BaseIndexInOutput.z + 0) * out_dim.x * out_dim.y;\n  long int out_idx111 = (BaseIndexInOutput.x + 1) + (BaseIndexInOutput.y + 1) * out_dim.x +\n                        (BaseIndexInOutput.z + 1) * out_dim.x * out_dim.y;\n\n  // Determine whether they are indeed in the volume\n  bool isInVolume_out_idx000 = (BaseIndexInOutput.x + 0 >= 0) && (BaseIndexInOutput.x + 0 < out_dim.x) &&\n                               (BaseIndexInOutput.y + 0 >= 0) && (BaseIndexInOutput.y + 0 < out_dim.y) &&\n                               (BaseIndexInOutput.z + 0 >= 0) && (BaseIndexInOutput.z + 0 < out_dim.z);\n\n  bool isInVolume_out_idx001 = (BaseIndexInOutput.x + 0 >= 0) && (BaseIndexInOutput.x + 0 < out_dim.x) &&\n                               (BaseIndexInOutput.y + 0 >= 0) && (BaseIndexInOutput.y + 0 < out_dim.y) &&\n                               (BaseIndexInOutput.z + 1 >= 0) && (BaseIndexInOutput.z + 1 < out_dim.z);\n\n  bool isInVolume_out_idx010 = (BaseIndexInOutput.x + 0 >= 0) && (BaseIndexInOutput.x + 0 < out_dim.x) &&\n                               (BaseIndexInOutput.y + 1 >= 0) && (BaseIndexInOutput.y + 1 < out_dim.y) &&\n                               (BaseIndexInOutput.z + 0 >= 0) && (BaseIndexInOutput.z + 0 < out_dim.z);\n\n  bool isInVolume_out_idx011 = (BaseIndexInOutput.x + 0 >= 0) && (BaseIndexInOutput.x + 0 < out_dim.x) &&\n                               (BaseIndexInOutput.y + 1 >= 0) && (BaseIndexInOutput.y + 1 < out_dim.y) &&\n                               (BaseIndexInOutput.z + 1 >= 0) && (BaseIndexInOutput.z + 1 < out_dim.z);\n\n  bool isInVolume_out_idx100 = (BaseIndexInOutput.x + 1 >= 0) && (BaseIndexInOutput.x + 1 < out_dim.x) &&\n                               (BaseIndexInOutput.y + 0 >= 0) && (BaseIndexInOutput.y + 0 < out_dim.y) &&\n                               (BaseIndexInOutput.z + 0 >= 0) && (BaseIndexInOutput.z + 0 < out_dim.z);\n\n  bool isInVolume_out_idx101 = (BaseIndexInOutput.x + 1 >= 0) && (BaseIndexInOutput.x + 1 < out_dim.x) &&\n                               (BaseIndexInOutput.y + 0 >= 0) && (BaseIndexInOutput.y + 0 < out_dim.y) &&\n                               (BaseIndexInOutput.z + 1 >= 0) && (BaseIndexInOutput.z + 1 < out_dim.z);\n\n  bool isInVolume_out_idx110 = (BaseIndexInOutput.x + 1 >= 0) && (BaseIndexInOutput.x + 1 < out_dim.x) &&\n                               (BaseIndexInOutput.y + 1 >= 0) && (BaseIndexInOutput.y + 1 < out_dim.y) &&\n                               (BaseIndexInOutput.z + 0 >= 0) && (BaseIndexInOutput.z + 0 < out_dim.z);\n\n  bool isInVolume_out_idx111 = (BaseIndexInOutput.x + 1 >= 0) && (BaseIndexInOutput.x + 1 < out_dim.x) &&\n                               (BaseIndexInOutput.y + 1 >= 0) && (BaseIndexInOutput.y + 1 < out_dim.y) &&\n                               (BaseIndexInOutput.z + 1 >= 0) && (BaseIndexInOutput.z + 1 < out_dim.z);\n\n  // Perform splat if voxel is indeed in output volume\n  if (isInVolume_out_idx000)\n  {\n    atomicAdd(&dev_vol_out[out_idx000], dev_vol_in[in_idx] * weight000);\n    atomicAdd(&dev_accumulate_weights[out_idx000], weight000);\n  }\n  if (isInVolume_out_idx001)\n  {\n    atomicAdd(&dev_vol_out[out_idx001], dev_vol_in[in_idx] * weight001);\n    atomicAdd(&dev_accumulate_weights[out_idx001], weight001);\n  }\n  if (isInVolume_out_idx010)\n  {\n    atomicAdd(&dev_vol_out[out_idx010], dev_vol_in[in_idx] * weight010);\n    atomicAdd(&dev_accumulate_weights[out_idx010], weight010);\n  }\n  if (isInVolume_out_idx011)\n  {\n    atomicAdd(&dev_vol_out[out_idx011], dev_vol_in[in_idx] * weight011);\n    atomicAdd(&dev_accumulate_weights[out_idx011], weight011);\n  }\n  if (isInVolume_out_idx100)\n  {\n    atomicAdd(&dev_vol_out[out_idx100], dev_vol_in[in_idx] * weight100);\n    atomicAdd(&dev_accumulate_weights[out_idx100], weight100);\n  }\n  if (isInVolume_out_idx101)\n  {\n    atomicAdd(&dev_vol_out[out_idx101], dev_vol_in[in_idx] * weight101);\n    atomicAdd(&dev_accumulate_weights[out_idx101], weight101);\n  }\n  if (isInVolume_out_idx110)\n  {\n    atomicAdd(&dev_vol_out[out_idx110], dev_vol_in[in_idx] * weight110);\n    atomicAdd(&dev_accumulate_weights[out_idx110], weight110);\n  }\n  if (isInVolume_out_idx111)\n  {\n    atomicAdd(&dev_vol_out[out_idx111], dev_vol_in[in_idx] * weight111);\n    atomicAdd(&dev_accumulate_weights[out_idx111], weight111);\n  }\n}\n\n__global__ void\nnearestNeighborSplat_3Dgrid(float *             dev_vol_in,\n                            float *             dev_vol_out,\n                            float *             dev_accumulate_weights,\n                            int3                in_dim,\n                            int3                out_dim,\n                            cudaTextureObject_t tex_xdvf,\n                            cudaTextureObject_t tex_ydvf,\n                            cudaTextureObject_t tex_zdvf)\n{\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= in_dim.x || j >= in_dim.y || k >= in_dim.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  long int in_idx = i + (j + k * in_dim.y) * (in_dim.x);\n\n  // Matrix multiply to get the index in the DVF texture of the current point in the output volume\n  float3 idx = make_float3(i, j, k);\n  float3 IndexInDVF = matrix_multiply(idx, c_IndexInputToIndexDVFMatrix);\n\n  // Get each component of the displacement vector by\n  // interpolation in the dvf\n  float3 Displacement;\n  Displacement.x = tex3D<float>(tex_xdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n  Displacement.y = tex3D<float>(tex_ydvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n  Displacement.z = tex3D<float>(tex_zdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n\n  // Matrix multiply to get the physical coordinates of the current point in the input volume\n  float3 PPinInput = matrix_multiply(idx, c_IndexInputToPPInputMatrix);\n\n  // Get the index corresponding to the current physical point in output displaced by the displacement vector\n  float3 PPDisplaced;\n  PPDisplaced.x = PPinInput.x + Displacement.x;\n  PPDisplaced.y = PPinInput.y + Displacement.y;\n  PPDisplaced.z = PPinInput.z + Displacement.z;\n\n  float3 IndexInOutput = matrix_multiply(PPDisplaced, c_PPOutputToIndexOutputMatrix);\n  IndexInOutput.x = floor(IndexInOutput.x + 0.5);\n  IndexInOutput.y = floor(IndexInOutput.y + 0.5);\n  IndexInOutput.z = floor(IndexInOutput.z + 0.5);\n\n  bool isInVolume = (IndexInOutput.x >= 0) && (IndexInOutput.x < out_dim.x) && (IndexInOutput.y >= 0) &&\n                    (IndexInOutput.y < out_dim.y) && (IndexInOutput.z >= 0) && (IndexInOutput.z < out_dim.z);\n\n  // Perform splat if voxel is indeed in output volume\n  if (isInVolume)\n  {\n    long int out_idx = IndexInOutput.x + IndexInOutput.y * out_dim.x + IndexInOutput.z * out_dim.x * out_dim.y;\n    atomicAdd(&dev_vol_out[out_idx], dev_vol_in[in_idx]);\n    atomicAdd(&dev_accumulate_weights[out_idx], 1);\n  }\n}\n\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_ForwardWarp /////////////////////////////\nvoid\nCUDA_ForwardWarp(int     input_vol_dim[3],\n                 int     input_dvf_dim[3],\n                 int     output_vol_dim[3],\n                 float   IndexInputToPPInputMatrix[12],\n                 float   IndexInputToIndexDVFMatrix[12],\n                 float   PPOutputToIndexOutputMatrix[12],\n                 float * dev_input_vol,\n                 float * dev_input_xdvf,\n                 float * dev_input_ydvf,\n                 float * dev_input_zdvf,\n                 float * dev_output_vol,\n                 bool    isLinear)\n{\n  // Prepare channel description for arrays\n  static cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();\n\n  ///////////////////////////////////\n  // Extent stuff, will be used for each component extraction\n  cudaArray *         array_xdvf, *array_ydvf, *array_zdvf;\n  cudaTextureObject_t tex_xdvf, tex_ydvf, tex_zdvf;\n  prepareScalarTextureObject(input_dvf_dim, dev_input_xdvf, array_xdvf, tex_xdvf, false);\n  prepareScalarTextureObject(input_dvf_dim, dev_input_ydvf, array_ydvf, tex_ydvf, false);\n  prepareScalarTextureObject(input_dvf_dim, dev_input_zdvf, array_zdvf, tex_zdvf, false);\n\n  ///////////////////////////////////////\n  // Copy matrices into constant memory\n  cudaMemcpyToSymbol(\n    c_IndexInputToPPInputMatrix, IndexInputToPPInputMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  cudaMemcpyToSymbol(\n    c_IndexInputToIndexDVFMatrix, IndexInputToIndexDVFMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  cudaMemcpyToSymbol(\n    c_PPOutputToIndexOutputMatrix, PPOutputToIndexOutputMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  CUDA_CHECK_ERROR;\n\n  ///////////////////////////////////////\n  /// Initialize the output\n  size_t memorySizeOutput = sizeof(float) * output_vol_dim[0] * output_vol_dim[1] * output_vol_dim[2];\n  cudaMemset((void *)dev_output_vol, 0, memorySizeOutput);\n\n  //////////////////////////////////////\n  /// Create an image to store the splat weights\n  /// (in order to normalize)\n\n  float * dev_accumulate_weights;\n  cudaMalloc((void **)&dev_accumulate_weights, memorySizeOutput);\n  cudaMemset((void *)dev_accumulate_weights, 0, memorySizeOutput);\n\n  // Thread Block Dimensions\n  constexpr int tBlock_x = 16;\n  constexpr int tBlock_y = 4;\n  constexpr int tBlock_z = 4;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (output_vol_dim[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (output_vol_dim[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (output_vol_dim[2] - 1) / tBlock_z + 1;\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n\n  // Note: the DVF is passed via texture memory\n  //-------------------------------------\n  if (isLinear)\n    linearSplat_3Dgrid<<<dimGrid, dimBlock>>>(dev_input_vol,\n                                              dev_output_vol,\n                                              dev_accumulate_weights,\n                                              make_int3(input_vol_dim[0], input_vol_dim[1], input_vol_dim[2]),\n                                              make_int3(output_vol_dim[0], output_vol_dim[1], output_vol_dim[2]),\n                                              tex_xdvf,\n                                              tex_ydvf,\n                                              tex_zdvf);\n  else\n    nearestNeighborSplat_3Dgrid<<<dimGrid, dimBlock>>>(\n      dev_input_vol,\n      dev_output_vol,\n      dev_accumulate_weights,\n      make_int3(input_vol_dim[0], input_vol_dim[1], input_vol_dim[2]),\n      make_int3(output_vol_dim[0], output_vol_dim[1], output_vol_dim[2]),\n      tex_xdvf,\n      tex_ydvf,\n      tex_zdvf);\n\n  CUDA_CHECK_ERROR;\n\n  normalize_3Dgrid<<<dimGrid, dimBlock>>>(\n    dev_output_vol, dev_accumulate_weights, make_int3(output_vol_dim[0], output_vol_dim[1], output_vol_dim[2]));\n  CUDA_CHECK_ERROR;\n\n  fillHoles_3Dgrid<<<dimGrid, dimBlock>>>(\n    dev_output_vol, dev_accumulate_weights, make_int3(output_vol_dim[0], output_vol_dim[1], output_vol_dim[2]));\n  CUDA_CHECK_ERROR;\n\n  // Cleanup\n  cudaFreeArray(array_xdvf);\n  CUDA_CHECK_ERROR;\n  cudaFreeArray(array_ydvf);\n  CUDA_CHECK_ERROR;\n  cudaFreeArray(array_zdvf);\n  CUDA_CHECK_ERROR;\n  cudaFree(dev_accumulate_weights);\n  CUDA_CHECK_ERROR;\n  cudaDestroyTextureObject(tex_xdvf);\n  CUDA_CHECK_ERROR;\n  cudaDestroyTextureObject(tex_ydvf);\n  CUDA_CHECK_ERROR;\n  cudaDestroyTextureObject(tex_zdvf);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaForwardWarpImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaForwardWarpImageFilter.h\"\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaForwardWarpImageFilter.hcu\"\n#include \"rtkHomogeneousMatrix.h\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkLinearInterpolateImageFunction.h>\n#include <itkMacro.h>\n\nnamespace rtk\n{\n\nCudaForwardWarpImageFilter ::CudaForwardWarpImageFilter() {}\n\nvoid\nCudaForwardWarpImageFilter ::GPUGenerateData()\n{\n  // Include non-zero index in matrix\n  itk::Matrix<double, 4, 4> matrixIdxOutputVol;\n  itk::Matrix<double, 4, 4> matrixIdxInputVol;\n  itk::Matrix<double, 4, 4> indexInputToPPInputMatrix;\n  itk::Matrix<double, 4, 4> indexInputToIndexDVFMatrix;\n  itk::Matrix<double, 4, 4> PPOutputToIndexOutputMatrix;\n  matrixIdxOutputVol.SetIdentity();\n  matrixIdxInputVol.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    matrixIdxOutputVol[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n    matrixIdxInputVol[i][3] = this->GetInput(0)->GetBufferedRegion().GetIndex()[i];\n  }\n\n  // Cuda convenient format for dimensions\n  int inputVolumeSize[3];\n  inputVolumeSize[0] = this->GetInput(0)->GetBufferedRegion().GetSize()[0];\n  inputVolumeSize[1] = this->GetInput(0)->GetBufferedRegion().GetSize()[1];\n  inputVolumeSize[2] = this->GetInput(0)->GetBufferedRegion().GetSize()[2];\n\n  int inputDVFSize[3];\n  inputDVFSize[0] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[0];\n  inputDVFSize[1] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[1];\n  inputDVFSize[2] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[2];\n\n  int outputVolumeSize[3];\n  outputVolumeSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  outputVolumeSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n  outputVolumeSize[2] = this->GetOutput()->GetBufferedRegion().GetSize()[2];\n\n  // Split the DVF into three images (one per component)\n  auto                  xCompDVF = ImageType::New();\n  auto                  yCompDVF = ImageType::New();\n  auto                  zCompDVF = ImageType::New();\n  ImageType::RegionType largest = this->GetDisplacementField()->GetLargestPossibleRegion();\n  xCompDVF->SetRegions(largest);\n  yCompDVF->SetRegions(largest);\n  zCompDVF->SetRegions(largest);\n  xCompDVF->Allocate();\n  yCompDVF->Allocate();\n  zCompDVF->Allocate();\n  itk::ImageRegionIterator<ImageType>    itxComp(xCompDVF, largest);\n  itk::ImageRegionIterator<ImageType>    ityComp(yCompDVF, largest);\n  itk::ImageRegionIterator<ImageType>    itzComp(zCompDVF, largest);\n  itk::ImageRegionConstIterator<DVFType> itDVF(this->GetDisplacementField(), largest);\n  while (!itDVF.IsAtEnd())\n  {\n    itxComp.Set(itDVF.Get()[0]);\n    ityComp.Set(itDVF.Get()[1]);\n    itzComp.Set(itDVF.Get()[2]);\n    ++itxComp;\n    ++ityComp;\n    ++itzComp;\n    ++itDVF;\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pinVol = (float *)(this->GetInput(0)->GetCudaDataManager()->GetGPUBufferPointer());\n  float * poutVol = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pinxDVF = (float *)(xCompDVF->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pinyDVF = (float *)(yCompDVF->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pinzDVF = (float *)(zCompDVF->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pinVol = *(float **)(this->GetInput(0)->GetCudaDataManager()->GetGPUBufferPointer());\n  float * poutVol = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pinxDVF = *(float **)(xCompDVF->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pinyDVF = *(float **)(yCompDVF->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pinzDVF = *(float **)(zCompDVF->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  // Transform matrices that we will need during the ForwardWarping process\n  indexInputToPPInputMatrix =\n    rtk::GetIndexToPhysicalPointMatrix(this->GetInput(0)).GetVnlMatrix() * matrixIdxInputVol.GetVnlMatrix();\n\n  indexInputToIndexDVFMatrix = rtk::GetPhysicalPointToIndexMatrix(this->GetDisplacementField()).GetVnlMatrix() *\n                               rtk::GetIndexToPhysicalPointMatrix(this->GetInput(0)).GetVnlMatrix() *\n                               matrixIdxInputVol.GetVnlMatrix();\n\n  PPOutputToIndexOutputMatrix = rtk::GetPhysicalPointToIndexMatrix(this->GetOutput()).GetVnlMatrix();\n\n  // Convert the matrices to arrays of floats (skipping the last line, as we don't care)\n  float fIndexInputToPPInputMatrix[12];\n  float fIndexInputToIndexDVFMatrix[12];\n  float fPPOutputToIndexOutputMatrix[12];\n  for (int j = 0; j < 12; j++)\n  {\n    fIndexInputToIndexDVFMatrix[j] = (float)indexInputToIndexDVFMatrix[j / 4][j % 4];\n    fPPOutputToIndexOutputMatrix[j] = (float)PPOutputToIndexOutputMatrix[j / 4][j % 4];\n    fIndexInputToPPInputMatrix[j] = (float)indexInputToPPInputMatrix[j / 4][j % 4];\n  }\n\n  bool isLinear;\n  if (std::string(\"LinearInterpolateImageFunction\").compare(this->GetInterpolator()->GetNameOfClass()) == 0)\n    isLinear = true;\n  else if (std::string(\"NearestNeighborInterpolateImageFunction\").compare(this->GetInterpolator()->GetNameOfClass()) ==\n           0)\n    isLinear = false;\n  else\n    itkGenericExceptionMacro(<< \"In rtkCudaForwardWarpImageFilter: unknown interpolator\");\n\n  // Run on GPU\n  CUDA_ForwardWarp(inputVolumeSize,\n                   inputDVFSize,\n                   outputVolumeSize,\n                   fIndexInputToPPInputMatrix,\n                   fIndexInputToIndexDVFMatrix,\n                   fPPOutputToIndexOutputMatrix,\n                   pinVol,\n                   pinxDVF,\n                   pinyDVF,\n                   pinzDVF,\n                   poutVol,\n                   isLinear);\n\n  // Get rid of the intermediate images used to split the DVF into three components\n  xCompDVF = nullptr;\n  yCompDVF = nullptr;\n  zCompDVF = nullptr;\n}\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkCudaInterpolateImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaInterpolateImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n#include <cublas_v2.h>\n#include <cuda_runtime.h>\n\nvoid\nCUDA_interpolation(const int4 & inputSize, float * input, float * output, int projectionNumber, float ** weights)\n{\n  cublasHandle_t handle;\n  cublasCreate(&handle);\n\n  // CUDA device pointers\n  size_t nVoxelsOutput = inputSize.x * inputSize.y * inputSize.z;\n  size_t memorySizeOutput = nVoxelsOutput * sizeof(float);\n\n  // Reset output volume\n  cudaMemset((void *)output, 0, memorySizeOutput);\n\n  for (int phase = 0; phase < inputSize.w; phase++)\n  {\n    float weight = weights[phase][projectionNumber];\n    if (weight != 0)\n    {\n      // Create a pointer to the \"phase\"-th volume in the input\n      float * p = input + phase * nVoxelsOutput;\n\n      // Add \"weight\" times the \"phase\"-th volume in the input to the output\n#if CUDA_VERSION < 12000\n      cublasSaxpy(handle, (int)nVoxelsOutput, &weight, p, 1, output, 1);\n#else\n      cublasSaxpy_64(handle, nVoxelsOutput, &weight, p, 1, output, 1);\n#endif\n    }\n  }\n\n  // Destroy Cublas context\n  cublasDestroy(handle);\n\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaInterpolateImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaInterpolateImageFilter.h\"\n#include \"rtkCudaInterpolateImageFilter.hcu\"\n\n#include <itkMacro.h>\n\nrtk::CudaInterpolateImageFilter ::CudaInterpolateImageFilter() {}\n\nvoid\nrtk::CudaInterpolateImageFilter ::GPUGenerateData()\n{\n  int4 inputSize;\n  inputSize.x = this->GetInputVolumeSeries()->GetBufferedRegion().GetSize()[0];\n  inputSize.y = this->GetInputVolumeSeries()->GetBufferedRegion().GetSize()[1];\n  inputSize.z = this->GetInputVolumeSeries()->GetBufferedRegion().GetSize()[2];\n  inputSize.w = this->GetInputVolumeSeries()->GetBufferedRegion().GetSize()[3];\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pvolseries = (float *)(this->GetInputVolumeSeries()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pvol = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pvolseries = *(float **)(this->GetInputVolumeSeries()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pvol = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_interpolation(inputSize, pvolseries, pvol, m_ProjectionNumber, m_Weights.data_array());\n}\n"
  },
  {
    "path": "src/rtkCudaIterativeFDKConeBeamReconstructionFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaIterativeFDKConeBeamReconstructionFilter.h\"\n\nrtk::CudaIterativeFDKConeBeamReconstructionFilter ::CudaIterativeFDKConeBeamReconstructionFilter()\n{\n  // Create each filter which are specific for cuda\n  m_DisplacedDetectorFilter = DisplacedDetectorFilterType::New();\n  m_ParkerFilter = ParkerFilterType::New();\n  m_FDKFilter = FDKFilterType::New();\n  m_ConstantProjectionStackSource = ConstantImageSourceType::New();\n\n  // Filter parameters\n  m_DisplacedDetectorFilter->SetPadOnTruncatedSide(false);\n\n  // Set default projector\n  this->m_CurrentForwardProjectionConfiguration = ForwardProjectionType::FP_CUDARAYCAST;\n}\n\nvoid\nrtk::CudaIterativeFDKConeBeamReconstructionFilter ::GPUGenerateData()\n{\n  Superclass::GenerateData();\n}\n"
  },
  {
    "path": "src/rtkCudaLagCorrectionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaLagCorrectionImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math_constants.h>\n\n__constant__ float cst_coef[9];\n\n__global__ void\nkernel_lag_correction(int3             proj_idx_in,\n                      int3             proj_size_in,\n                      int2             proj_size_in_buf,\n                      int3             proj_idx_out,\n                      int3             proj_size_out,\n                      int2             proj_size_out_buf,\n                      unsigned short * dev_proj_in,\n                      unsigned short * dev_proj_out,\n                      float *          state)\n{\n  constexpr int modelOrder = 4;\n\n  // compute thread index\n  int3 tIdx;\n  tIdx.x = blockIdx.x * blockDim.x + threadIdx.x;\n  tIdx.y = blockIdx.y * blockDim.y + threadIdx.y;\n  tIdx.z = blockIdx.z * blockDim.z + threadIdx.z;\n  long int tIdx_comp = tIdx.x + tIdx.y * proj_size_out.x + tIdx.z * proj_size_out_buf.x * proj_size_out_buf.y;\n\n  // check if outside of projection grid\n  if (tIdx.x >= proj_size_out.x || tIdx.y >= proj_size_out.y || tIdx.z >= proj_size_out.z)\n    return;\n\n  // compute projection index from thread index\n  int3 pIdx = make_int3(tIdx.x + proj_idx_out.x, tIdx.y + proj_idx_out.y, tIdx.z + proj_idx_out.z);\n  // combined proj. index -> use thread index in z because accessing memory only with this index\n  long int pIdx_comp = (pIdx.x - proj_idx_in.x) + (pIdx.y - proj_idx_in.y) * proj_size_in_buf.x +\n                       (pIdx.z - proj_idx_in.z) * proj_size_in_buf.x * proj_size_in_buf.y;\n\n  long int sIdx_comp = tIdx.x + tIdx.y * proj_size_out.x;\n  unsigned idx_s = sIdx_comp * modelOrder;\n\n  float yk = static_cast<float>(dev_proj_in[pIdx_comp]);\n  float xk = yk;\n\n  float Sa[modelOrder];\n  for (unsigned int n = 0; n < modelOrder; n++)\n  {\n    // Compute the update of internal state for nth exponential\n    float expmA_n = cst_coef[4 + n];\n    Sa[n] = expmA_n * state[idx_s + n];\n\n    // Update x[k] by removing contribution of the nth exponential\n    float B_n = cst_coef[n];\n    xk -= B_n * Sa[n];\n  }\n\n  // Apply normalization factor\n  xk = xk / cst_coef[8];\n\n  // Update internal state Snk\n  for (unsigned int n = 0; n < modelOrder; n++)\n  {\n    state[idx_s + n] = xk + Sa[n];\n  }\n\n  // Avoid negative values\n  xk = (xk < 0.0f) ? 0.f : xk;\n\n  dev_proj_out[tIdx_comp] = static_cast<unsigned short>(xk);\n}\n\nvoid\nCUDA_lag_correction(int              proj_idx_in[3],      // overlapping input region index\n                    int              proj_dim_in[3],      // overlapping input region size\n                    int              proj_dim_in_buf[2],  // input size of buffered region\n                    int              proj_idx_out[3],     // output region index\n                    int              proj_dim_out[3],     // output region size\n                    int              proj_dim_out_buf[2], // output size of buffered region\n                    unsigned short * dev_proj_in,\n                    unsigned short * dev_proj_out,\n                    float *          h_state,\n                    size_t           state_size,\n                    float *          coefficients)\n{\n  // Thread Block Dimensions\n  int tBlock_x = 16;\n  int tBlock_y = 16;\n  int tBlock_z = 2;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (proj_dim_out[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (proj_dim_out[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (proj_dim_out[2] - 1) / tBlock_z + 1;\n\n  float * d_state; // device state\n  cudaMalloc((void **)&d_state, state_size);\n  if (cudaMemcpy(d_state, h_state, state_size, cudaMemcpyHostToDevice) != cudaSuccess)\n  {\n    itkGenericExceptionMacro(\"Error allocating state\");\n  }\n\n  if (coefficients[8] <= 0.0)\n    coefficients[8] = 1.0;\n\n  cudaMemcpyToSymbol(cst_coef, coefficients, 9 * sizeof(float));\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n  kernel_lag_correction<<<dimGrid, dimBlock>>>(make_int3(proj_idx_in[0], proj_idx_in[1], proj_idx_in[2]),\n                                               make_int3(proj_dim_in[0], proj_dim_in[1], proj_dim_in[2]),\n                                               make_int2(proj_dim_in_buf[0], proj_dim_in_buf[1]),\n                                               make_int3(proj_idx_out[0], proj_idx_out[1], proj_idx_out[2]),\n                                               make_int3(proj_dim_out[0], proj_dim_out[1], proj_dim_out[2]),\n                                               make_int2(proj_dim_out_buf[0], proj_dim_out_buf[1]),\n                                               dev_proj_in,\n                                               dev_proj_out,\n                                               d_state);\n\n  cudaMemcpy(h_state, d_state, state_size, cudaMemcpyDeviceToHost);\n  cudaFree(d_state);\n\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaLagCorrectionImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaLagCorrectionImageFilter.h\"\n#include \"rtkCudaLagCorrectionImageFilter.hcu\"\n\nnamespace rtk\n{\n\nCudaLagCorrectionImageFilter ::CudaLagCorrectionImageFilter() {}\n\nCudaLagCorrectionImageFilter ::~CudaLagCorrectionImageFilter() {}\n\nvoid\nCudaLagCorrectionImageFilter ::GPUGenerateData()\n{\n  // compute overlap region by cropping output region with input buffer\n  OutputImageRegionType overlapRegion = this->GetOutput()->GetRequestedRegion();\n  // overlapRegion.Crop(this->GetInput()->GetBufferedRegion());\n\n  // Put the two data pointers at the same location\n#ifdef CudaCommon_VERSION_MAJOR\n  unsigned short * inBuffer =\n    static_cast<unsigned short *>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  unsigned short * inBuffer =\n    *static_cast<unsigned short **>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  inBuffer += this->GetInput()->ComputeOffset(overlapRegion.GetIndex());\n#ifdef CudaCommon_VERSION_MAJOR\n  unsigned short * outBuffer =\n    static_cast<unsigned short *>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  unsigned short * outBuffer =\n    *static_cast<unsigned short **>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  outBuffer += this->GetOutput()->ComputeOffset(this->GetOutput()->GetRequestedRegion().GetIndex());\n\n  int proj_idx_in[3];\n  proj_idx_in[0] = overlapRegion.GetIndex()[0];\n  proj_idx_in[1] = overlapRegion.GetIndex()[1];\n  proj_idx_in[2] = overlapRegion.GetIndex()[2];\n\n  int proj_size_in_buf[2];\n  proj_size_in_buf[0] = this->GetInput()->GetBufferedRegion().GetSize()[0];\n  proj_size_in_buf[1] = this->GetInput()->GetBufferedRegion().GetSize()[1];\n\n  int proj_size_in[3];\n  proj_size_in[0] = overlapRegion.GetSize()[0];\n  proj_size_in[1] = overlapRegion.GetSize()[1];\n  proj_size_in[2] = overlapRegion.GetSize()[2];\n\n  int proj_idx_out[3];\n  proj_idx_out[0] = this->GetOutput()->GetRequestedRegion().GetIndex()[0];\n  proj_idx_out[1] = this->GetOutput()->GetRequestedRegion().GetIndex()[1];\n  proj_idx_out[2] = this->GetOutput()->GetRequestedRegion().GetIndex()[2];\n\n  int proj_size_out_buf[2];\n  proj_size_out_buf[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  proj_size_out_buf[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n\n  int proj_size_out[3];\n  proj_size_out[0] = this->GetOutput()->GetRequestedRegion().GetSize()[0];\n  proj_size_out[1] = this->GetOutput()->GetRequestedRegion().GetSize()[1];\n  proj_size_out[2] = this->GetOutput()->GetRequestedRegion().GetSize()[2];\n\n  float coefficients[9] = { m_B[0], m_B[1], m_B[2], m_B[3], m_ExpmA[0], m_ExpmA[1], m_ExpmA[2], m_ExpmA[3], m_SumB };\n\n  size_t S_size = sizeof(float) * m_S.size();\n  CUDA_lag_correction(proj_idx_in,\n                      proj_size_in,\n                      proj_size_in_buf,\n                      proj_idx_out,\n                      proj_size_out,\n                      proj_size_out_buf,\n                      inBuffer,\n                      outBuffer,\n                      &m_S[0],\n                      S_size,\n                      coefficients);\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkCudaLaplacianImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaLaplacianImageFilter.hcu\"\n#include \"rtkCudaFirstOrderKernels.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n\nvoid\nCUDA_laplacian(int size[3], float spacing[3], float * dev_in, float * dev_out)\n{\n  int3   dev_Size = make_int3(size[0], size[1], size[2]);\n  float3 dev_Spacing = make_float3(spacing[0], spacing[1], spacing[2]);\n\n  // Reset output volume\n  size_t memorySizeOutput = sizeof(float) * size[0] * size[1] * size[2];\n  cudaMemset((void *)dev_out, 0, memorySizeOutput);\n\n  // Initialize volumes to store the gradient components\n  float * dev_grad_x;\n  float * dev_grad_y;\n  float * dev_grad_z;\n  cudaMalloc((void **)&dev_grad_x, memorySizeOutput);\n  cudaMalloc((void **)&dev_grad_y, memorySizeOutput);\n  cudaMalloc((void **)&dev_grad_z, memorySizeOutput);\n  cudaMemset(dev_grad_x, 0, memorySizeOutput);\n  cudaMemset(dev_grad_y, 0, memorySizeOutput);\n  cudaMemset(dev_grad_z, 0, memorySizeOutput);\n\n  // Thread Block Dimensions\n  dim3 dimBlock = dim3(16, 4, 4);\n\n  int blocksInX = iDivUp(size[0], dimBlock.x);\n  int blocksInY = iDivUp(size[1], dimBlock.y);\n  int blocksInZ = iDivUp(size[2], dimBlock.z);\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n\n  gradient_kernel<<<dimGrid, dimBlock>>>(dev_in, dev_grad_x, dev_grad_y, dev_grad_z, dev_Size, dev_Spacing);\n  CUDA_CHECK_ERROR;\n\n  divergence_kernel<<<dimGrid, dimBlock>>>(dev_grad_x, dev_grad_y, dev_grad_z, dev_out, dev_Size, dev_Spacing);\n  CUDA_CHECK_ERROR;\n\n  // Cleanup\n  cudaFree(dev_grad_x);\n  cudaFree(dev_grad_y);\n  cudaFree(dev_grad_z);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaLaplacianImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaLaplacianImageFilter.h\"\n#include \"rtkCudaLaplacianImageFilter.hcu\"\n\n#include <itkMacro.h>\n\nrtk::CudaLaplacianImageFilter ::CudaLaplacianImageFilter() {}\n\nvoid\nrtk::CudaLaplacianImageFilter ::GPUGenerateData()\n{\n  int   inputSize[3];\n  int   outputSize[3];\n  float inputSpacing[3];\n  float outputSpacing[3];\n\n  for (int i = 0; i < 3; i++)\n  {\n    inputSize[i] = this->GetInput()->GetBufferedRegion().GetSize()[i];\n    outputSize[i] = this->GetOutput()->GetBufferedRegion().GetSize()[i];\n    inputSpacing[i] = this->GetInput()->GetSpacing()[i];\n    outputSpacing[i] = this->GetOutput()->GetSpacing()[i];\n\n    if ((inputSize[i] != outputSize[i]) || (inputSpacing[i] != outputSpacing[i]))\n    {\n      std::cerr << \"The CUDA laplacian filter can only handle input and output regions of equal size and spacing\"\n                << std::endl;\n      exit(1);\n    }\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_laplacian(inputSize, inputSpacing, pin, pout);\n}\n"
  },
  {
    "path": "src/rtkCudaLastDimensionTVDenoisingImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaLastDimensionTVDenoisingImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n\n// TEXTURES AND CONSTANTS //\n\n__constant__ int4 c_Size;\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n__global__ void\ndenoise_oneD_TV_kernel(float * in, float * out, float beta, float gamma, int niter)\n{\n  // Allocate a few shared buffers\n  extern __shared__ float shared[];\n  float *                 input = &shared[0];\n  float *                 interm = &shared[c_Size.w];\n  float *                 output = &shared[2 * c_Size.w];\n  float *                 gradient = &shared[3 * c_Size.w];\n\n  // Each thread reads one element into the shared buffer\n  long int gindex = ((threadIdx.x * c_Size.z + blockIdx.z) * c_Size.y + blockIdx.y) * c_Size.x + blockIdx.x;\n  int      lindex = threadIdx.x;\n  input[lindex] = in[gindex];\n  __syncthreads();\n\n  ///////////////////////////////////////////////////\n  // Perform complete 1D TV denoising on the buffer\n  // with circular padding border conditions\n\n  // Multiply by beta\n  interm[lindex] = beta * input[lindex];\n\n  // Compute gradient\n  __syncthreads();\n  if (lindex == (c_Size.w - 1))\n    gradient[lindex] = interm[0] - interm[lindex];\n  else\n    gradient[lindex] = interm[lindex + 1] - interm[lindex];\n\n  // Magnitude threshold (in 1D, hard threshold on absolute value)\n  if (gradient[lindex] >= 0)\n    gradient[lindex] = fminf(gradient[lindex], gamma);\n  else\n    gradient[lindex] = fmaxf(gradient[lindex], -gamma);\n\n  // Rest of the iterations\n  for (int iter = 0; iter < niter; iter++)\n  {\n    // Compute divergence\n    __syncthreads();\n    if (lindex == 0)\n      interm[lindex] = gradient[lindex] - gradient[c_Size.w - 1];\n    else\n      interm[lindex] = gradient[lindex] - gradient[lindex - 1];\n\n    // Subtract and store in output buffer\n    __syncthreads();\n    output[lindex] = input[lindex] - interm[lindex];\n\n    // Multiply by beta\n    __syncthreads();\n    interm[lindex] = output[lindex] * beta;\n\n    // Compute gradient\n    __syncthreads();\n    if (lindex == (c_Size.w - 1))\n      gradient[lindex] -= (interm[0] - interm[lindex]);\n    else\n      gradient[lindex] -= (interm[lindex + 1] - interm[lindex]);\n\n    // Magnitude threshold\n    __syncthreads();\n    if (gradient[lindex] >= 0)\n      gradient[lindex] = fminf(gradient[lindex], gamma);\n    else\n      gradient[lindex] = fmaxf(gradient[lindex], -gamma);\n  }\n  // Done computing 1D TV for this buffer\n  ////////////////////////////////////////////////////////\n\n  // Each thread writes one element from the shared buffer into the global memory\n  out[gindex] = output[lindex];\n  //  out[gindex] = gindex;\n}\n\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\nvoid\nCUDA_total_variation_last_dimension(int     size[4],\n                                    float * dev_in,\n                                    float * dev_out,\n                                    float   gamma,\n                                    float   beta,\n                                    int     NumberOfIterations)\n{\n  int4 dev_Size = make_int4(size[0], size[1], size[2], size[3]);\n  cudaMemcpyToSymbol(c_Size, &dev_Size, sizeof(int4));\n\n  // Thread Block Dimensions\n  // Create one thread block per voxel of the 3D volume.\n  // Each thread block handles a single 1D temporal vector\n  dim3 dimBlock = dim3(size[3], 1, 1);\n\n  int blocksInX = size[0];\n  int blocksInY = size[1];\n  int blocksInZ = size[2];\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n\n  // Dynamic allocation of shared memory\n  denoise_oneD_TV_kernel<<<dimGrid, dimBlock, 4 * sizeof(float) * size[3]>>>(\n    dev_in, dev_out, beta, gamma, NumberOfIterations);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaLastDimensionTVDenoisingImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaLastDimensionTVDenoisingImageFilter.h\"\n#include \"rtkCudaLastDimensionTVDenoisingImageFilter.hcu\"\n\n#include <itkMacro.h>\n\nrtk::CudaLastDimensionTVDenoisingImageFilter ::CudaLastDimensionTVDenoisingImageFilter() { this->SetInPlace(true); }\n\nvoid\nrtk::CudaLastDimensionTVDenoisingImageFilter ::GPUGenerateData()\n{\n  // Allocate the output image\n  this->AllocateOutputs();\n\n  int inputSize[4];\n  int outputSize[4];\n\n  //   std::cout << \"PRINTING INPUT\" << std::endl;\n  //   this->GetInput()->Print(std::cout);\n  //   std::cout << \"PRINTING OUTPUT\" << std::endl;\n  //   this->GetOutput()->Print(std::cout);\n\n  for (int i = 0; i < 4; i++)\n  {\n    inputSize[i] = this->GetInput()->GetBufferedRegion().GetSize()[i];\n    outputSize[i] = this->GetOutput()->GetBufferedRegion().GetSize()[i];\n\n    if (inputSize[i] != outputSize[i])\n    {\n\n      itkGenericExceptionMacro(<< \"The CUDA Last Dimension Total Variation Denoising filter can only handle input and \"\n                                  \"output regions of equal size\");\n    }\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_total_variation_last_dimension(\n    inputSize, pin, pout, static_cast<float>(m_Gamma), static_cast<float>(m_Beta), m_NumberOfIterations);\n}\n"
  },
  {
    "path": "src/rtkCudaParkerShortScanImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaParkerShortScanImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math_constants.h>\n\ninline __device__ float\nTransformIndexToPhysicalPoint(int2 idx, float origin, float row, float column)\n{\n  return origin + row * idx.x + column * idx.y;\n}\n\ninline __device__ float\nToUntiltedCoordinateAtIsocenter(float tiltedCoord, float sdd, float sid, float sx, float px, float sidu)\n{\n  // sidu is the distance between the source and the virtual untilted detector\n  // l is the coordinate on the virtual detector parallel to the real detector\n  // and passing at the isocenter\n  const float l = (tiltedCoord + px - sx) * sid / sdd + sx;\n  // a is the angle between the virtual detector and the real detector\n  const float cosa = sx / sidu;\n  // the following relation refers to a note by R. Clackdoyle, title\n  // \"Samping a tilted detector\"\n  return l * sid / (sidu - l * cosa);\n}\n\n__global__ void\nkernel_parker_weight(int2                proj_idx,\n                     int3                proj_size,\n                     int2                proj_size_buf_in,\n                     int2                proj_size_buf_out,\n                     float *             dev_proj_in,\n                     float *             dev_proj_out,\n                     float               delta,\n                     float               firstAngle,\n                     float               proj_orig, // projection origin\n                     float               proj_row,  // projection row direction & spacing\n                     float               proj_col,  // projection col direction & spacing\n                     cudaTextureObject_t tex_geom   // geometry texture object\n)\n{\n  // compute projection index (== thread index)\n  int3 pIdx;\n  pIdx.x = blockIdx.x * blockDim.x + threadIdx.x;\n  pIdx.y = blockIdx.y * blockDim.y + threadIdx.y;\n  pIdx.z = blockIdx.z * blockDim.z + threadIdx.z;\n  long int pIdx_comp_in = pIdx.x + (pIdx.y + pIdx.z * proj_size_buf_in.y) * (proj_size_buf_in.x);\n  long int pIdx_comp_out = pIdx.x + (pIdx.y + pIdx.z * proj_size_buf_out.y) * (proj_size_buf_out.x);\n\n  // check if outside of projection grid\n  if (pIdx.x >= proj_size.x || pIdx.y >= proj_size.y || pIdx.z >= proj_size.z)\n    return;\n\n  float sdd = tex1Dfetch<float>(tex_geom, pIdx.z * 5 + 0);\n  float sx = tex1Dfetch<float>(tex_geom, pIdx.z * 5 + 1);\n  float px = tex1Dfetch<float>(tex_geom, pIdx.z * 5 + 2);\n  float sid = tex1Dfetch<float>(tex_geom, pIdx.z * 5 + 3);\n\n  // convert actual index to point\n  float pPoint =\n    TransformIndexToPhysicalPoint(make_int2(pIdx.x + proj_idx.x, pIdx.y + proj_idx.y), proj_orig, proj_row, proj_col);\n\n  // alpha projection angle\n  float hyp = sqrtf(sid * sid + sx * sx); // to untilted situation\n  float invsid = 1.f / hyp;\n  float l = ToUntiltedCoordinateAtIsocenter(pPoint, sdd, sid, sx, px, hyp);\n  float alpha = atan(-1 * l * invsid);\n\n  // beta projection angle: Parker's article assumes that the scan starts at 0\n  float beta = tex1Dfetch<float>(tex_geom, pIdx.z * 5 + 4);\n  beta -= firstAngle;\n  if (beta < 0)\n    beta += (2.f * CUDART_PI_F);\n\n  // compute weight\n  float weight = 0.;\n  if (beta <= (2 * delta - 2 * alpha))\n    weight = 2.f * powf(sinf((CUDART_PI_F * beta) / (4 * (delta - alpha))), 2.f);\n  else if (beta <= (CUDART_PI_F - 2 * alpha))\n    weight = 2.f;\n  else if (beta <= (CUDART_PI_F + 2 * delta))\n    weight = 2.f * powf(sinf((CUDART_PI_F * (CUDART_PI_F + 2 * delta - beta)) / (4 * (delta + alpha))), 2.f);\n\n  // compute outpout by multiplying with weight\n  dev_proj_out[pIdx_comp_out] = dev_proj_in[pIdx_comp_in] * weight;\n}\n\nvoid\nCUDA_parker_weight(int     proj_idx[2],\n                   int     proj_dim[3],\n                   int     proj_dim_buf_in[2],\n                   int     proj_dim_buf_out[2],\n                   float * dev_proj_in,\n                   float * dev_proj_out,\n                   float * geometry,\n                   float   delta,\n                   float   firstAngle,\n                   float   proj_orig,\n                   float   proj_row,\n                   float   proj_col)\n{\n  float *             dev_geom;\n  cudaTextureObject_t tex_geom;\n  prepareGeometryTextureObject(proj_dim[2], geometry, dev_geom, tex_geom, 5);\n\n  // Thread Block Dimensions\n  int tBlock_x = 16;\n  int tBlock_y = 16;\n  int tBlock_z = 2;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (proj_dim[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (proj_dim[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (proj_dim[2] - 1) / tBlock_z + 1;\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n\n  kernel_parker_weight<<<dimGrid, dimBlock>>>(make_int2(proj_idx[0], proj_idx[1]),\n                                              make_int3(proj_dim[0], proj_dim[1], proj_dim[2]),\n                                              make_int2(proj_dim_buf_in[0], proj_dim_buf_in[1]),\n                                              make_int2(proj_dim_buf_out[0], proj_dim_buf_out[1]),\n                                              dev_proj_in,\n                                              dev_proj_out,\n                                              delta,\n                                              firstAngle,\n                                              proj_orig,\n                                              proj_row,\n                                              proj_col,\n                                              tex_geom);\n\n  // destroy texture object\n  cudaDestroyTextureObject(tex_geom);\n  CUDA_CHECK_ERROR;\n  cudaFree(dev_geom);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaParkerShortScanImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaParkerShortScanImageFilter.h\"\n#include \"rtkCudaParkerShortScanImageFilter.hcu\"\n\nnamespace rtk\n{\n\nCudaParkerShortScanImageFilter ::CudaParkerShortScanImageFilter() {}\n\nCudaParkerShortScanImageFilter ::~CudaParkerShortScanImageFilter() {}\n\nvoid\nCudaParkerShortScanImageFilter ::GPUGenerateData()\n{\n  // Put the two data pointers at the same location\n#ifdef CudaCommon_VERSION_MAJOR\n  float * inBuffer = static_cast<float *>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * inBuffer = *static_cast<float **>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  inBuffer += this->GetInput()->ComputeOffset(this->GetInput()->GetRequestedRegion().GetIndex());\n#ifdef CudaCommon_VERSION_MAJOR\n  float * outBuffer = static_cast<float *>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * outBuffer = *static_cast<float **>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  outBuffer += this->GetOutput()->ComputeOffset(this->GetOutput()->GetRequestedRegion().GetIndex());\n\n  if (!m_IsShortScan)\n  {\n    if (outBuffer != inBuffer)\n    {\n      size_t count = this->GetOutput()->GetRequestedRegion().GetSize(0);\n      count *= sizeof(ImageType::PixelType);\n      for (unsigned int k = 0; k < this->GetOutput()->GetRequestedRegion().GetSize(2); k++)\n      {\n        for (unsigned int j = 0; j < this->GetOutput()->GetRequestedRegion().GetSize(1); j++)\n        {\n          cudaMemcpy(outBuffer, inBuffer, count, cudaMemcpyDeviceToDevice);\n          inBuffer += this->GetInput()->GetBufferedRegion().GetSize(0);\n          outBuffer += this->GetOutput()->GetBufferedRegion().GetSize(0);\n        }\n        inBuffer +=\n          (this->GetInput()->GetBufferedRegion().GetSize(1) - this->GetInput()->GetRequestedRegion().GetSize(1)) *\n          this->GetInput()->GetBufferedRegion().GetSize(0);\n        outBuffer +=\n          (this->GetOutput()->GetBufferedRegion().GetSize(1) - this->GetOutput()->GetRequestedRegion().GetSize(1)) *\n          this->GetOutput()->GetBufferedRegion().GetSize(0);\n      }\n    }\n    return;\n  }\n\n  // check for enough data\n  float proj_orig = this->GetInput()->GetOrigin()[0];\n\n  float proj_row = this->GetInput()->GetDirection()[0][0] * this->GetInput()->GetSpacing()[0];\n\n  float proj_col = this->GetInput()->GetDirection()[0][1] * this->GetInput()->GetSpacing()[1];\n\n  int proj_idx[2];\n  proj_idx[0] = this->GetInput()->GetRequestedRegion().GetIndex()[0];\n  proj_idx[1] = this->GetInput()->GetRequestedRegion().GetIndex()[1];\n\n  int proj_size[3];\n  proj_size[0] = this->GetInput()->GetRequestedRegion().GetSize()[0];\n  proj_size[1] = this->GetInput()->GetRequestedRegion().GetSize()[1];\n  proj_size[2] = this->GetInput()->GetRequestedRegion().GetSize()[2];\n\n  int proj_size_buf_in[2];\n  proj_size_buf_in[0] = this->GetInput()->GetBufferedRegion().GetSize()[0];\n  proj_size_buf_in[1] = this->GetInput()->GetBufferedRegion().GetSize()[1];\n\n  int proj_size_buf_out[2];\n  proj_size_buf_out[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  proj_size_buf_out[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n\n  // 2D matrix (numgeom * 3values) in one block for memcpy!\n  // for each geometry, the following structure is used:\n  // 0: sdd\n  // 1: projection offset x\n  // 2: gantry angle\n  int     geomIdx = this->GetInput()->GetRequestedRegion().GetIndex()[2];\n  float * geomMatrix = new float[proj_size[2] * 5];\n  if (geomMatrix == nullptr)\n    itkExceptionMacro(<< \"Couldn't allocate geomMatrix\");\n  for (int g = 0; g < proj_size[2]; ++g)\n  {\n    geomMatrix[g * 5 + 0] = this->GetGeometry()->GetSourceToDetectorDistances()[g + geomIdx];\n    geomMatrix[g * 5 + 1] = this->GetGeometry()->GetSourceOffsetsX()[g + geomIdx];\n    geomMatrix[g * 5 + 2] = this->GetGeometry()->GetProjectionOffsetsX()[g + geomIdx];\n    geomMatrix[g * 5 + 3] = this->GetGeometry()->GetSourceToIsocenterDistances()[g + geomIdx];\n    geomMatrix[g * 5 + 4] = this->GetGeometry()->GetGantryAngles()[g + geomIdx];\n  }\n\n  CUDA_parker_weight(proj_idx,\n                     proj_size,\n                     proj_size_buf_in,\n                     proj_size_buf_out,\n                     inBuffer,\n                     outBuffer,\n                     geomMatrix,\n                     m_Delta,\n                     m_FirstAngle,\n                     proj_orig,\n                     proj_row,\n                     proj_col);\n\n  delete[] geomMatrix;\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkCudaPolynomialGainCorrectionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaPolynomialGainCorrectionImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n#include <cuda.h>\n#include <cuda_runtime.h>\n#include <math_constants.h>\n\n__constant__ float cst_coef[2];\n\n__global__ void\nkernel_gain_correction(int3             proj_idx_in,\n                       int3             proj_size_in,\n                       int2             proj_size_in_buf,\n                       int3             proj_idx_out,\n                       int3             proj_size_out,\n                       int2             proj_size_out_buf,\n                       unsigned short * dev_proj_in,\n                       float *          dev_proj_out,\n                       unsigned short * dev_dark_in,\n                       float *          dev_gain_in,\n                       float *          powerlut)\n{\n  // compute thread index\n  int3 tIdx;\n  tIdx.x = blockIdx.x * blockDim.x + threadIdx.x;\n  tIdx.y = blockIdx.y * blockDim.y + threadIdx.y;\n  tIdx.z = blockIdx.z * blockDim.z + threadIdx.z;\n  long int tIdx_comp = tIdx.x + tIdx.y * proj_size_out.x + tIdx.z * proj_size_out_buf.x * proj_size_out_buf.y;\n\n  // check if outside of projection grid\n  if (tIdx.x >= proj_size_out.x || tIdx.y >= proj_size_out.y || tIdx.z >= proj_size_out.z)\n    return;\n\n  // compute projection index from thread index\n  int3 pIdx = make_int3(tIdx.x + proj_idx_out.x, tIdx.y + proj_idx_out.y, tIdx.z + proj_idx_out.z);\n  // combined proj. index -> use thread index in z because accessing memory only with this index\n  long int pIdx_comp = (pIdx.x - proj_idx_in.x) + (pIdx.y - proj_idx_in.y) * proj_size_in_buf.x +\n                       (pIdx.z - proj_idx_in.z) * proj_size_in_buf.x * proj_size_in_buf.y;\n\n  int modelOrder = static_cast<float>(cst_coef[0]);\n\n  long int sIdx_comp = tIdx.x + tIdx.y * proj_size_out.x; // in-slice index\n\n  // Correct for dark field\n  unsigned short xk = 0;\n  if (dev_proj_in[pIdx_comp] > dev_dark_in[sIdx_comp])\n    xk = dev_proj_in[pIdx_comp] - dev_dark_in[sIdx_comp];\n\n  float yk = 0.f;\n  int   lutidx = xk * modelOrder; // index to powerlut\n  int   projsize = proj_size_in.x * proj_size_in.y;\n  for (int n = 0; n < modelOrder; n++)\n  {\n    int   gainidx = n * projsize + sIdx_comp;\n    float gainM = dev_gain_in[gainidx];\n    yk += gainM * powerlut[lutidx + n];\n  }\n\n  // Apply normalization factor\n  yk = yk * cst_coef[1];\n\n  // Avoid negative values\n  yk = (yk < 0.0f) ? 0.f : yk;\n\n  dev_proj_out[tIdx_comp] = yk;\n}\n\nvoid\nCUDA_gain_correction(int              proj_idx_in[3],      // overlapping input region index\n                     int              proj_dim_in[3],      // overlapping input region size\n                     int              proj_dim_in_buf[2],  // input size of buffered region\n                     int              proj_idx_out[3],     // output region index\n                     int              proj_dim_out[3],     // output region size\n                     int              proj_dim_out_buf[2], // output size of buffered region\n                     unsigned short * dev_proj_in,\n                     float *          dev_proj_out,\n                     unsigned short * dev_dark_in,\n                     float *          dev_gain_in,\n                     float *          h_powerlut,\n                     size_t           lut_size,\n                     float *          coefficients)\n{\n  // Thread Block Dimensions\n  int tBlock_x = 16;\n  int tBlock_y = 16;\n  int tBlock_z = 2;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (proj_dim_out[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (proj_dim_out[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (proj_dim_out[2] - 1) / tBlock_z + 1;\n\n  float * d_powerlut; // device state\n  cudaMalloc((void **)&d_powerlut, lut_size);\n  if (cudaMemcpy(d_powerlut, h_powerlut, lut_size, cudaMemcpyHostToDevice) != cudaSuccess)\n  {\n    itkGenericExceptionMacro(\"Error allocating state\");\n  }\n\n  cudaMemcpyToSymbol(cst_coef, coefficients, 2 * sizeof(float));\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n  kernel_gain_correction<<<dimGrid, dimBlock>>>(make_int3(proj_idx_in[0], proj_idx_in[1], proj_idx_in[2]),\n                                                make_int3(proj_dim_in[0], proj_dim_in[1], proj_dim_in[2]),\n                                                make_int2(proj_dim_in_buf[0], proj_dim_in_buf[1]),\n                                                make_int3(proj_idx_out[0], proj_idx_out[1], proj_idx_out[2]),\n                                                make_int3(proj_dim_out[0], proj_dim_out[1], proj_dim_out[2]),\n                                                make_int2(proj_dim_out_buf[0], proj_dim_out_buf[1]),\n                                                dev_proj_in,\n                                                dev_proj_out,\n                                                dev_dark_in,\n                                                dev_gain_in,\n                                                d_powerlut);\n\n  cudaFree(d_powerlut);\n\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaPolynomialGainCorrectionImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaPolynomialGainCorrectionImageFilter.h\"\n#include \"rtkCudaPolynomialGainCorrectionImageFilter.hcu\"\n\nnamespace rtk\n{\n\nCudaPolynomialGainCorrectionImageFilter ::CudaPolynomialGainCorrectionImageFilter() {}\n\nCudaPolynomialGainCorrectionImageFilter ::~CudaPolynomialGainCorrectionImageFilter() {}\n\nvoid\nCudaPolynomialGainCorrectionImageFilter ::GPUGenerateData()\n{\n  // compute overlap region by cropping output region with input buffer\n  OutputImageRegionType overlapRegion = this->GetOutput()->GetRequestedRegion();\n\n  // Put the two data pointers at the same location\n#ifdef CudaCommon_VERSION_MAJOR\n  unsigned short * inBuffer =\n    static_cast<unsigned short *>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  unsigned short * inBuffer =\n    *static_cast<unsigned short **>(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  inBuffer += this->GetInput()->ComputeOffset(overlapRegion.GetIndex());\n#ifdef CudaCommon_VERSION_MAJOR\n  float * outBuffer = static_cast<float *>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * outBuffer = *static_cast<float **>(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n  outBuffer += this->GetOutput()->ComputeOffset(this->GetOutput()->GetRequestedRegion().GetIndex());\n\n#ifdef CudaCommon_VERSION_MAJOR\n  unsigned short * darkBuffer = static_cast<unsigned short *>(m_DarkImage->GetCudaDataManager()->GetGPUBufferPointer());\n\n  float * gainBuffer = static_cast<float *>(m_GainImage->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  unsigned short * darkBuffer =\n    *static_cast<unsigned short **>(m_DarkImage->GetCudaDataManager()->GetGPUBufferPointer());\n\n  float * gainBuffer = *static_cast<float **>(m_GainImage->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  int proj_idx_in[3];\n  proj_idx_in[0] = overlapRegion.GetIndex()[0];\n  proj_idx_in[1] = overlapRegion.GetIndex()[1];\n  proj_idx_in[2] = overlapRegion.GetIndex()[2];\n\n  int proj_size_in_buf[2];\n  proj_size_in_buf[0] = this->GetInput()->GetBufferedRegion().GetSize()[0];\n  proj_size_in_buf[1] = this->GetInput()->GetBufferedRegion().GetSize()[1];\n\n  int proj_size_in[3];\n  proj_size_in[0] = overlapRegion.GetSize()[0];\n  proj_size_in[1] = overlapRegion.GetSize()[1];\n  proj_size_in[2] = overlapRegion.GetSize()[2];\n\n  int proj_idx_out[3];\n  proj_idx_out[0] = this->GetOutput()->GetRequestedRegion().GetIndex()[0];\n  proj_idx_out[1] = this->GetOutput()->GetRequestedRegion().GetIndex()[1];\n  proj_idx_out[2] = this->GetOutput()->GetRequestedRegion().GetIndex()[2];\n\n  int proj_size_out_buf[2];\n  proj_size_out_buf[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  proj_size_out_buf[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n\n  int proj_size_out[3];\n  proj_size_out[0] = this->GetOutput()->GetRequestedRegion().GetSize()[0];\n  proj_size_out[1] = this->GetOutput()->GetRequestedRegion().GetSize()[1];\n  proj_size_out[2] = this->GetOutput()->GetRequestedRegion().GetSize()[2];\n\n  float coefficients[2] = { static_cast<float>(m_VModelOrder), m_K };\n\n  size_t LUT_size = sizeof(float) * m_PowerLut.size();\n  CUDA_gain_correction(proj_idx_in,\n                       proj_size_in,\n                       proj_size_in_buf,\n                       proj_idx_out,\n                       proj_size_out,\n                       proj_size_out_buf,\n                       inBuffer,\n                       outBuffer,\n                       darkBuffer,\n                       gainBuffer,\n                       &m_PowerLut[0],\n                       LUT_size,\n                       coefficients);\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkCudaRayCastBackProjectionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaIntersectBox.hcu\"\n#include \"rtkCudaRayCastBackProjectionImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n\n// TEXTURES AND CONSTANTS //\n\n__constant__ int3   c_projSize;\n__constant__ float3 c_boxMin;\n__constant__ float3 c_boxMax;\n__constant__ float3 c_spacing;\n__constant__ int3   c_volSize;\n__constant__ float  c_tStep;\n__constant__ float  c_radius;\n__constant__ float\n  c_translatedProjectionIndexTransformMatrices[SLAB_SIZE * 12]; // Can process stacks of at most SLAB_SIZE projections\n__constant__ float\n  c_translatedVolumeTransformMatrices[SLAB_SIZE * 12]; // Can process stacks of at most SLAB_SIZE projections\n__constant__ float c_sourcePos[SLAB_SIZE * 3];         // Can process stacks of at most SLAB_SIZE projections\n__constant__ bool  c_normalize;\n\n//__constant__ float3 spacingSquare;  // inverse view matrix\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n__device__ void\nsplat3D_getWeightsAndIndices(float3 pos, int3 floor_pos, int3 volSize, float * weights, long int * indices)\n{\n  // Compute the weights\n  float3 Distance;\n  Distance.x = pos.x - floor_pos.x;\n  Distance.y = pos.y - floor_pos.y;\n  Distance.z = pos.z - floor_pos.z;\n\n  weights[0] = (1 - Distance.x) * (1 - Distance.y) * (1 - Distance.z); // weight000\n  weights[1] = (1 - Distance.x) * (1 - Distance.y) * Distance.z;       // weight001\n  weights[2] = (1 - Distance.x) * Distance.y * (1 - Distance.z);       // weight010\n  weights[3] = (1 - Distance.x) * Distance.y * Distance.z;             // weight011\n  weights[4] = Distance.x * (1 - Distance.y) * (1 - Distance.z);       // weight100\n  weights[5] = Distance.x * (1 - Distance.y) * Distance.z;             // weight101\n  weights[6] = Distance.x * Distance.y * (1 - Distance.z);             // weight110\n  weights[7] = Distance.x * Distance.y * Distance.z;                   // weight111\n\n  // Compute positions of sampling, taking into account the clamping\n  int3 pos_low;\n  pos_low.x = max(floor_pos.x, 0);\n  pos_low.y = max(floor_pos.y, 0);\n  pos_low.z = max(floor_pos.z, 0);\n\n  int3 pos_high;\n  pos_high.x = min(floor_pos.x + 1, volSize.x - 1);\n  pos_high.y = min(floor_pos.y + 1, volSize.y - 1);\n  pos_high.z = min(floor_pos.z + 1, volSize.z - 1);\n\n  // Compute indices in the volume\n  indices[0] = pos_low.x + pos_low.y * volSize.x + pos_low.z * volSize.x * volSize.y;    // index000\n  indices[1] = pos_low.x + pos_low.y * volSize.x + pos_high.z * volSize.x * volSize.y;   // index001\n  indices[2] = pos_low.x + pos_high.y * volSize.x + pos_low.z * volSize.x * volSize.y;   // index010\n  indices[3] = pos_low.x + pos_high.y * volSize.x + pos_high.z * volSize.x * volSize.y;  // index011\n  indices[4] = pos_high.x + pos_low.y * volSize.x + pos_low.z * volSize.x * volSize.y;   // index100\n  indices[5] = pos_high.x + pos_low.y * volSize.x + pos_high.z * volSize.x * volSize.y;  // index101\n  indices[6] = pos_high.x + pos_high.y * volSize.x + pos_low.z * volSize.x * volSize.y;  // index110\n  indices[7] = pos_high.x + pos_high.y * volSize.x + pos_high.z * volSize.x * volSize.y; // index111\n}\n\n__device__ void\nsplat3D(float      toSplat,\n        float *    dev_accumulate_values,\n        float *    dev_accumulate_weights,\n        float *    weights,\n        long int * indices)\n{\n  // Perform splat\n  for (unsigned int i = 0; i < 8; i++)\n  {\n    atomicAdd(&dev_accumulate_values[indices[i]], toSplat * weights[i]);\n    atomicAdd(&dev_accumulate_weights[indices[i]], weights[i]);\n  }\n}\n\n\n// KERNEL normalize\n__global__ void\nkernel_normalize_and_add_to_output(float * dev_vol_in,\n                                   float * dev_vol_out,\n                                   float * dev_accumulate_weights,\n                                   float * dev_accumulate_values)\n{\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= c_volSize.x || j >= c_volSize.y || k >= c_volSize.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  long int out_idx = i + (j + k * c_volSize.y) * (c_volSize.x);\n\n  float eps = 1e-6;\n\n  // Divide the output volume's voxels by the accumulated splat weights\n  //   unless the accumulated splat weights are equal to zero\n  if (c_normalize)\n  {\n    if (abs(dev_accumulate_weights[out_idx]) > eps)\n      dev_vol_out[out_idx] = dev_vol_in[out_idx] + (dev_accumulate_values[out_idx] / dev_accumulate_weights[out_idx]);\n    else\n      dev_vol_out[out_idx] = dev_vol_in[out_idx];\n  }\n  else\n    dev_vol_out[out_idx] = dev_vol_in[out_idx] + dev_accumulate_values[out_idx];\n}\n\n// KERNEL kernel_ray_cast_back_project\n__global__ void\nkernel_ray_cast_back_project(float * dev_accumulate_values, float * dev_proj, float * dev_accumulate_weights)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int numThread = j * c_projSize.x + i;\n  unsigned int proj = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_projSize.x || j >= c_projSize.y || proj >= c_projSize.z)\n    return;\n\n  // Declare variables used in the loop\n  Ray    ray;\n  float3 pixelPos;\n  float  tnear, tfar;\n\n  // Setting ray origin\n  ray.o = make_float3(c_sourcePos[3 * proj], c_sourcePos[3 * proj + 1], c_sourcePos[3 * proj + 2]);\n\n  if (c_radius == 0)\n  {\n    pixelPos = matrix_multiply(make_float3(i, j, 0), &(c_translatedProjectionIndexTransformMatrices[12 * proj]));\n  }\n  else\n  {\n    float3 posProj;\n    posProj = matrix_multiply(make_float3(i, j, 0), &(c_translatedProjectionIndexTransformMatrices[12 * proj]));\n    double a = posProj.x / c_radius;\n    posProj.x = sin(a) * c_radius;\n    posProj.z += (1. - cos(a)) * c_radius;\n    pixelPos = matrix_multiply(posProj, &(c_translatedVolumeTransformMatrices[12 * proj]));\n  }\n\n  ray.d = pixelPos - ray.o;\n  ray.d = ray.d / sqrtf(dot(ray.d, ray.d));\n\n  // Detect intersection with box\n  if (intersectBox(ray, &tnear, &tfar, c_boxMin, c_boxMax) && !(tfar < 0.f))\n  {\n    if (tnear < 0.f)\n      tnear = 0.f; // clamp to near plane\n\n    // Step length in mm\n    float3 dirInMM = c_spacing * ray.d;\n    float  vStep = c_tStep / sqrtf(dot(dirInMM, dirInMM));\n    float3 step = vStep * ray.d;\n\n    // First position in the box\n    float3 pos;\n    float  halfVStep = 0.5f * vStep;\n    tnear = tnear + halfVStep;\n    pos = ray.o + tnear * ray.d;\n\n    float t;\n\n    float    toSplat;\n    long int indices[8];\n    float    weights[8];\n    int3     floor_pos;\n\n    if (tfar - tnear > halfVStep)\n    {\n      for (t = tnear; t <= tfar; t += vStep)\n      {\n        floor_pos.x = floorf(pos.x);\n        floor_pos.y = floorf(pos.y);\n        floor_pos.z = floorf(pos.z);\n\n        // Compute the weights and the voxel indices, taking into account border conditions (here clamping)\n        splat3D_getWeightsAndIndices(pos, floor_pos, c_volSize, weights, indices);\n\n        // Compute the value to be splatted\n        toSplat = dev_proj[numThread + proj * c_projSize.x * c_projSize.y] * c_tStep;\n        splat3D(toSplat, dev_accumulate_values, dev_accumulate_weights, weights, indices);\n\n        // Move to next position\n        pos += step;\n      }\n\n      // Last position\n      toSplat = dev_proj[numThread + proj * c_projSize.x * c_projSize.y] * c_tStep * (tfar - t + halfVStep) / vStep;\n      splat3D(toSplat, dev_accumulate_values, dev_accumulate_weights, weights, indices);\n    }\n  }\n}\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_ray_cast_backproject() //////////////////////////////////\nvoid\nCUDA_ray_cast_back_project(int      projSize[3],\n                           int      volSize[3],\n                           float *  translatedProjectionIndexTransformMatrices,\n                           float *  translatedVolumeTransformMatrices,\n                           float *  dev_vol_in,\n                           float *  dev_vol_out,\n                           float *  dev_proj,\n                           float    t_step,\n                           double * source_positions,\n                           float    radiusCylindricalDetector,\n                           float    box_min[3],\n                           float    box_max[3],\n                           float    spacing[3],\n                           bool     normalize)\n{\n  // Constant memory\n  cudaMemcpyToSymbol(c_projSize, projSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_boxMin, box_min, sizeof(float3));\n  cudaMemcpyToSymbol(c_boxMax, box_max, sizeof(float3));\n  cudaMemcpyToSymbol(c_spacing, spacing, sizeof(float3));\n  cudaMemcpyToSymbol(c_volSize, volSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_tStep, &t_step, sizeof(float));\n  cudaMemcpyToSymbol(c_radius, &radiusCylindricalDetector, sizeof(float));\n  cudaMemcpyToSymbol(c_normalize, &normalize, sizeof(bool));\n\n  // Copy the source position matrix into a float3 in constant memory\n  cudaMemcpyToSymbol(c_sourcePos, &(source_positions[0]), 3 * sizeof(float) * projSize[2]);\n\n  // Copy the projection matrices into constant memory\n  cudaMemcpyToSymbol(c_translatedProjectionIndexTransformMatrices,\n                     &(translatedProjectionIndexTransformMatrices[0]),\n                     12 * sizeof(float) * projSize[2]);\n  cudaMemcpyToSymbol(\n    c_translatedVolumeTransformMatrices, &(translatedVolumeTransformMatrices[0]), 12 * sizeof(float) * projSize[2]);\n\n  // Create an image to store the splatted values\n  // We cannot use the output image, because it may not be zero, in which case\n  // normalization by the splat weights would affect not only the backprojection\n  // of the current projection, but also the initial value of the output\n  float * dev_accumulate_values;\n  size_t  volMemSize = sizeof(float) * volSize[0] * volSize[1] * volSize[2];\n  cudaMalloc((void **)&dev_accumulate_values, volMemSize);\n  cudaMemset((void *)dev_accumulate_values, 0, volMemSize);\n\n  // Create an image to store the splat weights (in order to normalize)\n  float * dev_accumulate_weights;\n  cudaMalloc((void **)&dev_accumulate_weights, volMemSize);\n  cudaMemset((void *)dev_accumulate_weights, 0, volMemSize);\n\n  // Calling kernels\n  dim3 dimBlock = dim3(8, 8, 4);\n  dim3 dimGrid =\n    dim3(iDivUp(projSize[0], dimBlock.x), iDivUp(projSize[1], dimBlock.y), iDivUp(projSize[2], dimBlock.z));\n\n  kernel_ray_cast_back_project<<<dimGrid, dimBlock>>>(dev_accumulate_values, dev_proj, dev_accumulate_weights);\n\n  cudaDeviceSynchronize();\n  CUDA_CHECK_ERROR;\n\n  dim3 dimBlockVol = dim3(16, 4, 4);\n  dim3 dimGridVol =\n    dim3(iDivUp(volSize[0], dimBlockVol.x), iDivUp(volSize[1], dimBlockVol.y), iDivUp(volSize[2], dimBlockVol.z));\n\n  kernel_normalize_and_add_to_output<<<dimGridVol, dimBlockVol>>>(\n    dev_vol_in, dev_vol_out, dev_accumulate_weights, dev_accumulate_values);\n\n  CUDA_CHECK_ERROR;\n\n  // Cleanup\n  cudaFree(dev_accumulate_weights);\n  cudaFree(dev_accumulate_values);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaRayCastBackProjectionImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaRayCastBackProjectionImageFilter.h\"\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaRayCastBackProjectionImageFilter.hcu\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkLinearInterpolateImageFunction.h>\n#include <itkMacro.h>\n\nnamespace rtk\n{\n\nCudaRayCastBackProjectionImageFilter ::CudaRayCastBackProjectionImageFilter()\n  : m_StepSize(1)\n  , m_Normalize(true)\n{}\n\nvoid\nCudaRayCastBackProjectionImageFilter ::GPUGenerateData()\n{\n  if (this->GetGeometry()->GetSourceToDetectorDistances().size() &&\n      this->GetGeometry()->GetSourceToDetectorDistances()[0] == 0)\n  {\n    itkGenericExceptionMacro(<< \"Parallel geometry is not handled by CUDA forward projector.\");\n  }\n\n  const GeometryType * geometry = dynamic_cast<const GeometryType *>(this->GetGeometry());\n  if (!geometry)\n  {\n    itkGenericExceptionMacro(<< \"Error, ThreeDCircularProjectionGeometry expected\");\n  }\n  constexpr unsigned int Dimension = 3;\n  const unsigned int     iFirstProj = this->GetInput(1)->GetRequestedRegion().GetIndex(Dimension - 1);\n  const unsigned int     nProj = this->GetInput(1)->GetRequestedRegion().GetSize(Dimension - 1);\n  const unsigned int     nPixelsPerProj =\n    this->GetInput(1)->GetBufferedRegion().GetSize(0) * this->GetInput(1)->GetBufferedRegion().GetSize(1);\n\n  itk::Vector<double, 4> source_position;\n\n  // Setting BoxMin and BoxMax\n  // SR: we are using cuda textures where the pixel definition is not center but corner.\n  // Therefore, we set the box limits from index to index+size instead of, for ITK,\n  // index-0.5 to index+size-0.5.\n  float boxMin[3];\n  float boxMax[3];\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    boxMin[i] = this->GetInput(0)->GetBufferedRegion().GetIndex()[i] + 0.5;\n    boxMax[i] = boxMin[i] + this->GetInput(0)->GetBufferedRegion().GetSize()[i] - 1.0;\n  }\n\n  // Getting Spacing\n  float spacing[3];\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    spacing[i] = this->GetInput(0)->GetSpacing()[i];\n  }\n\n  // Cuda convenient format for dimensions\n  int projectionSize[3];\n  projectionSize[0] = this->GetInput(1)->GetBufferedRegion().GetSize()[0];\n  projectionSize[1] = this->GetInput(1)->GetBufferedRegion().GetSize()[1];\n\n  int volumeSize[3];\n  volumeSize[0] = this->GetOutput()->GetRequestedRegion().GetSize()[0];\n  volumeSize[1] = this->GetOutput()->GetRequestedRegion().GetSize()[1];\n  volumeSize[2] = this->GetOutput()->GetRequestedRegion().GetSize()[2];\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput(0)->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pproj = (float *)(this->GetInput(1)->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput(0)->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pproj = *(float **)(this->GetInput(1)->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  // Account for system rotations\n  GeometryType::ThreeDHomogeneousMatrixType volPPToIndex;\n  volPPToIndex = GetPhysicalPointToIndexMatrix(this->GetInput(0));\n\n  // Compute matrix to translate the pixel indices on the volume and the detector\n  // if the Requested region has non-zero index\n  GeometryType::ThreeDHomogeneousMatrixType projIndexTranslation, volIndexTranslation;\n  projIndexTranslation.SetIdentity();\n  volIndexTranslation.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    projIndexTranslation[i][3] = this->GetInput(1)->GetBufferedRegion().GetIndex(i);\n    volIndexTranslation[i][3] = -this->GetInput(0)->GetBufferedRegion().GetIndex(i);\n  }\n\n  // Compute matrices to transform projection index to volume index, one per projection\n  float * translatedProjectionIndexTransformMatrices = new float[12 * nProj];\n  float * translatedVolumeTransformMatrices = new float[12 * nProj];\n  float * source_positions = new float[4 * nProj];\n\n  float radiusCylindricalDetector = geometry->GetRadiusCylindricalDetector();\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    GeometryType::ThreeDHomogeneousMatrixType translatedProjectionIndexTransformMatrix;\n    GeometryType::ThreeDHomogeneousMatrixType translatedVolumeTransformMatrix;\n    translatedVolumeTransformMatrix.Fill(0);\n\n    // The matrices required depend on the type of detector\n    if (radiusCylindricalDetector == 0)\n    {\n      translatedProjectionIndexTransformMatrix =\n        volIndexTranslation.GetVnlMatrix() * volPPToIndex.GetVnlMatrix() *\n        geometry->GetProjectionCoordinatesToFixedSystemMatrix(iProj).GetVnlMatrix() *\n        rtk::GetIndexToPhysicalPointMatrix(this->GetInput(1)).GetVnlMatrix() * projIndexTranslation.GetVnlMatrix();\n      for (int j = 0; j < 3; j++) // Ignore the 4th row\n        for (int k = 0; k < 4; k++)\n          translatedProjectionIndexTransformMatrices[(j + 3 * (iProj - iFirstProj)) * 4 + k] =\n            (float)translatedProjectionIndexTransformMatrix[j][k];\n    }\n    else\n    {\n      translatedProjectionIndexTransformMatrix =\n        geometry->GetProjectionCoordinatesToDetectorSystemMatrix(iProj).GetVnlMatrix() *\n        rtk::GetIndexToPhysicalPointMatrix(this->GetInput(1)).GetVnlMatrix() * projIndexTranslation.GetVnlMatrix();\n      for (int j = 0; j < 3; j++) // Ignore the 4th row\n        for (int k = 0; k < 4; k++)\n          translatedProjectionIndexTransformMatrices[(j + 3 * (iProj - iFirstProj)) * 4 + k] =\n            (float)translatedProjectionIndexTransformMatrix[j][k];\n\n      translatedVolumeTransformMatrix = volIndexTranslation.GetVnlMatrix() * volPPToIndex.GetVnlMatrix() *\n                                        geometry->GetRotationMatrices()[iProj].GetInverse();\n      for (int j = 0; j < 3; j++) // Ignore the 4th row\n        for (int k = 0; k < 4; k++)\n          translatedVolumeTransformMatrices[(j + 3 * (iProj - iFirstProj)) * 4 + k] =\n            (float)translatedVolumeTransformMatrix[j][k];\n    }\n\n    // Compute source position in volume indices\n    source_position = volPPToIndex * geometry->GetSourcePosition(iProj);\n\n    // Copy it into a single large array\n    for (unsigned int d = 0; d < 3; d++)\n      source_positions[(iProj - iFirstProj) * 3 + d] = source_position[d]; // Ignore the 4th component\n  }\n\n  int projectionOffset = 0;\n  for (unsigned int i = 0; i < nProj; i += SLAB_SIZE)\n  {\n    // If nProj is not a multiple of SLAB_SIZE, the last slab will contain less than SLAB_SIZE projections\n    projectionSize[2] = std::min(nProj - i, (unsigned int)SLAB_SIZE);\n    projectionOffset = iFirstProj + i - this->GetInput(1)->GetBufferedRegion().GetIndex(2);\n\n    CUDA_ray_cast_back_project(projectionSize,\n                               volumeSize,\n                               (float *)&(translatedProjectionIndexTransformMatrices[12 * i]),\n                               (float *)&(translatedVolumeTransformMatrices[12 * i]),\n                               pin,\n                               pout,\n                               pproj + nPixelsPerProj * projectionOffset,\n                               m_StepSize,\n                               (double *)&(source_positions[3 * i]),\n                               radiusCylindricalDetector,\n                               boxMin,\n                               boxMax,\n                               spacing,\n                               m_Normalize);\n\n    // Re-use the output as input\n    pin = pout;\n  }\n\n  delete[] translatedProjectionIndexTransformMatrices;\n  delete[] translatedVolumeTransformMatrices;\n  delete[] source_positions;\n}\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkCudaSplatImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaInterpolateImageFilter.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n#include <cublas_v2.h>\n#include <cuda_runtime.h>\n\nvoid\nCUDA_splat(const int4 & outputSize, float * input, float * output, int projectionNumber, float ** weights)\n{\n  cublasHandle_t handle;\n  cublasCreate(&handle);\n\n  size_t numel = outputSize.x * outputSize.y * outputSize.z;\n\n  for (int phase = 0; phase < outputSize.w; phase++)\n  {\n    float weight = weights[phase][projectionNumber];\n    if (weight != 0)\n    {\n      // Create a pointer to the \"phase\"-th volume in the output\n      float * p = output + phase * numel;\n\n      // Add \"weight\" times the input to the \"phase\"-th volume in the output\n#if CUDA_VERSION < 12000\n      cublasSaxpy(handle, (int)numel, &weight, input, 1, p, 1);\n#else\n      cublasSaxpy_64(handle, numel, &weight, input, 1, p, 1);\n#endif\n    }\n  }\n\n  // Destroy Cublas context\n  cublasDestroy(handle);\n\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaSplatImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaSplatImageFilter.h\"\n#include \"rtkCudaSplatImageFilter.hcu\"\n\n#include <itkMacro.h>\n\nrtk::CudaSplatImageFilter ::CudaSplatImageFilter() {}\n\nvoid\nrtk::CudaSplatImageFilter ::GPUGenerateData()\n{\n  int4 outputSize;\n  outputSize.x = this->GetOutput()->GetLargestPossibleRegion().GetSize()[0];\n  outputSize.y = this->GetOutput()->GetLargestPossibleRegion().GetSize()[1];\n  outputSize.z = this->GetOutput()->GetLargestPossibleRegion().GetSize()[2];\n  outputSize.w = this->GetOutput()->GetLargestPossibleRegion().GetSize()[3];\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pvolseries = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pvol = (float *)(this->GetInputVolume()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pvolseries = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pvol = *(float **)(this->GetInputVolume()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_splat(outputSize, pvol, pvolseries, m_ProjectionNumber, m_Weights.data_array());\n}\n"
  },
  {
    "path": "src/rtkCudaTotalVariationDenoisingBPDQImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// rtk includes\n#include \"rtkCudaTotalVariationDenoisingBPDQImageFilter.hcu\"\n#include \"rtkCudaFirstOrderKernels.hcu\"\n#include \"rtkCudaUtilities.hcu\"\n\n#include <itkMacro.h>\n\n// cuda includes\n#include <cuda.h>\n\n// TEXTURES AND CONSTANTS //\n\n__constant__ int3   c_Size;\n__constant__ float3 c_Spacing;\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n__global__ void\nmagnitude_threshold_kernel(float * grad_x, float * grad_y, float * grad_z, float gamma)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z)\n    return;\n\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n\n  float norm = sqrt(grad_x[id] * grad_x[id] + grad_y[id] * grad_y[id] + grad_z[id] * grad_z[id]);\n  if (norm > gamma)\n  {\n    float ratio = gamma / norm;\n    grad_x[id] *= ratio;\n    grad_y[id] *= ratio;\n    grad_z[id] *= ratio;\n  }\n}\n\n__global__ void\ngradient_and_subtract_kernel(float * in, float * grad_x, float * grad_y, float * grad_z)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z)\n    return;\n\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n  long int id_x = (k * c_Size.y + j) * c_Size.x + i + 1;\n  long int id_y = (k * c_Size.y + j + 1) * c_Size.x + i;\n  long int id_z = ((k + 1) * c_Size.y + j) * c_Size.x + i;\n\n  if (i != (c_Size.x - 1))\n    grad_x[id] -= ((in[id_x] - in[id]) / c_Spacing.x);\n  if (j != (c_Size.y - 1))\n    grad_y[id] -= ((in[id_y] - in[id]) / c_Spacing.y);\n  if (k != (c_Size.z - 1))\n    grad_z[id] -= ((in[id_z] - in[id]) / c_Spacing.z);\n}\n\n__global__ void\nmultiply_by_beta_kernel(float * input, float * output, float beta)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z)\n    return;\n\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n\n  output[id] = input[id] * beta;\n}\n\n__global__ void\nsubtract_kernel(float * in1, float * in2, float * out)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int k = blockIdx.z * blockDim.z + threadIdx.z;\n\n  if (i >= c_Size.x || j >= c_Size.y || k >= c_Size.z)\n    return;\n\n  long int id = (k * c_Size.y + j) * c_Size.x + i;\n\n  out[id] = in1[id] - in2[id];\n}\n\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\nvoid\nCUDA_total_variation(int     size[3],\n                     float   spacing[3],\n                     float * dev_in,\n                     float * dev_out,\n                     float   gamma,\n                     float   beta,\n                     int     NumberOfIterations)\n{\n  int3 dev_Size = make_int3(size[0], size[1], size[2]);\n  cudaMemcpyToSymbol(c_Size, &dev_Size, sizeof(int3));\n\n  float3 dev_Spacing = make_float3(spacing[0], spacing[1], spacing[2]);\n  cudaMemcpyToSymbol(c_Spacing, &dev_Spacing, sizeof(float3));\n\n  float minSpacing = spacing[0];\n  if (spacing[1] < minSpacing)\n    minSpacing = spacing[1];\n  if (spacing[2] < minSpacing)\n    minSpacing = spacing[2];\n\n  // Reset output volume\n  size_t memorySizeOutput = sizeof(float) * size[0] * size[1] * size[2];\n  cudaMemset((void *)dev_out, 0, memorySizeOutput);\n\n  // Initialize volume to store intermediate images\n  float * dev_interm;\n  cudaMalloc((void **)&dev_interm, memorySizeOutput);\n  cudaMemset(dev_interm, 0, memorySizeOutput);\n\n  // Initialize volumes to store the gradient components\n  float * dev_grad_x;\n  float * dev_grad_y;\n  float * dev_grad_z;\n  cudaMalloc((void **)&dev_grad_x, memorySizeOutput);\n  cudaMalloc((void **)&dev_grad_y, memorySizeOutput);\n  cudaMalloc((void **)&dev_grad_z, memorySizeOutput);\n  cudaMemset(dev_grad_x, 0, memorySizeOutput);\n  cudaMemset(dev_grad_y, 0, memorySizeOutput);\n  cudaMemset(dev_grad_z, 0, memorySizeOutput);\n\n  // Thread Block Dimensions\n  dim3 dimBlock = dim3(16, 4, 4);\n\n  int blocksInX = iDivUp(size[0], dimBlock.x);\n  int blocksInY = iDivUp(size[1], dimBlock.y);\n  int blocksInZ = iDivUp(size[2], dimBlock.z);\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n\n  // First iteration\n  multiply_by_beta_kernel<<<dimGrid, dimBlock>>>(dev_in, dev_interm, beta);\n  CUDA_CHECK_ERROR;\n\n  gradient_kernel<<<dimGrid, dimBlock>>>(dev_interm, dev_grad_x, dev_grad_y, dev_grad_z, dev_Size, dev_Spacing);\n  CUDA_CHECK_ERROR;\n\n  magnitude_threshold_kernel<<<dimGrid, dimBlock>>>(dev_grad_x, dev_grad_y, dev_grad_z, gamma);\n  CUDA_CHECK_ERROR;\n\n  // Rest of the iterations\n  for (int iter = 0; iter < NumberOfIterations; iter++)\n  {\n    divergence_kernel<<<dimGrid, dimBlock>>>(dev_grad_x, dev_grad_y, dev_grad_z, dev_interm, dev_Size, dev_Spacing);\n    CUDA_CHECK_ERROR;\n\n    subtract_kernel<<<dimGrid, dimBlock>>>(dev_in, dev_interm, dev_out);\n    CUDA_CHECK_ERROR;\n\n    multiply_by_beta_kernel<<<dimGrid, dimBlock>>>(dev_out, dev_interm, beta * minSpacing);\n    CUDA_CHECK_ERROR;\n\n    gradient_and_subtract_kernel<<<dimGrid, dimBlock>>>(dev_interm, dev_grad_x, dev_grad_y, dev_grad_z);\n    CUDA_CHECK_ERROR;\n\n    magnitude_threshold_kernel<<<dimGrid, dimBlock>>>(dev_grad_x, dev_grad_y, dev_grad_z, gamma);\n    CUDA_CHECK_ERROR;\n  }\n\n  // Cleanup\n  cudaFree(dev_interm);\n  cudaFree(dev_grad_x);\n  cudaFree(dev_grad_y);\n  cudaFree(dev_grad_z);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaTotalVariationDenoisingBPDQImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaTotalVariationDenoisingBPDQImageFilter.h\"\n#include \"rtkCudaTotalVariationDenoisingBPDQImageFilter.hcu\"\n\n#include <itkMacro.h>\n\nrtk::CudaTotalVariationDenoisingBPDQImageFilter ::CudaTotalVariationDenoisingBPDQImageFilter() {}\n\nvoid\nrtk::CudaTotalVariationDenoisingBPDQImageFilter ::GPUGenerateData()\n{\n  int   inputSize[3];\n  int   outputSize[3];\n  float inputSpacing[3];\n  float outputSpacing[3];\n\n  for (int i = 0; i < 3; i++)\n  {\n    inputSize[i] = this->GetInput()->GetBufferedRegion().GetSize()[i];\n    outputSize[i] = this->GetOutput()->GetBufferedRegion().GetSize()[i];\n    inputSpacing[i] = this->GetInput()->GetSpacing()[i];\n    outputSpacing[i] = this->GetOutput()->GetSpacing()[i];\n\n    if ((inputSize[i] != outputSize[i]) || (inputSpacing[i] != outputSpacing[i]))\n    {\n      std::cerr << \"The CUDA Total Variation Denoising BPDQ filter can only handle input and output regions of equal \"\n                   \"size and spacing\"\n                << std::endl;\n      exit(1);\n    }\n  }\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  CUDA_total_variation(\n    inputSize, inputSpacing, pin, pout, static_cast<float>(m_Gamma), static_cast<float>(m_Beta), m_NumberOfIterations);\n}\n"
  },
  {
    "path": "src/rtkCudaUtilities.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaUtilities.hcu\"\n#include <cublas_v2.h>\n\nstd::vector<int>\nGetListOfCudaDevices()\n{\n  std::vector<int>      deviceList;\n  int                   deviceCount;\n  struct cudaDeviceProp properties;\n  if (cudaGetDeviceCount(&deviceCount) == cudaSuccess)\n  {\n    for (int device = 0; device < deviceCount; ++device)\n    {\n      cudaGetDeviceProperties(&properties, device);\n      if (properties.major != 9999) /* 9999 means emulation only */\n        deviceList.push_back(device);\n    }\n  }\n  if (deviceList.size() < 1)\n    itkGenericExceptionMacro(<< \"No CUDA device available\");\n\n  return deviceList;\n}\n\nstd::pair<int, int>\nGetCudaComputeCapability(int device)\n{\n  struct cudaDeviceProp properties;\n  if (cudaGetDeviceProperties(&properties, device) != cudaSuccess)\n    itkGenericExceptionMacro(<< \"Invalid CUDA device\");\n  return std::make_pair(properties.major, properties.minor);\n}\n\nsize_t\nGetFreeGPUGlobalMemory(int device)\n{\n  // The return result of cuda utility methods are stored in a CUresult\n  CUresult result;\n\n  // create cuda context\n  CUcontext cudaContext;\n  result = cuCtxCreate(&cudaContext, CU_CTX_SCHED_AUTO, device);\n  if (result != CUDA_SUCCESS)\n  {\n    itkGenericExceptionMacro(<< \"Could not create context on this CUDA device\");\n  }\n\n  // get the amount of free memory on the graphics card\n  size_t free;\n  size_t total;\n  result = cuMemGetInfo(&free, &total);\n  if (result != CUDA_SUCCESS)\n  {\n    itkGenericExceptionMacro(<< \"Could not obtain information on free memory on this CUDA device\");\n  }\n\n  cuCtxDestroy_v2(cudaContext);\n\n  return free;\n}\n\n__host__ void\nprepareScalarTextureObject(int                          size[3],\n                           float *                      dev_ptr,\n                           cudaArray *&                 threeDArray,\n                           cudaTextureObject_t &        tex,\n                           const bool                   isProjections,\n                           const bool                   isLinear,\n                           const cudaTextureAddressMode texAddressMode)\n{\n  // create texture object\n  cudaResourceDesc resDesc = {};\n  resDesc.resType = cudaResourceTypeArray;\n\n  cudaTextureDesc texDesc = {};\n  texDesc.readMode = cudaReadModeElementType;\n\n  for (int component = 0; component < 3; component++)\n    texDesc.addressMode[component] = texAddressMode;\n  if (isLinear)\n    texDesc.filterMode = cudaFilterModeLinear;\n  else\n    texDesc.filterMode = cudaFilterModePoint;\n\n  static cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32, 0, 0, 0, cudaChannelFormatKindFloat);\n  cudaExtent                   volExtent = make_cudaExtent(size[0], size[1], size[2]);\n\n  // Copy image data to arrays. The tricky part is the make_cudaPitchedPtr.\n  // The best way to understand it is to read\n  // https://stackoverflow.com/questions/16119943/how-and-when-should-i-use-pitched-pointer-with-the-cuda-api\n\n  // Allocate the cudaArray. Projections use layered arrays, volumes use default 3D arrays\n  if (isProjections)\n    cudaMalloc3DArray(&threeDArray, &channelDesc, volExtent, cudaArrayLayered);\n  else\n    cudaMalloc3DArray(&threeDArray, &channelDesc, volExtent);\n  CUDA_CHECK_ERROR;\n\n  // Fill it\n  cudaMemcpy3DParms CopyParams = {};\n  CopyParams.srcPtr = make_cudaPitchedPtr(dev_ptr, size[0] * sizeof(float), size[0], size[1]);\n  CUDA_CHECK_ERROR;\n  CopyParams.dstArray = threeDArray;\n  CopyParams.extent = volExtent;\n  CopyParams.kind = cudaMemcpyDeviceToDevice;\n  cudaMemcpy3D(&CopyParams);\n  CUDA_CHECK_ERROR;\n\n  // Fill in the texture object with all this information\n  resDesc.res.array.array = threeDArray;\n  cudaCreateTextureObject(&tex, &resDesc, &texDesc, NULL);\n  CUDA_CHECK_ERROR;\n}\n\n__host__ void\nprepareVectorTextureObject(int                                size[3],\n                           const float *                      dev_ptr,\n                           std::vector<cudaArray *> &         componentArrays,\n                           const unsigned int                 nComponents,\n                           std::vector<cudaTextureObject_t> & tex,\n                           const bool                         isProjections,\n                           const cudaTextureAddressMode       texAddressMode)\n{\n  componentArrays.resize(nComponents);\n  tex.resize(nComponents);\n\n  // Create CUBLAS context\n  cublasHandle_t handle;\n  cublasCreate(&handle);\n\n  // create texture object\n  cudaResourceDesc resDesc = {};\n  resDesc.resType = cudaResourceTypeArray;\n\n  cudaTextureDesc texDesc = {};\n  texDesc.readMode = cudaReadModeElementType;\n  for (int component = 0; component < 3; component++)\n    texDesc.addressMode[component] = texAddressMode;\n  texDesc.filterMode = cudaFilterModeLinear;\n\n  static cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(32, 0, 0, 0, cudaChannelFormatKindFloat);\n  cudaExtent                   volExtent = make_cudaExtent(size[0], size[1], size[2]);\n\n  // Allocate an intermediate memory space to extract the components of the input volume\n  float * singleComponent;\n  size_t  numel = size[0] * size[1] * size[2];\n  if (nComponents > 1)\n  {\n    cudaMalloc(&singleComponent, numel * sizeof(float));\n    CUDA_CHECK_ERROR;\n  }\n  float one = 1.0;\n\n  // Copy image data to arrays. The tricky part is the make_cudaPitchedPtr.\n  // The best way to understand it is to read\n  // https://stackoverflow.com/questions/16119943/how-and-when-should-i-use-pitched-pointer-with-the-cuda-api\n  for (unsigned int component = 0; component < nComponents; component++)\n  {\n    if (nComponents > 1)\n    {\n      // Reset the intermediate memory\n      cudaMemset((void *)singleComponent, 0, numel * sizeof(float));\n\n      // Fill it with the current component\n      const float * pComponent = dev_ptr + component;\n#if CUDA_VERSION < 12000\n      cublasSaxpy(handle, (int)numel, &one, pComponent, nComponents, singleComponent, 1);\n#else\n      cublasSaxpy_64(handle, numel, &one, pComponent, nComponents, singleComponent, 1);\n#endif\n    }\n\n    // Allocate the cudaArray. Projections use layered arrays, volumes use default 3D arrays\n    if (isProjections)\n      cudaMalloc3DArray(&componentArrays[component], &channelDesc, volExtent, cudaArrayLayered);\n    else\n      cudaMalloc3DArray(&componentArrays[component], &channelDesc, volExtent);\n    CUDA_CHECK_ERROR;\n\n    // Fill it with the current singleComponent\n    cudaMemcpy3DParms CopyParams = cudaMemcpy3DParms();\n    if (nComponents > 1)\n      CopyParams.srcPtr = make_cudaPitchedPtr(singleComponent, size[0] * sizeof(float), size[0], size[1]);\n    else\n      CopyParams.srcPtr = make_cudaPitchedPtr((void *)dev_ptr, size[0] * sizeof(float), size[0], size[1]);\n    CUDA_CHECK_ERROR;\n    CopyParams.dstArray = componentArrays[component];\n    CopyParams.extent = volExtent;\n    CopyParams.kind = cudaMemcpyDeviceToDevice;\n    cudaMemcpy3D(&CopyParams);\n    CUDA_CHECK_ERROR;\n\n    // Fill in the texture object with all this information\n    resDesc.res.array.array = componentArrays[component];\n    cudaCreateTextureObject(&tex[component], &resDesc, &texDesc, NULL);\n    CUDA_CHECK_ERROR;\n  }\n\n  // Intermediate memory is no longer needed\n  if (nComponents > 1)\n    cudaFree(singleComponent);\n\n  // Destroy CUBLAS context\n  cublasDestroy(handle);\n}\n\n__host__ void\nprepareGeometryTextureObject(int                   length,\n                             const float *         geometry,\n                             float *&              dev_geom,\n                             cudaTextureObject_t & tex_geom,\n                             const unsigned int    nParam)\n{\n  // copy geometry matrix to device, bind the matrix to the texture\n  cudaMalloc((void **)&dev_geom, sizeof(float) * length * nParam);\n  CUDA_CHECK_ERROR;\n  cudaMemcpy(dev_geom, geometry, sizeof(float) * length * nParam, cudaMemcpyHostToDevice);\n  CUDA_CHECK_ERROR;\n\n  // create texture object\n  cudaResourceDesc resDesc = {};\n  resDesc.resType = cudaResourceTypeLinear;\n  resDesc.res.linear.devPtr = dev_geom;\n  resDesc.res.linear.desc.f = cudaChannelFormatKindFloat;\n  resDesc.res.linear.desc.x = 32; // bits per channel\n  resDesc.res.linear.sizeInBytes = length * nParam * sizeof(float);\n\n  cudaTextureDesc texDesc = {};\n  texDesc.readMode = cudaReadModeElementType;\n\n  cudaCreateTextureObject(&tex_geom, &resDesc, &texDesc, NULL);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaWarpBackProjectionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/* -----------------------------------------------------------------------\n   See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information\n   ----------------------------------------------------------------------- */\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaWarpBackProjectionImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n// CONSTANTS //////////////////////////////////////////////////////////////\n__constant__ float c_matrices[SLAB_SIZE * 12]; // Can process stacks of at most SLAB_SIZE projections\n__constant__ float c_volIndexToProjPP[SLAB_SIZE * 12];\n__constant__ float c_projPPToProjIndex[9];\n__constant__ int3  c_projSize;\n__constant__ int3  c_volSize;\n__constant__ float c_IndexInputToIndexDVFMatrix[12];\n__constant__ float c_PPInputToIndexInputMatrix[12];\n__constant__ float c_IndexInputToPPInputMatrix[12];\n////////////////////////////////////////////////////////////////////////////\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n__global__ void\nkernel_warp_back_project_3Dgrid(float *             dev_vol_in,\n                                float *             dev_vol_out,\n                                cudaTextureObject_t tex_xdvf,\n                                cudaTextureObject_t tex_ydvf,\n                                cudaTextureObject_t tex_zdvf,\n                                cudaTextureObject_t tex_proj)\n{\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= c_volSize.x || j >= c_volSize.y || k >= c_volSize.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  long int vol_idx = i + (j + k * c_volSize.y) * (c_volSize.x);\n\n  float3 IndexInDVF, Displacement, PP, IndexInInput, ip;\n  float  voxel_data = 0;\n\n  for (unsigned int proj = 0; proj < c_projSize.z; proj++)\n  {\n    // Compute the index in the DVF\n    IndexInDVF = matrix_multiply(make_float3(i, j, k), c_IndexInputToIndexDVFMatrix);\n\n    // Get each component of the displacement vector by interpolation in the DVF\n    Displacement.x = tex3D<float>(tex_xdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n    Displacement.y = tex3D<float>(tex_ydvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n    Displacement.z = tex3D<float>(tex_zdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n\n    // Compute the physical point in input + the displacement vector\n    PP = matrix_multiply(make_float3(i, j, k), c_IndexInputToPPInputMatrix) + Displacement;\n\n    // Convert it to a continuous index\n    IndexInInput = matrix_multiply(PP, c_PPInputToIndexInputMatrix);\n\n    // Project the voxel onto the detector to find out which value to add to it\n    ip = matrix_multiply(IndexInInput, &(c_matrices[12 * proj]));\n\n    // Change coordinate systems\n    ip.z = 1 / ip.z;\n    ip.x = ip.x * ip.z;\n    ip.y = ip.y * ip.z;\n\n    // Get texture point, clip left to GPU\n    voxel_data += tex2DLayered<float>(tex_proj, ip.x, ip.y, proj);\n  }\n\n  // Place it into the volume\n  dev_vol_out[vol_idx] = dev_vol_in[vol_idx] + voxel_data;\n}\n\n__global__ void\nkernel_warp_back_project_3Dgrid_cylindrical_detector(float *             dev_vol_in,\n                                                     float *             dev_vol_out,\n                                                     float               radius,\n                                                     cudaTextureObject_t tex_xdvf,\n                                                     cudaTextureObject_t tex_ydvf,\n                                                     cudaTextureObject_t tex_zdvf,\n                                                     cudaTextureObject_t tex_proj)\n{\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= c_volSize.x || j >= c_volSize.y || k >= c_volSize.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  long int vol_idx = i + (j + k * c_volSize.y) * (c_volSize.x);\n\n  float3 IndexInDVF, Displacement, PP, IndexInInput, ip, pp;\n  float  voxel_data = 0;\n\n  for (unsigned int proj = 0; proj < c_projSize.z; proj++)\n  {\n    // Compute the index in the DVF\n    IndexInDVF = matrix_multiply(make_float3(i, j, k), c_IndexInputToIndexDVFMatrix);\n\n    // Get each component of the displacement vector by interpolation in the DVF\n    Displacement.x = tex3D<float>(tex_xdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n    Displacement.y = tex3D<float>(tex_ydvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n    Displacement.z = tex3D<float>(tex_zdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n\n    // Compute the physical point in input + the displacement vector\n    PP = matrix_multiply(make_float3(i, j, k), c_IndexInputToPPInputMatrix) + Displacement;\n\n    // Convert it to a continuous index\n    IndexInInput = matrix_multiply(PP, c_PPInputToIndexInputMatrix);\n\n    // Project the voxel onto the detector to find out which value to add to it\n    pp = matrix_multiply(IndexInInput, &(c_volIndexToProjPP[12 * proj]));\n\n    // Change coordinate systems\n    pp.z = 1 / pp.z;\n    pp.x = pp.x * pp.z;\n    pp.y = pp.y * pp.z;\n\n    // Apply correction for cylindrical detector\n    const float u = pp.x;\n    pp.x = radius * atan2(u, radius);\n    pp.y = pp.y * radius / sqrt(radius * radius + u * u);\n\n    // Get projection index\n    ip.x = c_projPPToProjIndex[0] * pp.x + c_projPPToProjIndex[1] * pp.y + c_projPPToProjIndex[2];\n    ip.y = c_projPPToProjIndex[3] * pp.x + c_projPPToProjIndex[4] * pp.y + c_projPPToProjIndex[5];\n\n    // Get texture point, clip left to GPU\n    voxel_data += tex2DLayered<float>(tex_proj, ip.x, ip.y, proj);\n  }\n\n  // Place it into the volume\n  dev_vol_out[vol_idx] = dev_vol_in[vol_idx] + voxel_data;\n}\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_back_project /////////////////////////////\nvoid\nCUDA_warp_back_project(int     projSize[3],\n                       int     volSize[3],\n                       int     dvf_size[3],\n                       float * matrices,\n                       float * volIndexToProjPPs,\n                       float * projPPToProjIndex,\n                       float * dev_vol_in,\n                       float * dev_vol_out,\n                       float * dev_proj,\n                       float * dev_input_dvf,\n                       float   IndexInputToIndexDVFMatrix[12],\n                       float   PPInputToIndexInputMatrix[12],\n                       float   IndexInputToPPInputMatrix[12],\n                       double  radiusCylindricalDetector)\n{\n  // Copy the size of inputs into constant memory\n  cudaMemcpyToSymbol(c_projSize, projSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_volSize, volSize, sizeof(int3));\n\n  // Copy the projection matrices into constant memory\n  cudaMemcpyToSymbol(c_matrices, &(matrices[0]), 12 * sizeof(float) * projSize[2]);\n  cudaMemcpyToSymbol(c_volIndexToProjPP, &(volIndexToProjPPs[0]), 12 * sizeof(float) * projSize[2]);\n  cudaMemcpyToSymbol(c_projPPToProjIndex, &(projPPToProjIndex[0]), 9 * sizeof(float));\n\n  // Prepare proj texture\n  cudaArray *         array_proj;\n  cudaTextureObject_t tex_proj;\n  prepareScalarTextureObject(projSize, dev_proj, array_proj, tex_proj, true);\n\n  // Prepare DVF textures\n  std::vector<cudaArray *>         DVFComponentArrays;\n  std::vector<cudaTextureObject_t> tex_dvf;\n  prepareVectorTextureObject(dvf_size, dev_input_dvf, DVFComponentArrays, 3, tex_dvf, false);\n\n  // Copy matrices into constant memory\n  cudaMemcpyToSymbol(\n    c_IndexInputToIndexDVFMatrix, IndexInputToIndexDVFMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  cudaMemcpyToSymbol(\n    c_PPInputToIndexInputMatrix, PPInputToIndexInputMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  cudaMemcpyToSymbol(\n    c_IndexInputToPPInputMatrix, IndexInputToPPInputMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n\n  // Thread Block Dimensions\n  constexpr int tBlock_x = 16;\n  constexpr int tBlock_y = 4;\n  constexpr int tBlock_z = 4;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (volSize[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (volSize[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (volSize[2] - 1) / tBlock_z + 1;\n\n  // Run kernels. Note: Projection data is passed via texture memory,\n  // transform matrix is passed via constant memory\n\n  // Compute block and grid sizes\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n  CUDA_CHECK_ERROR;\n\n  // Note: cbi->img is passed via texture memory\n  // Matrices are passed via constant memory\n  //-------------------------------------\n  if (radiusCylindricalDetector == 0)\n    kernel_warp_back_project_3Dgrid<<<dimGrid, dimBlock>>>(\n      dev_vol_in, dev_vol_out, tex_dvf[0], tex_dvf[1], tex_dvf[2], tex_proj);\n  else\n    kernel_warp_back_project_3Dgrid_cylindrical_detector<<<dimGrid, dimBlock>>>(\n      dev_vol_in, dev_vol_out, (float)radiusCylindricalDetector, tex_dvf[0], tex_dvf[1], tex_dvf[2], tex_proj);\n  CUDA_CHECK_ERROR;\n\n  // Cleanup\n  for (unsigned int c = 0; c < 3; c++)\n  {\n    cudaFreeArray(DVFComponentArrays[c]);\n    CUDA_CHECK_ERROR;\n    cudaDestroyTextureObject(tex_dvf[c]);\n    CUDA_CHECK_ERROR;\n  }\n  cudaFreeArray((cudaArray *)array_proj);\n  CUDA_CHECK_ERROR;\n  cudaDestroyTextureObject(tex_proj);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaWarpBackProjectionImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaWarpBackProjectionImageFilter.h\"\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaWarpBackProjectionImageFilter.hcu\"\n\n#include <itkImageRegionIterator.h>\n#include <itkImageRegionConstIterator.h>\n#include <itkMacro.h>\n#include <itkImageAlgorithm.h>\n\nnamespace rtk\n{\n\nCudaWarpBackProjectionImageFilter ::CudaWarpBackProjectionImageFilter() { this->SetNumberOfRequiredInputs(1); }\n\nvoid\nCudaWarpBackProjectionImageFilter ::SetInputVolume(const ImageType * Volume)\n{\n  this->SetInput(0, const_cast<ImageType *>(Volume));\n}\n\nvoid\nCudaWarpBackProjectionImageFilter ::SetInputProjectionStack(const ImageType * ProjectionStack)\n{\n  this->SetInput(1, const_cast<ImageType *>(ProjectionStack));\n}\n\nvoid\nCudaWarpBackProjectionImageFilter ::SetDisplacementField(const DVFType * DVF)\n{\n  this->SetInput(\"DisplacementField\", const_cast<DVFType *>(DVF));\n}\n\nCudaWarpBackProjectionImageFilter::ImageType::Pointer\nCudaWarpBackProjectionImageFilter ::GetInputVolume()\n{\n  return static_cast<ImageType *>(this->itk::ProcessObject::GetInput(0));\n}\n\nCudaWarpBackProjectionImageFilter::ImageType::Pointer\nCudaWarpBackProjectionImageFilter ::GetInputProjectionStack()\n{\n  return static_cast<ImageType *>(this->itk::ProcessObject::GetInput(1));\n}\n\nCudaWarpBackProjectionImageFilter::DVFType::Pointer\nCudaWarpBackProjectionImageFilter ::GetDisplacementField()\n{\n  return static_cast<DVFType *>(this->itk::ProcessObject::GetInput(\"DisplacementField\"));\n}\n\nvoid\nCudaWarpBackProjectionImageFilter ::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n\n  // Since we do not know where the DVF points, the\n  // whole input projection is required.\n  this->GetInputProjectionStack()->SetRequestedRegionToLargestPossibleRegion();\n\n  // To compute the DVF's requested region, we use the same method\n  // as in itk::WarpImageFilter, except if the ITK version is too old to\n  // contain the required methods\n  // If the output and the deformation field have the same\n  // information, just propagate up the output requested region for the\n  // deformation field. Otherwise, it is non-trivial to determine\n  // the smallest region of the deformation field that fully\n  // contains the physical space covered by the output's requested\n  // region, se we do the easy thing and request the largest possible region\n  DVFType::Pointer   fieldPtr = this->GetDisplacementField();\n  ImageType::Pointer outputPtr = this->GetOutput();\n  if (fieldPtr.IsNotNull())\n  {\n    // tolerance for origin and spacing depends on the size of pixel\n    // tolerance for direction is a fraction of the unit cube.\n    const itk::SpacePrecisionType coordinateTol =\n      this->GetCoordinateTolerance() * outputPtr->GetSpacing()[0]; // use first dimension spacing\n\n    bool DefFieldSameInformation =\n      (outputPtr->GetOrigin().GetVnlVector().is_equal(fieldPtr->GetOrigin().GetVnlVector(), coordinateTol)) &&\n      (outputPtr->GetSpacing().GetVnlVector().is_equal(fieldPtr->GetSpacing().GetVnlVector(), coordinateTol)) &&\n      (outputPtr->GetDirection().GetVnlMatrix().as_ref().is_equal(fieldPtr->GetDirection().GetVnlMatrix().as_ref(),\n                                                                  this->GetDirectionTolerance()));\n\n    if (DefFieldSameInformation)\n    {\n      fieldPtr->SetRequestedRegion(outputPtr->GetRequestedRegion());\n    }\n    else\n    {\n\n      DVFType::RegionType fieldRequestedRegion = itk::ImageAlgorithm::EnlargeRegionOverBox(\n        outputPtr->GetRequestedRegion(), outputPtr.GetPointer(), fieldPtr.GetPointer());\n      fieldPtr->SetRequestedRegion(fieldRequestedRegion);\n    }\n    if (!fieldPtr->VerifyRequestedRegion())\n    {\n      fieldPtr->SetRequestedRegion(fieldPtr->GetLargestPossibleRegion());\n    }\n  }\n}\n\n\nvoid\nCudaWarpBackProjectionImageFilter ::GPUGenerateData()\n{\n  const unsigned int Dimension = ImageType::ImageDimension;\n  const unsigned int nProj = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetSize(Dimension - 1);\n  const unsigned int iFirstProj = this->GetInputProjectionStack()->GetLargestPossibleRegion().GetIndex(Dimension - 1);\n\n  // Ramp factor is the correction for ramp filter which did not account for the\n  // divergence of the beam\n  //  const GeometryPointer geometry = dynamic_cast<GeometryType *>(this->GetGeometry().GetPointer() );\n\n  // Rotation center (assumed to be at 0 yet)\n  ImageType::PointType rotCenterPoint;\n  rotCenterPoint.Fill(0.0);\n  itk::ContinuousIndex<double, Dimension> rotCenterIndex =\n    this->GetInputVolume()->TransformPhysicalPointToContinuousIndex<ImageType::PointType::ValueType, double>(\n      rotCenterPoint);\n\n  // Include non-zero index in matrix\n  itk::Matrix<double, 4, 4> matrixIdxVol;\n  matrixIdxVol.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    matrixIdxVol[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n    rotCenterIndex[i] -= this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n  }\n\n  // Cuda convenient format for dimensions\n  int projectionSize[3];\n  projectionSize[0] = this->GetInputProjectionStack()->GetBufferedRegion().GetSize()[0];\n  projectionSize[1] = this->GetInputProjectionStack()->GetBufferedRegion().GetSize()[1];\n\n  int volumeSize[3];\n  volumeSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  volumeSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n  volumeSize[2] = this->GetOutput()->GetBufferedRegion().GetSize()[2];\n\n  int inputDVFSize[3];\n  inputDVFSize[0] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[0];\n  inputDVFSize[1] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[1];\n  inputDVFSize[2] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[2];\n\n  // Transform matrices that we will need during the warping process\n  itk::Matrix<double, 4, 4> indexInputToIndexDVFMatrix;\n  itk::Matrix<double, 4, 4> PPInputToIndexInputMatrix;\n  itk::Matrix<double, 4, 4> indexInputToPPInputMatrix;\n\n  indexInputToIndexDVFMatrix =\n    rtk::GetPhysicalPointToIndexMatrix(this->GetDisplacementField().GetPointer()).GetVnlMatrix() *\n    rtk::GetIndexToPhysicalPointMatrix(this->GetInputVolume().GetPointer()).GetVnlMatrix() *\n    matrixIdxVol.GetVnlMatrix();\n\n  PPInputToIndexInputMatrix = rtk::GetPhysicalPointToIndexMatrix(this->GetInputVolume().GetPointer()).GetVnlMatrix();\n\n  indexInputToPPInputMatrix = rtk::GetIndexToPhysicalPointMatrix(this->GetInputVolume().GetPointer()).GetVnlMatrix() *\n                              matrixIdxVol.GetVnlMatrix();\n\n  // Convert the matrices to arrays of floats (skipping the last line, as we don't care)\n  float fIndexInputToIndexDVFMatrix[12];\n  float fPPInputToIndexInputMatrix[12];\n  float fIndexInputToPPInputMatrix[12];\n  for (int j = 0; j < 12; j++)\n  {\n    fIndexInputToIndexDVFMatrix[j] = (float)indexInputToIndexDVFMatrix[j / 4][j % 4];\n    fPPInputToIndexInputMatrix[j] = (float)PPInputToIndexInputMatrix[j / 4][j % 4];\n    fIndexInputToPPInputMatrix[j] = (float)indexInputToPPInputMatrix[j / 4][j % 4];\n  }\n\n  // Load the required images onto the GPU (handled by the CudaDataManager)\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pDVF = (float *)(this->GetDisplacementField()->GetCudaDataManager()->GetGPUBufferPointer());\n\n  float * stackGPUPointer = (float *)(this->GetInputProjectionStack()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pDVF = *(float **)(this->GetDisplacementField()->GetCudaDataManager()->GetGPUBufferPointer());\n\n  float * stackGPUPointer = *(float **)(this->GetInputProjectionStack()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  ptrdiff_t projSize = this->GetInputProjectionStack()->GetBufferedRegion().GetSize()[0] *\n                       this->GetInputProjectionStack()->GetBufferedRegion().GetSize()[1];\n  stackGPUPointer += projSize * (iFirstProj - this->GetInputProjectionStack()->GetBufferedRegion().GetIndex()[2]);\n\n  // Allocate a large matrix to hold the matrix of all projections\n  // fMatrix is for flat detector, the other two are for cylindrical\n  float * fMatrix = new float[12 * nProj];\n  float * fvolIndexToProjPP = new float[12 * nProj];\n  float * fprojPPToProjIndex = new float[9];\n\n  // Correction for non-zero indices in the projections\n  itk::Matrix<double, 3, 3> matrixIdxProj;\n  matrixIdxProj.SetIdentity();\n  for (unsigned int i = 0; i < 2; i++)\n    // SR: 0.5 for 2D texture\n    matrixIdxProj[i][2] = -1 * (this->GetInput(1)->GetBufferedRegion().GetIndex()[i]) + 0.5;\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    // Projection physical point to projection index matrix\n    itk::Matrix<double, 3, 3> projPPToProjIndex = GetProjectionPhysicalPointToProjectionIndexMatrix(iProj);\n    projPPToProjIndex = matrixIdxProj.GetVnlMatrix() * projPPToProjIndex.GetVnlMatrix();\n    for (int j = 0; j < 9; j++)\n      fprojPPToProjIndex[j] = projPPToProjIndex[j / 3][j % 3];\n\n    // Volume index to projection physical point matrix\n    // normalized to have a correct backprojection weight\n    // (1 at the isocenter)\n    ProjectionMatrixType volIndexToProjPP = GetVolumeIndexToProjectionPhysicalPointMatrix(iProj);\n\n    // Correction for non-zero indices in the volume\n    volIndexToProjPP = volIndexToProjPP.GetVnlMatrix() * matrixIdxVol.GetVnlMatrix();\n\n    double perspFactor = volIndexToProjPP[Dimension - 1][Dimension];\n    for (unsigned int j = 0; j < Dimension; j++)\n      perspFactor += volIndexToProjPP[Dimension - 1][j] * rotCenterIndex[j];\n    volIndexToProjPP /= perspFactor;\n\n    ProjectionMatrixType matrix =\n      ProjectionMatrixType(projPPToProjIndex.GetVnlMatrix() * volIndexToProjPP.GetVnlMatrix());\n\n    // Fill float arrays with matrices coefficients, to be passed to GPU\n    for (int j = 0; j < 12; j++)\n    {\n      fvolIndexToProjPP[j + (iProj - iFirstProj) * 12] = volIndexToProjPP[j / 4][j % 4];\n      fMatrix[j + (iProj - iFirstProj) * 12] = matrix[j / 4][j % 4];\n    }\n  }\n\n  for (unsigned int i = 0; i < nProj; i += SLAB_SIZE)\n  {\n    // If nProj is not a multiple of SLAB_SIZE, the last slab will contain less than SLAB_SIZE projections\n    projectionSize[2] = std::min(nProj - i, (unsigned int)SLAB_SIZE);\n\n    // Run the back projection with a slab of SLAB_SIZE or less projections\n    CUDA_warp_back_project(projectionSize,\n                           volumeSize,\n                           inputDVFSize,\n                           fMatrix + 12 * i,\n                           fvolIndexToProjPP + 12 * i,\n                           fprojPPToProjIndex,\n                           pin,\n                           pout,\n                           stackGPUPointer + projSize * i,\n                           pDVF,\n                           fIndexInputToIndexDVFMatrix,\n                           fPPInputToIndexInputMatrix,\n                           fIndexInputToPPInputMatrix,\n                           this->m_Geometry->GetRadiusCylindricalDetector());\n\n    // Re-use the output as input\n    pin = pout;\n  }\n\n  delete[] fMatrix;\n  delete[] fvolIndexToProjPP;\n  delete[] fprojPPToProjIndex;\n}\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkCudaWarpForwardProjectionImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaIntersectBox.hcu\"\n#include \"rtkCudaWarpForwardProjectionImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n// CONSTANTS\n__constant__ int3   c_projSize;\n__constant__ float3 c_boxMin;\n__constant__ float3 c_boxMax;\n__constant__ float3 c_spacing;\n__constant__ int3   c_volSize;\n__constant__ float  c_tStep;\n__constant__ float  c_matrices[SLAB_SIZE * 12]; // Can process stacks of at most SLAB_SIZE projections\n__constant__ float  c_sourcePos[SLAB_SIZE * 3]; // Can process stacks of at most SLAB_SIZE projections\n\n__constant__ float c_IndexInputToPPInputMatrix[12];\n__constant__ float c_IndexInputToIndexDVFMatrix[12];\n__constant__ float c_PPInputToIndexInputMatrix[12];\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n// KERNEL kernel_forwardProject\n__global__ void\nkernel_warped_forwardProject(float *             dev_proj_in,\n                             float *             dev_proj_out,\n                             cudaTextureObject_t tex_xdvf,\n                             cudaTextureObject_t tex_ydvf,\n                             cudaTextureObject_t tex_zdvf,\n                             cudaTextureObject_t tex_vol)\n{\n  unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;\n  unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;\n  unsigned int numThread = j * c_projSize.x + i;\n\n  if (i >= c_projSize.x || j >= c_projSize.y)\n    return;\n\n  // Setting ray origin\n  Ray    ray;\n  float3 pixelPos;\n  float  tnear, tfar;\n\n  for (unsigned int proj = 0; proj < c_projSize.z; proj++)\n  {\n    // Setting ray origin\n    ray.o = make_float3(c_sourcePos[3 * proj], c_sourcePos[3 * proj + 1], c_sourcePos[3 * proj + 2]);\n\n    pixelPos = matrix_multiply(make_float3(i, j, 0), &(c_matrices[12 * proj]));\n\n    ray.d = pixelPos - ray.o;\n    ray.d = ray.d / sqrtf(dot(ray.d, ray.d));\n\n    // Detect intersection with box\n    if (!intersectBox(ray, &tnear, &tfar, c_boxMin, c_boxMax) || tfar < 0.f)\n    {\n      dev_proj_out[numThread + proj * c_projSize.x * c_projSize.y] =\n        dev_proj_in[numThread + proj * c_projSize.x * c_projSize.y];\n    }\n    else\n    {\n      if (tnear < 0.f)\n        tnear = 0.f; // clamp to near plane\n\n      // Step length in mm\n      float3 dirInMM = c_spacing * ray.d;\n      float  vStep = c_tStep / sqrtf(dot(dirInMM, dirInMM));\n      float3 step = vStep * ray.d;\n\n      // First position in the box\n      float halfVStep = 0.5f * vStep;\n      tnear = tnear + halfVStep;\n      float3 pos = ray.o + tnear * ray.d;\n\n      float t;\n      float sample = 0.0f;\n      float sum = 0.0f;\n\n      float3 IndexInDVF, Displacement, PP, IndexInInput;\n\n      for (t = tnear; t <= tfar; t += vStep)\n      {\n        IndexInDVF = matrix_multiply(pos, c_IndexInputToIndexDVFMatrix);\n\n        // Get each component of the displacement vector by\n        // interpolation in the dvf\n        Displacement.x = tex3D<float>(tex_xdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n        Displacement.y = tex3D<float>(tex_ydvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n        Displacement.z = tex3D<float>(tex_zdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n\n        // Matrix multiply to get the physical coordinates of the current point in the output volume\n        // + the displacement\n        PP = matrix_multiply(pos, c_IndexInputToPPInputMatrix) + Displacement;\n\n        // Convert it to a continuous index\n        IndexInInput = matrix_multiply(PP, c_PPInputToIndexInputMatrix);\n\n        // Read from 3D texture from volume\n        sample = tex3D<float>(tex_vol, IndexInInput.x, IndexInInput.y, IndexInInput.z);\n\n        // Accumulate, and move forward along the ray\n        sum += sample;\n        pos += step;\n      }\n      dev_proj_out[numThread + proj * c_projSize.x * c_projSize.y] =\n        dev_proj_in[numThread + proj * c_projSize.x * c_projSize.y] +\n        (sum + (tfar - t + halfVStep) / vStep * sample) * c_tStep;\n    }\n  }\n}\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_forward_project() //////////////////////////////////\nvoid\nCUDA_warp_forward_project(int     projSize[3],\n                          int     volSize[3],\n                          int     dvfSize[3],\n                          float * matrices,\n                          float * dev_proj_in,\n                          float * dev_proj_out,\n                          float * dev_vol,\n                          float   t_step,\n                          float * source_positions,\n                          float   box_min[3],\n                          float   box_max[3],\n                          float   spacing[3],\n                          float * dev_input_dvf,\n                          float   IndexInputToIndexDVFMatrix[12],\n                          float   PPInputToIndexInputMatrix[12],\n                          float   IndexInputToPPInputMatrix[12])\n{\n  // constant memory\n  cudaMemcpyToSymbol(c_projSize, projSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_boxMin, box_min, sizeof(float3));\n  cudaMemcpyToSymbol(c_boxMax, box_max, sizeof(float3));\n  cudaMemcpyToSymbol(c_spacing, spacing, sizeof(float3));\n  cudaMemcpyToSymbol(c_volSize, volSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_tStep, &t_step, sizeof(float));\n\n  // Copy the source position matrix into a float3 in constant memory\n  cudaMemcpyToSymbol(c_sourcePos, &(source_positions[0]), 3 * sizeof(float) * projSize[2]);\n\n  // Copy the projection matrices into constant memory\n  cudaMemcpyToSymbol(c_matrices, &(matrices[0]), 12 * sizeof(float) * projSize[2]);\n\n  // Prepare volume texture\n  cudaArray *         array_vol;\n  cudaTextureObject_t tex_vol;\n  prepareScalarTextureObject(volSize, dev_vol, array_vol, tex_vol, false, true, cudaAddressModeClamp);\n\n  // Prepare DVF textures\n  std::vector<cudaArray *>         DVFComponentArrays;\n  std::vector<cudaTextureObject_t> tex_dvf;\n  prepareVectorTextureObject(dvfSize, dev_input_dvf, DVFComponentArrays, 3, tex_dvf, false);\n\n  // Copy matrices into constant memory\n  cudaMemcpyToSymbol(\n    c_IndexInputToPPInputMatrix, IndexInputToPPInputMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  cudaMemcpyToSymbol(\n    c_IndexInputToIndexDVFMatrix, IndexInputToIndexDVFMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  cudaMemcpyToSymbol(\n    c_PPInputToIndexInputMatrix, PPInputToIndexInputMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n\n  ///////////////\n  // RUN\n  dim3 dimBlock = dim3(16, 16, 1);\n  dim3 dimGrid = dim3(iDivUp(projSize[0], dimBlock.x), iDivUp(projSize[1], dimBlock.y));\n\n  kernel_warped_forwardProject<<<dimGrid, dimBlock>>>(\n    dev_proj_in, dev_proj_out, tex_dvf[0], tex_dvf[1], tex_dvf[2], tex_vol);\n\n  // Cleanup\n  for (unsigned int c = 0; c < 3; c++)\n  {\n    cudaFreeArray(DVFComponentArrays[c]);\n    CUDA_CHECK_ERROR;\n    cudaDestroyTextureObject(tex_dvf[c]);\n    CUDA_CHECK_ERROR;\n  }\n  cudaFreeArray((cudaArray *)array_vol);\n  CUDA_CHECK_ERROR;\n  cudaDestroyTextureObject(tex_vol);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaWarpForwardProjectionImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef __rtkCudaWarpForwardProjectionImageFilter_hxx\n#define __rtkCudaWarpForwardProjectionImageFilter_hxx\n\n#include \"rtkCudaWarpForwardProjectionImageFilter.h\"\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaWarpForwardProjectionImageFilter.hcu\"\n#include \"rtkHomogeneousMatrix.h\"\n#include \"rtkMacro.h\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkLinearInterpolateImageFunction.h>\n#include <itkMacro.h>\n#include <itkImageRegionIterator.h>\n#include <itkImageAlgorithm.h>\n#include \"itkCudaUtil.h\"\n\nnamespace rtk\n{\n\nCudaWarpForwardProjectionImageFilter ::CudaWarpForwardProjectionImageFilter()\n  : m_StepSize(1)\n{\n  this->SetNumberOfRequiredInputs(2);\n}\n\nvoid\nCudaWarpForwardProjectionImageFilter ::SetInputProjectionStack(const InputImageType * ProjectionStack)\n{\n  this->SetInput(0, const_cast<InputImageType *>(ProjectionStack));\n}\n\nvoid\nCudaWarpForwardProjectionImageFilter ::SetInputVolume(const InputImageType * Volume)\n{\n  this->SetInput(1, const_cast<InputImageType *>(Volume));\n}\n\nvoid\nCudaWarpForwardProjectionImageFilter ::SetDisplacementField(const DVFType * DVF)\n{\n  this->SetInput(\"DisplacementField\", const_cast<DVFType *>(DVF));\n}\n\nCudaWarpForwardProjectionImageFilter::InputImageType::Pointer\nCudaWarpForwardProjectionImageFilter ::GetInputProjectionStack()\n{\n  return static_cast<InputImageType *>(this->itk::ProcessObject::GetInput(0));\n}\n\nCudaWarpForwardProjectionImageFilter::InputImageType::Pointer\nCudaWarpForwardProjectionImageFilter ::GetInputVolume()\n{\n  return static_cast<InputImageType *>(this->itk::ProcessObject::GetInput(1));\n}\n\nCudaWarpForwardProjectionImageFilter::DVFType::Pointer\nCudaWarpForwardProjectionImageFilter ::GetDisplacementField()\n{\n  return static_cast<DVFType *>(this->itk::ProcessObject::GetInput(\"DisplacementField\"));\n}\n\nvoid\nCudaWarpForwardProjectionImageFilter ::GenerateInputRequestedRegion()\n{\n  Superclass::GenerateInputRequestedRegion();\n\n  // Since we do not know where the DVF points, the\n  // whole input volume is required.\n  this->GetInputVolume()->SetRequestedRegionToLargestPossibleRegion();\n\n  // The requested region on the projection stack input is the same as the output requested region\n  this->GetInputProjectionStack()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());\n\n  // Determine the smallest region of the deformation field that fully\n  // contains the physical space covered by the input volume's requested\n  // region\n  DVFType::Pointer        fieldPtr = this->GetDisplacementField();\n  InputImageType::Pointer inputPtr = this->GetInputVolume();\n  if (fieldPtr.IsNotNull())\n  {\n    // tolerance for origin and spacing depends on the size of pixel\n    // tolerance for direction is a fraction of the unit cube.\n    const itk::SpacePrecisionType coordinateTol =\n      this->GetCoordinateTolerance() * inputPtr->GetSpacing()[0]; // use first dimension spacing\n\n    bool DefFieldSameInformation =\n      (inputPtr->GetOrigin().GetVnlVector().is_equal(fieldPtr->GetOrigin().GetVnlVector(), coordinateTol)) &&\n      (inputPtr->GetSpacing().GetVnlVector().is_equal(fieldPtr->GetSpacing().GetVnlVector(), coordinateTol)) &&\n      (inputPtr->GetDirection().GetVnlMatrix().as_ref().is_equal(fieldPtr->GetDirection().GetVnlMatrix().as_ref(),\n                                                                 this->GetDirectionTolerance()));\n\n    if (DefFieldSameInformation)\n    {\n      fieldPtr->SetRequestedRegion(inputPtr->GetRequestedRegion());\n    }\n    else\n    {\n\n      DVFType::RegionType fieldRequestedRegion = itk::ImageAlgorithm::EnlargeRegionOverBox(\n        inputPtr->GetRequestedRegion(), inputPtr.GetPointer(), fieldPtr.GetPointer());\n      fieldPtr->SetRequestedRegion(fieldRequestedRegion);\n    }\n    if (!fieldPtr->VerifyRequestedRegion())\n    {\n      fieldPtr->SetRequestedRegion(fieldPtr->GetLargestPossibleRegion());\n    }\n  }\n}\n\n\nvoid\nCudaWarpForwardProjectionImageFilter ::GPUGenerateData()\n{\n  if (this->GetGeometry()->GetSourceToDetectorDistances().size() &&\n      this->GetGeometry()->GetSourceToDetectorDistances()[0] == 0)\n  {\n    itkGenericExceptionMacro(<< \"Parallel geometry is not handled by CUDA forward projector.\");\n  }\n\n  itk::Matrix<double, 4, 4> matrixIdxInputVol;\n  itk::Matrix<double, 4, 4> indexInputToPPInputMatrix;\n  itk::Matrix<double, 4, 4> indexInputToIndexDVFMatrix;\n  itk::Matrix<double, 4, 4> PPInputToIndexInputMatrix;\n  matrixIdxInputVol.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    matrixIdxInputVol[i][3] = this->GetInputVolume()->GetBufferedRegion().GetIndex()[i]; // Should 0.5 be added here ?\n  }\n\n  const Superclass::GeometryType * geometry = this->GetGeometry();\n  const unsigned int               Dimension = InputImageType::ImageDimension;\n  const unsigned int iFirstProj = this->GetInputProjectionStack()->GetRequestedRegion().GetIndex(Dimension - 1);\n  const unsigned int nProj = this->GetInputProjectionStack()->GetRequestedRegion().GetSize(Dimension - 1);\n  const unsigned int nPixelsPerProj =\n    this->GetOutput()->GetBufferedRegion().GetSize(0) * this->GetOutput()->GetBufferedRegion().GetSize(1);\n\n  itk::Vector<double, 4> source_position;\n\n  // Setting BoxMin and BoxMax\n  // SR: we are using cuda textures where the pixel definition is not center but corner.\n  // Therefore, we set the box limits from index to index+size instead of, for ITK,\n  // index-0.5 to index+size-0.5.\n  float boxMin[3];\n  float boxMax[3];\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    boxMin[i] = this->GetInputVolume()->GetBufferedRegion().GetIndex()[i] + 0.5;\n    boxMax[i] = boxMin[i] + this->GetInputVolume()->GetBufferedRegion().GetSize()[i] - 1.0;\n  }\n\n  // Getting Spacing\n  float spacing[3];\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    spacing[i] = this->GetInputVolume()->GetSpacing()[i];\n  }\n\n  // Cuda convenient format for dimensions\n  int projectionSize[3];\n  projectionSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  projectionSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n\n  int volumeSize[3];\n  volumeSize[0] = this->GetInputVolume()->GetBufferedRegion().GetSize()[0];\n  volumeSize[1] = this->GetInputVolume()->GetBufferedRegion().GetSize()[1];\n  volumeSize[2] = this->GetInputVolume()->GetBufferedRegion().GetSize()[2];\n\n  int inputDVFSize[3];\n  inputDVFSize[0] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[0];\n  inputDVFSize[1] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[1];\n  inputDVFSize[2] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[2];\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pin = (float *)(this->GetInputProjectionStack()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pvol = (float *)(this->GetInputVolume()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pDVF = (float *)(this->GetDisplacementField()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pin = *(float **)(this->GetInputProjectionStack()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pout = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pvol = *(float **)(this->GetInputVolume()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pDVF = *(float **)(this->GetDisplacementField()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  // Transform matrices that we will need during the warping process\n  indexInputToPPInputMatrix = rtk::GetIndexToPhysicalPointMatrix(this->GetInputVolume().GetPointer()).GetVnlMatrix() *\n                              matrixIdxInputVol.GetVnlMatrix();\n\n  indexInputToIndexDVFMatrix =\n    rtk::GetPhysicalPointToIndexMatrix(this->GetDisplacementField().GetPointer()).GetVnlMatrix() *\n    rtk::GetIndexToPhysicalPointMatrix(this->GetInputVolume().GetPointer()).GetVnlMatrix() *\n    matrixIdxInputVol.GetVnlMatrix();\n\n  PPInputToIndexInputMatrix = rtk::GetPhysicalPointToIndexMatrix(this->GetInputVolume().GetPointer()).GetVnlMatrix();\n\n  // Convert the matrices to arrays of floats (skipping the last line, as we don't care)\n  float fIndexInputToIndexDVFMatrix[12];\n  float fPPInputToIndexInputMatrix[12];\n  float fIndexInputToPPInputMatrix[12];\n  for (int j = 0; j < 12; j++)\n  {\n    fIndexInputToIndexDVFMatrix[j] = (float)indexInputToIndexDVFMatrix[j / 4][j % 4];\n    fPPInputToIndexInputMatrix[j] = (float)PPInputToIndexInputMatrix[j / 4][j % 4];\n    fIndexInputToPPInputMatrix[j] = (float)indexInputToPPInputMatrix[j / 4][j % 4];\n  }\n\n  // Account for system rotations\n  Superclass::GeometryType::ThreeDHomogeneousMatrixType volPPToIndex;\n  volPPToIndex = GetPhysicalPointToIndexMatrix(this->GetInputVolume().GetPointer());\n\n  // Compute matrix to translate the pixel indices on the volume and the detector\n  // if the Requested region has non-zero index\n  Superclass::GeometryType::ThreeDHomogeneousMatrixType projIndexTranslation, volIndexTranslation;\n  projIndexTranslation.SetIdentity();\n  volIndexTranslation.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    projIndexTranslation[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex(i);\n    volIndexTranslation[i][3] = -this->GetInputVolume()->GetBufferedRegion().GetIndex(i);\n\n    // Adding 0.5 offset to change from the centered pixel convention (ITK)\n    // to the corner pixel convention (CUDA).\n    volPPToIndex[i][3] += 0.5;\n  }\n\n  // Compute matrices to transform projection index to volume index, one per projection\n  float * matrices = new float[12 * nProj];\n  float * source_positions = new float[4 * nProj];\n\n  // Go over each projection\n  for (unsigned int iProj = iFirstProj; iProj < iFirstProj + nProj; iProj++)\n  {\n    Superclass::GeometryType::ThreeDHomogeneousMatrixType d_matrix;\n    d_matrix = volIndexTranslation.GetVnlMatrix() * volPPToIndex.GetVnlMatrix() *\n               geometry->GetProjectionCoordinatesToFixedSystemMatrix(iProj).GetVnlMatrix() *\n               rtk::GetIndexToPhysicalPointMatrix(this->GetInput()).GetVnlMatrix() *\n               projIndexTranslation.GetVnlMatrix();\n    for (int j = 0; j < 3; j++) // Ignore the 4th row\n      for (int k = 0; k < 4; k++)\n        matrices[(j + 3 * (iProj - iFirstProj)) * 4 + k] = (float)d_matrix[j][k];\n\n    // Compute source position in volume indices\n    source_position = volPPToIndex * geometry->GetSourcePosition(iProj);\n\n    // Copy it into a single large array\n    for (unsigned int d = 0; d < 3; d++)\n      source_positions[(iProj - iFirstProj) * 3 + d] = source_position[d]; // Ignore the 4th component\n  }\n\n  int projectionOffset = 0;\n  for (unsigned int i = 0; i < nProj; i += SLAB_SIZE)\n  {\n    // If nProj is not a multiple of SLAB_SIZE, the last slab will contain less than SLAB_SIZE projections\n    projectionSize[2] = std::min(nProj - i, (unsigned int)SLAB_SIZE);\n    projectionOffset = iFirstProj + i - this->GetOutput()->GetBufferedRegion().GetIndex(2);\n\n    CUDA_warp_forward_project(projectionSize,\n                              volumeSize,\n                              inputDVFSize,\n                              (float *)&(matrices[12 * i]),\n                              pin + nPixelsPerProj * projectionOffset,\n                              pout + nPixelsPerProj * projectionOffset,\n                              pvol,\n                              m_StepSize,\n                              (float *)&(source_positions[3 * i]),\n                              boxMin,\n                              boxMax,\n                              spacing,\n                              pDVF,\n                              fIndexInputToIndexDVFMatrix,\n                              fPPInputToIndexInputMatrix,\n                              fIndexInputToPPInputMatrix);\n  }\n\n  delete[] matrices;\n  delete[] source_positions;\n}\n\n} // end namespace rtk\n\n#endif\n"
  },
  {
    "path": "src/rtkCudaWarpImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/* -----------------------------------------------------------------------\n   See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information\n   ----------------------------------------------------------------------- */\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaWarpImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n\n// CONSTANTS //////////////////////////////////////////////////////////////\n__constant__ float c_IndexOutputToPPOutputMatrix[12];\n__constant__ float c_IndexOutputToIndexDVFMatrix[12];\n__constant__ float c_PPInputToIndexInputMatrix[12];\n////////////////////////////////////////////////////////////////////////////\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n__global__ void\nkernel_3Dgrid(float *             dev_vol_out,\n              int3                vol_dim,\n              cudaTextureObject_t tex_xdvf,\n              cudaTextureObject_t tex_ydvf,\n              cudaTextureObject_t tex_zdvf,\n              cudaTextureObject_t tex_input_vol)\n{\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= vol_dim.x || j >= vol_dim.y || k >= vol_dim.z)\n  {\n    return;\n  }\n\n  // Index row major into the volume\n  long int vol_idx = i + (j + k * vol_dim.y) * (vol_dim.x);\n\n  // Matrix multiply to get the index in the DVF texture of the current point in the output volume\n  float3 IndexInDVF = matrix_multiply(make_float3(i, j, k), c_IndexOutputToIndexDVFMatrix);\n\n  // Get each component of the displacement vector by\n  // interpolation in the dvf\n  float3 Displacement;\n  Displacement.x = tex3D<float>(tex_xdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n  Displacement.y = tex3D<float>(tex_ydvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n  Displacement.z = tex3D<float>(tex_zdvf, IndexInDVF.x + 0.5f, IndexInDVF.y + 0.5f, IndexInDVF.z + 0.5f);\n\n  // Matrix multiply to get the physical coordinates of the current point in the output volume\n  float3 PP = matrix_multiply(make_float3(i, j, k), c_IndexOutputToPPOutputMatrix);\n\n  // Get the index corresponding to the current physical point in output displaced by the displacement vector\n  PP += Displacement;\n\n  // Convert it to a continuous index\n  float3 IndexInInput = matrix_multiply(PP, c_PPInputToIndexInputMatrix);\n\n  // Interpolate in the input and copy into the output\n  dev_vol_out[vol_idx] =\n    tex3D<float>(tex_input_vol, IndexInInput.x + 0.5f, IndexInInput.y + 0.5f, IndexInInput.z + 0.5f);\n}\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_warp /////////////////////////////\nvoid\nCUDA_warp(int     input_vol_dim[3],\n          int     input_dvf_dim[3],\n          int     output_vol_dim[3],\n          float   IndexOutputToPPOutputMatrix[12],\n          float   IndexOutputToIndexDVFMatrix[12],\n          float   PPInputToIndexInputMatrix[12],\n          float * dev_input_vol,\n          float * dev_output_vol,\n          float * dev_DVF,\n          bool    isLinear)\n{\n  // Prepare DVF textures\n  std::vector<cudaArray *>         DVFComponentArrays;\n  std::vector<cudaTextureObject_t> tex_dvf;\n  prepareVectorTextureObject(input_dvf_dim, dev_DVF, DVFComponentArrays, 3, tex_dvf, false);\n\n  // Prepare volume texture\n  cudaArray *         array_input_vol;\n  cudaTextureObject_t tex_input_vol;\n  prepareScalarTextureObject(output_vol_dim, dev_input_vol, array_input_vol, tex_input_vol, false, isLinear);\n\n  // Copy matrices into constant memory\n  cudaMemcpyToSymbol(\n    c_IndexOutputToPPOutputMatrix, IndexOutputToPPOutputMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  cudaMemcpyToSymbol(\n    c_IndexOutputToIndexDVFMatrix, IndexOutputToIndexDVFMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  cudaMemcpyToSymbol(\n    c_PPInputToIndexInputMatrix, PPInputToIndexInputMatrix, 12 * sizeof(float), 0, cudaMemcpyHostToDevice);\n  CUDA_CHECK_ERROR;\n\n  // Thread Block Dimensions\n  constexpr int tBlock_x = 16;\n  constexpr int tBlock_y = 4;\n  constexpr int tBlock_z = 4;\n\n  // Each element in the volume (each voxel) gets 1 thread\n  unsigned int blocksInX = (output_vol_dim[0] - 1) / tBlock_x + 1;\n  unsigned int blocksInY = (output_vol_dim[1] - 1) / tBlock_y + 1;\n  unsigned int blocksInZ = (output_vol_dim[2] - 1) / tBlock_z + 1;\n\n  dim3 dimGrid = dim3(blocksInX, blocksInY, blocksInZ);\n  dim3 dimBlock = dim3(tBlock_x, tBlock_y, tBlock_z);\n\n  kernel_3Dgrid<<<dimGrid, dimBlock>>>(dev_output_vol,\n                                       make_int3(output_vol_dim[0], output_vol_dim[1], output_vol_dim[2]),\n                                       tex_dvf[0],\n                                       tex_dvf[1],\n                                       tex_dvf[2],\n                                       tex_input_vol);\n  CUDA_CHECK_ERROR;\n\n  // Cleanup\n  for (unsigned int c = 0; c < 3; c++)\n  {\n    cudaFreeArray(DVFComponentArrays[c]);\n    CUDA_CHECK_ERROR;\n    cudaDestroyTextureObject(tex_dvf[c]);\n    CUDA_CHECK_ERROR;\n  }\n  cudaFreeArray(array_input_vol);\n  CUDA_CHECK_ERROR;\n  cudaDestroyTextureObject(tex_input_vol);\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkCudaWarpImageFilter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkCudaWarpImageFilter.h\"\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkCudaWarpImageFilter.hcu\"\n#include \"rtkHomogeneousMatrix.h\"\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itkLinearInterpolateImageFunction.h>\n#include <itkMacro.h>\n\nnamespace rtk\n{\n\nCudaWarpImageFilter ::CudaWarpImageFilter() {}\n\nvoid\nCudaWarpImageFilter ::GPUGenerateData()\n{\n  // Include non-zero index in matrix\n  itk::Matrix<double, 4, 4> matrixIdxOutputVol;\n  itk::Matrix<double, 4, 4> matrixIdxInputVol;\n  itk::Matrix<double, 4, 4> indexOutputToPPOutputMatrix;\n  itk::Matrix<double, 4, 4> indexOutputToIndexDVFMatrix;\n  itk::Matrix<double, 4, 4> PPInputToIndexInputMatrix;\n  matrixIdxOutputVol.SetIdentity();\n  matrixIdxInputVol.SetIdentity();\n  for (unsigned int i = 0; i < 3; i++)\n  {\n    matrixIdxOutputVol[i][3] = this->GetOutput()->GetRequestedRegion().GetIndex()[i];\n    matrixIdxInputVol[i][3] = this->GetInput()->GetBufferedRegion().GetIndex()[i]; // Should 0.5 be added here ?\n  }\n\n  // Cuda convenient format for dimensions\n  int inputVolumeSize[3];\n  inputVolumeSize[0] = this->GetInput(0)->GetBufferedRegion().GetSize()[0];\n  inputVolumeSize[1] = this->GetInput(0)->GetBufferedRegion().GetSize()[1];\n  inputVolumeSize[2] = this->GetInput(0)->GetBufferedRegion().GetSize()[2];\n\n  int inputDVFSize[3];\n  inputDVFSize[0] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[0];\n  inputDVFSize[1] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[1];\n  inputDVFSize[2] = this->GetDisplacementField()->GetBufferedRegion().GetSize()[2];\n\n  int outputVolumeSize[3];\n  outputVolumeSize[0] = this->GetOutput()->GetBufferedRegion().GetSize()[0];\n  outputVolumeSize[1] = this->GetOutput()->GetBufferedRegion().GetSize()[1];\n  outputVolumeSize[2] = this->GetOutput()->GetBufferedRegion().GetSize()[2];\n\n#ifdef CudaCommon_VERSION_MAJOR\n  float * pinVol = (float *)(this->GetInput(0)->GetCudaDataManager()->GetGPUBufferPointer());\n  float * poutVol = (float *)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pDVF = (float *)(this->GetDisplacementField()->GetCudaDataManager()->GetGPUBufferPointer());\n#else\n  float * pinVol = *(float **)(this->GetInput(0)->GetCudaDataManager()->GetGPUBufferPointer());\n  float * poutVol = *(float **)(this->GetOutput()->GetCudaDataManager()->GetGPUBufferPointer());\n  float * pDVF = *(float **)(this->GetDisplacementField()->GetCudaDataManager()->GetGPUBufferPointer());\n#endif\n\n  // Transform matrices that we will need during the warping process\n  indexOutputToPPOutputMatrix =\n    rtk::GetIndexToPhysicalPointMatrix(this->GetOutput()).GetVnlMatrix() * matrixIdxOutputVol.GetVnlMatrix();\n\n  indexOutputToIndexDVFMatrix = rtk::GetPhysicalPointToIndexMatrix(this->GetDisplacementField()).GetVnlMatrix() *\n                                rtk::GetIndexToPhysicalPointMatrix(this->GetOutput()).GetVnlMatrix() *\n                                matrixIdxOutputVol.GetVnlMatrix();\n\n  PPInputToIndexInputMatrix = rtk::GetPhysicalPointToIndexMatrix(this->GetInput(0)).GetVnlMatrix();\n\n  // Convert the matrices to arrays of floats (skipping the last line, as we don't care)\n  float fIndexOutputToPPOutputMatrix[12];\n  float fIndexOutputToIndexDVFMatrix[12];\n  float fPPInputToIndexInputMatrix[12];\n  for (int j = 0; j < 12; j++)\n  {\n    fIndexOutputToIndexDVFMatrix[j] = (float)indexOutputToIndexDVFMatrix[j / 4][j % 4];\n    fPPInputToIndexInputMatrix[j] = (float)PPInputToIndexInputMatrix[j / 4][j % 4];\n    fIndexOutputToPPOutputMatrix[j] = (float)indexOutputToPPOutputMatrix[j / 4][j % 4];\n  }\n\n  bool isLinear;\n  if (std::string(\"LinearInterpolateImageFunction\").compare(this->GetInterpolator()->GetNameOfClass()) == 0)\n    isLinear = true;\n  else if (std::string(\"NearestNeighborInterpolateImageFunction\").compare(this->GetInterpolator()->GetNameOfClass()) ==\n           0)\n    isLinear = false;\n  else\n    itkGenericExceptionMacro(<< \"In rtkCudaWarpImageFilter: unknown interpolator\");\n\n  // Run on GPU\n  CUDA_warp(inputVolumeSize,\n            inputDVFSize,\n            outputVolumeSize,\n            fIndexOutputToPPOutputMatrix,\n            fIndexOutputToIndexDVFMatrix,\n            fPPInputToIndexInputMatrix,\n            pinVol,\n            poutVol,\n            pDVF,\n            isLinear);\n}\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkCudaWeidingerForwardModelImageFilter.cu",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n/* -----------------------------------------------------------------------\n   See COPYRIGHT.TXT and LICENSE.TXT for copyright and license information\n   ----------------------------------------------------------------------- */\n/*****************\n *  rtk #includes *\n *****************/\n#include \"rtkCudaUtilities.hcu\"\n#include \"rtkConfiguration.h\"\n#include \"rtkCudaWeidingerForwardModelImageFilter.hcu\"\n\n/*****************\n *  C   #includes *\n *****************/\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <cmath>\n\n/*****************\n * CUDA #includes *\n *****************/\n#include <cuda.h>\n#include <cuda_runtime.h>\n\n#define IDX2D(r, c, cols) ((r) * (cols) + (c))\n\n// CONSTANTS //////////////////////////////////////////////////////////////\n__constant__ int3  c_projSize;\n__constant__ float c_materialAttenuations[3 * 150];\n__constant__ float c_binnedDetectorResponse[5 * 150];\n////////////////////////////////////////////////////////////////////////////\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_( S T A R T )_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\ntemplate <unsigned int VBins, unsigned int VEnergies, unsigned int VMaterials>\n__global__ void\nkernel_forward_model(float *      pMatProj,\n                     float *      pPhoCount,\n                     float *      pSpectrum,\n                     float *      pProjOnes,\n                     float *      pOut1,\n                     float *      pOut2,\n                     unsigned int nProjSpectrum,\n                     int          nIdxProj)\n{\n  unsigned int i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;\n  unsigned int j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;\n  unsigned int k = __umul24(blockIdx.z, blockDim.z) + threadIdx.z;\n\n  if (i >= c_projSize.x || j >= c_projSize.y || k >= c_projSize.z)\n  {\n    return;\n  }\n\n  // Index row major in the projection\n  long int first_proj_idx =\n    i + (j + (nIdxProj + k) % nProjSpectrum * c_projSize.y) * c_projSize.x; // To determine the efficient spectrum\n  long int proj_idx = i + (j + k * c_projSize.y) * (c_projSize.x);          // For all the rest\n\n  // Compute the efficient spectrum at the current pixel\n  float efficientSpectrum[VBins * VEnergies];\n  for (unsigned int b = 0; b < VBins; b++)\n    for (unsigned int e = 0; e < VEnergies; e++)\n      efficientSpectrum[IDX2D(b, e, VEnergies)] =\n        pSpectrum[e + VEnergies * first_proj_idx] * c_binnedDetectorResponse[IDX2D(b, e, VEnergies)];\n\n  // Get attenuation factors at each energy from material projections\n  float attenuationFactors[VEnergies];\n  matrix_matrix_multiply(\n    c_materialAttenuations, (float *)&pMatProj[proj_idx * VMaterials], attenuationFactors, VEnergies, 1, VMaterials);\n\n  for (unsigned int e = 0; e < VEnergies; e++)\n    attenuationFactors[e] = std::exp(-attenuationFactors[e]);\n\n  // Get the expected photon counts through these attenuations\n  float expectedCounts[VBins];\n  matrix_matrix_multiply(efficientSpectrum, attenuationFactors, expectedCounts, VBins, 1, VEnergies);\n\n  // Get intermediate variables used in the computation of the first output\n  float oneMinusRatios[VBins];\n  for (unsigned int b = 0; b < VBins; b++)\n    oneMinusRatios[b] = 1 - (pPhoCount[proj_idx * VBins + b] / expectedCounts[b]);\n\n  // Form an intermediate variable used for the gradient of the cost function,\n  // (the derivation of the exponential implies that a m_MaterialAttenuations\n  // gets out), by equivalent of element-wise product with implicit extension\n  float intermForGradient[VEnergies * VMaterials];\n  for (unsigned int e = 0; e < VEnergies; e++)\n    for (unsigned int m = 0; m < VMaterials; m++)\n      intermForGradient[IDX2D(e, m, VMaterials)] =\n        c_materialAttenuations[IDX2D(e, m, VMaterials)] * attenuationFactors[e];\n\n  // Multiply by the spectrum\n  float interm2ForGradient[VBins * VMaterials];\n  matrix_matrix_multiply(efficientSpectrum, intermForGradient, interm2ForGradient, VBins, VMaterials, VEnergies);\n\n  // Take the opposite\n  for (unsigned int b = 0; b < VBins; b++)\n    for (unsigned int m = 0; m < VMaterials; m++)\n      interm2ForGradient[IDX2D(b, m, VMaterials)] *= -1;\n\n  // Compute the product with oneMinusRatios, with implicit extension\n  for (unsigned int b = 0; b < VBins; b++)\n    for (unsigned int m = 0; m < VMaterials; m++)\n      interm2ForGradient[IDX2D(b, m, VMaterials)] *= oneMinusRatios[b];\n\n  // Finally, compute the vector to be written in first output\n  // by summing on the bins\n  for (unsigned int b = 0; b < VBins; b++)\n    for (unsigned int m = 0; m < VMaterials; m++)\n      pOut1[proj_idx * VMaterials + m] += interm2ForGradient[IDX2D(b, m, VMaterials)];\n\n  // Now compute output2\n\n  // Form an intermediate variable used for the hessian of the cost function,\n  // (the double derivation of the exponential implies that a m_MaterialAttenuations^2\n  // gets out), by equivalent of element-wise product with implicit extension\n  float intermForHessian[VEnergies * VMaterials * VMaterials];\n  for (unsigned int r = 0; r < VEnergies; r++)\n    for (unsigned int c = 0; c < VMaterials; c++)\n      for (unsigned int c2 = 0; c2 < VMaterials; c2++)\n        intermForHessian[(r * VMaterials + c) * VMaterials + c2] = c_materialAttenuations[c + VMaterials * r] *\n                                                                   c_materialAttenuations[c2 + VMaterials * r] *\n                                                                   attenuationFactors[r];\n\n  // Multiply by the spectrum\n  float interm2ForHessian[VBins * VMaterials * VMaterials];\n  matrix_matrix_multiply(\n    efficientSpectrum, intermForHessian, interm2ForHessian, VBins, VMaterials * VMaterials, VEnergies);\n\n  // Sum on the bins\n  for (unsigned int b = 0; b < VBins; b++)\n    for (unsigned int c = 0; c < VMaterials * VMaterials; c++)\n      pOut2[proj_idx * VMaterials * VMaterials + c] += interm2ForHessian[IDX2D(b, c, VMaterials * VMaterials)];\n\n  // Multiply by the projection of ones\n  for (unsigned int c = 0; c < VMaterials * VMaterials; c++)\n    pOut2[proj_idx * VMaterials * VMaterials + c] *= pProjOnes[proj_idx];\n}\n\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n// K E R N E L S -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-( E N D )-_-_\n//_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_\n\n///////////////////////////////////////////////////////////////////////////\n// FUNCTION: CUDA_WeidingerForwardModel /////////////////////////////\nvoid\nCUDA_WeidingerForwardModel(int          projectionSize[3],\n                           float *      materialAttenuations,\n                           float *      binnedDetectorResponse,\n                           float *      pMatProj,\n                           float *      pPhoCount,\n                           float *      pSpectrum,\n                           float *      pProjOnes,\n                           float *      pOut1,\n                           float *      pOut2,\n                           unsigned int nBins,\n                           unsigned int nEnergies,\n                           unsigned int nMaterials,\n                           unsigned int nProjSpectrum,\n                           int          nIdxProj)\n{\n  cudaMemcpyToSymbol(c_projSize, projectionSize, sizeof(int3));\n  cudaMemcpyToSymbol(c_binnedDetectorResponse, &(binnedDetectorResponse[0]), nBins * nEnergies * sizeof(float));\n  cudaMemcpyToSymbol(c_materialAttenuations, &(materialAttenuations[0]), nMaterials * nEnergies * sizeof(float));\n\n  // Set both outputs to zeros\n  size_t memSize = sizeof(float) * projectionSize[0] * projectionSize[1] * projectionSize[2] * nMaterials;\n  cudaMemset((void *)pOut1, 0, memSize);\n  cudaMemset((void *)pOut2, 0, memSize);\n\n  dim3 dimBlock = dim3(4, 4, 4);\n  dim3 dimGrid = dim3(iDivUp(projectionSize[0], dimBlock.x),\n                      iDivUp(projectionSize[1], dimBlock.y),\n                      iDivUp(projectionSize[2], dimBlock.z));\n\n  if (nBins == 5 && nEnergies == 150)\n  {\n    switch (nMaterials)\n    {\n      case 2:\n        kernel_forward_model<5, 150, 2>\n          <<<dimGrid, dimBlock>>>(pMatProj, pPhoCount, pSpectrum, pProjOnes, pOut1, pOut2, nProjSpectrum, nIdxProj);\n        break;\n\n      case 3:\n        kernel_forward_model<5, 150, 3>\n          <<<dimGrid, dimBlock>>>(pMatProj, pPhoCount, pSpectrum, pProjOnes, pOut1, pOut2, nProjSpectrum, nIdxProj);\n        break;\n\n      default:\n      {\n        itkGenericExceptionMacro(<< \"The CUDA version of WeidingerForwardModel works with hard-coded parameters, \"\n                                    \"currently set to 2 or 3 materials.\"\n                                 << nMaterials << \" is not supported.\");\n      }\n    }\n    CUDA_CHECK_ERROR;\n  }\n  else if (nBins == 1 && nEnergies == 79)\n  {\n    switch (nMaterials)\n    {\n      case 2:\n        kernel_forward_model<1, 79, 2>\n          <<<dimGrid, dimBlock>>>(pMatProj, pPhoCount, pSpectrum, pProjOnes, pOut1, pOut2, nProjSpectrum, nIdxProj);\n        break;\n      case 3:\n        kernel_forward_model<1, 79, 3>\n          <<<dimGrid, dimBlock>>>(pMatProj, pPhoCount, pSpectrum, pProjOnes, pOut1, pOut2, nProjSpectrum, nIdxProj);\n        break;\n      default:\n      {\n        itkGenericExceptionMacro(<< \"The CUDA version of WeidingerForwardModel works with hard-coded parameters, \"\n                                    \"currently set to 2 or 3 materials.\"\n                                 << nMaterials << \" is not supported.\");\n      }\n    }\n    CUDA_CHECK_ERROR;\n  }\n  else\n  {\n    itkGenericExceptionMacro(<< \"The CUDA version of WeidingerForwardModel works with hard-coded parameters \"\n                                \"(nBins,nEnergies) equal to (5,150),(5,150),(1,79),(1,79).\");\n  }\n  CUDA_CHECK_ERROR;\n}\n"
  },
  {
    "path": "src/rtkDCMImagXImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkDCMImagXImageIO.h\"\n\n#include <gdcmImageReader.h>\n#include <gdcmAttribute.h>\n\nvoid\nrtk::DCMImagXImageIO::ReadImageInformation()\n{\n  Superclass::ReadImageInformation();\n\n  this->SetOrigin(0, (this->GetDimensions(0) - 1) * (-0.5) * this->GetSpacing(0));\n  this->SetOrigin(1, (this->GetDimensions(1) - 1) * (-0.5) * this->GetSpacing(1));\n  this->SetOrigin(2, 0.);\n}\n\nbool\nrtk::DCMImagXImageIO::CanReadFile(const char * FileNameToRead)\n{\n  if (!Superclass::CanReadFile(FileNameToRead))\n    return false;\n\n  // Check IBA label, reading manufacturer's name\n  gdcm::ImageReader reader;\n  reader.SetFileName(FileNameToRead);\n  reader.Read();\n\n  gdcm::DataSet &            ds = reader.GetFile().GetDataSet();\n  gdcm::Attribute<0x8, 0x70> at1;\n  at1.SetFromDataSet(ds);\n  std::string value = at1.GetValue();\n\n  return bool(value == \"IBA \");\n}\n\nbool\nrtk::DCMImagXImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n"
  },
  {
    "path": "src/rtkDCMImagXImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkDCMImagXImageIOFactory.h\"\n\n//====================================================================\nrtk::DCMImagXImageIOFactory::DCMImagXImageIOFactory()\n{\n  this->RegisterOverride(\"itkImageIOBase\",\n                         \"DCMImagXImageIO\",\n                         \"ImagX Image IO for its DICOM file format\",\n                         true,\n                         itk::CreateObjectFunction<DCMImagXImageIO>::New());\n}\n\n// Undocumented API used to register during static initialization.\n// DO NOT CALL DIRECTLY.\n\nnamespace itk\n{\n\nstatic bool DCMImagXImageIOFactoryHasBeenRegistered;\n\nvoid RTK_EXPORT\nDCMImagXImageIOFactoryRegister__Private()\n{\n  if (!DCMImagXImageIOFactoryHasBeenRegistered)\n  {\n    DCMImagXImageIOFactoryHasBeenRegistered = true;\n    rtk::DCMImagXImageIOFactory::RegisterOneFactory();\n  }\n}\n\n} // end namespace itk\n"
  },
  {
    "path": "src/rtkDbf.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include <utility>\n\n#include \"rtkDbf.h\"\n\nnamespace rtk\n{\n\nDbfField::DbfField(std::string name, char type, unsigned char length, short recOffset)\n  : m_Name(std::move(name))\n  , m_Type(type)\n  , m_Length(length)\n  , m_RecOffset(recOffset)\n{}\n\nDbfFile::DbfFile(std::string fileName)\n{\n  m_Stream.open(fileName.c_str(), std::ios_base::in | std::ios_base::binary);\n  if (!m_Stream.is_open())\n    return;\n\n  // Ignore version and date\n  m_Stream.seekg(4);\n\n  // Read number of records, header size, record size\n  m_Stream.read((char *)&m_NumRecords, sizeof(m_NumRecords));\n  m_Stream.read((char *)&m_HeaderSize, sizeof(m_HeaderSize));\n  m_Stream.read((char *)&m_RecordSize, sizeof(m_RecordSize));\n\n  // Record allocation\n  m_Record = new char[m_RecordSize];\n\n  // The number of fields depends on the header size (32 are the blocks\n  // describing the global part and each field, 1 is the terminator length)\n  const unsigned int numFields = (m_HeaderSize - 32 - 1) / 32;\n\n  // First byte is the deletion character. Then the field data are concatenated\n  short fldRecOffset = 1;\n  for (unsigned int i = 0; i < numFields; i++)\n  {\n\n    // Go to beginning of current field structure description\n    m_Stream.seekg(32 * (1 + i));\n\n    // Field names\n    char fldName[11];\n    m_Stream.read(fldName, 11);\n\n    // Field types\n    char fldType = 0;\n    m_Stream.read((char *)&fldType, sizeof(fldType));\n\n    // Skip displacement of field in record?\n    m_Stream.seekg(4, std::ios_base::cur);\n\n    // Field length\n    unsigned char fldLength = 0;\n    m_Stream.read((char *)&fldLength, sizeof(fldLength));\n\n    // Add field and go to next\n    m_Fields.emplace_back(fldName, fldType, fldLength, fldRecOffset);\n    m_MapFieldNameIndex[m_Fields.back().GetName()] = i;\n\n    fldRecOffset += fldLength;\n  }\n\n  // Seek to first record\n  m_Stream.seekg(m_HeaderSize);\n}\n\nDbfFile::~DbfFile() { delete[] m_Record; }\n\nbool\nDbfFile::ReadNextRecord()\n{\n  do\n  {\n    m_Stream.read(m_Record, m_RecordSize);\n  } while (m_Stream.gcount() == m_RecordSize && m_Record[0] == 0x2A);\n  return m_Stream.gcount() == m_RecordSize;\n}\n\nstd::string\nDbfFile::GetFieldAsString(std::string fldName)\n{\n  DbfField &  field = m_Fields[m_MapFieldNameIndex[fldName]];\n  std::string result(m_Record + field.GetRecOffset(), field.GetLength());\n\n  // Revome begin/end spaces\n  std::string::size_type pos = result.find_last_not_of(' ');\n\n  if (pos != std::string::npos)\n  {\n    result.erase(pos + 1);\n    pos = result.find_first_not_of(' ');\n    if (pos != std::string::npos)\n      result.erase(0, pos);\n  }\n  else\n    result.erase(result.begin(), result.end());\n\n  return result;\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkDigisensGeometryReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkDigisensGeometryReader.h\"\n#include \"rtkDigisensGeometryXMLFileReader.h\"\n\n#include <itkMetaDataObject.h>\n#include <itkVersor.h>\n#include <itkCenteredEuler3DTransform.h>\n\nrtk::DigisensGeometryReader ::DigisensGeometryReader() = default;\n\nvoid\nrtk::DigisensGeometryReader ::GenerateData()\n{\n  // Create new RTK geometry object\n  m_Geometry = GeometryType::New();\n\n  // Read Varian XML file (for common geometric information)\n  rtk::DigisensGeometryXMLFileReader::Pointer digisensXmlReader;\n  digisensXmlReader = rtk::DigisensGeometryXMLFileReader::New();\n  digisensXmlReader->SetFilename(m_XMLFileName);\n  digisensXmlReader->GenerateOutputInformation();\n\n  // Constants used to generate projection matrices\n  itk::MetaDataDictionary & dic = *(digisensXmlReader->GetOutputObject());\n\n  // Getting elements positions\n  using MetaDataVectorType = itk::MetaDataObject<GeometryType::VectorType>;\n  GeometryType::VectorType rotationAxis =\n    dynamic_cast<MetaDataVectorType *>(dic[\"ROTATIONaxis\"].GetPointer())->GetMetaDataObjectValue();\n  GeometryType::VectorType rotationCenter =\n    dynamic_cast<MetaDataVectorType *>(dic[\"ROTATIONcenter\"].GetPointer())->GetMetaDataObjectValue();\n  GeometryType::VectorType sourcePosition =\n    dynamic_cast<MetaDataVectorType *>(dic[\"XRAYsource\"].GetPointer())->GetMetaDataObjectValue();\n  GeometryType::VectorType detectorPosition =\n    dynamic_cast<MetaDataVectorType *>(dic[\"CAMERAreference\"].GetPointer())->GetMetaDataObjectValue();\n  GeometryType::VectorType detectorNormal =\n    dynamic_cast<MetaDataVectorType *>(dic[\"CAMERAnormal\"].GetPointer())->GetMetaDataObjectValue();\n  GeometryType::VectorType detectorHorizontal =\n    dynamic_cast<MetaDataVectorType *>(dic[\"CAMERAhorizontal\"].GetPointer())->GetMetaDataObjectValue();\n  GeometryType::VectorType detectorVertical =\n    dynamic_cast<MetaDataVectorType *>(dic[\"CAMERAvertical\"].GetPointer())->GetMetaDataObjectValue();\n\n  // Check assumptions\n  if (sourcePosition[0] != 0. || sourcePosition[1] != 0. || detectorNormal[0] != 0. || detectorNormal[1] != 0. ||\n      detectorHorizontal[1] != 0. || detectorHorizontal[2] != 0. || detectorVertical[0] != 0. ||\n      detectorVertical[2] != 0.)\n  {\n    itkGenericExceptionMacro(<< \"Geometric assumptions not verified\");\n  }\n\n  // Source / Detector / Center distances\n  double sdd = itk::Math::abs(sourcePosition[2] - detectorPosition[2]);\n  double sid = itk::Math::abs(sourcePosition[2] - rotationCenter[2]);\n\n  // Scaling\n  using MetaDataIntegerType = itk::MetaDataObject<int>;\n  // int pixelWidth = dynamic_cast<MetaDataIntegerType *>(dic[\"CAMERApixelWidth\"].GetPointer()\n  // )->GetMetaDataObjectValue(); int pixelHeight = dynamic_cast<MetaDataIntegerType\n  // *>(dic[\"CAMERApixelHeight\"].GetPointer() )->GetMetaDataObjectValue();\n  using MetaDataDoubleType = itk::MetaDataObject<double>;\n  // double totalWidth = dynamic_cast<MetaDataDoubleType *>(dic[\"CAMERAtotalWidth\"].GetPointer()\n  // )->GetMetaDataObjectValue(); double totalHeight = dynamic_cast<MetaDataDoubleType\n  // *>(dic[\"CAMERAtotalHeight\"].GetPointer() )->GetMetaDataObjectValue(); double projectionScalingX =\n  // detectorHorizontal[0] * totalWidth / (pixelWidth-1); double projectionScalingY = detectorVertical[1] * totalHeight\n  // / (pixelHeight-1);\n\n  // Projection offset: the offset is given in the volume coordinate system =>\n  // convert to\n  double projectionOffsetX = detectorPosition[0] * detectorHorizontal[0];\n  double projectionOffsetY = detectorPosition[1] * detectorVertical[1];\n\n  // Rotation\n  double startAngle =\n    dynamic_cast<MetaDataDoubleType *>(dic[\"RADIOSstartAngle\"].GetPointer())->GetMetaDataObjectValue();\n  double angularRange =\n    dynamic_cast<MetaDataDoubleType *>(dic[\"RADIOSangularRange\"].GetPointer())->GetMetaDataObjectValue();\n  int nProj = dynamic_cast<MetaDataIntegerType *>(dic[\"RADIOSNumberOfFiles\"].GetPointer())->GetMetaDataObjectValue();\n  for (int i = 0; i < nProj; i++)\n  {\n    // Convert rotation center and rotation axis parameterization to euler angles\n    double angle = -startAngle - i * angularRange / nProj;\n\n    const double        degreesToRadians = std::atan(1.0) / 45.0;\n    itk::Versor<double> xfm3DVersor;\n    xfm3DVersor.Set(rotationAxis, angle * degreesToRadians);\n\n    auto xfm3D = itk::CenteredEuler3DTransform<double>::New();\n    xfm3D->SetMatrix(xfm3DVersor.GetMatrix());\n\n    m_Geometry->AddProjectionInRadians(sid,\n                                       sdd,\n                                       xfm3D->GetAngleY(),\n                                       projectionOffsetX,\n                                       projectionOffsetY,\n                                       xfm3D->GetAngleX(),\n                                       xfm3D->GetAngleZ(),\n                                       rotationCenter[0],\n                                       rotationCenter[1]);\n  }\n}\n"
  },
  {
    "path": "src/rtkDigisensGeometryXMLFileReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkDigisensGeometryXMLFileReader.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n#include <itkVector.h>\n\nnamespace rtk\n{\n\nDigisensGeometryXMLFileReader::DigisensGeometryXMLFileReader()\n{\n  m_OutputObject = &m_Dictionary;\n  m_NumberOfFiles = 0;\n  m_CurrentSection = NONE;\n  m_TreeLevel = 0;\n}\n\nint\nDigisensGeometryXMLFileReader::CanReadFile(const char * name)\n{\n  if (!itksys::SystemTools::FileExists(name) || itksys::SystemTools::FileIsDirectory(name) ||\n      itksys::SystemTools::FileLength(name) == 0)\n    return 0;\n  return 1;\n}\n\nvoid\nDigisensGeometryXMLFileReader::StartElement(const char * name, const char ** itkNotUsed(atts))\n{\n  m_CurCharacterData = \"\";\n\n  if (m_TreeLevel == 1)\n  {\n    if (itksys::SystemTools::Strucmp(name, \"Rotation\") == 0)\n      m_CurrentSection = ROTATION;\n    else if (itksys::SystemTools::Strucmp(name, \"XRay\") == 0)\n      m_CurrentSection = XRAY;\n    else if (itksys::SystemTools::Strucmp(name, \"Camera\") == 0)\n      m_CurrentSection = CAMERA;\n    else if (itksys::SystemTools::Strucmp(name, \"Radios\") == 0)\n    {\n      m_CurrentSection = RADIOS;\n      m_NumberOfFiles = 0;\n    }\n    else if (itksys::SystemTools::Strucmp(name, \"Grid\") == 0)\n      m_CurrentSection = GRID;\n    else if (itksys::SystemTools::Strucmp(name, \"Processing\") == 0)\n      m_CurrentSection = PROCESSING;\n  }\n  m_TreeLevel++;\n}\n\nvoid\nDigisensGeometryXMLFileReader::EndElement(const char * name)\n{\n  using VectorThreeDType = itk::Vector<double, 3>;\n  using Vector4DType = itk::Vector<double, 4>;\n\n#define ENCAPLULATE_META_DATA_3D(section, metaName)                                     \\\n  if (m_CurrentSection == section && itksys::SystemTools::Strucmp(name, metaName) == 0) \\\n  {                                                                                     \\\n    VectorThreeDType   vec;                                                             \\\n    std::istringstream iss(m_CurCharacterData);                                         \\\n    iss >> vec;                                                                         \\\n    itk::EncapsulateMetaData<VectorThreeDType>(m_Dictionary, #section metaName, vec);   \\\n  }\n\n#define ENCAPLULATE_META_DATA_4D(section, metaName)                                     \\\n  if (m_CurrentSection == section && itksys::SystemTools::Strucmp(name, metaName) == 0) \\\n  {                                                                                     \\\n    Vector4DType       vec;                                                             \\\n    std::istringstream iss(m_CurCharacterData);                                         \\\n    iss >> vec;                                                                         \\\n    itk::EncapsulateMetaData<Vector4DType>(m_Dictionary, #section metaName, vec);       \\\n  }\n\n#define ENCAPLULATE_META_DATA_INTEGER(section, metaName)                                \\\n  if (m_CurrentSection == section && itksys::SystemTools::Strucmp(name, metaName) == 0) \\\n  {                                                                                     \\\n    int i = std::stoi(m_CurCharacterData.c_str());                                      \\\n    itk::EncapsulateMetaData<int>(m_Dictionary, #section metaName, i);                  \\\n  }\n\n#define ENCAPLULATE_META_DATA_DOUBLE(section, metaName)                                 \\\n  if (m_CurrentSection == section && itksys::SystemTools::Strucmp(name, metaName) == 0) \\\n  {                                                                                     \\\n    double d = std::stod(m_CurCharacterData.c_str());                                   \\\n    itk::EncapsulateMetaData<double>(m_Dictionary, #section metaName, d);               \\\n  }\n\n  ENCAPLULATE_META_DATA_4D(GRID, \"rotation\");\n\n  ENCAPLULATE_META_DATA_3D(ROTATION, \"axis\");\n  ENCAPLULATE_META_DATA_3D(ROTATION, \"center\");\n  ENCAPLULATE_META_DATA_3D(XRAY, \"source\");\n  ENCAPLULATE_META_DATA_3D(CAMERA, \"reference\");\n  ENCAPLULATE_META_DATA_3D(CAMERA, \"normal\");\n  ENCAPLULATE_META_DATA_3D(CAMERA, \"horizontal\");\n  ENCAPLULATE_META_DATA_3D(CAMERA, \"vertical\");\n  ENCAPLULATE_META_DATA_3D(GRID, \"center\");\n  ENCAPLULATE_META_DATA_3D(GRID, \"scale\");\n  ENCAPLULATE_META_DATA_3D(GRID, \"resolution\");\n\n  ENCAPLULATE_META_DATA_INTEGER(CAMERA, \"pixelWidth\");\n  ENCAPLULATE_META_DATA_INTEGER(CAMERA, \"pixelHeight\");\n\n  ENCAPLULATE_META_DATA_DOUBLE(CAMERA, \"totalWidth\");\n  ENCAPLULATE_META_DATA_DOUBLE(CAMERA, \"totalHeight\");\n  ENCAPLULATE_META_DATA_DOUBLE(RADIOS, \"angularRange\");\n  ENCAPLULATE_META_DATA_DOUBLE(RADIOS, \"startAngle\");\n\n  if (m_CurrentSection == RADIOS && itksys::SystemTools::Strucmp(name, \"files\") == 0)\n    itk::EncapsulateMetaData<int>(m_Dictionary, \"RADIOSNumberOfFiles\", m_NumberOfFiles);\n\n  if (itksys::SystemTools::Strucmp(name, \"file\") == 0)\n    m_NumberOfFiles++;\n\n  m_TreeLevel--;\n}\n\nvoid\nDigisensGeometryXMLFileReader::CharacterDataHandler(const char * inData, int inLength)\n{\n  for (int i = 0; i < inLength; i++)\n    m_CurCharacterData = m_CurCharacterData + inData[i];\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkEdfImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkEdfImageIO.h\"\n#include <itk_zlib.h>\n#include <itkByteSwapper.h>\n#include <itkRawImageIO.h>\n\n//--------------------------------------------------------------------\n/* Find value_ptr as pointer to the parameter of the given key in the header.\n * Returns NULL on success.\n */\nchar *\nrtk::EdfImageIO::edf_findInHeader(char * header, const char * key)\n{\n  char * value_ptr = strstr(header, key);\n\n  if (!value_ptr)\n    return nullptr;\n  /* an edf line is \"key     = value ;\" */\n  value_ptr = 1 + strchr(value_ptr + strlen(key), '=');\n  while (isspace(*value_ptr))\n    value_ptr++;\n  return value_ptr;\n}\n\n//--------------------------------------------------------------------\n// Read Image Information\nvoid\nrtk::EdfImageIO::ReadImageInformation()\n{\n  int    k = 0;\n  char * header = nullptr;\n  int    header_size = 0;\n  char * p = nullptr;\n  gzFile inp = nullptr;\n\n  inp = gzopen(m_FileName.c_str(), \"rb\");\n  if (!inp)\n    itkGenericExceptionMacro(<< \"Cannot open input file \" << m_FileName);\n\n  // read header: it is a multiple of 512 B ending by \"}\\n\"\n  while (header_size == 0 || strncmp(&header[header_size - 2], \"}\\n\", 2))\n  {\n    int header_size_prev = header_size;\n    header_size += 512;\n    if (!header)\n      header = (char *)malloc(header_size + 1);\n    else\n      header = (char *)realloc(header, header_size + 1);\n    header[header_size_prev] = 0; /* protection against empty file */\n    // fread(header+header_size_prev, 512, 1, fp);\n    k = gzread(inp, header + header_size_prev, 512);\n    if (k < 512)\n    { /* protection against infinite loop */\n      gzclose(inp);\n      free(header);\n      itkGenericExceptionMacro(<< \"Damaged EDF header of \" << m_FileName << \": not multiple of 512 B.\");\n    }\n    header[header_size] = 0; /* end of string: protection against strstr later\n                               on */\n  }\n\n  // parse the header\n  int    dim1 = -1, dim2 = -1, datalen = -1;\n  char * otherfile_name = nullptr; // this file, or another file with the data (EDF vs\n                                   // EHF formats)\n  int otherfile_skip = 0;\n\n  if ((p = edf_findInHeader(header, \"EDF_BinaryFileName\")))\n  {\n    int plen = strcspn(p, \" ;\\n\");\n    otherfile_name = (char *)realloc(otherfile_name, plen + 1);\n    strncpy(otherfile_name, p, plen);\n    otherfile_name[plen] = '\\0';\n    if ((p = edf_findInHeader(header, \"EDF_BinaryFilePosition\")))\n      otherfile_skip = std::stoi(p);\n  }\n\n  if ((p = edf_findInHeader(header, \"Dim_1\")))\n    dim1 = std::stoi(p);\n  if ((p = edf_findInHeader(header, \"Dim_2\")))\n    dim2 = std::stoi(p);\n\n  //  int orig1 = -1, orig2 = -1;\n  //  if ((p = edf_findInHeader(header, \"row_beg\")))\n  //    orig1 = std::stoi(p);\n  //  if ((p = edf_findInHeader(header, \"col_beg\")))\n  //    orig2 = std::stoi(p);\n\n  static const struct table3 edf_datatype_table[] = { { \"UnsignedByte\", U_CHAR_DATATYPE, 1 },\n                                                      { \"SignedByte\", CHAR_DATATYPE, 1 },\n                                                      { \"UnsignedShort\", U_SHORT_DATATYPE, 2 },\n                                                      { \"SignedShort\", SHORT_DATATYPE, 2 },\n                                                      { \"UnsignedInteger\", U_INT_DATATYPE, 4 },\n                                                      { \"SignedInteger\", INT_DATATYPE, 4 },\n                                                      { \"UnsignedLong\", U_L_INT_DATATYPE, 4 },\n                                                      { \"SignedLong\", L_INT_DATATYPE, 4 },\n                                                      { \"FloatValue\", FLOAT_DATATYPE, 4 },\n                                                      { \"DoubleValue\", DOUBLE_DATATYPE, 8 },\n                                                      { \"Float\", FLOAT_DATATYPE, 4 },   // Float and FloatValue\n                                                                                        // are synonyms\n                                                      { \"Double\", DOUBLE_DATATYPE, 8 }, // Double and DoubleValue\n                                                                                        // are synonyms\n                                                      { nullptr, -1, -1 } };\n  if ((p = edf_findInHeader(header, \"DataType\")))\n  {\n    k = lookup_table3_nth(edf_datatype_table, p);\n    if (k < 0)\n    { // unknown EDF DataType\n      gzclose(inp);\n      free(header);\n      itkGenericExceptionMacro(<< \"Unknown EDF datatype \\\"\" << p << \"\\\"\");\n    }\n    datalen = edf_datatype_table[k].sajzof;\n    switch (edf_datatype_table[k].value)\n    {\n      case U_CHAR_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::UCHAR);\n        break;\n      case CHAR_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::CHAR);\n        break;\n      case U_SHORT_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::USHORT);\n        break;\n      case SHORT_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::SHORT);\n        break;\n      case U_INT_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::UINT);\n        break;\n      case INT_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::INT);\n        break;\n      case U_L_INT_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::UINT);\n        break;\n      case L_INT_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::INT);\n        break;\n      case FLOAT_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::FLOAT);\n        break;\n      case DOUBLE_DATATYPE:\n        SetComponentType(itk::ImageIOBase::IOComponentEnum::DOUBLE);\n        break;\n    }\n  }\n\n  static const struct table edf_byteorder_table[] = {\n    { \"LowByteFirst\", static_cast<int>(IOByteOrderEnum::LittleEndian) }, /* little endian */\n    { \"HighByteFirst\", static_cast<int>(IOByteOrderEnum::BigEndian) },   /* big endian */\n    { nullptr, -1 }\n  };\n\n  int byteorder = static_cast<int>(IOByteOrderEnum::LittleEndian);\n  if ((p = edf_findInHeader(header, \"ByteOrder\")))\n  {\n    k = lookup_table_nth(edf_byteorder_table, p);\n    if (k >= 0)\n    {\n\n      byteorder = edf_byteorder_table[k].value;\n      if (byteorder == static_cast<int>(IOByteOrderEnum::LittleEndian))\n        this->SetByteOrder(IOByteOrderEnum::LittleEndian);\n      else\n        this->SetByteOrder(IOByteOrderEnum::BigEndian);\n    }\n  }\n  else\n    itkWarningMacro(<< \"ByteOrder not specified in the header! Not swapping bytes (figure may not be correct).\");\n  // Get and verify size of the data:\n  int datasize = dim1 * dim2 * datalen;\n  if ((p = edf_findInHeader(header, \"Size\")))\n  {\n    int d = std::stoi(p);\n    if (d != datasize)\n    {\n      itkWarningMacro(<< \"Size \" << datasize << \" is not \" << dim1 << 'x' << dim2 << \"x\" << datalen << \" = \" << d\n                      << \". Supposing the latter.\");\n    }\n  }\n\n  // EHF files: binary data are in another file than the header file\n  m_BinaryFileName = m_FileName;\n  m_BinaryFileSkip = header_size;\n  if (otherfile_name)\n  {\n    m_BinaryFileName = std::string(otherfile_name);\n    m_BinaryFileSkip = otherfile_skip;\n  }\n\n  double spacing = 1.;\n  if ((p = edf_findInHeader(header, \"optic_used\")))\n  {\n    spacing = std::stod(p);\n    if (spacing == 0.)\n      spacing = 1.;\n  }\n\n\n  free(header);\n  gzclose(inp);\n\n  SetNumberOfDimensions(2);\n  SetDimensions(0, dim1);\n  SetDimensions(1, dim2);\n  SetSpacing(0, spacing);\n  SetSpacing(1, spacing);\n  SetOrigin(0, 0.);\n  SetOrigin(1, 0.);\n} ////\n\n//--------------------------------------------------------------------\n// Read Image Information\nbool\nrtk::EdfImageIO::CanReadFile(const char * FileNameToRead)\n{\n  std::string                  filename(FileNameToRead);\n  const std::string::size_type it = filename.find_last_of(\".\");\n  std::string                  fileExt(filename, it + 1, filename.length());\n\n  if (fileExt != std::string(\"edf\"))\n    return false;\n  return true;\n} ////\n\n//--------------------------------------------------------------------\n// Read Image Content\nvoid\nrtk::EdfImageIO::Read(void * buffer)\n{\n  gzFile inp = nullptr;\n\n  inp = gzopen(m_BinaryFileName.c_str(), \"rb\");\n  if (!inp)\n    itkGenericExceptionMacro(<< \"Cannot open file \\\"\" << m_FileName << \"\\\"\");\n  gzseek(inp, m_BinaryFileSkip, SEEK_SET);\n\n  // read the data (image)\n  long numberOfBytesToBeRead = GetComponentSize();\n  for (unsigned int i = 0; i < GetNumberOfDimensions(); i++)\n    numberOfBytesToBeRead *= GetDimensions(i);\n\n  if (numberOfBytesToBeRead != gzread(inp, buffer, numberOfBytesToBeRead))\n    itkGenericExceptionMacro(<< \"The image \" << m_BinaryFileName << \" cannot be read completely.\");\n\n  gzclose(inp);\n\n  // Adapted from itkRawImageIO\n  const auto          componentType = this->GetComponentType();\n  const SizeValueType numberOfComponents = this->GetImageSizeInComponents();\n  ReadRawBytesAfterSwapping(componentType, buffer, m_ByteOrder, numberOfComponents);\n}\n\n//--------------------------------------------------------------------\n// Write Image Information\nvoid\nrtk::EdfImageIO::WriteImageInformation(bool itkNotUsed(keepOfStream))\n{}\n\n//--------------------------------------------------------------------\n// Write Image Information\nbool\nrtk::EdfImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n\n//--------------------------------------------------------------------\n// Write Image\nvoid\nrtk::EdfImageIO::Write(const void * itkNotUsed(buffer))\n{} ////\n"
  },
  {
    "path": "src/rtkEdfImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkEdfImageIOFactory.h\"\n\n//====================================================================\nrtk::EdfImageIOFactory::EdfImageIOFactory()\n{\n  this->RegisterOverride(\n    \"itkImageIOBase\", \"EdfImageIO\", \"Edf Image IO\", true, itk::CreateObjectFunction<EdfImageIO>::New());\n}\n"
  },
  {
    "path": "src/rtkElektaSynergyGeometryReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n\n#include \"rtkElektaSynergyGeometryReader.h\"\n#include \"rtkDbf.h\"\n#include \"rtkMacro.h\"\n\nrtk::ElektaSynergyGeometryReader ::ElektaSynergyGeometryReader()\n  : m_Geometry(nullptr)\n  , m_DicomUID(\"\")\n  , m_ImageDbfFileName(\"IMAGE.DBF\")\n  , m_FrameDbfFileName(\"FRAME.DBF\")\n{}\n\nstd::string\nrtk::ElektaSynergyGeometryReader ::GetImageIDFromDicomUID()\n{\n  // Open frame database file\n  rtk::DbfFile dbImage(m_ImageDbfFileName);\n  if (!dbImage.is_open())\n    itkGenericExceptionMacro(<< \"Couldn't open \" << m_ImageDbfFileName);\n\n  // Search for correct record\n  bool bReadOk = false;\n  do\n  {\n    bReadOk = dbImage.ReadNextRecord();\n  } while (bReadOk && std::string(m_DicomUID) != dbImage.GetFieldAsString(\"DICOM_UID\"));\n\n  // Error message if not found\n  if (!bReadOk)\n  {\n    itkGenericExceptionMacro(<< \"Couldn't find acquisition with DICOM_UID \" << m_DicomUID << \" in table \"\n                             << m_ImageDbfFileName);\n  }\n\n  return dbImage.GetFieldAsString(\"DBID\");\n}\n\nvoid\nrtk::ElektaSynergyGeometryReader ::GetProjInfoFromDB(const std::string &  imageID,\n                                                     std::vector<float> & projAngle,\n                                                     std::vector<float> & projFlexX,\n                                                     std::vector<float> & projFlexY)\n{\n  // Open frame database file\n  rtk::DbfFile dbFrame(m_FrameDbfFileName);\n  if (!dbFrame.is_open())\n    itkGenericExceptionMacro(<< \"Couldn't open \" << m_FrameDbfFileName);\n\n  // Go through the database, select correct records and get data\n  while (dbFrame.ReadNextRecord())\n  {\n    if (dbFrame.GetFieldAsString(\"IMA_DBID\") == imageID)\n    {\n      projAngle.push_back(dbFrame.GetFieldAsDouble(\"PROJ_ANG\"));\n      projFlexX.push_back(dbFrame.GetFieldAsDouble(\"U_CENTRE\"));\n      projFlexY.push_back(dbFrame.GetFieldAsDouble(\"V_CENTRE\"));\n    }\n  }\n}\n\nvoid\nrtk::ElektaSynergyGeometryReader ::GenerateData()\n{\n  // Create new RTK geometry object\n  m_Geometry = GeometryType::New();\n\n  // Get information from Synergy database\n  std::vector<float> projAngle, projFlexX, projFlexY;\n  GetProjInfoFromDB(GetImageIDFromDicomUID(), projAngle, projFlexX, projFlexY);\n\n  // Projection matrices\n  for (unsigned int noProj = 0; noProj < projAngle.size(); noProj++)\n  {\n    m_Geometry->AddProjection(1000., 1536., projAngle[noProj], -projFlexX[noProj], -projFlexY[noProj]);\n  }\n}\n"
  },
  {
    "path": "src/rtkElektaXVI5GeometryXMLFileReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkElektaXVI5GeometryXMLFileReader.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n#include <itkIOCommon.h>\n\n#include <iomanip>\n\nnamespace rtk\n{\n\nElektaXVI5GeometryXMLFileReader::ElektaXVI5GeometryXMLFileReader() { this->m_OutputObject = &(*m_Geometry); }\n\nint\nElektaXVI5GeometryXMLFileReader::CanReadFile(const char * name)\n{\n  if (!itksys::SystemTools::FileExists(name) || itksys::SystemTools::FileIsDirectory(name) ||\n      itksys::SystemTools::FileLength(name) == 0)\n    return 0;\n  return 1;\n}\n\nvoid\nElektaXVI5GeometryXMLFileReader::StartElement(const char * name, const char ** itkNotUsed(atts))\n{\n  m_CurCharacterData = \"\";\n  this->StartElement(name);\n}\n\nvoid\nElektaXVI5GeometryXMLFileReader::StartElement(const char * itkNotUsed(name))\n{}\n\nvoid\nElektaXVI5GeometryXMLFileReader::EndElement(const char * name)\n{\n  if (itksys::SystemTools::Strucmp(name, \"GantryAngle\") == 0 ||\n      itksys::SystemTools::Strucmp(name, \"Angle\") == 0 ||      // For backward compatibility\n      itksys::SystemTools::Strucmp(name, \"antryAngle\") == 0 || // Seen in anonymized _Frames.xml files\n      itksys::SystemTools::Strucmp(name, \"Gantryngle\") == 0)   // Seen in anonymized _Frames.xml files\n  {\n    m_GantryAngle = std::stod(this->m_CurCharacterData.c_str());\n    if (m_GantryAngle < 0)\n      m_GantryAngle = m_GantryAngle + 360.0;\n  }\n\n  // Regarding PanelOffset, XVI5 specifies position of the center(UCentre, VCentre) instead of offset.\n  // Therefore, negation is required to get classical m_ProjectionOffsetX and m_ProjectionOffsetY values.\n  if (itksys::SystemTools::Strucmp(name, \"UCentre\") == 0 ||\n      itksys::SystemTools::Strucmp(name, \"Uentre\") == 0) // Seen in anonymized _Frames.xml files\n    m_ProjectionOffsetX = std::stod(this->m_CurCharacterData.c_str()) * -1.0;\n\n  if (itksys::SystemTools::Strucmp(name, \"VCentre\") == 0 ||\n      itksys::SystemTools::Strucmp(name, \"Ventre\") == 0) // Seen in anonymized _Frames.xml files\n  {\n    m_ProjectionOffsetY = std::stod(this->m_CurCharacterData.c_str()) * -1.0;\n  }\n\n  if (itksys::SystemTools::Strucmp(name, \"Frame\") == 0)\n  {\n    this->m_OutputObject->AddProjection(m_SourceToIsocenterDistance,\n                                        m_SourceToDetectorDistance,\n                                        m_GantryAngle,\n                                        m_ProjectionOffsetX,\n                                        m_ProjectionOffsetY,\n                                        m_OutOfPlaneAngle,\n                                        m_InPlaneAngle,\n                                        m_SourceOffsetX,\n                                        m_SourceOffsetY);\n  }\n}\n\nvoid\nElektaXVI5GeometryXMLFileReader::CharacterDataHandler(const char * inData, int inLength)\n{\n  for (int i = 0; i < inLength; i++)\n    m_CurCharacterData = m_CurCharacterData + inData[i];\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkForbildPhantomFileReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"math.h\"\n#include <cstdlib>\n#include <clocale>\n#include <fstream>\n#include <itksys/RegularExpression.hxx>\n\n#include \"rtkForbildPhantomFileReader.h\"\n#include \"rtkQuadricShape.h\"\n#include \"rtkBoxShape.h\"\n#include \"rtkIntersectionOfConvexShapes.h\"\n\nnamespace rtk\n{\nvoid\nForbildPhantomFileReader::GenerateOutputInformation()\n{\n  // Save locale setting\n  const std::string oldLocale = setlocale(LC_NUMERIC, nullptr);\n  setlocale(LC_NUMERIC, \"C\");\n  m_GeometricPhantom = GeometricPhantom::New();\n\n  std::ifstream myFile;\n  myFile.open(m_Filename.c_str());\n  if (!myFile.is_open())\n  {\n    itkGenericExceptionMacro(\"Error opening file\" << m_Filename);\n  }\n  while (!myFile.eof())\n  {\n    // A figure is between curly brackets\n    std::string line;\n    getline(myFile, line, '{');\n    getline(myFile, line, '}');\n\n    // Find fig\n    std::string               regex = \"\\\\[ *([a-zA-Z_]*):\";\n    itksys::RegularExpression re;\n    if (!re.compile(regex.c_str()))\n      itkExceptionMacro(<< \"Could not compile \" << regex);\n    if (!re.find(line.c_str()))\n      continue;\n    const std::string fig = re.match(1);\n\n    // Find density\n    ScalarType rho = NAN;\n    if (!FindParameterInString(\"rho\", line, rho))\n      itkGenericExceptionMacro(\"Could not find rho in \" << line);\n\n    // Find center\n    m_Center.Fill(0.);\n    FindParameterInString(\"x\", line, m_Center[0]);\n    FindParameterInString(\"y\", line, m_Center[1]);\n    FindParameterInString(\"z\", line, m_Center[2]);\n\n    // Find radius\n    if (fig == \"Sphere\")\n      CreateForbildSphere(line);\n    else if (fig == \"Box\")\n      CreateForbildBox(line);\n    else if (fig.substr(0, 8) == \"Cylinder\")\n      CreateForbildCylinder(line, fig);\n    else if (fig.substr(0, 10) == \"Ellipt_Cyl\")\n      CreateForbildElliptCyl(line, fig);\n    else if (fig.substr(0, 9) == \"Ellipsoid\")\n      CreateForbildEllipsoid(line, fig);\n    else if (fig.substr(0, 4) == \"Cone\")\n      CreateForbildCone(line, fig);\n\n    // Density\n    ScalarType density = rho;\n    for (const auto & convexShape : m_GeometricPhantom->GetConvexShapes())\n    {\n      if (convexShape->IsInside(m_Center))\n        density -= convexShape->GetDensity();\n    }\n    for (const auto & m_Union : m_Unions)\n    {\n      if (m_Union->IsInside(m_Center))\n        density -= m_Union->GetDensity();\n    }\n    if (m_ConvexShape.IsNotNull())\n    {\n      m_ConvexShape->SetDensity(density);\n      FindClipPlanes(line);\n      m_GeometricPhantom->AddConvexShape(m_ConvexShape);\n      FindUnions(line);\n      m_ConvexShape = ConvexShape::Pointer(nullptr);\n    }\n  }\n  for (const auto & m_Union : m_Unions)\n    m_GeometricPhantom->AddConvexShape(m_Union);\n  myFile.close();\n  setlocale(LC_NUMERIC, oldLocale.c_str());\n}\n\nvoid\nForbildPhantomFileReader::CreateForbildSphere(const std::string & s)\n{\n  ScalarType r = 0.;\n  if (!FindParameterInString(\"r\", s, r))\n    itkExceptionMacro(<< \"Could not find r (radius) in \" << s);\n  VectorType axes;\n  axes.Fill(r);\n  auto q = QuadricShape::New();\n  q->SetEllipsoid(m_Center, axes);\n  m_ConvexShape = q.GetPointer();\n}\n\nvoid\nForbildPhantomFileReader::CreateForbildBox(const std::string & s)\n{\n  VectorType length;\n  if (!FindParameterInString(\"dx\", s, length[0]))\n    itkExceptionMacro(<< \"Could not find dx in \" << s);\n  if (!FindParameterInString(\"dy\", s, length[1]))\n    itkExceptionMacro(<< \"Could not find dy in \" << s);\n  if (!FindParameterInString(\"dz\", s, length[2]))\n    itkExceptionMacro(<< \"Could not find dz in \" << s);\n  auto b = BoxShape::New();\n  b->SetBoxMin(m_Center - 0.5 * length);\n  b->SetBoxMax(m_Center + 0.5 * length);\n  m_ConvexShape = b.GetPointer();\n}\n\nvoid\nForbildPhantomFileReader::CreateForbildCylinder(const std::string & s, const std::string & fig)\n{\n  ScalarType l = 0.;\n  if (!FindParameterInString(\"l\", s, l))\n    itkExceptionMacro(<< \"Could not find l (length) in \" << s);\n  ScalarType r = 0.;\n  if (!FindParameterInString(\"r\", s, r))\n    itkExceptionMacro(<< \"Could not find r (radius) in \" << s);\n  VectorType axes;\n  axes.Fill(r);\n  VectorType planeDir;\n  planeDir.Fill(0.);\n  ConvexShape::RotationMatrixType rot;\n  rot.SetIdentity();\n  if (fig == \"Cylinder_x\")\n  {\n    axes[0] = 0.;\n    planeDir[0] = 1.;\n  }\n  else if (fig == \"Cylinder_y\")\n  {\n    axes[1] = 0.;\n    planeDir[1] = 1.;\n  }\n  else if (fig == \"Cylinder_z\")\n  {\n    axes[2] = 0.;\n    planeDir[2] = 1.;\n  }\n  else // Cylinder\n  {\n    axes[0] = 0.;\n    planeDir[0] = 1.;\n    VectorType dir;\n    if (!FindVectorInString(\"axis\", s, dir))\n      itkExceptionMacro(<< \"Could not find axis in \" << s);\n    rot = ComputeRotationMatrixBetweenVectors(planeDir, dir);\n  }\n  auto q = QuadricShape::New();\n  q->SetEllipsoid(VectorType(0.), axes);\n  q->AddClipPlane(planeDir, 0.5 * l);\n  q->AddClipPlane(-1. * planeDir, 0.5 * l);\n  q->Rotate(rot);\n  q->Translate(m_Center);\n  m_ConvexShape = q.GetPointer();\n}\n\nvoid\nForbildPhantomFileReader::CreateForbildElliptCyl(const std::string & s, const std::string & fig)\n{\n  ScalarType l = 0.;\n  if (!FindParameterInString(\"l\", s, l))\n    itkExceptionMacro(<< \"Could not find l (length) in \" << s);\n  VectorType axes;\n  axes.Fill(0.);\n  size_t found = 0;\n  if (FindParameterInString(\"dx\", s, axes[0]))\n    found++;\n  if (FindParameterInString(\"dy\", s, axes[1]))\n    found++;\n  if (FindParameterInString(\"dz\", s, axes[2]))\n    found++;\n  if (found != 2)\n    itkExceptionMacro(<< \"Exactly two among dx dy dz are required for \" << fig << \", \" << found << \" found in \" << s);\n  VectorType planeDir;\n  for (unsigned int i = 0; i < Dimension; i++)\n    planeDir[i] = (axes[i] == 0.) ? 1. : 0.;\n\n  auto q = QuadricShape::New();\n  q->SetEllipsoid(VectorType(0.), axes);\n  q->AddClipPlane(planeDir, 0.5 * l);\n  q->AddClipPlane(-1. * planeDir, 0.5 * l);\n  if (fig == \"Ellipt_Cyl\")\n  {\n    VectorType a_x;\n    bool       a_x_Found = FindVectorInString(\"a_x\", s, a_x);\n    VectorType a_y;\n    bool       a_y_Found = FindVectorInString(\"a_y\", s, a_y);\n    VectorType a_z;\n    bool       a_z_Found = FindVectorInString(\"axis\", s, a_z);\n    if (a_x_Found && a_y_Found)\n    {\n      a_x /= a_x.GetNorm();\n      a_y /= a_y.GetNorm();\n      a_z = CrossProduct(a_x, a_y);\n    }\n    else if (a_x_Found && a_z_Found)\n    {\n      a_x /= a_x.GetNorm();\n      a_z /= a_z.GetNorm();\n      a_y = CrossProduct(a_z, a_x);\n    }\n    else if (a_y_Found && a_z_Found)\n    {\n      a_y /= a_y.GetNorm();\n      a_z /= a_z.GetNorm();\n      a_x = CrossProduct(a_y, a_z);\n    }\n    else\n    {\n      itkExceptionMacro(<< \"Could not find 2 vectors among a_x, a_y and axis in \" << s);\n    }\n    RotationMatrixType rot;\n    for (unsigned int i = 0; i < Dimension; i++)\n    {\n      rot[i][0] = a_x[i];\n      rot[i][1] = a_y[i];\n      rot[i][2] = a_z[i];\n    }\n    q->Rotate(rot);\n  }\n  q->Translate(m_Center);\n  m_ConvexShape = q.GetPointer();\n}\n\nvoid\nForbildPhantomFileReader::CreateForbildEllipsoid(const std::string & s, const std::string & fig)\n{\n  VectorType axes;\n  if (!FindParameterInString(\"dx\", s, axes[0]))\n    itkExceptionMacro(<< \"Could not find dx in \" << s);\n  if (!FindParameterInString(\"dy\", s, axes[1]))\n    itkExceptionMacro(<< \"Could not find dy in \" << s);\n  if (!FindParameterInString(\"dz\", s, axes[2]))\n    itkExceptionMacro(<< \"Could not find dz in \" << s);\n  auto q = QuadricShape::New();\n  q->SetEllipsoid(VectorType(0.), axes);\n\n  if (fig == \"Ellipsoid_free\")\n  {\n    RotationMatrixType rot;\n    VectorType         dirx, diry, dirz;\n    bool               bx = FindVectorInString(\"a_x\", s, dirx);\n    bool               by = FindVectorInString(\"a_y\", s, diry);\n    bool               bz = FindVectorInString(\"a_z\", s, dirz);\n    if (bx)\n      dirx /= dirx.GetNorm();\n    if (by)\n      diry /= diry.GetNorm();\n    if (bz)\n      dirz /= dirz.GetNorm();\n    if (!bx)\n      dirx = CrossProduct(diry, dirz);\n    if (!by)\n      diry = CrossProduct(dirz, dirx);\n    if (!bz)\n      dirz = CrossProduct(dirx, diry);\n    for (unsigned int i = 0; i < Dimension; i++)\n    {\n      rot[i][0] = dirx[i];\n      rot[i][1] = diry[i];\n      rot[i][2] = dirz[i];\n    }\n    q->Rotate(rot);\n  }\n  q->Translate(m_Center);\n  m_ConvexShape = q.GetPointer();\n}\n\nvoid\nForbildPhantomFileReader::CreateForbildCone(const std::string & s, const std::string & fig)\n{\n  ScalarType l = 0.;\n  if (!FindParameterInString(\"l\", s, l))\n    itkExceptionMacro(<< \"Could not find l (length) in \" << s);\n  size_t     found = 0;\n  ScalarType r1 = 0.;\n  if (!FindParameterInString(\"r1\", s, r1))\n  {\n    itkExceptionMacro(<< \"Missing radius r1 in \" << fig << \", \" << found << \" found in \" << s);\n  }\n  ScalarType r2 = 0.;\n  if (!FindParameterInString(\"r2\", s, r2))\n  {\n    itkExceptionMacro(<< \"Missing radius r2 in \" << fig << \", \" << found << \" found in \" << s);\n  }\n\n  VectorType axes;\n  axes.Fill(r1);\n  VectorType planeDir;\n  planeDir[0] = 0.;\n  planeDir[1] = 0.;\n  planeDir[2] = 1.;\n\n  auto      q = QuadricShape::New();\n  PointType spatialOffset;\n  spatialOffset[0] = 0.;\n  spatialOffset[1] = 0.;\n  if (r2 > r1)\n  {\n    axes[2] = -l * r1 / (r2 - r1);\n    q->AddClipPlane(-1. * planeDir, axes[2]);\n    q->AddClipPlane(planeDir, l - axes[2]);\n    spatialOffset[2] = axes[2] - 0.5 * l;\n  }\n  else\n  {\n    axes[2] = -l * r1 / (r1 - r2);\n    q->AddClipPlane(-1. * planeDir, -axes[2]);\n    q->AddClipPlane(planeDir, l + axes[2]);\n    spatialOffset[2] = -axes[2] - 0.5 * l;\n  }\n  q->SetEllipsoid(VectorType(0.), axes);\n  q->SetJ(0.);\n\n  RotationMatrixType rot;\n  rot.Fill(0.);\n  if (fig == \"Cone_x\")\n  {\n    rot[0][2] = 1.;\n    rot[1][0] = 1.;\n    rot[2][1] = 1.;\n  }\n  else if (fig == \"Cone_y\")\n  {\n    rot[0][1] = 1.;\n    rot[1][2] = 1.;\n    rot[2][0] = 1.;\n  }\n  else if (fig == \"Cone_z\")\n  {\n    rot.SetIdentity();\n  }\n  else if (fig == \"Cone\")\n  {\n    VectorType dir;\n    if (!FindVectorInString(\"axis\", s, dir))\n      itkExceptionMacro(<< \"Could not find axis in \" << s);\n    rot = ComputeRotationMatrixBetweenVectors(planeDir, dir);\n  }\n  else\n  {\n    itkExceptionMacro(<< \"Unknown figure: \" << fig);\n  }\n  q->Rotate(rot);\n  q->Translate(m_Center + rot * spatialOffset);\n  m_ConvexShape = q.GetPointer();\n}\n\nvoid\nForbildPhantomFileReader::CreateForbildTetrahedron(const std::string & /*s*/)\n{}\n\nbool\nForbildPhantomFileReader::FindParameterInString(const std::string & name, const std::string & s, ScalarType & param)\n{\n  std::string               regex = std::string(\"  *\") + name + std::string(\" *= *([-+0-9.]*)\");\n  itksys::RegularExpression re;\n  if (!re.compile(regex.c_str()))\n    itkExceptionMacro(<< \"Could not compile \" << regex);\n  bool bFound = re.find(s.c_str());\n  if (bFound)\n    param = std::stod(re.match(1).c_str());\n  return bFound;\n}\n\nbool\nForbildPhantomFileReader::FindVectorInString(const std::string & name, const std::string & s, VectorType & vec)\n{\n  std::string regex = std::string(\" *\") + name + std::string(\" *\\\\( *([-+0-9.]*) *, *([-+0-9.]*) *, *([-+0-9.]*) *\\\\)\");\n  itksys::RegularExpression re;\n  if (!re.compile(regex.c_str()))\n    itkExceptionMacro(<< \"Could not compile \" << regex);\n  bool bFound = re.find(s.c_str());\n  if (bFound)\n  {\n    for (size_t i = 0; i < 3; i++)\n    {\n      vec[i] = std::stod(re.match(i + 1).c_str());\n    }\n  }\n  return bFound;\n}\n\nForbildPhantomFileReader::RotationMatrixType\nForbildPhantomFileReader::ComputeRotationMatrixBetweenVectors(const VectorType & source, const VectorType & dest) const\n{\n  // https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d/476311#476311\n  VectorType         s = source / source.GetNorm();\n  VectorType         d = dest / dest.GetNorm();\n  RotationMatrixType r;\n  r.SetIdentity();\n  ScalarType c = s * d;\n  if (itk::Math::abs(c) - 1. == itk::NumericTraits<ScalarType>::ZeroValue())\n  {\n    return r;\n  }\n  VectorType                      v = CrossProduct(s, d);\n  ConvexShape::RotationMatrixType vx;\n  vx.Fill(0.);\n  vx[0][1] = -v[2];\n  vx[0][2] = v[1];\n  vx[1][0] = v[2];\n  vx[1][2] = -v[0];\n  vx[2][0] = -v[1];\n  vx[2][1] = v[0];\n  r += vx;\n  r += vx * vx * 1. / (1. + c);\n  return r;\n}\n\nvoid\nForbildPhantomFileReader::FindClipPlanes(const std::string & s)\n{\n  // of the form r(x,y,z) > expr\n  std::string               regex(\" +r *\\\\( *([-+0-9.]*) *, *([-+0-9.]*) *, *([-+0-9.]*) *\\\\) *([<>]) *([-+0-9.]*)\");\n  itksys::RegularExpression re;\n  if (!re.compile(regex.c_str()))\n    itkExceptionMacro(<< \"Could not compile \" << regex);\n  const char * currs = s.c_str();\n  while (re.find(currs))\n  {\n    VectorType vec;\n    for (size_t i = 0; i < 3; i++)\n    {\n      vec[i] = std::stod(re.match(i + 1).c_str());\n    }\n    vec /= vec.GetNorm();\n    ScalarType sign = (re.match(4) == std::string(\"<\")) ? 1. : -1.;\n    ScalarType expr = std::stod(re.match(5).c_str());\n    m_ConvexShape->AddClipPlane(sign * vec, sign * expr);\n    currs += re.end();\n  }\n\n  // of the form x>expr or x<expr\n  regex = \" +x *([<>]) *([-+0-9.]*)\";\n  if (!re.compile(regex.c_str()))\n    itkExceptionMacro(<< \"Could not compile \" << regex);\n  currs = s.c_str();\n  while (re.find(currs))\n  {\n    VectorType vec;\n    vec.Fill(0.);\n    vec[0] = 1.;\n    ScalarType sign = (re.match(1) == std::string(\"<\")) ? 1. : -1.;\n    ScalarType expr = std::stod(re.match(2).c_str());\n    m_ConvexShape->AddClipPlane(sign * vec, sign * expr);\n    currs += re.end();\n  }\n\n  // of the form y>expr or y<expr\n  regex = \" +y *([<>]) *([-+0-9.]*)\";\n  if (!re.compile(regex.c_str()))\n    itkExceptionMacro(<< \"Could not compile \" << regex);\n  currs = s.c_str();\n  while (re.find(currs))\n  {\n    VectorType vec;\n    vec.Fill(0.);\n    vec[1] = 1.;\n    ScalarType sign = (re.match(1) == std::string(\"<\")) ? 1. : -1.;\n    ScalarType expr = std::stod(re.match(2).c_str());\n    m_ConvexShape->AddClipPlane(sign * vec, sign * expr);\n    currs += re.end();\n  }\n\n  // of the form z>expr or z<expr\n  regex = \" +z *([<>]) *([-+0-9.]*)\";\n  if (!re.compile(regex.c_str()))\n    itkExceptionMacro(<< \"Could not compile \" << regex);\n  currs = s.c_str();\n  while (re.find(currs))\n  {\n    VectorType vec;\n    vec.Fill(0.);\n    vec[2] = 1.;\n    ScalarType sign = (re.match(1) == std::string(\"<\")) ? 1. : -1.;\n    ScalarType expr = std::stod(re.match(2).c_str());\n    m_ConvexShape->AddClipPlane(sign * vec, sign * expr);\n    currs += re.end();\n  }\n}\n\nvoid\nForbildPhantomFileReader::FindUnions(const std::string & s)\n{\n  std::string               regex(\" +union *= *([-0-9]*)\");\n  itksys::RegularExpression re;\n  if (!re.compile(regex.c_str()))\n    itkExceptionMacro(<< \"Could not compile \" << regex);\n  const char * currs = s.c_str();\n  m_UnionWith.push_back(-1);\n  while (re.find(currs))\n  {\n    currs += re.end();\n    auto ico = IntersectionOfConvexShapes::New();\n    ico->AddConvexShape(m_ConvexShape);\n    size_t len = m_GeometricPhantom->GetConvexShapes().size();\n    int    u = std::stoi(re.match(1).c_str());\n    size_t pos = len + u - 1;\n    ico->AddConvexShape(m_GeometricPhantom->GetConvexShapes()[pos]);\n    if (m_ConvexShape->GetDensity() != m_GeometricPhantom->GetConvexShapes()[pos]->GetDensity())\n      itkExceptionMacro(<< \"Cannot unionize objects of different density in \" << s);\n    ico->SetDensity(-1. * m_ConvexShape->GetDensity());\n\n    m_UnionWith.back() = pos;\n    m_Unions.push_back(ico.GetPointer());\n\n    // Handles the union of three objects. Union of more objects would require\n    // the implementation of the inclusion-exclusion formula\n    // https://en.wikipedia.org/wiki/Inclusion%E2%80%93exclusion_principle\n    if (m_UnionWith[pos] != -1)\n    {\n      ico = IntersectionOfConvexShapes::New();\n      ico->AddConvexShape(m_ConvexShape);\n      ico->AddConvexShape(m_GeometricPhantom->GetConvexShapes()[m_UnionWith[pos]]);\n      ico->SetDensity(-1. * m_ConvexShape->GetDensity());\n      m_Unions.push_back(ico.GetPointer());\n\n      ico = IntersectionOfConvexShapes::New();\n      ico->AddConvexShape(m_ConvexShape);\n      ico->AddConvexShape(m_GeometricPhantom->GetConvexShapes()[pos]);\n      ico->AddConvexShape(m_GeometricPhantom->GetConvexShapes()[m_UnionWith[pos]]);\n      ico->SetDensity(m_ConvexShape->GetDensity());\n      m_Unions.push_back(ico.GetPointer());\n    }\n  }\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkGeometricPhantom.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkGeometricPhantom.h\"\n\nnamespace rtk\n{\nvoid\nGeometricPhantom ::Rescale(const VectorType & r)\n{\n  for (auto & convexShape : m_ConvexShapes)\n  {\n    convexShape->Rescale(r);\n  }\n}\n\nvoid\nGeometricPhantom ::Translate(const VectorType & t)\n{\n  for (auto & convexShape : m_ConvexShapes)\n  {\n    convexShape->Translate(t);\n  }\n}\n\nvoid\nGeometricPhantom ::Rotate(const RotationMatrixType & r)\n{\n  for (auto & convexShape : m_ConvexShapes)\n  {\n    convexShape->Rotate(r);\n  }\n}\n\nvoid\nGeometricPhantom ::AddConvexShape(const ConvexShape * co)\n{\n  m_ConvexShapes.push_back(co->Clone());\n  for (size_t i = 0; i < m_PlaneDirections.size(); i++)\n    m_ConvexShapes.back()->AddClipPlane(m_PlaneDirections[i], m_PlanePositions[i]);\n}\n\nvoid\nGeometricPhantom ::AddClipPlane(const VectorType & dir, const ScalarType & pos)\n{\n  for (size_t i = 0; i < m_PlanePositions.size(); i++)\n  {\n    if (dir == m_PlaneDirections[i] && pos == m_PlanePositions[i])\n      return;\n  }\n  m_PlaneDirections.push_back(dir);\n  m_PlanePositions.push_back(pos);\n  for (auto & convexShape : m_ConvexShapes)\n    convexShape->AddClipPlane(dir, pos);\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkGlobalResourceProbe.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#include \"rtkGlobalResourceProbe.h\"\n#include \"itkObjectFactory.h\"\n\nnamespace rtk\n{\nGlobalResourceProbe::Pointer GlobalResourceProbe::m_Instance = nullptr;\n\n/**\n * Prompting off by default\n */\nGlobalResourceProbe ::GlobalResourceProbe() { m_Verbose = false; }\n\nGlobalResourceProbe ::~GlobalResourceProbe()\n{\n  if (m_Verbose)\n    this->Report(std::cout);\n  this->Clear();\n}\n\nvoid\nGlobalResourceProbe ::PrintSelf(std::ostream & os, Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n\n  os << indent << \"GlobalResourceProbe (single instance): \" << (void *)GlobalResourceProbe::m_Instance << std::endl;\n}\n\n/**\n * Return the single instance of the GlobalResourceProbe\n */\nGlobalResourceProbe::Pointer\nGlobalResourceProbe ::GetInstance()\n{\n  if (!GlobalResourceProbe::m_Instance)\n  {\n    // Try the factory first\n    GlobalResourceProbe::m_Instance = ObjectFactory<Self>::Create();\n    // if the factory did not provide one, then create it here\n    if (!GlobalResourceProbe::m_Instance)\n    {\n      GlobalResourceProbe::m_Instance = new GlobalResourceProbe;\n      // Remove extra reference from construction.\n      GlobalResourceProbe::m_Instance->UnRegister();\n    }\n  }\n  /**\n   * return the instance\n   */\n  return GlobalResourceProbe::m_Instance;\n}\n\n/**\n * This just calls GetInstance\n */\nGlobalResourceProbe::Pointer\nGlobalResourceProbe ::New()\n{\n  return GetInstance();\n}\n\nvoid\nGlobalResourceProbe ::Watch(ProcessObject * o)\n{\n  m_Mutex.lock();\n  auto * w = new rtk::WatcherForResourceProbe(o);\n  m_Watchers.push_back(w);\n  m_Mutex.unlock();\n}\n\nvoid\nGlobalResourceProbe ::Remove(const rtk::WatcherForResourceProbe * w)\n{\n  m_Mutex.lock();\n  auto itw = std::find(m_Watchers.begin(), m_Watchers.end(), w);\n  if (itw != m_Watchers.end())\n  {\n    delete *itw;\n    m_Watchers.erase(itw);\n  }\n  m_Mutex.unlock();\n}\n\nvoid\nGlobalResourceProbe ::Start(const char * id)\n{\n  m_Mutex.lock();\n  m_ResourceProbesCollector.Start(id);\n  m_Mutex.unlock();\n}\n\nvoid\nGlobalResourceProbe ::Stop(const char * id)\n{\n  m_Mutex.lock();\n  m_ResourceProbesCollector.Stop(id);\n  m_Mutex.unlock();\n}\n\nvoid\nGlobalResourceProbe ::Report(std::ostream & os) const\n{\n  m_ResourceProbesCollector.Report(os);\n}\n\nvoid\nGlobalResourceProbe ::Clear()\n{\n  m_Mutex.lock();\n  m_ResourceProbesCollector.Clear();\n  m_Watchers.clear();\n  m_Mutex.unlock();\n}\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkHisImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#define HEADER_INFO_SIZE 68\n\n// Based on a true story by the Nederlands Kanker Instituut (AVS_HEIMANN.CPP\n// from the 20090608)\n\n// Includes\n#include <fstream>\n#include \"rtkHisImageIO.h\"\n#include \"rtkMacro.h\"\n\n//--------------------------------------------------------------------\n// Read Image Information\nvoid\nrtk::HisImageIO::ReadImageInformation()\n{\n  // open file\n  std::ifstream file(m_FileName.c_str(), std::ios::in | std::ios::binary);\n\n  if (file.fail())\n    itkGenericExceptionMacro(<< \"Could not open file (for reading): \" << m_FileName);\n\n  // read header\n  unsigned char header[HEADER_INFO_SIZE];\n  file.read((char *)header, HEADER_INFO_SIZE);\n\n  if (header[0] != 0 || header[1] != 112 || header[2] != 68 || header[3] != 0)\n  {\n    itkExceptionMacro(<< \"rtk::HisImageIO::ReadImageInformation: file \" << m_FileName\n                      << \" not in Heimann HIS format version 100\");\n    return;\n  }\n\n  int nrframes = 0, type = 0, ulx = 0, uly = 0, brx = 0, bry = 0;\n  m_HeaderSize = header[10] + (header[11] << 8);\n  ulx = header[12] + (header[13] << 8);\n  uly = header[14] + (header[15] << 8);\n  brx = header[16] + (header[17] << 8);\n  bry = header[18] + (header[19] << 8);\n  nrframes = header[20] + (header[21] << 8);\n  type = header[32] + (header[34] << 8);\n\n  switch (type)\n  {\n    case 4:\n      SetComponentType(itk::ImageIOBase::IOComponentEnum::USHORT);\n      break;\n      //    case  8: SetComponentType(itk::ImageIOBase::INT);   break;\n      //    case 16: SetComponentType(itk::ImageIOBase::FLOAT); break;\n      //    case 32: SetComponentType(itk::ImageIOBase::INT);   break;\n    default:\n      SetComponentType(itk::ImageIOBase::IOComponentEnum::USHORT);\n      break;\n  }\n\n  switch (nrframes)\n  {\n    case 1:\n      SetNumberOfDimensions(2);\n      break;\n    default:\n      SetNumberOfDimensions(3);\n      break;\n  }\n\n  SetDimensions(0, bry - uly + 1);\n  SetDimensions(1, brx - ulx + 1);\n  if (nrframes > 1)\n    SetDimensions(2, nrframes);\n\n  SetSpacing(0, 409.6 / GetDimensions(0));\n  SetSpacing(1, 409.6 / GetDimensions(1));\n\n  SetOrigin(0, -0.5 * (GetDimensions(0) - 1) * GetSpacing(0));\n  SetOrigin(1, -0.5 * (GetDimensions(1) - 1) * GetSpacing(1));\n} ////\n\n//--------------------------------------------------------------------\n// Read Image Information\nbool\nrtk::HisImageIO::CanReadFile(const char * FileNameToRead)\n{\n  std::string                  filename(FileNameToRead);\n  const std::string::size_type it = filename.find_last_of(\".\");\n  std::string                  fileExt(filename, it + 1, filename.length());\n\n  if (fileExt != std::string(\"his\"))\n    return false;\n  return true;\n} ////\n\n//--------------------------------------------------------------------\n// Read Image Content\nvoid\nrtk::HisImageIO::Read(void * buffer)\n{\n  // open file\n  std::ifstream file(m_FileName.c_str(), std::ios::in | std::ios::binary);\n\n  if (file.fail())\n    itkGenericExceptionMacro(<< \"Could not open file (for reading): \" << m_FileName);\n\n  file.seekg(m_HeaderSize + HEADER_INFO_SIZE, std::ios::beg);\n  if (file.fail())\n    itkExceptionMacro(<< \"File seek failed (His Read)\");\n\n  file.read((char *)buffer, GetImageSizeInBytes());\n  if (file.fail())\n    itkExceptionMacro(<< \"Read failed: Wanted \" << GetImageSizeInBytes() << \" bytes, but read \" << file.gcount()\n                      << \" bytes. The current state is: \" << file.rdstate());\n}\n\n//--------------------------------------------------------------------\nbool\nrtk::HisImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n\n//--------------------------------------------------------------------\n// Write Image\nvoid\nrtk::HisImageIO::Write(const void * itkNotUsed(buffer))\n{} ////\n"
  },
  {
    "path": "src/rtkHisImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkHisImageIOFactory.h\"\n\n#include <fstream>\n\nrtk::HisImageIOFactory::HisImageIOFactory()\n{\n  this->RegisterOverride(\n    \"itkImageIOBase\", \"HisImageIO\", \"His Image IO\", true, itk::CreateObjectFunction<HisImageIO>::New());\n}\n\n// Undocumented API used to register during static initialization.\n// DO NOT CALL DIRECTLY.\n\nnamespace itk\n{\n\nstatic bool HisImageIOFactoryHasBeenRegistered;\n\nvoid RTK_EXPORT\nHisImageIOFactoryRegister__Private()\n{\n  if (!HisImageIOFactoryHasBeenRegistered)\n  {\n    HisImageIOFactoryHasBeenRegistered = true;\n    rtk::HisImageIOFactory::RegisterOneFactory();\n  }\n}\n\n} // namespace itk\n"
  },
  {
    "path": "src/rtkHncImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// std include\n#include <cstdio>\n#include <valarray>\n#include <numeric>\n\n#include \"rtkHncImageIO.h\"\n#include <itkMetaDataObject.h>\n\n//--------------------------------------------------------------------\n// Read Image Information\nvoid\nrtk::HncImageIO::ReadImageInformation()\n{\n  Hnc_header hnc;\n  FILE *     fp;\n\n  fp = fopen(m_FileName.c_str(), \"rb\");\n  if (fp == nullptr)\n    itkGenericExceptionMacro(<< \"Could not open file (for reading): \" << m_FileName);\n\n  size_t nelements = 0;\n  nelements += fread((void *)hnc.sFileType, sizeof(char), 32, fp);\n  nelements += fread((void *)&hnc.FileLength, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnc.sChecksumSpec, sizeof(char), 4, fp);\n  nelements += fread((void *)&hnc.nCheckSum, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnc.sCreationDate, sizeof(char), 8, fp);\n  nelements += fread((void *)hnc.sCreationTime, sizeof(char), 8, fp);\n  nelements += fread((void *)hnc.sPatientID, sizeof(char), 16, fp);\n  nelements += fread((void *)&hnc.nPatientSer, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnc.sSeriesID, sizeof(char), 16, fp);\n  nelements += fread((void *)&hnc.nSeriesSer, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnc.sSliceID, sizeof(char), 16, fp);\n  nelements += fread((void *)&hnc.nSliceSer, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnc.SizeX, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnc.SizeY, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnc.dSliceZPos, sizeof(double), 1, fp);\n  nelements += fread((void *)hnc.sModality, sizeof(char), 16, fp);\n  nelements += fread((void *)&hnc.nWindow, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnc.nLevel, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnc.nPixelOffset, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnc.sImageType, sizeof(char), 4, fp);\n  nelements += fread((void *)&hnc.dGantryRtn, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dSAD, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dSFD, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCollX1, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCollX2, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCollY1, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCollY2, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCollRtn, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dFieldX, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dFieldY, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dBladeX1, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dBladeX2, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dBladeY1, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dBladeY2, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dIDUPosLng, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dIDUPosLat, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dIDUPosVrt, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dIDUPosRtn, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dPatientSupportAngle, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dTableTopEccentricAngle, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCouchVrt, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCouchLng, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCouchLat, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dIDUResolutionX, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dIDUResolutionY, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dImageResolutionX, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dImageResolutionY, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dEnergy, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dDoseRate, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dXRayKV, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dXRayMA, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dMetersetExposure, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dAcqAdjustment, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCTProjectionAngle, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dCTNormChamber, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dGatingTimeTag, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dGating4DInfoX, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dGating4DInfoY, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dGating4DInfoZ, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnc.dGating4DInfoTime, sizeof(double), 1, fp);\n\n  if (nelements != /*char*/ 120 + /*itk::uint32_t*/ 10 + /*double*/ 41)\n    itkGenericExceptionMacro(<< \"Could not read header data in \" << m_FileName);\n\n  if (fclose(fp) != 0)\n    itkGenericExceptionMacro(<< \"Could not close file: \" << m_FileName);\n\n  /* Convert hnc to ITK image information */\n  SetNumberOfDimensions(2);\n  SetDimensions(0, hnc.SizeX);\n  SetDimensions(1, hnc.SizeY);\n  SetSpacing(0, hnc.dIDUResolutionX);\n  SetSpacing(1, hnc.dIDUResolutionY);\n  SetOrigin(0, -0.5 * (hnc.SizeX - 1) * hnc.dIDUResolutionX); // SR: assumed centered\n  SetOrigin(1, -0.5 * (hnc.SizeY - 1) * hnc.dIDUResolutionY); // SR: assumed centered\n  SetComponentType(itk::ImageIOBase::IOComponentEnum::USHORT);\n\n  /* Store important meta information in the meta data dictionary */\n  itk::EncapsulateMetaData<double>(this->GetMetaDataDictionary(), \"dCTProjectionAngle\", hnc.dCTProjectionAngle);\n  itk::EncapsulateMetaData<double>(this->GetMetaDataDictionary(), \"dCTNormChamber\", hnc.dCTNormChamber);\n}\n\n//--------------------------------------------------------------------\nbool\nrtk::HncImageIO::CanReadFile(const char * FileNameToRead)\n{\n  std::string                  filename(FileNameToRead);\n  const std::string::size_type it = filename.find_last_of(\".\");\n  std::string                  fileExt(filename, it + 1, filename.length());\n\n  if (fileExt != std::string(\"hnc\"))\n    return false;\n  return true;\n}\n\n//--------------------------------------------------------------------\n// Read Image Content\nvoid\nrtk::HncImageIO::Read(void * buffer)\n{\n  FILE * fp;\n\n  fp = fopen(m_FileName.c_str(), \"rb\");\n  if (fp == nullptr)\n  {\n    itkGenericExceptionMacro(<< \"Could not open file (for reading): \" << m_FileName);\n    return;\n  }\n\n  if (fseek(fp, 512, SEEK_SET) != 0)\n    itkGenericExceptionMacro(<< \"Could not seek 512 bytes in \" << m_FileName);\n\n  size_t nelements = GetDimensions(0) * GetDimensions(1);\n  if (fread(buffer, sizeof(unsigned short int), nelements, fp) != nelements)\n    itkGenericExceptionMacro(<< \"Could not read \" << nelements << \" bytes in \" << m_FileName);\n\n  fclose(fp);\n  return;\n}\n\n//--------------------------------------------------------------------\nbool\nrtk::HncImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n\n//--------------------------------------------------------------------\n// Write Image\nvoid\nrtk::HncImageIO::Write(const void * itkNotUsed(buffer))\n{\n  // TODO?\n}\n"
  },
  {
    "path": "src/rtkHncImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkHncImageIOFactory.h\"\n\n#include <fstream>\n\n//====================================================================\nrtk::HncImageIOFactory::HncImageIOFactory()\n{\n  this->RegisterOverride(\n    \"itkImageIOBase\", \"HncImageIO\", \"Hnc Image IO\", 1, itk::CreateObjectFunction<HncImageIO>::New());\n}\n\n// Undocumented API used to register during static initialization.\n// DO NOT CALL DIRECTLY.\n\nnamespace itk\n{\n\nstatic bool HncImageIOFactoryHasBeenRegistered;\n\nvoid RTK_EXPORT\nHncImageIOFactoryRegister__Private()\n{\n  if (!HncImageIOFactoryHasBeenRegistered)\n  {\n    HncImageIOFactoryHasBeenRegistered = true;\n    rtk::HncImageIOFactory::RegisterOneFactory();\n  }\n}\n\n} // end namespace itk\n"
  },
  {
    "path": "src/rtkHndImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// std include\n#include <cstdio>\n#include <numeric>\n\n#include \"rtkHndImageIO.h\"\n#include <itkMetaDataObject.h>\n\n//--------------------------------------------------------------------\n// Read Image Information\nvoid\nrtk::HndImageIO::ReadImageInformation()\n{\n  Hnd_header hnd;\n  FILE *     fp = nullptr;\n\n  fp = fopen(m_FileName.c_str(), \"rb\");\n  if (fp == nullptr)\n    itkGenericExceptionMacro(<< \"Could not open file (for reading): \" << m_FileName);\n\n  size_t nelements = 0;\n  nelements += fread((void *)hnd.sFileType, sizeof(char), 32, fp);\n  nelements += fread((void *)&hnd.FileLength, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnd.sChecksumSpec, sizeof(char), 4, fp);\n  nelements += fread((void *)&hnd.nCheckSum, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnd.sCreationDate, sizeof(char), 8, fp);\n  nelements += fread((void *)hnd.sCreationTime, sizeof(char), 8, fp);\n  nelements += fread((void *)hnd.sPatientID, sizeof(char), 16, fp);\n  nelements += fread((void *)&hnd.nPatientSer, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnd.sSeriesID, sizeof(char), 16, fp);\n  nelements += fread((void *)&hnd.nSeriesSer, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnd.sSliceID, sizeof(char), 16, fp);\n  nelements += fread((void *)&hnd.nSliceSer, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnd.SizeX, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnd.SizeY, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnd.dSliceZPos, sizeof(double), 1, fp);\n  nelements += fread((void *)hnd.sModality, sizeof(char), 16, fp);\n  nelements += fread((void *)&hnd.nWindow, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnd.nLevel, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)&hnd.nPixelOffset, sizeof(itk::uint32_t), 1, fp);\n  nelements += fread((void *)hnd.sImageType, sizeof(char), 4, fp);\n  nelements += fread((void *)&hnd.dGantryRtn, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dSAD, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dSFD, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCollX1, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCollX2, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCollY1, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCollY2, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCollRtn, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dFieldX, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dFieldY, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dBladeX1, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dBladeX2, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dBladeY1, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dBladeY2, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dIDUPosLng, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dIDUPosLat, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dIDUPosVrt, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dIDUPosRtn, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dPatientSupportAngle, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dTableTopEccentricAngle, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCouchVrt, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCouchLng, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCouchLat, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dIDUResolutionX, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dIDUResolutionY, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dImageResolutionX, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dImageResolutionY, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dEnergy, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dDoseRate, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dXRayKV, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dXRayMA, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dMetersetExposure, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dAcqAdjustment, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCTProjectionAngle, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dCTNormChamber, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dGatingTimeTag, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dGating4DInfoX, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dGating4DInfoY, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dGating4DInfoZ, sizeof(double), 1, fp);\n  nelements += fread((void *)&hnd.dGating4DInfoTime, sizeof(double), 1, fp);\n\n  if (nelements != /*char*/ 120 + /*itk::uint32_t*/ 10 + /*double*/ 41)\n    itkGenericExceptionMacro(<< \"Could not read header data in \" << m_FileName);\n\n  if (fclose(fp) != 0)\n    itkGenericExceptionMacro(<< \"Could not close file: \" << m_FileName);\n\n  /* Convert hnd to ITK image information */\n  SetNumberOfDimensions(2);\n  SetDimensions(0, hnd.SizeX);\n  SetDimensions(1, hnd.SizeY);\n  SetSpacing(0, hnd.dIDUResolutionX);\n  SetSpacing(1, hnd.dIDUResolutionY);\n  SetOrigin(0, -0.5 * (hnd.SizeX - 1) * hnd.dIDUResolutionX); // SR: assumed centered\n  SetOrigin(1, -0.5 * (hnd.SizeY - 1) * hnd.dIDUResolutionY); // SR: assumed centered\n\n  // We need 32 bytes, on many systems UINT seems to work, but on some it may not.\n  auto component_type = itk::ImageIOBase::IOComponentEnum::UINT;\n  SetComponentType(component_type);\n  if (GetComponentSize() < 4)\n  {\n    component_type = itk::ImageIOBase::IOComponentEnum::ULONG;\n    SetComponentType(component_type);\n    if (GetComponentSize() > 4)\n    {\n      itkGenericExceptionMacro(<< \"Could not find a 32bit unsigned integer type\");\n    }\n  }\n\n  /* Store important meta information in the meta data dictionary */\n  itk::EncapsulateMetaData<double>(this->GetMetaDataDictionary(), \"dCTProjectionAngle\", hnd.dCTProjectionAngle);\n}\n\n//--------------------------------------------------------------------\nbool\nrtk::HndImageIO::CanReadFile(const char * FileNameToRead)\n{\n  std::string                  filename(FileNameToRead);\n  const std::string::size_type it = filename.find_last_of(\".\");\n  std::string                  fileExt(filename, it + 1, filename.length());\n\n  if (fileExt != std::string(\"hnd\"))\n    return false;\n  return true;\n}\n\n//--------------------------------------------------------------------\ntemplate <typename T>\ninline T\nload_binary_char_as(const unsigned char * bin_vals, const size_t n_bytes)\n{\n  T tmp_val;\n  std::memcpy(&tmp_val, bin_vals, n_bytes);\n  return tmp_val;\n}\n\ntemplate <typename T>\ninline T\ncast_binary_char_to(const unsigned char * bin_vals, const size_t n_bytes)\n{\n  T out_val = 0;\n  switch (n_bytes)\n  {\n    case 1:\n      out_val = static_cast<T>(load_binary_char_as<int8_t>(bin_vals, n_bytes));\n      break;\n    case 2:\n      out_val = static_cast<T>(load_binary_char_as<int16_t>(bin_vals, n_bytes));\n      break;\n    case 4:\n      out_val = static_cast<T>(load_binary_char_as<int32_t>(bin_vals, n_bytes));\n      break;\n  }\n  return out_val;\n}\n\ninline size_t\nlut_to_bytes(const char val)\n{\n  switch (val)\n  {\n    case 0:\n      return 1;\n    case 1:\n      return 2;\n    case 2:\n      return 4;\n    default: // only 0, 1 & 2 should be possible\n      return 8;\n  }\n}\n\n// Read Image Content\nvoid\nrtk::HndImageIO::Read(void * buffer)\n{\n  FILE * fp = nullptr;\n  // Long is only garanteed to be AT LEAST 32 bits, it could be 64 bit\n  using Int4 = itk::uint32_t;\n  Int4 * buf = (Int4 *)buffer;\n\n  fp = fopen(m_FileName.c_str(), \"rb\");\n  if (fp == nullptr)\n    itkGenericExceptionMacro(<< \"Could not open file (for reading): \" << m_FileName);\n\n  if (fseek(fp, 1024, SEEK_SET) != 0)\n    itkGenericExceptionMacro(<< \"Could not seek to image data in: \" << m_FileName);\n\n  const auto   xdim = GetDimensions(0);\n  const auto   ydim = GetDimensions(1);\n  const size_t lookUpTableSize = (ydim - 1) * xdim / 4;\n  // De\"compress\" image\n  auto m_lookup_table = std::vector<unsigned char>(lookUpTableSize);\n  if (lookUpTableSize != fread((void *)&m_lookup_table[0], sizeof(unsigned char), lookUpTableSize, fp))\n  {\n    itkGenericExceptionMacro(<< \"Could not read lookup table from Hnd file: \" << m_FileName);\n  }\n\n  if (xdim * ydim == 0)\n  {\n    itkGenericExceptionMacro(<< \"Dimensions of image was 0 in: \" << m_FileName);\n  }\n\n  if ((xdim + 1) != fread(&buf[0], sizeof(Int4), xdim + 1, fp))\n    itkGenericExceptionMacro(<< \"Could not read first row +1 in: \" << m_FileName);\n\n  std::vector<unsigned char> byte_table(lookUpTableSize);\n  std::transform(m_lookup_table.begin(), m_lookup_table.end(), byte_table.begin(), [](const unsigned char & v) {\n    unsigned char bytes = 0;\n    bytes += lut_to_bytes(v & 0b00000011);        // 0x03\n    bytes += lut_to_bytes((v & 0b00001100) >> 2); // 0x0C\n    bytes += lut_to_bytes((v & 0b00110000) >> 4); // 0x30\n    bytes += lut_to_bytes((v & 0b11000000) >> 6); // 0xC0\n    return bytes;\n  });\n\n  const auto total_bytes = std::accumulate(std::begin(byte_table), std::end(byte_table), 0ull);\n\n  auto compr_img_buffer = std::vector<unsigned char>(total_bytes);\n  // total_bytes - 3 because the last two bits can be redundant (according to Xim docs)\n  if ((total_bytes - 3) > fread((void *)&compr_img_buffer[0], sizeof(unsigned char), total_bytes, fp))\n  {\n    itkGenericExceptionMacro(<< \"Could not read image buffer of Hnd file: \" << m_FileName);\n  }\n\n  size_t j = 0U;\n  size_t i = xdim;\n  size_t iminxdim = 0;\n\n  for (auto lut_idx = 0U; lut_idx < lookUpTableSize; ++lut_idx)\n  {\n    const auto v = m_lookup_table[lut_idx];\n    auto       bytes = lut_to_bytes(v & 0b00000011); // 0x03\n    assert(bytes == 1 || bytes == 2 || bytes == 4);\n    auto diff1 = cast_binary_char_to<long long>(&compr_img_buffer[j], bytes);\n    j += bytes;\n\n    bytes = lut_to_bytes((v & 0b00001100) >> 2); // 0x0C\n    assert(bytes == 1 || bytes == 2 || bytes == 4);\n    auto diff2 = cast_binary_char_to<long long>(&compr_img_buffer[j], bytes);\n    j += bytes;\n\n    bytes = lut_to_bytes((v & 0b00110000) >> 4); // 0x30\n    assert(bytes == 1 || bytes == 2 || bytes == 4);\n    auto diff3 = cast_binary_char_to<long long>(&compr_img_buffer[j], bytes);\n    j += bytes;\n\n    bytes = lut_to_bytes((v & 0b11000000) >> 6); // 0xC0\n    assert(bytes == 1 || bytes == 2 || bytes == 4);\n    auto diff4 = cast_binary_char_to<long long>(&compr_img_buffer[j], bytes);\n    j += bytes;\n\n    buf[i + 1] = static_cast<Int4>(diff1 + buf[i] + buf[iminxdim + 1] - buf[iminxdim]);\n    buf[i + 2] = static_cast<Int4>(diff2 + buf[i + 1] + buf[iminxdim + 2] - buf[iminxdim + 1]);\n    buf[i + 3] = static_cast<Int4>(diff3 + buf[i + 2] + buf[iminxdim + 3] - buf[iminxdim + 2]);\n    if (i + 4 < xdim * ydim)\n    {\n      buf[i + 4] = static_cast<Int4>(diff4 + buf[i + 3] + buf[iminxdim + 4] - buf[iminxdim + 3]);\n    }\n\n    i += 4;\n    iminxdim += 4;\n  }\n\n  assert(j == total_bytes);\n  assert(i == (xdim * ydim));\n\n  if (fclose(fp) != 0)\n    itkGenericExceptionMacro(<< \"Could not close file: \" << m_FileName);\n}\n\n//--------------------------------------------------------------------\nbool\nrtk::HndImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n\n//--------------------------------------------------------------------\n// Write Image\nvoid\nrtk::HndImageIO::Write(const void * itkNotUsed(buffer))\n{\n  // TODO?\n}\n"
  },
  {
    "path": "src/rtkHndImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkHndImageIOFactory.h\"\n\n#include <fstream>\n\n//====================================================================\nrtk::HndImageIOFactory::HndImageIOFactory()\n{\n  this->RegisterOverride(\n    \"itkImageIOBase\", \"HndImageIO\", \"Hnd Image IO\", true, itk::CreateObjectFunction<HndImageIO>::New());\n}\n\n// Undocumented API used to register during static initialization.\n// DO NOT CALL DIRECTLY.\n\nnamespace itk\n{\n\nstatic bool HndImageIOFactoryHasBeenRegistered;\n\nvoid RTK_EXPORT\nHndImageIOFactoryRegister__Private()\n{\n  if (!HndImageIOFactoryHasBeenRegistered)\n  {\n    HndImageIOFactoryHasBeenRegistered = true;\n    rtk::HndImageIOFactory::RegisterOneFactory();\n  }\n}\n\n} // end namespace itk\n"
  },
  {
    "path": "src/rtkIOFactories.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkIOFactories.h\"\n#include <itkImageIOFactory.h>\n#include <itkGDCMImageIOFactory.h>\n\n// Varian Obi includes\n#include \"rtkHndImageIOFactory.h\"\n#include \"rtkHncImageIOFactory.h\"\n\n// Varian ProBeam includes\n#include \"rtkXimImageIOFactory.h\"\n\n// Elekta Synergy includes\n#include \"rtkHisImageIOFactory.h\"\n\n// ImagX includes\n#include \"rtkImagXImageIOFactory.h\"\n#include \"rtkDCMImagXImageIOFactory.h\"\n\n// European Synchrotron Radiation Facility\n#include \"rtkEdfImageIOFactory.h\"\n\n// Xrad small animal scanner\n#include \"rtkXRadImageIOFactory.h\"\n\n// Ora / medPhoton file format\n#include \"rtkOraImageIOFactory.h\"\n\nnamespace rtk\n{\n\nvoid\nRegisterIOFactories()\n{\n  // First unregister GDCMImageIO to let ImageXDCM\n  std::list<itk::ObjectFactoryBase *> fl = itk::GDCMImageIOFactory::GetRegisteredFactories();\n  for (auto & factory : fl)\n    if (dynamic_cast<itk::GDCMImageIOFactory *>(factory))\n    {\n      itk::GDCMImageIOFactory::UnRegisterFactory(factory);\n    }\n  rtk::HndImageIOFactory::RegisterOneFactory();\n  rtk::HncImageIOFactory::RegisterOneFactory();\n  rtk::XimImageIOFactory::RegisterOneFactory();\n  rtk::HisImageIOFactory::RegisterOneFactory();\n  rtk::ImagXImageIOFactory::RegisterOneFactory();\n  rtk::DCMImagXImageIOFactory::RegisterOneFactory();\n  rtk::EdfImageIOFactory::RegisterOneFactory();\n  rtk::XRadImageIOFactory::RegisterOneFactory();\n  rtk::OraImageIOFactory::RegisterOneFactory();\n  itk::GDCMImageIOFactory::RegisterOneFactory();\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkImagXImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkImagXImageIO.h\"\n#include \"rtkImagXXMLFileReader.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n#include <itkMatrix.h>\n#include <itkByteSwapper.h>\n#include <itkRawImageIO.h>\n\n//--------------------------------------------------------------------\n// Read Image Information\nvoid\nrtk::ImagXImageIO::ReadImageInformation()\n{\n  rtk::ImagXXMLFileReader::Pointer xmlReader;\n\n  xmlReader = rtk::ImagXXMLFileReader::New();\n  xmlReader->SetFilename(m_FileName);\n  xmlReader->GenerateOutputInformation();\n\n  itk::MetaDataDictionary & dic = *(xmlReader->GetOutputObject());\n\n  using MetaDataDoubleType = itk::MetaDataObject<double>;\n  using MetaDataStringType = itk::MetaDataObject<std::string>;\n  using MetaDataIntType = itk::MetaDataObject<int>;\n\n  std::string pixelType = dynamic_cast<MetaDataStringType *>(dic[\"pixelFormat\"].GetPointer())->GetMetaDataObjectValue();\n  if (pixelType == \"Type_uint8\")\n    SetComponentType(itk::ImageIOBase::IOComponentEnum::UCHAR);\n  if (pixelType == \"Type_sint8\")\n    SetComponentType(itk::ImageIOBase::IOComponentEnum::CHAR);\n  if (pixelType == \"Type_uint16\")\n    SetComponentType(itk::ImageIOBase::IOComponentEnum::USHORT);\n  if (pixelType == \"Type_sint16\")\n    SetComponentType(itk::ImageIOBase::IOComponentEnum::SHORT);\n  if (pixelType == \"Type_uint32\")\n    SetComponentType(itk::ImageIOBase::IOComponentEnum::UINT);\n  if (pixelType == \"Type_sint32\")\n    SetComponentType(itk::ImageIOBase::IOComponentEnum::INT);\n  if (pixelType == \"Type_float\")\n    SetComponentType(itk::ImageIOBase::IOComponentEnum::FLOAT);\n\n  if (dic[\"dimensions\"].GetPointer() == nullptr)\n    SetNumberOfDimensions(3);\n  else\n    SetNumberOfDimensions((dynamic_cast<MetaDataIntType *>(dic[\"dimensions\"].GetPointer())->GetMetaDataObjectValue()));\n\n  SetDimensions(0, dynamic_cast<MetaDataIntType *>(dic[\"x\"].GetPointer())->GetMetaDataObjectValue());\n  SetSpacing(0, dynamic_cast<MetaDataDoubleType *>(dic[\"spacing_x\"].GetPointer())->GetMetaDataObjectValue());\n  if (GetNumberOfDimensions() > 1)\n  {\n    SetDimensions(1, dynamic_cast<MetaDataIntType *>(dic[\"y\"].GetPointer())->GetMetaDataObjectValue());\n    SetSpacing(1, dynamic_cast<MetaDataDoubleType *>(dic[\"spacing_y\"].GetPointer())->GetMetaDataObjectValue());\n  }\n  if (GetNumberOfDimensions() > 2)\n  {\n    SetDimensions(2, dynamic_cast<MetaDataIntType *>(dic[\"z\"].GetPointer())->GetMetaDataObjectValue());\n    SetSpacing(2, dynamic_cast<MetaDataDoubleType *>(dic[\"spacing_z\"].GetPointer())->GetMetaDataObjectValue());\n    if (GetSpacing(2) == 0)\n      SetSpacing(2, 1);\n  }\n\n  itk::Matrix<double, 4, 4> matrix;\n  if (dic[\"matrixTransform\"].GetPointer() == nullptr)\n    matrix.SetIdentity();\n  else\n  {\n    std::istringstream iss(\n      dynamic_cast<MetaDataStringType *>(dic[\"matrixTransform\"].GetPointer())->GetMetaDataObjectValue());\n    for (unsigned int j = 0; j < 4; j++)\n      for (unsigned int i = 0; i < 4; i++)\n        iss >> matrix[j][i];\n    matrix /= matrix[3][3];\n  }\n\n  std::vector<double> direction;\n  for (unsigned int i = 0; i < GetNumberOfDimensions(); i++)\n  {\n    direction.clear();\n    for (unsigned int j = 0; j < GetNumberOfDimensions(); j++)\n      direction.push_back(matrix[i][j]);\n    SetDirection(i, direction);\n    SetOrigin(i, matrix[i][3]);\n  }\n\n  if (std::string(\"LSB\") == dynamic_cast<MetaDataStringType *>(dic[\"byteOrder\"].GetPointer())->GetMetaDataObjectValue())\n    this->SetByteOrder(IOByteOrderEnum::LittleEndian);\n  else\n    this->SetByteOrder(IOByteOrderEnum::BigEndian);\n\n  // Prepare raw file name\n  m_RawFileName = itksys::SystemTools::GetFilenamePath(m_FileName);\n  if (!m_RawFileName.empty())\n    m_RawFileName += std::string(\"/\");\n  m_RawFileName += dynamic_cast<MetaDataStringType *>(dic[\"rawFile\"].GetPointer())->GetMetaDataObjectValue();\n} ////\n\n//--------------------------------------------------------------------\n// Read Image Information\nbool\nrtk::ImagXImageIO::CanReadFile(const char * FileNameToRead)\n{\n  std::string ext = itksys::SystemTools::GetFilenameLastExtension(FileNameToRead);\n\n  if (ext != std::string(\".xml\"))\n    return false;\n\n  std::ifstream is(FileNameToRead);\n  if (!is.is_open())\n    return false;\n\n  // If the XML file has \"<image name=\" at the beginning of the first or second\n  // line, we assume this is an ImagX file\n  std::string line;\n\n  std::getline(is, line);\n  if (line.substr(0, 12) == std::string(\"<image name=\"))\n    return true;\n\n  std::getline(is, line);\n  if (line.substr(0, 12) == std::string(\"<image name=\"))\n    return true;\n\n  return false;\n} ////\n\n//--------------------------------------------------------------------\n// Read Image Content\nvoid\nrtk::ImagXImageIO::Read(void * buffer)\n{\n  // Adapted from itkRawImageIO\n  std::ifstream is(m_RawFileName.c_str(), std::ios::binary);\n\n  if (!is.is_open())\n    itkExceptionMacro(<< \"Could not open file \" << m_RawFileName);\n\n  unsigned long numberOfBytesToBeRead = GetComponentSize();\n  for (unsigned int i = 0; i < GetNumberOfDimensions(); i++)\n    numberOfBytesToBeRead *= GetDimensions(i);\n\n  if (!this->ReadBufferAsBinary(is, buffer, numberOfBytesToBeRead))\n  {\n    itkExceptionMacro(<< \"Read failed: Wanted \" << numberOfBytesToBeRead << \" bytes, but read \" << is.gcount()\n                      << \" bytes.\");\n  }\n  itkDebugMacro(<< \"Reading Done\");\n\n  const auto          componentType = this->GetComponentType();\n  const SizeValueType numberOfComponents = this->GetImageSizeInComponents();\n  ReadRawBytesAfterSwapping(componentType, buffer, m_ByteOrder, numberOfComponents);\n}\n\n//--------------------------------------------------------------------\n// Write Image Information\nvoid\nrtk::ImagXImageIO::WriteImageInformation(bool itkNotUsed(keepOfStream))\n{}\n\n//--------------------------------------------------------------------\n// Write Image Information\nbool\nrtk::ImagXImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n\n//--------------------------------------------------------------------\n// Write Image\nvoid\nrtk::ImagXImageIO::Write(const void * itkNotUsed(buffer))\n{} ////\n"
  },
  {
    "path": "src/rtkImagXImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkImagXImageIOFactory.h\"\n\n//====================================================================\nrtk::ImagXImageIOFactory::ImagXImageIOFactory()\n{\n  this->RegisterOverride(\n    \"itkImageIOBase\", \"ImagXImageIO\", \"ImagX Image IO\", true, itk::CreateObjectFunction<ImagXImageIO>::New());\n}\n\n// Undocumented API used to register during static initialization.\n// DO NOT CALL DIRECTLY.\n\nnamespace itk\n{\n\nstatic bool ImagXImageIOFactoryHasBeenRegistered;\n\nvoid RTK_EXPORT\nImagXImageIOFactoryRegister__Private()\n{\n  if (!ImagXImageIOFactoryHasBeenRegistered)\n  {\n    ImagXImageIOFactoryHasBeenRegistered = true;\n    rtk::ImagXImageIOFactory::RegisterOneFactory();\n  }\n}\n\n} // end namespace itk\n"
  },
  {
    "path": "src/rtkImagXXMLFileReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkImagXXMLFileReader.h\"\n#include \"itkMacro.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n\nnamespace rtk\n{\n\nint\nImagXXMLFileReader::CanReadFile(const char * name)\n{\n  if (!itksys::SystemTools::FileExists(name) || itksys::SystemTools::FileIsDirectory(name) ||\n      itksys::SystemTools::FileLength(name) == 0)\n    return 0;\n  return 1;\n}\n\nvoid\nImagXXMLFileReader::StartElement(const char * name, const char ** atts)\n{\n#define ENCAPLULATE_META_DATA_INT(metaName)                   \\\n  if (itksys::SystemTools::Strucmp(atts[i], metaName) == 0)   \\\n  {                                                           \\\n    double d = std::stod(atts[i + 1]);                        \\\n    itk::EncapsulateMetaData<int>(m_Dictionary, metaName, d); \\\n  }\n\n#define ENCAPLULATE_META_DATA_STRING(metaName)                                  \\\n  if (itksys::SystemTools::Strucmp(atts[i], metaName) == 0)                     \\\n  {                                                                             \\\n    itk::EncapsulateMetaData<std::string>(m_Dictionary, metaName, atts[i + 1]); \\\n  }\n\n  if (std::string(name) == std::string(\"image\"))\n  {\n    for (int i = 0; atts[i] != nullptr; i += 2)\n    {\n      ENCAPLULATE_META_DATA_STRING(\"name\");\n      ENCAPLULATE_META_DATA_INT(\"bitDepth\");\n      ENCAPLULATE_META_DATA_STRING(\"pixelFormat\");\n      ENCAPLULATE_META_DATA_STRING(\"byteOrder\");\n      ENCAPLULATE_META_DATA_STRING(\"modality\");\n      ENCAPLULATE_META_DATA_STRING(\"matrixTransform\");\n      ENCAPLULATE_META_DATA_INT(\"dimensions\");\n      ENCAPLULATE_META_DATA_INT(\"sequence\");\n      ENCAPLULATE_META_DATA_STRING(\"rawFile\");\n    }\n  }\n  if (std::string(name) == std::string(\"size\"))\n  {\n    for (int i = 0; atts[i] != nullptr; i += 2)\n    {\n      ENCAPLULATE_META_DATA_INT(\"x\");\n      ENCAPLULATE_META_DATA_INT(\"y\");\n      ENCAPLULATE_META_DATA_INT(\"z\");\n    }\n  }\n  if (std::string(name) == std::string(\"spacing\"))\n  {\n#define ENCAPLULATE_META_DATA_DOUBLE(metaName)                                                          \\\n  if (itksys::SystemTools::Strucmp(atts[i], metaName) == 0)                                             \\\n  {                                                                                                     \\\n    double d = std::stod(atts[i + 1]);                                                                  \\\n    itk::EncapsulateMetaData<double>(m_Dictionary, std::string(\"spacing_\") + std::string(metaName), d); \\\n  }\n    for (int i = 0; atts[i] != nullptr; i += 2)\n    {\n      ENCAPLULATE_META_DATA_DOUBLE(\"x\");\n      ENCAPLULATE_META_DATA_DOUBLE(\"y\");\n      ENCAPLULATE_META_DATA_DOUBLE(\"z\");\n    }\n  }\n  m_CurCharacterData = \"\";\n}\n\nvoid\nImagXXMLFileReader::EndElement(const char * itkNotUsed(name))\n{}\n\nvoid\nImagXXMLFileReader::CharacterDataHandler(const char * inData, int inLength)\n{\n  for (int i = 0; i < inLength; i++)\n    m_CurCharacterData = m_CurCharacterData + inData[i];\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkIntersectionOfConvexShapes.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"math.h\"\n\n#include \"rtkIntersectionOfConvexShapes.h\"\n\nnamespace rtk\n{\n\nIntersectionOfConvexShapes ::IntersectionOfConvexShapes() = default;\n\nvoid\nIntersectionOfConvexShapes ::SetConvexShapes(const ConvexShapeVector & _arg)\n{\n  m_ConvexShapes.clear();\n  for (auto & convexShape : _arg)\n    this->AddConvexShape(convexShape);\n  this->Modified();\n}\n\nbool\nIntersectionOfConvexShapes ::IsInside(const PointType & point) const\n{\n  for (const auto & convexShape : m_ConvexShapes)\n  {\n    if (!convexShape->IsInside(point))\n      return false;\n  }\n  return true;\n}\n\nbool\nIntersectionOfConvexShapes ::IsIntersectedByRay(const PointType &  rayOrigin,\n                                                const VectorType & rayDirection,\n                                                ScalarType &       nearDist,\n                                                ScalarType &       farDist) const\n{\n  nearDist = itk::NumericTraits<ScalarType>::NonpositiveMin();\n  farDist = itk::NumericTraits<ScalarType>::max();\n  for (const auto & convexShape : m_ConvexShapes)\n  {\n    ScalarType n = NAN, f = NAN;\n    if (!convexShape->IsIntersectedByRay(rayOrigin, rayDirection, n, f))\n      return false;\n    nearDist = std::max(nearDist, n);\n    farDist = std::min(farDist, f);\n    if (nearDist >= farDist)\n      return false;\n  }\n  return true;\n}\n\nvoid\nIntersectionOfConvexShapes ::Rescale(const VectorType & r)\n{\n  Superclass::Rescale(r);\n  for (auto & convexShape : m_ConvexShapes)\n    convexShape->Rescale(r);\n}\n\nvoid\nIntersectionOfConvexShapes ::Translate(const VectorType & t)\n{\n  Superclass::Translate(t);\n  for (auto & convexShape : m_ConvexShapes)\n    convexShape->Translate(t);\n}\n\nvoid\nIntersectionOfConvexShapes ::Rotate(const RotationMatrixType & r)\n{\n  Superclass::Rotate(r);\n  for (auto & convexShape : m_ConvexShapes)\n    convexShape->Rotate(r);\n}\n\nvoid\nIntersectionOfConvexShapes ::AddConvexShape(const ConvexShape * co)\n{\n  ConvexShapePointer clone = co->Clone();\n  m_ConvexShapes.push_back(clone);\n}\n\nitk::LightObject::Pointer\nIntersectionOfConvexShapes ::InternalClone() const\n{\n  LightObject::Pointer loPtr = Superclass::InternalClone();\n  Self::Pointer        clone = dynamic_cast<Self *>(loPtr.GetPointer());\n\n  clone->SetConvexShapes(this->GetConvexShapes());\n\n  return loPtr;\n}\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkOraGeometryReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkOraGeometryReader_hxx\n#define rtkOraGeometryReader_hxx\n\n#include \"rtkMacro.h\"\n#include \"rtkOraGeometryReader.h\"\n#include \"rtkOraXMLFileReader.h\"\n#include \"rtkIOFactories.h\"\n\n#include <itkImageIOBase.h>\n#include <itkImageIOFactory.h>\n#include <itkVersorRigid3DTransform.h>\n#include <itkQuaternionRigidTransform.h>\n\nnamespace rtk\n{\n\n\nvoid\nOraGeometryReader::GenerateData()\n{\n  m_Geometry = GeometryType::New();\n  RegisterIOFactories();\n  itk::QuaternionRigidTransform<double>::Pointer firstQuaternionsX{ nullptr };\n  itk::Vector<double, 3>                         firstTranslation{ 0.0 };\n  for (const std::string & projectionsFileName : m_ProjectionsFileNames)\n  {\n    itk::ImageIOBase::Pointer reader;\n\n    reader =\n      itk::ImageIOFactory::CreateImageIO(projectionsFileName.c_str(), itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n    if (!reader)\n    {\n      itkExceptionMacro(\"Error reading file \" << projectionsFileName);\n    }\n    reader->SetFileName(projectionsFileName.c_str());\n    reader->ReadImageInformation();\n    itk::MetaDataDictionary & dic = reader->GetMetaDataDictionary();\n\n    using MetaDataVectorType = itk::MetaDataObject<VectorType>;\n    using MetaDataMatrixType = itk::MetaDataObject<Matrix3x3Type>;\n    using MetaDataDoubleType = itk::MetaDataObject<double>;\n    using MetaDataVectorDoubleType = itk::MetaDataObject<std::vector<double>>;\n    using MetaDataVectorIntType = itk::MetaDataObject<std::vector<int>>;\n\n    // Source position\n    MetaDataVectorType * spMeta = dynamic_cast<MetaDataVectorType *>(dic[\"SourcePosition\"].GetPointer());\n    if (spMeta == nullptr)\n    {\n      itkExceptionMacro(<< \"No SourcePosition in \" << projectionsFileName);\n    }\n    PointType sp(&(spMeta->GetMetaDataObjectValue()[0]));\n\n    // Origin (detector position)\n    MetaDataVectorType * dpMeta = dynamic_cast<MetaDataVectorType *>(dic[\"Origin\"].GetPointer());\n    if (dpMeta == nullptr)\n    {\n      itkExceptionMacro(<< \"No Origin in \" << projectionsFileName);\n    }\n    PointType dp(&(dpMeta->GetMetaDataObjectValue()[0]));\n\n    // Direction (detector orientation)\n    MetaDataMatrixType * matMeta = dynamic_cast<MetaDataMatrixType *>(dic[\"Direction\"].GetPointer());\n    if (matMeta == nullptr)\n    {\n      itkExceptionMacro(<< \"No Direction in \" << projectionsFileName);\n    }\n    Matrix3x3Type mat = matMeta->GetMetaDataObjectValue();\n    VectorType    u = VectorType(&(mat[0][0]));\n    VectorType    v = VectorType(&(mat[1][0]));\n\n    // table_axis_distance_cm\n    MetaDataDoubleType * thMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"table_axis_distance_cm\"].GetPointer());\n    if (thMeta == nullptr)\n    {\n      itkExceptionMacro(<< \"No table_axis_distance_cm in \" << projectionsFileName);\n    }\n    double th = thMeta->GetMetaDataObjectValue();\n    sp[2] -= th * 10.;\n    dp[2] -= th * 10.;\n\n    // longitudinalposition_cm\n    MetaDataDoubleType * axMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"longitudinalposition_cm\"].GetPointer());\n    if (axMeta == nullptr)\n    {\n      itkExceptionMacro(<< \"No longitudinalposition_cm in \" << projectionsFileName);\n    }\n    double ax = axMeta->GetMetaDataObjectValue();\n    sp[1] -= ax * 10.;\n    dp[1] -= ax * 10.;\n\n    // Ring tilt (only available in some versions)\n    MetaDataDoubleType * tiltLeftMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"tiltleft_deg\"].GetPointer());\n    if (tiltLeftMeta != nullptr && m_OptiTrackObjectID < 0)\n    {\n      double               tiltLeft = tiltLeftMeta->GetMetaDataObjectValue();\n      MetaDataDoubleType * tiltRightMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"tiltright_deg\"].GetPointer());\n      double               tiltRight = tiltRightMeta->GetMetaDataObjectValue();\n      auto                 tiltTransform = itk::VersorRigid3DTransform<double>::New();\n      const double         deg2rad = std::atan(1.0) / 45.0;\n      tiltTransform->SetRotation(itk::MakeVector(1., 0., 0.), 0.5 * (tiltLeft + tiltRight) * deg2rad);\n\n      // Set center of rotation\n      MetaDataDoubleType * yvecMeta =\n        dynamic_cast<MetaDataDoubleType *>(dic[\"ydistancebaseunitcs2imagingcs_cm\"].GetPointer());\n      double               yvec = yvecMeta->GetMetaDataObjectValue();\n      MetaDataDoubleType * zvecMeta =\n        dynamic_cast<MetaDataDoubleType *>(dic[\"zdistancebaseunitcs2imagingcs_cm\"].GetPointer());\n      double zvec = zvecMeta->GetMetaDataObjectValue();\n      tiltTransform->SetCenter(itk::MakePoint(0., -10. * yvec, -10. * zvec));\n\n      sp = tiltTransform->TransformPoint(sp);\n      dp = tiltTransform->TransformPoint(dp);\n      u = tiltTransform->TransformVector(u);\n      v = tiltTransform->TransformVector(v);\n    }\n\n    // Ring yaw (only available in some versions)\n    MetaDataDoubleType * yawMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"room_cs_yaw_deg\"].GetPointer());\n    if (yawMeta != nullptr && m_OptiTrackObjectID < 0)\n    {\n      double       yaw = yawMeta->GetMetaDataObjectValue();\n      auto         tiltTransform = itk::VersorRigid3DTransform<double>::New();\n      const double deg2rad = std::atan(1.0) / 45.0;\n      tiltTransform->SetRotation(itk::MakeVector(0., 0., 1.), yaw * deg2rad);\n\n      // Set center of rotation\n      MetaDataDoubleType * yvecMeta =\n        dynamic_cast<MetaDataDoubleType *>(dic[\"ydistancebaseunitcs2imagingcs_cm\"].GetPointer());\n      double yvec = yvecMeta->GetMetaDataObjectValue();\n      tiltTransform->SetCenter(itk::MakePoint(0., -10. * yvec, 0.));\n\n      sp = tiltTransform->TransformPoint(sp);\n      dp = tiltTransform->TransformPoint(dp);\n      u = tiltTransform->TransformVector(u);\n      v = tiltTransform->TransformVector(v);\n    }\n\n    // OptiTrack objects (objects tracked with infrared cameras)\n    if (m_OptiTrackObjectID >= 0)\n    {\n      // Find ID index of the OptiTrack object\n      MetaDataVectorIntType * idsMeta = dynamic_cast<MetaDataVectorIntType *>(dic[\"optitrack_object_ids\"].GetPointer());\n      if (idsMeta == nullptr)\n        itkExceptionMacro(\"Could not find optitrack_object_ids in \" << projectionsFileName);\n      const std::vector<int> ids = idsMeta->GetMetaDataObjectValue();\n      auto                   idIt = std::find(ids.begin(), ids.end(), m_OptiTrackObjectID);\n      unsigned int           idIdx = idIt - ids.begin();\n\n      // Translation\n      MetaDataVectorDoubleType * posMeta =\n        dynamic_cast<MetaDataVectorDoubleType *>(dic[\"optitrack_positions\"].GetPointer());\n      if (posMeta == nullptr)\n        itkExceptionMacro(\"Could not find optitrack_positions in \" << projectionsFileName);\n      const std::vector<double> p = posMeta->GetMetaDataObjectValue();\n      if (p.size() < 3 * (idIdx + 1))\n        itkExceptionMacro(\"Not enough values in optitrack_positions of \" << projectionsFileName);\n      itk::Vector<double, 3> translation = 10. * itk::MakeVector(p[idIdx * 3], p[idIdx * 3 + 1], p[idIdx * 3 + 2]);\n\n      // Rotation\n      MetaDataVectorDoubleType * rotMeta =\n        dynamic_cast<MetaDataVectorDoubleType *>(dic[\"optitrack_rotations\"].GetPointer());\n      if (rotMeta == nullptr)\n        itkExceptionMacro(\"Could not find optitrack_rotations in \" << projectionsFileName);\n      const std::vector<double> optitrackRotations = rotMeta->GetMetaDataObjectValue();\n      if (optitrackRotations.size() < 4 * (idIdx + 1))\n        itkExceptionMacro(\"Not enough values in optitrack_rotations of \" << projectionsFileName);\n      auto                                                  quaternionsX = itk::QuaternionRigidTransform<double>::New();\n      itk::QuaternionRigidTransform<double>::ParametersType quaternionsXParam(7);\n      quaternionsXParam[3] = optitrackRotations[idIdx * 4];\n      quaternionsXParam[0] = optitrackRotations[idIdx * 4 + 1];\n      quaternionsXParam[1] = optitrackRotations[idIdx * 4 + 2];\n      quaternionsXParam[2] = optitrackRotations[idIdx * 4 + 3];\n      quaternionsXParam[4] = 0.;\n      quaternionsXParam[5] = 0.;\n      quaternionsXParam[6] = 0.;\n      quaternionsX->SetParameters(quaternionsXParam);\n\n      if (firstQuaternionsX.GetPointer() == nullptr)\n      {\n        firstQuaternionsX = quaternionsX;\n        firstTranslation = translation;\n      }\n      else\n      {\n        itk::MatrixOffsetTransformBase<double, 3, 3>::InverseTransformBasePointer invQuaternionsX =\n          quaternionsX->GetInverseTransform();\n\n        sp = sp - translation;\n        dp = dp - translation;\n        sp = invQuaternionsX->TransformPoint(sp);\n        dp = invQuaternionsX->TransformPoint(dp);\n        u = invQuaternionsX->TransformVector(u);\n        v = invQuaternionsX->TransformVector(v);\n\n        sp = firstQuaternionsX->TransformPoint(sp);\n        dp = firstQuaternionsX->TransformPoint(dp);\n        u = firstQuaternionsX->TransformVector(u);\n        v = firstQuaternionsX->TransformVector(v);\n        sp = sp + firstTranslation;\n        dp = dp + firstTranslation;\n      }\n    }\n\n    // Got it, add to geometry\n    if (!m_Geometry->AddProjection(sp, dp, u, v))\n    {\n      itkWarningMacro(\"Could not add \" << projectionsFileName << \" with sp=\" << sp << \", dp=\" << dp << \", u=\" << u\n                                       << \" and v=\" << v);\n    }\n\n    // Now add the collimation\n    // longitudinalposition_cm\n    double               uinf = std::numeric_limits<double>::max();\n    MetaDataDoubleType * uinfMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"xrayx1_cm\"].GetPointer());\n    if (uinfMeta != nullptr)\n    {\n      uinf = 10. * uinfMeta->GetMetaDataObjectValue() + m_CollimationMargin[0];\n    }\n\n    double               usup = std::numeric_limits<double>::max();\n    MetaDataDoubleType * usupMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"xrayx2_cm\"].GetPointer());\n    if (usupMeta != nullptr)\n    {\n      usup = 10. * usupMeta->GetMetaDataObjectValue() + m_CollimationMargin[1];\n    }\n\n    double               vinf = std::numeric_limits<double>::max();\n    MetaDataDoubleType * vinfMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"xrayy1_cm\"].GetPointer());\n    if (vinfMeta != nullptr)\n    {\n      vinf = 10. * vinfMeta->GetMetaDataObjectValue() + m_CollimationMargin[2];\n    }\n\n    double               vsup = std::numeric_limits<double>::max();\n    MetaDataDoubleType * vsupMeta = dynamic_cast<MetaDataDoubleType *>(dic[\"xrayy2_cm\"].GetPointer());\n    if (vsupMeta != nullptr)\n    {\n      vsup = 10. * vsupMeta->GetMetaDataObjectValue() + m_CollimationMargin[3];\n    }\n    m_Geometry->SetCollimationOfLastProjection(uinf, usup, vinf, vsup);\n  }\n}\n} // namespace rtk\n#endif\n"
  },
  {
    "path": "src/rtkOraImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkOraImageIO.h\"\n#include \"rtkOraXMLFileReader.h\"\n\n#include <itksys/SystemTools.hxx>\n\nvoid\nrtk::OraImageIO::ReadImageInformation()\n{\n  rtk::OraXMLFileReader::Pointer xmlReader;\n\n  std::string oraFileName = this->GetFileName();\n\n  xmlReader = rtk::OraXMLFileReader::New();\n  xmlReader->SetFilename(oraFileName);\n  xmlReader->GenerateOutputInformation();\n\n  this->SetMetaDataDictionary(*(xmlReader->GetOutputObject()));\n\n  // Retrieve MHD file name\n  using MetaDataStringType = itk::MetaDataObject<std::string>;\n  MetaDataStringType * mhdMeta =\n    dynamic_cast<MetaDataStringType *>(this->GetMetaDataDictionary()[\"MHD_File\"].GetPointer());\n  if (mhdMeta == nullptr)\n  {\n    itkExceptionMacro(<< \"No MHD_File in \" << oraFileName);\n  }\n  m_MetaFileName = itksys::SystemTools::GetFilenamePath(oraFileName);\n  m_MetaFileName += '/';\n  m_MetaFileName += mhdMeta->GetMetaDataObjectValue();\n\n  this->SetFileName(m_MetaFileName);\n  Superclass::ReadImageInformation();\n  this->SetFileName(oraFileName);\n}\n\nbool\nrtk::OraImageIO::CanReadFile(const char * FileNameToRead)\n{\n  std::string filename(FileNameToRead);\n  if (filename.size() < 8)\n    return false;\n  std::string extension = filename.substr(filename.size() - 7, 7);\n\n  if (extension != std::string(\"ora.xml\"))\n    return false;\n\n  return true;\n}\n\nvoid\nrtk::OraImageIO::Read(void * buffer)\n{\n  std::string oraFileName = this->GetFileName();\n  this->SetFileName(m_MetaFileName);\n  Superclass::Read(buffer);\n  this->SetFileName(oraFileName);\n}\n\nbool\nrtk::OraImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n"
  },
  {
    "path": "src/rtkOraImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkOraImageIOFactory.h\"\n\n#include <fstream>\n\n//====================================================================\nrtk::OraImageIOFactory::OraImageIOFactory()\n{\n  this->RegisterOverride(\n    \"itkImageIOBase\", \"OraImageIO\", \"Ora Image IO\", true, itk::CreateObjectFunction<OraImageIO>::New());\n}\n\n// Undocumented API used to register during static initialization.\n// DO NOT CALL DIRECTLY.\n\nnamespace itk\n{\n\nstatic bool OraImageIOFactoryHasBeenRegistered;\n\nvoid RTK_EXPORT\nOraImageIOFactoryRegister__Private()\n{\n  if (!OraImageIOFactoryHasBeenRegistered)\n  {\n    OraImageIOFactoryHasBeenRegistered = true;\n    rtk::OraImageIOFactory::RegisterOneFactory();\n  }\n}\n\n} // end namespace itk\n"
  },
  {
    "path": "src/rtkOraXMLFileReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkOraXMLFileReader.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n\nnamespace rtk\n{\nOraXMLFileReader::OraXMLFileReader() { m_OutputObject = &m_Dictionary; }\n\nint\nOraXMLFileReader::CanReadFile(const char * name)\n{\n  if (!itksys::SystemTools::FileExists(name) || itksys::SystemTools::FileIsDirectory(name) ||\n      itksys::SystemTools::FileLength(name) == 0)\n    return 0;\n  return 1;\n}\n\nvoid\nOraXMLFileReader::StartElement(const char * itkNotUsed(name), const char ** itkNotUsed(atts))\n{\n  m_CurCharacterData = \"\";\n}\n\nvoid\nOraXMLFileReader::EndElement(const char * name)\n{\n  EncapsulatePoint(\"SourcePosition\", name);\n  EncapsulatePoint(\"Origin\", name);\n  EncapsulateMatrix3x3(\"Direction\", name);\n  EncapsulateDouble(\"table_axis_distance_cm\", name);\n  EncapsulateDouble(\"longitudinalposition_cm\", name);\n  EncapsulateDouble(\"rescale_slope\", name);\n  EncapsulateDouble(\"rescale_intercept\", name);\n  EncapsulateString(\"MHD_File\", name);\n  EncapsulateDouble(\"xrayx1_cm\", name);\n  EncapsulateDouble(\"xrayx2_cm\", name);\n  EncapsulateDouble(\"xrayy1_cm\", name);\n  EncapsulateDouble(\"xrayy2_cm\", name);\n  EncapsulateDouble(\"tiltleft_deg\", name);\n  EncapsulateDouble(\"tiltright_deg\", name);\n  EncapsulateDouble(\"room_cs_yaw_deg\", name);\n  EncapsulateDouble(\"ydistancebaseunitcs2imagingcs_cm\", name);\n  EncapsulateDouble(\"zdistancebaseunitcs2imagingcs_cm\", name);\n  EncapsulateVector<int>(\"optitrack_object_ids\", name);\n  EncapsulateVector<double>(\"optitrack_positions\", name);\n  EncapsulateVector<double>(\"optitrack_rotations\", name);\n}\n\nvoid\nOraXMLFileReader::CharacterDataHandler(const char * inData, int inLength)\n{\n  for (int i = 0; i < inLength; i++)\n    m_CurCharacterData = m_CurCharacterData + inData[i];\n}\n\nvoid\nOraXMLFileReader::EncapsulatePoint(const char * metaName, const char * name)\n{\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)\n  {\n    using PointType = itk::Vector<double, 3>;\n    PointType          p;\n    std::istringstream iss(m_CurCharacterData);\n    for (int i = 0; i < 3; i++)\n    {\n      iss >> p[i];\n      iss.ignore(1);\n    }\n    itk::EncapsulateMetaData<PointType>(m_Dictionary, metaName, p);\n  }\n}\n\nvoid\nOraXMLFileReader::EncapsulateMatrix3x3(const char * metaName, const char * name)\n{\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)\n  {\n    using Matrix3x3Type = itk::Matrix<double, 3, 3>;\n    Matrix3x3Type      m;\n    std::istringstream iss(m_CurCharacterData);\n    for (int i = 0; i < 3; i++)\n    {\n      for (int j = 0; j < 3; j++)\n      {\n        iss >> m[i][j];\n        iss.ignore(1);\n      }\n    }\n    itk::EncapsulateMetaData<Matrix3x3Type>(m_Dictionary, metaName, m);\n  }\n}\n\nvoid\nOraXMLFileReader::EncapsulateDouble(const char * metaName, const char * name)\n{\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)\n  {\n    double d = std::stod(m_CurCharacterData.c_str());\n    itk::EncapsulateMetaData<double>(m_Dictionary, metaName, d);\n  }\n}\n\ntemplate <typename TValue>\nvoid\nOraXMLFileReader::EncapsulateVector(const char * metaName, const char * name)\n{\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)\n  {\n    std::vector<TValue> v;\n    std::istringstream  iss(m_CurCharacterData);\n    TValue              d;\n    iss >> d;\n    while (!iss.fail())\n    {\n      v.push_back(d);\n      iss.ignore(1);\n      iss >> d;\n    }\n    itk::EncapsulateMetaData<std::vector<TValue>>(m_Dictionary, metaName, v);\n  }\n}\n\nvoid\nOraXMLFileReader::EncapsulateString(const char * metaName, const char * name)\n{\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)\n  {\n    itk::EncapsulateMetaData<std::string>(m_Dictionary, metaName, m_CurCharacterData);\n  }\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkPhaseReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkPhaseReader.h\"\n\n#include \"itksys/SystemTools.hxx\"\n\nnamespace rtk\n{\n\nPhaseReader::PhaseReader() = default;\n\nvoid\nPhaseReader::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n  for (unsigned int proj = 0; proj < m_Phases.size(); proj++)\n    os << this->m_Phases[proj] << std::endl;\n}\n\nvoid\nPhaseReader::Parse()\n{\n  this->m_InputStream.clear();\n  this->m_InputStream.open(this->m_FileName.c_str());\n  if (this->m_InputStream.fail())\n  {\n    itkExceptionMacro(\"The file \" << this->m_FileName << \" cannot be opened for reading!\" << std::endl\n                                  << \"Reason: \" << itksys::SystemTools::GetLastSystemError());\n  }\n\n  // Prepare to parse the file\n  itk::SizeValueType rows = 0, columns = 0;\n  this->GetDataDimension(rows, columns);\n  if (columns > 1)\n  {\n    itkExceptionMacro(\"The file \" << this->m_FileName << \" should have only one column\" << std::endl);\n  }\n  unsigned NumberOfProjections = rows;\n\n  // parse the numeric data\n  m_Phases.clear();\n  std::string entry;\n  for (unsigned int j = 0; j < NumberOfProjections; j++)\n  {\n    this->GetNextField(entry);\n    m_Phases.push_back(std::stod(entry.c_str()));\n  }\n\n  this->m_InputStream.close();\n}\n\n/** Update method */\n\nvoid\nPhaseReader::Update()\n{\n  this->Parse();\n}\n\n/** Get the output */\n\nstd::vector<float>\nPhaseReader::GetOutput()\n{\n  return this->m_Phases;\n}\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkPhasesToInterpolationWeights.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#include \"rtkPhasesToInterpolationWeights.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMath.h>\n\nnamespace rtk\n{\n\nPhasesToInterpolationWeights::PhasesToInterpolationWeights()\n{\n  this->m_NumberOfReconstructedFrames = 0;\n  this->m_UnevenTemporalSpacing = false;\n  this->m_SelectedProjections = std::vector<bool>(0);\n}\n\nvoid\nPhasesToInterpolationWeights::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n  os << this->m_Array2D << std::endl;\n}\n\nvoid\nPhasesToInterpolationWeights::SetSelectedProjections(std::vector<bool> sprojs)\n{\n  this->m_SelectedProjections = sprojs;\n  this->Modified();\n}\n\nvoid\nPhasesToInterpolationWeights::Parse()\n{\n  itk::SizeValueType rows = 0;\n  itk::SizeValueType columns = 0;\n\n  this->PrepareForParsing();\n\n  this->m_InputStream.clear();\n  this->m_InputStream.open(this->m_FileName.c_str());\n  if (this->m_InputStream.fail())\n  {\n    itkExceptionMacro(\"The file \" << this->m_FileName << \" cannot be opened for reading!\" << std::endl\n                                  << \"Reason: \" << itksys::SystemTools::GetLastSystemError());\n  }\n\n  // Get the data dimension and set the matrix size\n  this->GetDataDimension(rows, columns);\n  unsigned int NumberOfProjections = 0;\n\n  // If m_SelectedProjections has not been set, use all projections\n  if (m_SelectedProjections.empty())\n    NumberOfProjections = rows + 1;\n  else\n  {\n    // Check that the size of m_SelectedProjections is consistent with the number of rows in the phase file\n    if (!(m_SelectedProjections.size() == rows + 1))\n    {\n      itkExceptionMacro(\"The lists of selected projections and phases have inconsistent sizes\");\n    }\n    else\n    {\n      for (const bool m_SelectedProjection : m_SelectedProjections)\n        if (m_SelectedProjection)\n          NumberOfProjections += 1;\n    }\n  }\n  this->m_Array2D.SetSize(this->m_NumberOfReconstructedFrames, NumberOfProjections);\n\n  // Create a vector to hold the projections' phases\n  std::vector<float> projectionPhases;    // Stores the instant of the cycle at which each projection was acquired\n  std::vector<float> reconstructedFrames; // Stores the instant of the cycle each frame represents\n\n  std::string entry;\n\n  // parse the numeric data into the Array2D object\n  for (unsigned int j = 0; j < rows + 1; j++)\n  {\n    this->GetNextField(entry);\n    if ((m_SelectedProjections.empty()) || (m_SelectedProjections[j]))\n      projectionPhases.push_back(itk::Math::Round<float>(std::stod(entry.c_str()) * 1000.) / 1000.);\n  }\n\n  // Compute the instant of the cycle each phase represents\n  // Create one more phase point than is strictly necessary, so that projections phases\n  // are always between two reconstructed phases. The first and last reconstructed phases\n  // represent the same instant. This is accounted for when computing the weights\n\n  if (m_UnevenTemporalSpacing) // Create an unbalanced distribution of phase points : more of them will be placed during\n                               // systole than during diastole\n  {\n    std::vector<float> cumulatedWeights;\n    cumulatedWeights.push_back(1);\n    for (int i = 1; i < 100; i++)\n    {\n      float weight = 1;\n      if ((i > 30) && (i < 50))\n        weight = 2; // The higher this number, the better the temporal resolution in systole\n      cumulatedWeights.push_back(cumulatedWeights[i - 1] + weight);\n    }\n    float step = cumulatedWeights[99] / m_NumberOfReconstructedFrames;\n\n    reconstructedFrames.push_back(0);\n    for (int n = 1; n < this->m_NumberOfReconstructedFrames; n++)\n    {\n      int i = 0;\n      while (cumulatedWeights[reconstructedFrames[n - 1] * 100] + step > cumulatedWeights[i])\n      {\n        i = i + 1;\n      }\n      reconstructedFrames.push_back(((float)i) / 100.);\n    }\n    reconstructedFrames.push_back(1);\n    for (int n = 0; n < this->m_NumberOfReconstructedFrames; n++)\n    {\n      std::cout << reconstructedFrames[n] << std::endl;\n    }\n  }\n  else // The reconstructed phases are all separated by the same amount of time\n  {\n    for (float n = 0.; n < this->m_NumberOfReconstructedFrames + 1; n++)\n    {\n      reconstructedFrames.push_back(n / this->m_NumberOfReconstructedFrames);\n    }\n  }\n  m_Array2D.Fill(0);\n\n  // Compute the interpolation weights and fill the Array2D\n  for (unsigned int c = 0; c < NumberOfProjections; c++)\n  {\n    int lower = 0;\n    int upper = 1;\n    while (!((projectionPhases[c] >= reconstructedFrames[lower]) && (projectionPhases[c] < reconstructedFrames[upper])))\n    {\n      lower++;\n      upper++;\n      if (lower == this->m_NumberOfReconstructedFrames)\n      {\n        std::cout << \"Problem while determining the interpolation weights\" << std::endl;\n      }\n    }\n    float lowerWeight =\n      (reconstructedFrames[upper] - projectionPhases[c]) / (reconstructedFrames[upper] - reconstructedFrames[lower]);\n    float upperWeight =\n      (projectionPhases[c] - reconstructedFrames[lower]) / (reconstructedFrames[upper] - reconstructedFrames[lower]);\n\n    // The last phase is equal to the first one (see comment above when filling \"reconstructedFrames\")\n    if (upper == this->m_NumberOfReconstructedFrames)\n      upper = 0;\n\n    m_Array2D[lower][c] = itk::Math::Round<float>(lowerWeight * 100.) / 100.;\n    m_Array2D[upper][c] = itk::Math::Round<float>(upperWeight * 100.) / 100.;\n  }\n  this->m_InputStream.close();\n}\n\n/** Update method */\n\nvoid\nPhasesToInterpolationWeights::Update()\n{\n  this->Parse();\n}\n\n/** Get the output */\n\nPhasesToInterpolationWeights::Array2DType\nPhasesToInterpolationWeights ::GetOutput()\n{\n  return this->m_Array2D;\n}\n\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkQuadricShape.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkQuadricShape.h\"\n\nnamespace rtk\n{\n\nQuadricShape ::QuadricShape() = default;\n\nbool\nQuadricShape ::IsInside(const PointType & point) const\n{\n  return (IsInsideQuadric(point) && ApplyClipPlanes(point));\n}\n\nbool\nQuadricShape ::IsInsideQuadric(const PointType & point) const\n{\n  ScalarType QuadricEllip = this->GetA() * point[0] * point[0] + this->GetB() * point[1] * point[1] +\n                            this->GetC() * point[2] * point[2] + this->GetD() * point[0] * point[1] +\n                            this->GetE() * point[0] * point[2] + this->GetF() * point[1] * point[2] +\n                            this->GetG() * point[0] + this->GetH() * point[1] + this->GetI() * point[2] + this->GetJ();\n  return (QuadricEllip <= 0);\n}\n\nbool\nQuadricShape ::IsIntersectedByRay(const PointType &  rayOrigin,\n                                  const VectorType & rayDirection,\n                                  double &           nearDist,\n                                  double &           farDist) const\n{\n  // https://education.siggraph.org/static/HyperGraph/raytrace/rtinter4.htm\n  ScalarType Aq = m_A * rayDirection[0] * rayDirection[0] + m_B * rayDirection[1] * rayDirection[1] +\n                  m_C * rayDirection[2] * rayDirection[2] + m_D * rayDirection[0] * rayDirection[1] +\n                  m_E * rayDirection[0] * rayDirection[2] + m_F * rayDirection[1] * rayDirection[2];\n  ScalarType Bq = 2 * (m_A * rayOrigin[0] * rayDirection[0] + m_B * rayOrigin[1] * rayDirection[1] +\n                       m_C * rayOrigin[2] * rayDirection[2]) +\n                  m_D * (rayOrigin[0] * rayDirection[1] + rayOrigin[1] * rayDirection[0]) +\n                  m_E * (rayOrigin[2] * rayDirection[0] + rayOrigin[0] * rayDirection[2]) +\n                  m_F * (rayOrigin[1] * rayDirection[2] + rayOrigin[2] * rayDirection[1]) + m_G * rayDirection[0] +\n                  m_H * rayDirection[1] + m_I * rayDirection[2];\n  ScalarType Cq = m_A * rayOrigin[0] * rayOrigin[0] + m_B * rayOrigin[1] * rayOrigin[1] +\n                  m_C * rayOrigin[2] * rayOrigin[2] + m_D * rayOrigin[0] * rayOrigin[1] +\n                  m_E * rayOrigin[0] * rayOrigin[2] + m_F * rayOrigin[1] * rayOrigin[2] + m_G * rayOrigin[0] +\n                  m_H * rayOrigin[1] + m_I * rayOrigin[2] + m_J;\n\n  const ScalarType zero = itk::NumericTraits<ScalarType>::ZeroValue();\n  if (Aq == zero)\n  {\n    // Only one intersection with, e.g., a plane: check which half line should be kept\n    nearDist = -Cq / Bq;\n    auto bOriginIsInside = IsInsideQuadric(rayOrigin);\n    if ((bOriginIsInside && nearDist < 0.) || (!bOriginIsInside && nearDist > 0.))\n      farDist = itk::NumericTraits<ScalarType>::max();\n    else\n    {\n      farDist = nearDist;\n      nearDist = -itk::NumericTraits<ScalarType>::max();\n    }\n  }\n  else\n  {\n    ScalarType discriminant = Bq * Bq - 4 * Aq * Cq;\n    // The epsilon value allows detection of very close intersections, i.e., a\n    // ray tangent to the quadric\n    static constexpr ScalarType eps = 1e5 * itk::NumericTraits<ScalarType>::epsilon();\n    if (discriminant <= eps)\n    {\n      // No intersection but one might be dealing with an infinite line\n      // in the quadric, e.g. a line parallel to and in a cylinder.\n      if (IsInsideQuadric(rayOrigin))\n      {\n        nearDist = -itk::NumericTraits<ScalarType>::max();\n        farDist = itk::NumericTraits<ScalarType>::max();\n        return ApplyClipPlanes(rayOrigin, rayDirection, nearDist, farDist);\n      }\n      else\n        return false;\n    }\n    nearDist = (-Bq - sqrt(discriminant)) / (2 * Aq);\n    farDist = (-Bq + sqrt(discriminant)) / (2 * Aq);\n    if (nearDist > farDist)\n      std::swap(nearDist, farDist);\n\n    // Check if the central point between the two intersections is in the quadric\n    if (!IsInsideQuadric(rayOrigin + 0.5 * (farDist + nearDist) * rayDirection))\n    {\n      // If not, one is dealing with a half line, searching for the good one\n      double tmpNearDist = -itk::NumericTraits<ScalarType>::max();\n      double tmpFarDist = itk::NumericTraits<ScalarType>::max();\n      if (!ApplyClipPlanes(rayOrigin, rayDirection, tmpNearDist, tmpFarDist))\n        return false;\n      if (tmpFarDist > farDist)\n      {\n        if (tmpNearDist < nearDist)\n        {\n          itkGenericExceptionMacro(<< \"Intersection of the quadric with the line \"\n                                   << \"gives two half lines, add clip planes to select which one\");\n        }\n        else\n        {\n          nearDist = std::max(farDist, tmpNearDist);\n          farDist = tmpFarDist;\n          return true;\n        }\n      }\n      else if (tmpNearDist < nearDist)\n      {\n        farDist = std::min(nearDist, tmpFarDist);\n        nearDist = tmpNearDist;\n        return true;\n      }\n      else\n        return false;\n    }\n  }\n\n  return ApplyClipPlanes(rayOrigin, rayDirection, nearDist, farDist);\n}\n\nvoid\nQuadricShape ::Rescale(const VectorType & r)\n{\n  Superclass::Rescale(r);\n  m_A /= r[0] * r[0];\n  m_B /= r[1] * r[1];\n  m_C /= r[2] * r[2];\n  m_D /= r[0] * r[1];\n  m_E /= r[0] * r[2];\n  m_F /= r[1] * r[2];\n  m_G /= r[0];\n  m_H /= r[1];\n  m_I /= r[2];\n}\n\nvoid\nQuadricShape ::Translate(const VectorType & t)\n{\n  Superclass::Translate(t);\n\n  // Translation Parameters\n  ScalarType newG = m_G - 2. * m_A * t[0] - m_D * t[1] - m_E * t[2];\n  ScalarType newH = m_H - 2. * m_B * t[1] - m_D * t[0] - m_F * t[2];\n  ScalarType newI = m_I - 2. * m_C * t[2] - m_E * t[0] - m_F * t[1];\n  ScalarType newJ = m_J + m_A * std::pow(t[0], 2.0) + m_B * std::pow(t[1], 2.0) + m_C * std::pow(t[2], 2.) +\n                    m_D * t[0] * t[1] + m_E * t[0] * t[2] + m_F * t[1] * t[2] - m_G * t[0] - m_H * t[1] - m_I * t[2];\n  m_G = newG;\n  m_H = newH;\n  m_I = newI;\n  m_J = newJ;\n}\n\nvoid\nQuadricShape ::Rotate(const RotationMatrixType & r)\n{\n  Superclass::Rotate(r);\n  VectorType newABC, newDFE, newGHI;\n  newABC.Fill(0.);\n  newDFE.Fill(0.);\n  newGHI.Fill(0.);\n  VectorType oldABC, oldDFE, oldGHI;\n  oldABC[0] = m_A;\n  oldABC[1] = m_B;\n  oldABC[2] = m_C;\n  oldDFE[0] = m_D;\n  oldDFE[1] = m_F;\n  oldDFE[2] = m_E;\n  oldGHI[0] = m_G;\n  oldGHI[1] = m_H;\n  oldGHI[2] = m_I;\n  for (unsigned int j = 0; j < Dimension; j++) // Columns\n  {\n    for (unsigned int i = 0; i < Dimension; i++) // Lines\n    {\n      newABC[j] += r[j][i] * r[j][i] * oldABC[i];\n      newDFE[j] += 2. * r[j][i] * r[(j + 1) % Dimension][i] * oldABC[i];\n      newABC[j] += r[j][i] * r[j][(i + 1) % Dimension] * oldDFE[i];\n      newDFE[j] += r[j][i] * r[(j + 1) % Dimension][(i + 1) % Dimension] * oldDFE[i];\n      newDFE[j] += r[(j + 1) % Dimension][i] * r[j][(i + 1) % Dimension] * oldDFE[i];\n      newGHI[j] += r[j][i] * oldGHI[i];\n    }\n  }\n  m_A = newABC[0];\n  m_B = newABC[1];\n  m_C = newABC[2];\n  m_D = newDFE[0];\n  m_F = newDFE[1];\n  m_E = newDFE[2];\n  m_G = newGHI[0];\n  m_H = newGHI[1];\n  m_I = newGHI[2];\n}\n\nvoid\nQuadricShape ::SetEllipsoid(const PointType & center, const VectorType & axis, const ScalarType & yangle)\n{\n  // A\n  if (axis[0] > itk::NumericTraits<ScalarType>::ZeroValue())\n    m_A = 1 / std::pow(axis[0], 2.0);\n  else if (axis[0] < itk::NumericTraits<ScalarType>::ZeroValue())\n    m_A = -1 / std::pow(axis[0], 2.0);\n  else\n    m_A = 0.;\n\n  // B\n  if (axis[1] > itk::NumericTraits<ScalarType>::ZeroValue())\n    m_B = 1 / std::pow(axis[1], 2.0);\n  else if (axis[1] < itk::NumericTraits<ScalarType>::ZeroValue())\n    m_B = -1 / std::pow(axis[1], 2.0);\n  else\n    m_B = 0.;\n\n  // C\n  if (axis[2] > itk::NumericTraits<ScalarType>::ZeroValue())\n    m_C = 1 / std::pow(axis[2], 2.0);\n  else if (axis[2] < itk::NumericTraits<ScalarType>::ZeroValue())\n    m_C = -1 / std::pow(axis[2], 2.0);\n  else\n    m_C = 0.;\n\n  m_D = 0.;\n  m_E = 0.;\n  m_F = 0.;\n  m_G = 0.;\n  m_H = 0.;\n  m_I = 0.;\n  m_J = -1.;\n\n  // Rotate arround Y according to angle\n  ScalarType TempA = m_A;\n  ScalarType TempB = m_B;\n  ScalarType TempC = m_C;\n  ScalarType TempG = m_G;\n  ScalarType TempH = m_H;\n  ScalarType TempI = m_I;\n  ScalarType TempJ = m_J;\n\n  // Applying Rotation on Y-axis\n  m_A = TempA * std::pow(cos(yangle * (itk::Math::pi / 180)), 2.0) +\n        TempC * std::pow(sin(yangle * (itk::Math::pi / 180)), 2.0);\n  m_B = TempB;\n  m_C = TempA * std::pow(sin(yangle * (itk::Math::pi / 180)), 2.0) +\n        TempC * std::pow(cos(yangle * (itk::Math::pi / 180)), 2.0);\n  m_D = 0.;\n  m_E = 2 * cos(yangle * (itk::Math::pi / 180)) * sin(yangle * (itk::Math::pi / 180)) * (TempA - TempC);\n  m_F = 0.;\n  m_G = TempG * cos(yangle * (itk::Math::pi / 180)) - TempI * sin(yangle * (itk::Math::pi / 180));\n  m_H = TempH;\n  m_I = TempG * sin(yangle * (itk::Math::pi / 180)) + TempI * cos(yangle * (itk::Math::pi / 180));\n  m_J = TempJ;\n\n  Translate(center);\n}\n\nitk::LightObject::Pointer\nQuadricShape ::InternalClone() const\n{\n  LightObject::Pointer loPtr = Superclass::InternalClone();\n  Self::Pointer        clone = dynamic_cast<Self *>(loPtr.GetPointer());\n\n  clone->SetA(this->GetA());\n  clone->SetB(this->GetB());\n  clone->SetC(this->GetC());\n  clone->SetD(this->GetD());\n  clone->SetE(this->GetE());\n  clone->SetF(this->GetF());\n  clone->SetG(this->GetG());\n  clone->SetH(this->GetH());\n  clone->SetI(this->GetI());\n  clone->SetJ(this->GetJ());\n\n  return loPtr;\n}\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkReg23ProjectionGeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkReg23ProjectionGeometry.h\"\n\nrtk::Reg23ProjectionGeometry::Reg23ProjectionGeometry()\n  : rtk::ThreeDCircularProjectionGeometry()\n{}\n\nrtk::Reg23ProjectionGeometry::~Reg23ProjectionGeometry() = default;\n\nbool\nrtk::Reg23ProjectionGeometry::AddReg23Projection(const PointType &  sourcePosition,\n                                                 const PointType &  detectorPosition,\n                                                 const VectorType & detectorRowVector,\n                                                 const VectorType & detectorColumnVector)\n{\n  return Superclass::AddProjection(sourcePosition, detectorPosition, detectorRowVector, detectorColumnVector);\n}\n"
  },
  {
    "path": "src/rtkResourceProbesCollector.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkResourceProbesCollector.h\"\n#include <iostream>\n\nnamespace rtk\n{\n\nvoid\nResourceProbesCollector::Start(const char * id)\n{\n  // if the probe does not exist yet, it is created.\n  this->m_TimeProbes[id].SetNameOfProbe(id);\n  this->m_TimeProbes[id].Start();\n  this->m_MemoryProbes[id].SetNameOfProbe(id);\n  this->m_MemoryProbes[id].Start();\n#ifdef RTK_USE_CUDA\n  this->m_CudaMemoryProbes[id].SetNameOfProbe(id);\n  this->m_CudaMemoryProbes[id].Start();\n#endif\n}\n\n\nvoid\nResourceProbesCollector::Stop(const char * id)\n{\n  IdType tid = id;\n\n  auto pos = this->m_TimeProbes.find(tid);\n  if (pos == this->m_TimeProbes.end())\n  {\n    itkGenericExceptionMacro(<< \"The probe \\\"\" << id << \"\\\" does not exist. It can not be stopped.\");\n    return;\n  }\n  pos->second.Stop();\n  m_MemoryProbes[tid].Stop();\n#ifdef RTK_USE_CUDA\n  m_CudaMemoryProbes[tid].Stop();\n#endif\n}\n\n\nvoid\nResourceProbesCollector::Report(std::ostream & os) const\n{\n  auto tProbe = this->m_TimeProbes.begin();\n  auto tEnd = this->m_TimeProbes.end();\n\n  if (tProbe == tEnd)\n  {\n    return;\n  }\n\n  unsigned int maxlength = sizeof(\"Probe Tag\") / sizeof(char);\n  while (tProbe != tEnd)\n    maxlength = std::max(maxlength, (unsigned int)(tProbe++)->first.size());\n  maxlength += 2;\n  tProbe = this->m_TimeProbes.begin();\n\n  auto mProbe = this->m_MemoryProbes.begin();\n#ifdef RTK_USE_CUDA\n  auto cProbe = this->m_CudaMemoryProbes.begin();\n#endif\n  os << std::endl << std::endl;\n#ifdef RTK_USE_CUDA\n  os.width(maxlength + 10 + 10 + 15 + 15 + 15);\n#else\n  os.width(maxlength + 10 + 10 + 15 + 15);\n#endif\n  os << std::setfill('*') << \"\" << std::endl << std::setfill(' ');\n  os.width(maxlength);\n  os << std::left;\n  os << \"Probe Tag\";\n  os.width(10);\n  os << \"Starts\";\n  os.width(10);\n  os << \"Stops\";\n  os.width(15);\n  os << std::string(tProbe->second.GetType() + \" (\" + tProbe->second.GetUnit() + \")\");\n  os.width(15);\n  os << std::string(mProbe->second.GetType() + \" (\" + mProbe->second.GetUnit() + \")\");\n#ifdef RTK_USE_CUDA\n  os.width(15);\n  os << std::string(cProbe->second.GetType() + \" (\" + cProbe->second.GetUnit() + \")\");\n#endif\n  os << std::endl;\n#ifdef RTK_USE_CUDA\n  os.width(maxlength + 10 + 10 + 15 + 15 + 15);\n#else\n  os.width(maxlength + 10 + 10 + 15 + 15);\n#endif\n  os << std::setfill('*') << \"\" << std::endl << std::setfill(' ');\n\n  while (tProbe != tEnd)\n  {\n    os.width(maxlength);\n    os << tProbe->first;\n    os.width(10);\n    os << tProbe->second.GetNumberOfStarts();\n    os.width(10);\n    os << tProbe->second.GetNumberOfStops();\n    os.width(15);\n    os << tProbe++->second.GetMean();\n    os.width(15);\n    os << mProbe++->second.GetMean();\n#ifdef RTK_USE_CUDA\n    os.width(15);\n    os << cProbe++->second.GetMean();\n#endif\n    os << std::endl;\n  }\n  os << std::setfill('*') << \"\" << std::endl << std::setfill(' ');\n}\n\nvoid\nResourceProbesCollector::Clear()\n{\n  this->m_TimeProbes.clear();\n  this->m_MemoryProbes.clear();\n#ifdef RTK_USE_CUDA\n  this->m_CudaMemoryProbes.clear();\n#endif\n}\n\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkSheppLoganPhantom.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkSheppLoganPhantom.h\"\n\nnamespace rtk\n{\nSheppLoganPhantom ::SheppLoganPhantom()\n{\n  SetEllipsoid(0.69, 0.90, 0.92, 0., 0., 0., 0., 2.);\n  SetEllipsoid(0.6624, 0.880, 0.874, 0., 0., 0., 0., -0.98);\n  SetEllipsoid(0.41, 0.21, 0.16, -0.22, -0.25, 0., 108., -0.02);\n  SetEllipsoid(0.31, 0.22, 0.11, 0.22, -0.25, 0., 72., -0.02);\n  SetEllipsoid(0.21, 0.50, 0.25, 0., -0.25, 0.35, 0., 0.02);\n  SetEllipsoid(0.046, 0.046, 0.046, 0., -0.25, 0.10, 0., 0.02);\n  SetEllipsoid(0.046, 0.02, 0.023, -0.08, -0.25, -0.65, 0., 0.01);\n  SetEllipsoid(0.046, 0.02, 0.023, 0.06, -0.25, -0.65, 90., 0.01);\n  SetEllipsoid(0.056, 0.1, 0.04, 0.06, 0.625, -0.105, 90., 0.02);\n  SetEllipsoid(0.056, 0.1, 0.056, 0., 0.625, 0.1, 0., -0.02);\n}\n\nvoid\nSheppLoganPhantom ::SetEllipsoid(ScalarType spax,\n                                 ScalarType spay,\n                                 ScalarType spaz,\n                                 ScalarType centerx,\n                                 ScalarType centery,\n                                 ScalarType centerz,\n                                 ScalarType angle,\n                                 ScalarType density)\n{\n  auto semiprincipalaxis = itk::MakeVector(spax, spay, spaz);\n  auto center = itk::MakeVector(centerx, centery, centerz);\n  auto q = QuadricShape::New();\n  q->SetEllipsoid(center, semiprincipalaxis, angle);\n  q->SetDensity(density);\n  this->AddConvexShape(q.GetPointer());\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkSignalToInterpolationWeights.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkSignalToInterpolationWeights.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMath.h>\n\nnamespace rtk\n{\n\nSignalToInterpolationWeights::SignalToInterpolationWeights() { this->m_NumberOfReconstructedFrames = 0; }\n\nvoid\nSignalToInterpolationWeights::PrintSelf(std::ostream & os, itk::Indent indent) const\n{\n  Superclass::PrintSelf(os, indent);\n  os << this->m_Array2D << std::endl;\n}\n\nvoid\nSignalToInterpolationWeights::SetSignal(const std::vector<double> signal)\n{\n  this->m_Signal = signal;\n}\n\n/** Update method */\nvoid\nSignalToInterpolationWeights::Update()\n{\n  // Set the matrix size\n  unsigned int NumberOfProjections = m_Signal.size();\n  this->m_Array2D.SetSize(this->m_NumberOfReconstructedFrames, NumberOfProjections);\n\n  // Create a vector to hold the projections' Signal\n  std::vector<float> reconstructedFrames; // Stores the instant of the cycle each frame represents\n\n  // Compute the instant of the cycle each phase represents\n  // Create one more phase point than is strictly necessary, so that projections Signal\n  // are always between two reconstructed Signal. The first and last reconstructed Signal\n  // represent the same instant. This is accounted for when computing the weights\n  for (float n = 0.; n < this->m_NumberOfReconstructedFrames + 1; n++)\n    reconstructedFrames.push_back(n / this->m_NumberOfReconstructedFrames);\n\n  // Compute the interpolation weights and fill the Array2D\n  m_Array2D.Fill(0);\n  for (unsigned int c = 0; c < NumberOfProjections; c++)\n  {\n    int lower = 0;\n    int upper = 1;\n    while (!((m_Signal[c] >= reconstructedFrames[lower]) && (m_Signal[c] < reconstructedFrames[upper])))\n    {\n      lower++;\n      upper++;\n      if (lower == this->m_NumberOfReconstructedFrames)\n      {\n        std::cout << \"Problem while determining the interpolation weights\" << std::endl;\n      }\n    }\n    float lowerWeight =\n      (reconstructedFrames[upper] - m_Signal[c]) / (reconstructedFrames[upper] - reconstructedFrames[lower]);\n    float upperWeight =\n      (m_Signal[c] - reconstructedFrames[lower]) / (reconstructedFrames[upper] - reconstructedFrames[lower]);\n\n    // The last phase is equal to the first one (see comment above when filling \"reconstructedFrames\")\n    if (upper == this->m_NumberOfReconstructedFrames)\n      upper = 0;\n\n    m_Array2D[lower][c] = itk::Math::Round<float>(lowerWeight * 100.) / 100.;\n    m_Array2D[upper][c] = itk::Math::Round<float>(upperWeight * 100.) / 100.;\n  }\n}\n\n/** Get the output */\n\nSignalToInterpolationWeights::Array2DType\nSignalToInterpolationWeights ::GetOutput()\n{\n  return this->m_Array2D;\n}\n\n\n} // end namespace rtk\n"
  },
  {
    "path": "src/rtkThreeDCircularProjectionGeometry.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"math.h\"\n\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkMacro.h\"\n\n#include <algorithm>\n#include <cmath>\n\n#include <itkCenteredEuler3DTransform.h>\n#include <itkEuler3DTransform.h>\n\nrtk::ThreeDCircularProjectionGeometry::ThreeDCircularProjectionGeometry() = default;\n\ndouble\nrtk::ThreeDCircularProjectionGeometry::ConvertAngleBetween0And360Degrees(const double a)\n{\n  return a - 360 * floor(a / 360);\n}\n\ndouble\nrtk::ThreeDCircularProjectionGeometry::ConvertAngleBetween0And2PIRadians(const double a)\n{\n  return a - 2 * itk::Math::pi * floor(a / (2 * itk::Math::pi));\n}\n\ndouble\nrtk::ThreeDCircularProjectionGeometry::ConvertAngleBetweenMinusAndPlusPIRadians(const double a)\n{\n  double d = ConvertAngleBetween0And2PIRadians(a);\n  if (d > itk::Math::pi)\n    d -= 2 * itk::Math::pi;\n  return d;\n}\n\nvoid\nrtk::ThreeDCircularProjectionGeometry::AddProjection(const double sid,\n                                                     const double sdd,\n                                                     const double gantryAngle,\n                                                     const double projOffsetX,\n                                                     const double projOffsetY,\n                                                     const double outOfPlaneAngle,\n                                                     const double inPlaneAngle,\n                                                     const double sourceOffsetX,\n                                                     const double sourceOffsetY)\n{\n  const double degreesToRadians = std::atan(1.0) / 45.0;\n  AddProjectionInRadians(sid,\n                         sdd,\n                         degreesToRadians * gantryAngle,\n                         projOffsetX,\n                         projOffsetY,\n                         degreesToRadians * outOfPlaneAngle,\n                         degreesToRadians * inPlaneAngle,\n                         sourceOffsetX,\n                         sourceOffsetY);\n}\n\nvoid\nrtk::ThreeDCircularProjectionGeometry::AddProjectionInRadians(const double sid,\n                                                              const double sdd,\n                                                              const double gantryAngle,\n                                                              const double projOffsetX,\n                                                              const double projOffsetY,\n                                                              const double outOfPlaneAngle,\n                                                              const double inPlaneAngle,\n                                                              const double sourceOffsetX,\n                                                              const double sourceOffsetY)\n{\n  // Check parallel / divergent projections consistency\n  if (!m_GantryAngles.empty())\n  {\n    if (sdd == 0. && m_SourceToDetectorDistances[0] != 0.)\n    {\n      itkGenericExceptionMacro(\n        << \"Cannot add a parallel projection in a 3D geometry object containing divergent projections\");\n    }\n    if (sdd != 0. && m_SourceToDetectorDistances[0] == 0.)\n    {\n      itkGenericExceptionMacro(\n        << \"Cannot add a divergent projection in a 3D geometry object containing parallel projections\");\n    }\n  }\n\n  // Detector orientation parameters\n  m_GantryAngles.push_back(ConvertAngleBetween0And2PIRadians(gantryAngle));\n  m_OutOfPlaneAngles.push_back(ConvertAngleBetween0And2PIRadians(outOfPlaneAngle));\n  m_InPlaneAngles.push_back(ConvertAngleBetween0And2PIRadians(inPlaneAngle));\n\n  // Source position parameters\n  m_SourceToIsocenterDistances.push_back(sid);\n  m_SourceOffsetsX.push_back(sourceOffsetX);\n  m_SourceOffsetsY.push_back(sourceOffsetY);\n\n  // Detector position parameters\n  m_SourceToDetectorDistances.push_back(sdd);\n  m_ProjectionOffsetsX.push_back(projOffsetX);\n  m_ProjectionOffsetsY.push_back(projOffsetY);\n\n  // Compute sub-matrices\n  AddProjectionTranslationMatrix(\n    ComputeTranslationHomogeneousMatrix(sourceOffsetX - projOffsetX, sourceOffsetY - projOffsetY));\n  AddMagnificationMatrix(ComputeProjectionMagnificationMatrix(-sdd, -sid));\n  AddRotationMatrix(ComputeRotationHomogeneousMatrix(-outOfPlaneAngle, -gantryAngle, -inPlaneAngle));\n  AddSourceTranslationMatrix(ComputeTranslationHomogeneousMatrix(-sourceOffsetX, -sourceOffsetY, 0.));\n\n  Superclass::MatrixType matrix;\n  matrix = this->GetProjectionTranslationMatrices().back().GetVnlMatrix() *\n           this->GetMagnificationMatrices().back().GetVnlMatrix() *\n           this->GetSourceTranslationMatrices().back().GetVnlMatrix() *\n           this->GetRotationMatrices().back().GetVnlMatrix();\n  this->AddMatrix(matrix);\n\n  // Calculate source angle\n  VectorType z;\n  z.Fill(0.);\n  z[2] = 1.;\n  HomogeneousVectorType sph = GetSourcePosition(m_GantryAngles.size() - 1);\n  sph[1] = 0.; // Project position to central plane\n  VectorType sp(&(sph[0]));\n  sp.Normalize();\n  double a = acos(sp * z);\n  if (sp[0] > 0.)\n    a = 2. * itk::Math::pi - a;\n  m_SourceAngles.push_back(ConvertAngleBetween0And2PIRadians(a));\n\n  // Default collimation (uncollimated)\n  m_CollimationUInf.push_back(std::numeric_limits<double>::max());\n  m_CollimationUSup.push_back(std::numeric_limits<double>::max());\n  m_CollimationVInf.push_back(std::numeric_limits<double>::max());\n  m_CollimationVSup.push_back(std::numeric_limits<double>::max());\n\n  this->Modified();\n}\n\nbool\nrtk::ThreeDCircularProjectionGeometry::AddProjection(const PointType &  sourcePosition,\n                                                     const PointType &  detectorPosition,\n                                                     const VectorType & detectorRowVector,\n                                                     const VectorType & detectorColumnVector)\n{\n  using EulerType = itk::Euler3DTransform<double>;\n\n  // these parameters relate absolutely to the WCS (IEC-based):\n  const VectorType & r = detectorRowVector;       // row dir\n  const VectorType & c = detectorColumnVector;    // column dir\n  VectorType         n = itk::CrossProduct(r, c); // normal\n  const PointType &  S = sourcePosition;          // source pos\n  const PointType &  R = detectorPosition;        // detector pos\n\n  if (itk::Math::abs(r * c) > 1e-6) // non-orthogonal row/column vectors\n    return false;\n\n  // Euler angles (ZXY convention) from detector orientation in IEC-based WCS:\n  double ga = NAN; // gantry angle\n  double oa = NAN; // out-of-plane angle\n  double ia = NAN; // in-plane angle\n  // extract Euler angles from the orthogonal matrix which is established\n  // by the detector orientation; however, we would like RTK to internally\n  // store the inverse of this rotation matrix, therefore the corresponding\n  // angles are computed here:\n  Matrix3x3Type rm; // reference matrix\n  // NOTE: This transposed matrix should internally\n  // set by rtk::ThreeDProjectionGeometry (inverse)\n  // of external rotation!\n  rm[0][0] = r[0];\n  rm[0][1] = r[1];\n  rm[0][2] = r[2];\n  rm[1][0] = c[0];\n  rm[1][1] = c[1];\n  rm[1][2] = c[2];\n  rm[2][0] = n[0];\n  rm[2][1] = n[1];\n  rm[2][2] = n[2];\n  // extract Euler angles by using the standard ITK implementation:\n  auto euler = EulerType::New();\n  euler->SetComputeZYX(false); // ZXY order\n  // workaround: Orthogonality tolerance problem when using\n  // Euler3DTransform->SetMatrix() due to error magnification.\n  // Parent class MatrixOffsetTransformBase does not perform an\n  // orthogonality check on the matrix!\n  euler->itk::MatrixOffsetTransformBase<double>::SetMatrix(rm);\n  oa = euler->GetAngleX(); // delivers radians\n  ga = euler->GetAngleY();\n  ia = euler->GetAngleZ();\n  // verify that extracted ZXY angles result in the *desired* matrix:\n  // (at some angle constellations we may run into numerical troubles, therefore,\n  // verify angles and try to fix instabilities)\n  if (!VerifyAngles(oa, ga, ia, rm))\n  {\n    if (!FixAngles(oa, ga, ia, rm))\n    {\n      itkWarningMacro(<< \"Failed to AddProjection\");\n      return false;\n    }\n  }\n  // since rtk::ThreeDCircularProjectionGeometry::AddProjection() mirrors the\n  // angles (!) internally, let's invert the computed ones in order to\n  // get at the end what we would like (see above); convert rad->deg:\n  ga *= -1.;\n  oa *= -1.;\n  ia *= -1.;\n\n  // SID: distance from source to isocenter along detector normal\n  double SID = n[0] * S[0] + n[1] * S[1] + n[2] * S[2];\n  // SDD: distance from source to detector along detector normal\n  double SDD = n[0] * (S[0] - R[0]) + n[1] * (S[1] - R[1]) + n[2] * (S[2] - R[2]);\n  if (itk::Math::abs(SDD) < 1.0E-06)\n  {\n    itkDebugMacro(<< \"SourceDetectorDistance is less than 1.0E-06. For parallel geometry SDD is set to 0.0\");\n    SDD = 0.0;\n  }\n  // source offset: compute source's \"in-plane\" x/y shift off isocenter\n  VectorType Sv;\n  Sv[0] = S[0];\n  Sv[1] = S[1];\n  Sv[2] = S[2];\n  double oSx = Sv * r;\n  double oSy = Sv * c;\n\n  // detector offset: compute detector's in-plane x/y shift off isocenter\n  VectorType Rv;\n  Rv[0] = R[0];\n  Rv[1] = R[1];\n  Rv[2] = R[2];\n  double oRx = Rv * r;\n  double oRy = Rv * c;\n\n  // configure native RTK geometry\n  this->AddProjectionInRadians(SID, SDD, ga, oRx, oRy, oa, ia, oSx, oSy);\n\n  return true;\n}\n\nbool\nrtk::ThreeDCircularProjectionGeometry::AddProjection(const HomogeneousProjectionMatrixType & pMat)\n{\n  Matrix3x3Type A;\n  for (unsigned int i = 0; i < 3; i++)\n    for (unsigned int j = 0; j < 3; j++)\n    {\n      A(i, j) = pMat(i, j);\n    }\n\n  VectorType p;\n  p[0] = pMat(0, 3);\n  p[1] = pMat(1, 3);\n  p[2] = pMat(2, 3);\n\n  // Compute determinant of A\n  double d = pMat(0, 0) * pMat(1, 1) * pMat(2, 2) + pMat(0, 1) * pMat(1, 2) * pMat(2, 0) +\n             pMat(0, 2) * pMat(1, 0) * pMat(2, 1) - pMat(0, 0) * pMat(1, 2) * pMat(2, 1) -\n             pMat(0, 1) * pMat(1, 0) * pMat(2, 2) - pMat(0, 2) * pMat(1, 1) * pMat(2, 0);\n\n  if (itk::Math::abs(d) < std::numeric_limits<double>::epsilon()) // parallel geometry\n  {\n    // setup rotation matrix from three rotated unit vectors\n    // v1, v2 - standard unit vectors, n - normal (cross product) [v1,v2]\n    VectorType v1, v2;\n    v1[0] = A(0, 0);\n    v1[1] = A(0, 1);\n    v1[2] = A(0, 2);\n    v2[0] = A(1, 0);\n    v2[1] = A(1, 1);\n    v2[2] = A(1, 2);\n    VectorType n = itk::CrossProduct(v1, v2);\n    A(2, 0) = n[0];\n    A(2, 1) = n[1];\n    A(2, 2) = n[2];\n\n    // Declare a 3D euler transform in order to properly extract angles\n    using EulerType = itk::Euler3DTransform<double>;\n    auto euler = EulerType::New();\n    euler->SetComputeZYX(false); // ZXY order\n\n    // Extract angle using parent method without orthogonality check\n    euler->itk::MatrixOffsetTransformBase<double>::SetMatrix(A);\n    double oa = euler->GetAngleX();\n    double ga = euler->GetAngleY();\n    double ia = euler->GetAngleZ();\n\n    // verify that extracted ZXY angles result in the *desired* matrix:\n    // (at some angle constellations we may run into numerical troubles, therefore,\n    // verify angles and try to fix instabilities)\n    if (!VerifyAngles(oa, ga, ia, A))\n    {\n      if (!FixAngles(oa, ga, ia, A))\n      {\n        itkWarningMacro(<< \"Failed to AddProjection\");\n        return false;\n      }\n    }\n\n    this->AddProjectionInRadians(1000., 0., -1. * ga, -1. * p[0], -1. * p[1], -1. * oa, -1. * ia);\n    return true;\n  }\n\n  d = -1. * d / itk::Math::abs(d);\n\n  // Extract intrinsic parameters u0, v0 and f (f is chosen to be positive at that point)\n  // The extraction of u0 and v0 is independant of KR-decomp.\n  double u0 = (pMat(0, 0) * pMat(2, 0)) + (pMat(0, 1) * pMat(2, 1)) + (pMat(0, 2) * pMat(2, 2));\n  double v0 = (pMat(1, 0) * pMat(2, 0)) + (pMat(1, 1) * pMat(2, 1)) + (pMat(1, 2) * pMat(2, 2));\n  double aU = sqrt(pMat(0, 0) * pMat(0, 0) + pMat(0, 1) * pMat(0, 1) + pMat(0, 2) * pMat(0, 2) - u0 * u0);\n  double aV = sqrt(pMat(1, 0) * pMat(1, 0) + pMat(1, 1) * pMat(1, 1) + pMat(1, 2) * pMat(1, 2) - v0 * v0);\n  double sdd = 0.5 * (aU + aV);\n\n  // Def matrix K so that detK = det P[:,:3]\n  Matrix3x3Type K;\n  K.Fill(0.0f);\n  K(0, 0) = sdd;\n  K(1, 1) = sdd;\n  K(2, 2) = -1.0;\n  K(0, 2) = -1. * u0;\n  K(1, 2) = -1. * v0;\n  K *= d;\n\n  // Compute R (since det K = det P[:,:3], detR = 1 is enforced)\n  Matrix3x3Type invK(K.GetInverse());\n  Matrix3x3Type R = invK * A;\n\n  // Declare a 3D euler transform in order to properly extract angles\n  using EulerType = itk::Euler3DTransform<double>;\n  auto euler = EulerType::New();\n  euler->SetComputeZYX(false); // ZXY order\n\n  // Extract angle using parent method without orthogonality check\n  euler->itk::MatrixOffsetTransformBase<double>::SetMatrix(R);\n  double oa = euler->GetAngleX();\n  double ga = euler->GetAngleY();\n  double ia = euler->GetAngleZ();\n\n  // verify that extracted ZXY angles result in the *desired* matrix:\n  // (at some angle constellations we may run into numerical troubles, therefore,\n  // verify angles and try to fix instabilities)\n  if (!VerifyAngles(oa, ga, ia, R))\n  {\n    if (!FixAngles(oa, ga, ia, R))\n    {\n      itkWarningMacro(<< \"Failed to AddProjection\");\n      return false;\n    }\n  }\n\n  // Coordinates of source in oriented coord sys :\n  // (sx,sy,sid) = RS = R(-A^{-1}P[:,3]) = -K^{-1}P[:,3]\n  Matrix3x3Type invA(A.GetInverse());\n  VectorType    v = invK * p;\n  v *= -1.;\n  double sx = v[0];\n  double sy = v[1];\n  double sid = v[2];\n\n  // Add to geometry\n  this->AddProjectionInRadians(sid, sdd, -1. * ga, sx - u0, sy - v0, -1. * oa, -1. * ia, sx, sy);\n\n  return true;\n}\n\nvoid\nrtk::ThreeDCircularProjectionGeometry::Clear()\n{\n  Superclass::Clear();\n\n  m_GantryAngles.clear();\n  m_OutOfPlaneAngles.clear();\n  m_InPlaneAngles.clear();\n  m_SourceAngles.clear();\n  m_SourceToIsocenterDistances.clear();\n  m_SourceOffsetsX.clear();\n  m_SourceOffsetsY.clear();\n  m_SourceToDetectorDistances.clear();\n  m_ProjectionOffsetsX.clear();\n  m_ProjectionOffsetsY.clear();\n  m_CollimationUInf.clear();\n  m_CollimationUSup.clear();\n  m_CollimationVInf.clear();\n  m_CollimationVSup.clear();\n\n  m_ProjectionTranslationMatrices.clear();\n  m_MagnificationMatrices.clear();\n  m_RotationMatrices.clear();\n  m_SourceTranslationMatrices.clear();\n  this->Modified();\n}\n\nconst std::vector<double>\nrtk::ThreeDCircularProjectionGeometry::GetTiltAngles() const\n{\n  const std::vector<double> sangles = this->GetSourceAngles();\n  const std::vector<double> gangles = this->GetGantryAngles();\n  std::vector<double>       tang;\n  for (unsigned int iProj = 0; iProj < gangles.size(); iProj++)\n  {\n    double angle = -1. * gangles[iProj] - sangles[iProj];\n    tang.push_back(ConvertAngleBetween0And2PIRadians(angle));\n  }\n  return tang;\n}\n\nconst std::multimap<double, unsigned int>\nrtk::ThreeDCircularProjectionGeometry::GetSortedAngles(const std::vector<double> & angles) const\n{\n  unsigned int                        nProj = angles.size();\n  std::multimap<double, unsigned int> sangles;\n  for (unsigned int iProj = 0; iProj < nProj; iProj++)\n  {\n    double angle = angles[iProj];\n    sangles.insert(std::pair<double, unsigned int>(angle, iProj));\n  }\n  return sangles;\n}\n\nconst std::map<double, unsigned int>\nrtk::ThreeDCircularProjectionGeometry::GetUniqueSortedAngles(const std::vector<double> & angles) const\n{\n  unsigned int                   nProj = angles.size();\n  std::map<double, unsigned int> sangles;\n  for (unsigned int iProj = 0; iProj < nProj; iProj++)\n  {\n    double angle = angles[iProj];\n    sangles.insert(std::pair<double, unsigned int>(angle, iProj));\n  }\n  return sangles;\n}\n\nconst std::vector<double>\nrtk::ThreeDCircularProjectionGeometry::GetAngularGapsWithNext(const std::vector<double> & angles) const\n{\n  std::vector<double> angularGaps;\n  unsigned int        nProj = angles.size();\n  angularGaps.resize(nProj);\n\n  // Special management of single or empty dataset\n  if (nProj == 1)\n    angularGaps[0] = 2 * itk::Math::pi;\n  if (nProj < 2)\n    return angularGaps;\n\n  // Otherwise we sort the angles in a multimap\n  std::multimap<double, unsigned int> sangles = this->GetSortedAngles(angles);\n\n  // We then go over the sorted angles and deduce the angular weight\n  std::multimap<double, unsigned int>::const_iterator curr = sangles.begin(), next = sangles.begin();\n  next++;\n\n  // All but the last projection\n  while (next != sangles.end())\n  {\n    angularGaps[curr->second] = (next->first - curr->first);\n    curr++;\n    next++;\n  }\n\n  // Last projection wraps the angle of the first one\n  angularGaps[curr->second] = sangles.begin()->first + 2 * itk::Math::pi - curr->first;\n\n  return angularGaps;\n}\n\nconst std::vector<double>\nrtk::ThreeDCircularProjectionGeometry::GetAngularGaps(const std::vector<double> & angles)\n{\n  std::vector<double> angularGaps;\n  unsigned int        nProj = angles.size();\n  angularGaps.resize(nProj);\n\n  // Special management of single or empty dataset\n  if (nProj == 1)\n    angularGaps[0] = 2 * itk::Math::pi;\n  if (nProj < 2)\n    return angularGaps;\n\n  // Otherwise we sort the angles in a multimap\n  std::multimap<double, unsigned int> sangles = this->GetSortedAngles(angles);\n\n  // We then go over the sorted angles and deduce the angular weight\n  std::multimap<double, unsigned int>::const_iterator prev = sangles.begin(), curr = sangles.begin(),\n                                                      next = sangles.begin();\n  next++;\n\n  // First projection wraps the angle of the last one\n  angularGaps[curr->second] = 0.5 * (next->first - sangles.rbegin()->first + 2 * itk::Math::pi);\n  curr++;\n  next++;\n\n  // Rest of the angles\n  while (next != sangles.end())\n  {\n    angularGaps[curr->second] = 0.5 * (next->first - prev->first);\n    prev++;\n    curr++;\n    next++;\n  }\n\n  // Last projection wraps the angle of the first one\n  angularGaps[curr->second] = 0.5 * (sangles.begin()->first + 2 * itk::Math::pi - prev->first);\n\n  // FIXME: Trick for the half scan in parallel geometry case\n  if (m_SourceToDetectorDistances[0] == 0.)\n  {\n    auto it = std::max_element(angularGaps.begin(), angularGaps.end());\n    if (*it > itk::Math::pi_over_2)\n    {\n      for (auto & gap : angularGaps)\n      {\n        if (gap > itk::Math::pi_over_2)\n          gap -= itk::Math::pi_over_2;\n        gap *= 2.;\n      }\n    }\n  }\n\n  return angularGaps;\n}\n\nrtk::ThreeDCircularProjectionGeometry::ThreeDHomogeneousMatrixType\nrtk::ThreeDCircularProjectionGeometry::ComputeRotationHomogeneousMatrix(double angleX, double angleY, double angleZ)\n{\n  auto xfm = itk::CenteredEuler3DTransform<double>::New();\n  xfm->SetIdentity();\n  xfm->SetRotation(angleX, angleY, angleZ);\n\n  ThreeDHomogeneousMatrixType matrix;\n  matrix.SetIdentity();\n  for (int i = 0; i < 3; i++)\n    for (int j = 0; j < 3; j++)\n      matrix[i][j] = xfm->GetMatrix()[i][j];\n\n  return matrix;\n}\n\nrtk::ThreeDCircularProjectionGeometry::TwoDHomogeneousMatrixType\nrtk::ThreeDCircularProjectionGeometry::ComputeTranslationHomogeneousMatrix(double transX, double transY)\n{\n  TwoDHomogeneousMatrixType matrix;\n  matrix.SetIdentity();\n  matrix[0][2] = transX;\n  matrix[1][2] = transY;\n  return matrix;\n}\n\nrtk::ThreeDCircularProjectionGeometry::ThreeDHomogeneousMatrixType\nrtk::ThreeDCircularProjectionGeometry::ComputeTranslationHomogeneousMatrix(double transX, double transY, double transZ)\n{\n  ThreeDHomogeneousMatrixType matrix;\n  matrix.SetIdentity();\n  matrix[0][3] = transX;\n  matrix[1][3] = transY;\n  matrix[2][3] = transZ;\n  return matrix;\n}\n\nrtk::ThreeDCircularProjectionGeometry::Superclass::MatrixType\nrtk::ThreeDCircularProjectionGeometry::ComputeProjectionMagnificationMatrix(double sdd, const double sid)\n{\n  Superclass::MatrixType matrix;\n  matrix.Fill(0.0);\n  for (unsigned int i = 0; i < 2; i++)\n    matrix[i][i] = (sdd == 0.) ? 1. : sdd;\n  matrix[2][2] = (sdd == 0.) ? 0. : 1.;\n  matrix[2][3] = (sdd == 0.) ? 1. : sid;\n  return matrix;\n}\n\nvoid\nrtk::ThreeDCircularProjectionGeometry::SetCollimationOfLastProjection(const double uinf,\n                                                                      const double usup,\n                                                                      const double vinf,\n                                                                      const double vsup)\n{\n  m_CollimationUInf.back() = uinf;\n  m_CollimationUSup.back() = usup;\n  m_CollimationVInf.back() = vinf;\n  m_CollimationVSup.back() = vsup;\n}\n\nconst rtk::ThreeDCircularProjectionGeometry::HomogeneousVectorType\nrtk::ThreeDCircularProjectionGeometry::GetSourcePosition(const unsigned int i) const\n{\n  HomogeneousVectorType sourcePosition;\n  sourcePosition[0] = this->GetSourceOffsetsX()[i];\n  sourcePosition[1] = this->GetSourceOffsetsY()[i];\n  sourcePosition[2] = this->GetSourceToIsocenterDistances()[i];\n  sourcePosition[3] = 1.;\n\n  // Rotate\n  sourcePosition.SetVnlVector(GetRotationMatrices()[i].GetInverse() * sourcePosition.GetVnlVector());\n  return sourcePosition;\n}\n\nconst rtk::ThreeDCircularProjectionGeometry::ThreeDHomogeneousMatrixType\nrtk::ThreeDCircularProjectionGeometry::GetProjectionCoordinatesToDetectorSystemMatrix(const unsigned int i) const\n{\n  // Compute projection inverse and distance to source\n  ThreeDHomogeneousMatrixType matrix;\n  matrix.SetIdentity();\n  matrix[0][3] = this->GetProjectionOffsetsX()[i];\n  matrix[1][3] = this->GetProjectionOffsetsY()[i];\n  if (this->GetSourceToDetectorDistances()[i] == 0.)\n  {\n    matrix[2][3] = -1. * this->GetSourceToIsocenterDistances()[i];\n  }\n  else\n  {\n    matrix[2][3] = this->GetSourceToIsocenterDistances()[i] - this->GetSourceToDetectorDistances()[i];\n  }\n  matrix[2][2] = 0.; // Force z to axis to detector distance\n  return matrix;\n}\n\nconst rtk::ThreeDCircularProjectionGeometry::ThreeDHomogeneousMatrixType\nrtk::ThreeDCircularProjectionGeometry::GetProjectionCoordinatesToFixedSystemMatrix(const unsigned int i) const\n{\n  ThreeDHomogeneousMatrixType matrix;\n  matrix =\n    this->GetRotationMatrices()[i].GetInverse() * GetProjectionCoordinatesToDetectorSystemMatrix(i).GetVnlMatrix();\n  return matrix;\n}\n\n\ndouble\nrtk::ThreeDCircularProjectionGeometry::ToUntiltedCoordinateAtIsocenter(const unsigned int noProj,\n                                                                       const double       tiltedCoord) const\n{\n  // Aliases / constant\n  const double sid = this->GetSourceToIsocenterDistances()[noProj];\n  const double sid2 = sid * sid;\n  const double sdd = this->GetSourceToDetectorDistances()[noProj];\n  const double sx = this->GetSourceOffsetsX()[noProj];\n  const double px = this->GetProjectionOffsetsX()[noProj];\n\n  // sidu is the distance between the source and the virtual untilted detector\n  const double sidu = sqrt(sid2 + sx * sx);\n  // l is the coordinate on the virtual detector parallel to the real detector\n  // and passing at the isocenter\n  const double l = (tiltedCoord + px - sx) * sid / sdd + sx;\n\n  // a is the angle between the virtual detector and the real detector\n  const double cosa = sx / sidu;\n\n  // the following relation refers to a note by R. Clackdoyle, title\n  // \"Samping a tilted detector\"\n  return l * itk::Math::abs(sid) / (sidu - l * cosa);\n}\n\nbool\nrtk::ThreeDCircularProjectionGeometry::VerifyAngles(const double          outOfPlaneAngleRAD,\n                                                    const double          gantryAngleRAD,\n                                                    const double          inPlaneAngleRAD,\n                                                    const Matrix3x3Type & referenceMatrix) const\n{\n  // Check if parameters are Nan. Fails if they are.\n  if (outOfPlaneAngleRAD != outOfPlaneAngleRAD || gantryAngleRAD != gantryAngleRAD ||\n      inPlaneAngleRAD != inPlaneAngleRAD)\n    return false;\n\n  using EulerType = itk::Euler3DTransform<double>;\n\n  const Matrix3x3Type & rm = referenceMatrix; // shortcut\n\n  auto euler = EulerType::New();\n  euler->SetComputeZYX(false); // ZXY order\n  euler->SetRotation(outOfPlaneAngleRAD, gantryAngleRAD, inPlaneAngleRAD);\n  Matrix3x3Type m = euler->GetMatrix(); // resultant matrix\n\n  for (int i = 0; i < 3; i++) // check whether matrices match\n    for (int j = 0; j < 3; j++)\n      if (itk::Math::abs(rm[i][j] - m[i][j]) > m_VerifyAnglesTolerance)\n        return false;\n\n  return true;\n}\n\nbool\nrtk::ThreeDCircularProjectionGeometry::FixAngles(double &              outOfPlaneAngleRAD,\n                                                 double &              gantryAngleRAD,\n                                                 double &              inPlaneAngleRAD,\n                                                 const Matrix3x3Type & referenceMatrix) const\n{\n  const Matrix3x3Type & rm = referenceMatrix; // shortcut\n\n  if (itk::Math::abs(itk::Math::abs(rm[2][1]) - 1.) > m_FixAnglesTolerance)\n  {\n    double oa = NAN, ga = NAN, ia = NAN;\n\n    // @see Slabaugh, GG, \"Computing Euler angles from a rotation matrix\"\n    // but their convention is XYZ where we use the YXZ convention\n\n    // first trial:\n    oa = asin(rm[2][1]);\n    double coa = cos(oa);\n    ga = atan2(-rm[2][0] / coa, rm[2][2] / coa);\n    ia = atan2(-rm[0][1] / coa, rm[1][1] / coa);\n    if (VerifyAngles(oa, ga, ia, rm))\n    {\n      outOfPlaneAngleRAD = oa;\n      gantryAngleRAD = ga;\n      inPlaneAngleRAD = ia;\n      return true;\n    }\n\n    // second trial:\n    oa = 3.1415926535897932384626433832795 /*PI*/ - asin(rm[2][1]);\n    coa = cos(oa);\n    ga = atan2(-rm[2][0] / coa, rm[2][2] / coa);\n    ia = atan2(-rm[0][1] / coa, rm[1][1] / coa);\n    if (VerifyAngles(oa, ga, ia, rm))\n    {\n      outOfPlaneAngleRAD = oa;\n      gantryAngleRAD = ga;\n      inPlaneAngleRAD = ia;\n      return true;\n    }\n  }\n  else\n  {\n    // Gimbal lock, one angle in {ia,oa} has to be set randomly\n    double ia = NAN;\n    ia = 0.;\n    if (rm[2][1] < 0.)\n    {\n      double oa = -itk::Math::pi_over_2;\n      double ga = atan2(rm[0][2], rm[0][0]);\n      if (VerifyAngles(oa, ga, ia, rm))\n      {\n        outOfPlaneAngleRAD = oa;\n        gantryAngleRAD = ga;\n        inPlaneAngleRAD = ia;\n        return true;\n      }\n    }\n    else\n    {\n      double oa = itk::Math::pi_over_2;\n      double ga = atan2(rm[0][2], rm[0][0]);\n      if (VerifyAngles(oa, ga, ia, rm))\n      {\n        outOfPlaneAngleRAD = oa;\n        gantryAngleRAD = ga;\n        inPlaneAngleRAD = ia;\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nitk::LightObject::Pointer\nrtk::ThreeDCircularProjectionGeometry::InternalClone() const\n{\n  LightObject::Pointer loPtr = Superclass::InternalClone();\n  Self::Pointer        clone = dynamic_cast<Self *>(loPtr.GetPointer());\n  for (unsigned int iProj = 0; iProj < this->GetGantryAngles().size(); iProj++)\n  {\n    clone->AddProjectionInRadians(this->GetSourceToIsocenterDistances()[iProj],\n                                  this->GetSourceToDetectorDistances()[iProj],\n                                  this->GetGantryAngles()[iProj],\n                                  this->GetProjectionOffsetsX()[iProj],\n                                  this->GetProjectionOffsetsY()[iProj],\n                                  this->GetOutOfPlaneAngles()[iProj],\n                                  this->GetInPlaneAngles()[iProj],\n                                  this->GetSourceOffsetsX()[iProj],\n                                  this->GetSourceOffsetsY()[iProj]);\n    clone->SetCollimationOfLastProjection(this->GetCollimationUInf()[iProj],\n                                          this->GetCollimationUSup()[iProj],\n                                          this->GetCollimationVInf()[iProj],\n                                          this->GetCollimationVSup()[iProj]);\n  }\n  clone->SetRadiusCylindricalDetector(this->GetRadiusCylindricalDetector());\n  return loPtr;\n}\n"
  },
  {
    "path": "src/rtkThreeDCircularProjectionGeometryXMLFileReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef _rtkThreeDCircularProjectionGeometryXMLFileReader_cxx\n#define _rtkThreeDCircularProjectionGeometryXMLFileReader_cxx\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFileReader.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n#include <itkIOCommon.h>\n\n#include <iomanip>\n\nnamespace rtk\n{\n\nThreeDCircularProjectionGeometryXMLFileReader::ThreeDCircularProjectionGeometryXMLFileReader()\n{\n  this->m_OutputObject = &(*m_Geometry);\n}\n\nint\nThreeDCircularProjectionGeometryXMLFileReader::CanReadFile(const char * name)\n{\n  if (!itksys::SystemTools::FileExists(name) || itksys::SystemTools::FileIsDirectory(name) ||\n      itksys::SystemTools::FileLength(name) == 0)\n    return 0;\n  return 1;\n}\n\nvoid\nThreeDCircularProjectionGeometryXMLFileReader::StartElement(const char * name, const char ** atts)\n{\n  m_CurCharacterData = \"\";\n  this->StartElement(name);\n\n  // Check on last version of file format. Warning if not.\n  if (std::string(name) == \"RTKThreeDCircularGeometry\")\n  {\n    while ((*atts) != nullptr)\n    {\n      if (std::string(atts[0]) == \"version\")\n        m_Version = std::stoi(atts[1]);\n      atts += 2;\n    }\n    // Version 3 is backward compatible with version 2\n    if (m_Version != this->CurrentVersion && !(m_Version == 2 && this->CurrentVersion == 3))\n      itkGenericExceptionMacro(<< \"Incompatible version of input geometry (v\" << m_Version\n                               << \") with current geometry (v\" << this->CurrentVersion\n                               << \"). You must re-generate your geometry file again.\");\n    this->m_OutputObject->Clear();\n  }\n}\n\nvoid\nThreeDCircularProjectionGeometryXMLFileReader::StartElement(const char * itkNotUsed(name))\n{}\n\nvoid\nThreeDCircularProjectionGeometryXMLFileReader::EndElement(const char * name)\n{\n  if (itksys::SystemTools::Strucmp(name, \"InPlaneAngle\") == 0)\n    m_InPlaneAngle = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"GantryAngle\") == 0 ||\n      itksys::SystemTools::Strucmp(name, \"Angle\") == 0) // Second one for backward compatibility\n    m_GantryAngle = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"OutOfPlaneAngle\") == 0)\n    m_OutOfPlaneAngle = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"SourceToIsocenterDistance\") == 0)\n    m_SourceToIsocenterDistance = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"SourceOffsetX\") == 0)\n    m_SourceOffsetX = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"SourceOffsetY\") == 0)\n    m_SourceOffsetY = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"SourceToDetectorDistance\") == 0)\n    m_SourceToDetectorDistance = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"ProjectionOffsetX\") == 0)\n    m_ProjectionOffsetX = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"ProjectionOffsetY\") == 0)\n    m_ProjectionOffsetY = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"RadiusCylindricalDetector\") == 0)\n  {\n    double radiusCylindricalDetector = std::stod(this->m_CurCharacterData.c_str());\n    this->m_OutputObject->SetRadiusCylindricalDetector(radiusCylindricalDetector);\n  }\n\n  if (itksys::SystemTools::Strucmp(name, \"CollimationUInf\") == 0)\n    m_CollimationUInf = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"CollimationUSup\") == 0)\n    m_CollimationUSup = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"CollimationVInf\") == 0)\n    m_CollimationVInf = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"CollimationVSup\") == 0)\n    m_CollimationVSup = std::stod(this->m_CurCharacterData.c_str());\n\n  if (itksys::SystemTools::Strucmp(name, \"Matrix\") == 0)\n  {\n    std::istringstream iss(this->m_CurCharacterData);\n    double             value = 0.;\n    for (unsigned int i = 0; i < m_Matrix.RowDimensions; i++)\n      for (unsigned int j = 0; j < m_Matrix.ColumnDimensions; j++)\n      {\n        iss >> value;\n        m_Matrix[i][j] = value;\n      }\n  }\n\n  if (itksys::SystemTools::Strucmp(name, \"Projection\") == 0)\n  {\n    this->m_OutputObject->AddProjection(m_SourceToIsocenterDistance,\n                                        m_SourceToDetectorDistance,\n                                        m_GantryAngle,\n                                        m_ProjectionOffsetX,\n                                        m_ProjectionOffsetY,\n                                        m_OutOfPlaneAngle,\n                                        m_InPlaneAngle,\n                                        m_SourceOffsetX,\n                                        m_SourceOffsetY);\n\n    this->m_OutputObject->SetCollimationOfLastProjection(\n      m_CollimationUInf, m_CollimationUSup, m_CollimationVInf, m_CollimationVSup);\n\n    for (unsigned int i = 0; i < m_Matrix.RowDimensions; i++)\n      for (unsigned int j = 0; j < m_Matrix.ColumnDimensions; j++)\n      {\n        // Tolerance can not be vcl_numeric_limits<double>::epsilon(), too strict\n        // 0.001 is a random choice to catch \"large\" inconsistencies\n        if (itk::Math::abs(m_Matrix[i][j] - m_OutputObject->GetMatrices().back()[i][j]) > 0.001)\n        {\n          itkGenericExceptionMacro(<< \"Matrix and parameters are not consistent.\" << std::endl\n                                   << \"Read matrix from geometry file: \" << std::endl\n                                   << m_Matrix << std::endl\n                                   << \"Computed matrix from parameters:\" << std::endl\n                                   << m_OutputObject->GetMatrices().back());\n        }\n      }\n  }\n}\n\nvoid\nThreeDCircularProjectionGeometryXMLFileReader::CharacterDataHandler(const char * inData, int inLength)\n{\n  for (int i = 0; i < inLength; i++)\n    m_CurCharacterData = m_CurCharacterData + inData[i];\n}\n\nThreeDCircularProjectionGeometry::Pointer\nReadGeometry(const std::string & filename)\n{\n  const auto reader = ThreeDCircularProjectionGeometryXMLFileReader::New();\n  reader->SetFilename(filename);\n  reader->GenerateOutputInformation();\n  return reader->GetOutputObject();\n}\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "src/rtkThreeDCircularProjectionGeometryXMLFileWriter.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef _rtkThreeDCircularProjectionGeometryXMLFileWriter_cxx\n#define _rtkThreeDCircularProjectionGeometryXMLFileWriter_cxx\n\n#include \"rtkThreeDCircularProjectionGeometryXMLFileReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFileWriter.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n#include <itkIOCommon.h>\n\n#include <iomanip>\n\nnamespace rtk\n{\n\nint\nThreeDCircularProjectionGeometryXMLFileWriter::CanWriteFile(const char * name)\n{\n  std::ofstream output(name);\n\n  if (output.fail())\n    return false;\n  return true;\n}\n\nint\nThreeDCircularProjectionGeometryXMLFileWriter::WriteFile()\n{\n  if (this->m_InputObject->GetGantryAngles().empty())\n    itkGenericExceptionMacro(<< \"Geometry object is empty, cannot write it\");\n\n  std::ofstream output(this->m_Filename.c_str());\n  constexpr int maxDigits = 15;\n\n  output.precision(maxDigits);\n  std::string indent(\"  \");\n\n  this->WriteStartElement(\"?xml version=\\\"1.0\\\"?\", output);\n  output << std::endl;\n  this->WriteStartElement(\"!DOCTYPE RTKGEOMETRY\", output);\n  output << std::endl;\n  std::ostringstream startWithVersion;\n  startWithVersion << \"RTKThreeDCircularGeometry version=\\\"\"\n                   << ThreeDCircularProjectionGeometryXMLFileReader::CurrentVersion << '\"';\n  this->WriteStartElement(startWithVersion.str().c_str(), output);\n  output << std::endl;\n\n  // First, we test for each of the 9 parameters per projection if it's constant\n  // over all projection images except GantryAngle which is supposed to be different\n  // for all projections. If 0. for OutOfPlaneAngle, InPlaneAngle, projection and source\n  // offsets X and Y, it is not written (default value).\n  bool bSIDGlobal = WriteGlobalParameter(\n    output, indent, this->m_InputObject->GetSourceToIsocenterDistances(), \"SourceToIsocenterDistance\");\n  bool bSDDGlobal = WriteGlobalParameter(\n    output, indent, this->m_InputObject->GetSourceToDetectorDistances(), \"SourceToDetectorDistance\");\n  bool bSourceXGlobal = WriteGlobalParameter(output, indent, this->m_InputObject->GetSourceOffsetsX(), \"SourceOffsetX\");\n  bool bSourceYGlobal = WriteGlobalParameter(output, indent, this->m_InputObject->GetSourceOffsetsY(), \"SourceOffsetY\");\n  bool bProjXGlobal =\n    WriteGlobalParameter(output, indent, this->m_InputObject->GetProjectionOffsetsX(), \"ProjectionOffsetX\");\n  bool bProjYGlobal =\n    WriteGlobalParameter(output, indent, this->m_InputObject->GetProjectionOffsetsY(), \"ProjectionOffsetY\");\n  bool bInPlaneGlobal =\n    WriteGlobalParameter(output, indent, this->m_InputObject->GetInPlaneAngles(), \"InPlaneAngle\", true);\n  bool bOutOfPlaneGlobal =\n    WriteGlobalParameter(output, indent, this->m_InputObject->GetOutOfPlaneAngles(), \"OutOfPlaneAngle\", true);\n\n  bool bCollimationUInf = WriteGlobalParameter(output,\n                                               indent,\n                                               this->m_InputObject->GetCollimationUInf(),\n                                               \"CollimationUInf\",\n                                               false,\n                                               std::numeric_limits<double>::max());\n\n  bool bCollimationUSup = WriteGlobalParameter(output,\n                                               indent,\n                                               this->m_InputObject->GetCollimationUSup(),\n                                               \"CollimationUSup\",\n                                               false,\n                                               std::numeric_limits<double>::max());\n\n  bool bCollimationVInf = WriteGlobalParameter(output,\n                                               indent,\n                                               this->m_InputObject->GetCollimationVInf(),\n                                               \"CollimationVInf\",\n                                               false,\n                                               std::numeric_limits<double>::max());\n\n  bool bCollimationVSup = WriteGlobalParameter(output,\n                                               indent,\n                                               this->m_InputObject->GetCollimationVSup(),\n                                               \"CollimationVSup\",\n                                               false,\n                                               std::numeric_limits<double>::max());\n\n  const double radius = this->m_InputObject->GetRadiusCylindricalDetector();\n  if (0. != radius)\n    WriteLocalParameter(output, indent, radius, \"RadiusCylindricalDetector\");\n\n  // Second, write per projection parameters (if corresponding parameter is not global)\n  const double radiansToDegrees = 45. / std::atan(1.);\n  for (unsigned int i = 0; i < this->m_InputObject->GetMatrices().size(); i++)\n  {\n    output << indent;\n    this->WriteStartElement(\"Projection\", output);\n    output << std::endl;\n\n    // Only the GantryAngle is necessarily projection specific\n    WriteLocalParameter(output, indent, radiansToDegrees * this->m_InputObject->GetGantryAngles()[i], \"GantryAngle\");\n    if (!bSIDGlobal)\n      WriteLocalParameter(\n        output, indent, this->m_InputObject->GetSourceToIsocenterDistances()[i], \"SourceToIsocenterDistance\");\n    if (!bSDDGlobal)\n      WriteLocalParameter(\n        output, indent, this->m_InputObject->GetSourceToDetectorDistances()[i], \"SourceToDetectorDistance\");\n    if (!bSourceXGlobal)\n      WriteLocalParameter(output, indent, this->m_InputObject->GetSourceOffsetsX()[i], \"SourceOffsetX\");\n    if (!bSourceYGlobal)\n      WriteLocalParameter(output, indent, this->m_InputObject->GetSourceOffsetsY()[i], \"SourceOffsetY\");\n    if (!bProjXGlobal)\n      WriteLocalParameter(output, indent, this->m_InputObject->GetProjectionOffsetsX()[i], \"ProjectionOffsetX\");\n    if (!bProjYGlobal)\n      WriteLocalParameter(output, indent, this->m_InputObject->GetProjectionOffsetsY()[i], \"ProjectionOffsetY\");\n    if (!bInPlaneGlobal)\n      WriteLocalParameter(\n        output, indent, radiansToDegrees * this->m_InputObject->GetInPlaneAngles()[i], \"InPlaneAngle\");\n    if (!bOutOfPlaneGlobal)\n      WriteLocalParameter(\n        output, indent, radiansToDegrees * this->m_InputObject->GetOutOfPlaneAngles()[i], \"OutOfPlaneAngle\");\n\n    if (!bCollimationUInf)\n      WriteLocalParameter(output, indent, this->m_InputObject->GetCollimationUInf()[i], \"CollimationUInf\");\n\n    if (!bCollimationUSup)\n      WriteLocalParameter(output, indent, this->m_InputObject->GetCollimationUSup()[i], \"CollimationUSup\");\n\n    if (!bCollimationVInf)\n      WriteLocalParameter(output, indent, this->m_InputObject->GetCollimationVInf()[i], \"CollimationVInf\");\n\n    if (!bCollimationVSup)\n      WriteLocalParameter(output, indent, this->m_InputObject->GetCollimationVSup()[i], \"CollimationVSup\");\n\n    // Matrix\n    output << indent << indent;\n    this->WriteStartElement(\"Matrix\", output);\n    output << std::endl;\n    for (unsigned int j = 0; j < 3; j++)\n    {\n      output << indent << indent << indent;\n      for (unsigned int k = 0; k < 4; k++)\n        output << std::setw(maxDigits + 4) << this->m_InputObject->GetMatrices()[i][j][k] << ' ';\n      output.seekp(-1, std::ios_base::cur);\n      output << std::endl;\n    }\n    output << indent << indent;\n    this->WriteEndElement(\"Matrix\", output);\n    output << std::endl;\n\n    output << indent;\n    this->WriteEndElement(\"Projection\", output);\n    output << std::endl;\n  }\n\n  this->WriteEndElement(\"RTKThreeDCircularGeometry\", output);\n  output << std::endl;\n\n  return 0;\n}\n\nbool\nThreeDCircularProjectionGeometryXMLFileWriter::WriteGlobalParameter(std::ofstream &             output,\n                                                                    const std::string &         indent,\n                                                                    const std::vector<double> & v,\n                                                                    const std::string &         s,\n                                                                    bool                        convertToDegrees,\n                                                                    double                      defval)\n{\n  // Test if all values in vector v are equal. Return false if not.\n  for (size_t i = 0; i < v.size(); i++)\n    if (v[i] != v[0])\n      return false;\n\n  // Write value in file if not 0.\n  if (defval != v[0])\n  {\n    double val = v[0];\n    if (convertToDegrees)\n      val *= 45. / std::atan(1.);\n\n    WriteLocalParameter(output, indent, val, s);\n  }\n  return true;\n}\n\nvoid\nThreeDCircularProjectionGeometryXMLFileWriter::WriteLocalParameter(std::ofstream &     output,\n                                                                   const std::string & indent,\n                                                                   const double &      v,\n                                                                   const std::string & s)\n{\n  std::string ss(s);\n  output << indent << indent;\n  this->WriteStartElement(ss, output);\n  output << v;\n  this->WriteEndElement(ss, output);\n  output << std::endl;\n}\n\n} // namespace rtk\n\n#endif\n"
  },
  {
    "path": "src/rtkVarianObiGeometryReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n\n#include \"math.h\"\n\n#include \"rtkVarianObiGeometryReader.h\"\n#include \"rtkVarianObiXMLFileReader.h\"\n#include \"rtkHndImageIOFactory.h\"\n#include \"rtkHncImageIOFactory.h\"\n\n#include <itkImageFileReader.h>\n#include <itksys/SystemTools.hxx>\n\nrtk::VarianObiGeometryReader ::VarianObiGeometryReader()\n  : m_Geometry(nullptr)\n{}\n\nvoid\nrtk::VarianObiGeometryReader ::GenerateData()\n{\n  // Create new RTK geometry object\n  m_Geometry = GeometryType::New();\n\n  // Read Varian XML file (for common geometric information)\n  rtk::VarianObiXMLFileReader::Pointer obiXmlReader;\n  obiXmlReader = rtk::VarianObiXMLFileReader::New();\n  obiXmlReader->SetFilename(m_XMLFileName);\n  obiXmlReader->GenerateOutputInformation();\n\n  // Constants used to generate projection matrices\n  itk::MetaDataDictionary & dic = *(obiXmlReader->GetOutputObject());\n  using MetaDataDoubleType = itk::MetaDataObject<double>;\n  const double sdd = dynamic_cast<MetaDataDoubleType *>(dic[\"CalibratedSID\"].GetPointer())->GetMetaDataObjectValue();\n  const double sid = dynamic_cast<MetaDataDoubleType *>(dic[\"CalibratedSAD\"].GetPointer())->GetMetaDataObjectValue();\n\n  double      offsetx = NAN;\n  std::string fanType =\n    dynamic_cast<const itk::MetaDataObject<std::string> *>(dic[\"FanType\"].GetPointer())->GetMetaDataObjectValue();\n  if (itksys::SystemTools::Strucmp(fanType.c_str(), \"HalfFan\") == 0)\n  {\n    // Half Fan (offset detector), get lateral offset from XML file\n    offsetx =\n      dynamic_cast<MetaDataDoubleType *>(dic[\"CalibratedDetectorOffsetX\"].GetPointer())->GetMetaDataObjectValue() +\n      dynamic_cast<MetaDataDoubleType *>(dic[\"DetectorPosLat\"].GetPointer())->GetMetaDataObjectValue();\n  }\n  else\n  {\n    // Full Fan (centered detector)\n    offsetx =\n      dynamic_cast<MetaDataDoubleType *>(dic[\"CalibratedDetectorOffsetX\"].GetPointer())->GetMetaDataObjectValue();\n  }\n  const double offsety =\n    dynamic_cast<MetaDataDoubleType *>(dic[\"CalibratedDetectorOffsetY\"].GetPointer())->GetMetaDataObjectValue();\n\n  // Projections reader (for angle)\n  rtk::HndImageIOFactory::RegisterOneFactory();\n  rtk::HncImageIOFactory::RegisterOneFactory();\n\n  // Projection matrices\n  for (const std::string & projectionsFileName : m_ProjectionsFileNames)\n  {\n\n    auto reader = itk::ImageFileReader<itk::Image<unsigned int, 2>>::New();\n    reader->SetFileName(projectionsFileName);\n    reader->UpdateOutputInformation();\n\n    const double angle =\n      dynamic_cast<MetaDataDoubleType *>(reader->GetMetaDataDictionary()[\"dCTProjectionAngle\"].GetPointer())\n        ->GetMetaDataObjectValue();\n\n    m_Geometry->AddProjection(sid, sdd, angle, offsetx, offsety);\n  }\n}\n"
  },
  {
    "path": "src/rtkVarianObiXMLFileReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkVarianObiXMLFileReader.h\"\n#include \"itkMacro.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n\nnamespace rtk\n{\n\nint\nVarianObiXMLFileReader::CanReadFile(const char * name)\n{\n  if (!itksys::SystemTools::FileExists(name) || itksys::SystemTools::FileIsDirectory(name) ||\n      itksys::SystemTools::FileLength(name) == 0)\n    return 0;\n  return 1;\n}\n\nvoid\nVarianObiXMLFileReader::StartElement(const char * itkNotUsed(name), const char ** itkNotUsed(atts))\n{\n  m_CurCharacterData = \"\";\n}\n\nvoid\nVarianObiXMLFileReader::EndElement(const char * name)\n{\n#define ENCAPLULATE_META_DATA_DOUBLE(metaName)                   \\\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)         \\\n  {                                                              \\\n    double d = std::stod(m_CurCharacterData.c_str());            \\\n    itk::EncapsulateMetaData<double>(m_Dictionary, metaName, d); \\\n  }\n\n#define ENCAPLULATE_META_DATA_STRING(metaName)                                         \\\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)                               \\\n  {                                                                                    \\\n    itk::EncapsulateMetaData<std::string>(m_Dictionary, metaName, m_CurCharacterData); \\\n  }\n\n  ENCAPLULATE_META_DATA_DOUBLE(\"GantryRtnSpeed\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"CalibratedSAD\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"CalibratedSID\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"CalibratedDetectorOffsetX\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"CalibratedDetectorOffsetY\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"DetectorSizeX\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"DetectorSizeY\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"DetectorPosLat\");\n  ENCAPLULATE_META_DATA_STRING(\"FanType\");\n}\n\nvoid\nVarianObiXMLFileReader::CharacterDataHandler(const char * inData, int inLength)\n{\n  for (int i = 0; i < inLength; i++)\n    m_CurCharacterData = m_CurCharacterData + inData[i];\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkVarianProBeamGeometryReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n\n#include \"rtkVarianProBeamGeometryReader.h\"\n#include \"rtkVarianProBeamXMLFileReader.h\"\n#include \"rtkXimImageIOFactory.h\"\n\n#include <itkImageFileReader.h>\n#include <itksys/SystemTools.hxx>\n\nrtk::VarianProBeamGeometryReader ::VarianProBeamGeometryReader()\n  : m_Geometry(nullptr)\n{}\n\nvoid\nrtk::VarianProBeamGeometryReader ::GenerateData()\n{\n  // Create new RTK geometry object\n  m_Geometry = GeometryType::New();\n\n  // Read Varian XML file (for common geometric information)\n  rtk::VarianProBeamXMLFileReader::Pointer proBeamXmlReader;\n  proBeamXmlReader = rtk::VarianProBeamXMLFileReader::New();\n  proBeamXmlReader->SetFilename(m_XMLFileName);\n  proBeamXmlReader->GenerateOutputInformation();\n\n  // Constants used to generate projection matrices\n  itk::MetaDataDictionary & dic = *(proBeamXmlReader->GetOutputObject());\n  using MetaDataDoubleType = itk::MetaDataObject<double>;\n  const double sdd = dynamic_cast<MetaDataDoubleType *>(dic[\"SID\"].GetPointer())->GetMetaDataObjectValue();\n  const double sid = dynamic_cast<MetaDataDoubleType *>(dic[\"SAD\"].GetPointer())->GetMetaDataObjectValue();\n\n  // Projections reader (for angle)\n  rtk::XimImageIOFactory::RegisterOneFactory();\n  // Projection matrices\n  for (const std::string & projectionsFileName : m_ProjectionsFileNames)\n  {\n\n    auto reader = itk::ImageFileReader<itk::Image<unsigned int, 2>>::New();\n    reader->SetFileName(projectionsFileName);\n    reader->UpdateOutputInformation();\n\n    const double angle =\n      dynamic_cast<MetaDataDoubleType *>(reader->GetMetaDataDictionary()[\"dCTProjectionAngle\"].GetPointer())\n        ->GetMetaDataObjectValue();\n    if (angle != 6000)\n    {\n      /* Warning: The offsets in the test scans were very small,\n      however this configuration improved reconstruction quality slightly.*/\n      const double offsetx =\n        dynamic_cast<MetaDataDoubleType *>(reader->GetMetaDataDictionary()[\"dDetectorOffsetX\"].GetPointer())\n          ->GetMetaDataObjectValue();\n      const double offsety =\n        dynamic_cast<MetaDataDoubleType *>(reader->GetMetaDataDictionary()[\"dDetectorOffsetY\"].GetPointer())\n          ->GetMetaDataObjectValue();\n      /*The angle-direction of RTK is opposite of the Xim properties\n      (There doesn't seem to be a flag for direction in neither the xml nor xim file) */\n      m_Geometry->AddProjection(sid, sdd, 180.0 - angle, offsetx, offsety);\n    }\n  }\n}\n"
  },
  {
    "path": "src/rtkVarianProBeamXMLFileReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkVarianProBeamXMLFileReader.h\"\n#include \"itkMacro.h\"\n\n#include <itksys/SystemTools.hxx>\n#include <itkMetaDataObject.h>\n\nnamespace rtk\n{\n\nint\nVarianProBeamXMLFileReader::CanReadFile(const char * name)\n{\n  if (!itksys::SystemTools::FileExists(name) || itksys::SystemTools::FileIsDirectory(name) ||\n      itksys::SystemTools::FileLength(name) == 0)\n    return 0;\n  return 1;\n}\n\nvoid\nVarianProBeamXMLFileReader::StartElement(const char * itkNotUsed(name), const char ** itkNotUsed(atts))\n{\n  m_CurCharacterData = \"\";\n}\n\nvoid\nVarianProBeamXMLFileReader::EndElement(const char * name)\n{\n#define ENCAPLULATE_META_DATA_DOUBLE(metaName)                   \\\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)         \\\n  {                                                              \\\n    double d = std::stod(m_CurCharacterData.c_str());            \\\n    itk::EncapsulateMetaData<double>(m_Dictionary, metaName, d); \\\n  }\n\n#define ENCAPLULATE_META_DATA_DOUBLE_AS(metaName, encapsulatedName)      \\\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)                 \\\n  {                                                                      \\\n    double d = std::stod(m_CurCharacterData.c_str());                    \\\n    itk::EncapsulateMetaData<double>(m_Dictionary, encapsulatedName, d); \\\n  }\n\n#define MODIFY_META_DATA_DOUBLE_MULTIPLY(metaName, encapsulatedName)                                             \\\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)                                                         \\\n  {                                                                                                              \\\n    double d = std::stod(m_CurCharacterData.c_str());                                                            \\\n    using MetaDataDoubleType = itk::MetaDataObject<double>;                                                      \\\n    const double multiplier =                                                                                    \\\n      dynamic_cast<MetaDataDoubleType *>(m_Dictionary[encapsulatedName].GetPointer())->GetMetaDataObjectValue(); \\\n    itk::EncapsulateMetaData<double>(m_Dictionary, encapsulatedName, d * multiplier);                            \\\n  }\n\n#define ENCAPLULATE_META_DATA_STRING(metaName)                                         \\\n  if (itksys::SystemTools::Strucmp(name, metaName) == 0)                               \\\n  {                                                                                    \\\n    itk::EncapsulateMetaData<std::string>(m_Dictionary, metaName, m_CurCharacterData); \\\n  }\n\n  ENCAPLULATE_META_DATA_DOUBLE(\"Velocity\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"SAD\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"SID\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"SourceAngleOffset\");\n  ENCAPLULATE_META_DATA_DOUBLE_AS(\"ImagerSizeX\", \"DetectorSizeX\"); // DetectorSize = ImagerSize * ImagerRes\n  ENCAPLULATE_META_DATA_DOUBLE_AS(\"ImagerSizeY\", \"DetectorSizeY\");\n  MODIFY_META_DATA_DOUBLE_MULTIPLY(\"ImagerResX\", \"DetectorSizeX\"); // Assumes ImagerSize is always read first!!\n  MODIFY_META_DATA_DOUBLE_MULTIPLY(\"ImagerResY\", \"DetectorSizeY\");\n  ENCAPLULATE_META_DATA_DOUBLE(\"ImagerLat\");\n  ENCAPLULATE_META_DATA_STRING(\"Fan\");\n}\n\nvoid\nVarianProBeamXMLFileReader::CharacterDataHandler(const char * inData, int inLength)\n{\n  for (int i = 0; i < inLength; i++)\n    m_CurCharacterData = m_CurCharacterData + inData[i];\n}\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkWatcherForResourceProbe.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n#include \"rtkWatcherForResourceProbe.h\"\n#include \"rtkGlobalResourceProbe.h\"\n\nnamespace rtk\n{\nWatcherForResourceProbe ::WatcherForResourceProbe(ProcessObject * o)\n{\n  // Initialize state\n  m_Process = o;\n\n  // Create a series of commands\n  m_StartFilterCommand = CommandType::New();\n  m_EndFilterCommand = CommandType::New();\n  m_DeleteFilterCommand = CommandType::New();\n\n  // Assign the callbacks\n  m_StartFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::StartFilter);\n  m_EndFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::EndFilter);\n  m_DeleteFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::DeleteFilter);\n\n  // Add the commands as observers\n  m_StartTag = m_Process->AddObserver(StartEvent(), m_StartFilterCommand);\n  m_EndTag = m_Process->AddObserver(EndEvent(), m_EndFilterCommand);\n  m_DeleteTag = m_Process->AddObserver(DeleteEvent(), m_DeleteFilterCommand);\n}\n\nvoid\nWatcherForResourceProbe ::StartFilter()\n{\n  rtk::GlobalResourceProbe::GetInstance()->Start(m_Process->GetNameOfClass());\n}\n\nvoid\nWatcherForResourceProbe ::EndFilter()\n{\n  rtk::GlobalResourceProbe::GetInstance()->Stop(m_Process->GetNameOfClass());\n}\n\nvoid\nWatcherForResourceProbe ::DeleteFilter()\n{\n  if (m_StartFilterCommand)\n  {\n    m_Process->RemoveObserver(m_StartTag);\n  }\n  if (m_EndFilterCommand)\n  {\n    m_Process->RemoveObserver(m_EndTag);\n  }\n  if (m_DeleteFilterCommand)\n  {\n    m_Process->RemoveObserver(m_DeleteTag);\n  }\n  rtk::GlobalResourceProbe::GetInstance()->Remove(this);\n}\n\nWatcherForResourceProbe ::WatcherForResourceProbe(const WatcherForResourceProbe & watch)\n{\n  // Remove any observers we have on the old process object\n  if (m_Process)\n  {\n    if (m_StartFilterCommand)\n    {\n      m_Process->RemoveObserver(m_StartTag);\n    }\n    if (m_EndFilterCommand)\n    {\n      m_Process->RemoveObserver(m_EndTag);\n    }\n    if (m_DeleteFilterCommand)\n    {\n      m_Process->RemoveObserver(m_DeleteTag);\n    }\n  }\n\n  // Initialize state\n  m_Process = watch.m_Process;\n  m_StartTag = 0;\n  m_EndTag = 0;\n  m_DeleteTag = 0;\n\n  // Create a series of commands\n  if (m_Process)\n  {\n    m_StartFilterCommand = CommandType::New();\n    m_EndFilterCommand = CommandType::New();\n    m_DeleteFilterCommand = CommandType::New();\n\n    // Assign the callbacks\n    m_StartFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::StartFilter);\n    m_EndFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::EndFilter);\n    m_DeleteFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::DeleteFilter);\n\n    // Add the commands as observers\n    m_StartTag = m_Process->AddObserver(StartEvent(), m_StartFilterCommand);\n    m_EndTag = m_Process->AddObserver(EndEvent(), m_EndFilterCommand);\n    m_DeleteTag = m_Process->AddObserver(DeleteEvent(), m_DeleteFilterCommand);\n  }\n}\n\nWatcherForResourceProbe &\nWatcherForResourceProbe ::operator=(const WatcherForResourceProbe & watch)\n{\n  if (this != &watch)\n  {\n    // Remove any observers we have on the old process object\n    if (m_Process)\n    {\n      if (m_StartFilterCommand)\n      {\n        m_Process->RemoveObserver(m_StartTag);\n      }\n      if (m_EndFilterCommand)\n      {\n        m_Process->RemoveObserver(m_EndTag);\n      }\n      if (m_DeleteFilterCommand)\n      {\n        m_Process->RemoveObserver(m_DeleteTag);\n      }\n    }\n\n    // Initialize state\n    m_Process = watch.m_Process;\n\n    m_StartTag = 0;\n    m_EndTag = 0;\n    m_DeleteTag = 0;\n\n    // Create a series of commands\n    if (m_Process)\n    {\n      m_StartFilterCommand = CommandType::New();\n      m_EndFilterCommand = CommandType::New();\n      m_DeleteFilterCommand = CommandType::New();\n\n      // Assign the callbacks\n      m_StartFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::StartFilter);\n      m_EndFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::EndFilter);\n      m_DeleteFilterCommand->SetCallbackFunction(this, &WatcherForResourceProbe::DeleteFilter);\n\n      // Add the commands as observers\n      m_StartTag = m_Process->AddObserver(StartEvent(), m_StartFilterCommand);\n      m_EndTag = m_Process->AddObserver(EndEvent(), m_EndFilterCommand);\n      m_DeleteTag = m_Process->AddObserver(DeleteEvent(), m_DeleteFilterCommand);\n    }\n  }\n  return *this;\n}\n\nWatcherForResourceProbe ::~WatcherForResourceProbe() = default;\n\n} // namespace rtk\n"
  },
  {
    "path": "src/rtkXRadGeometryReader.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n\n#include \"rtkXRadGeometryReader.h\"\n#include \"rtkXRadImageIOFactory.h\"\n\n#include <itkImageIOFactory.h>\n#include <itkMetaDataObject.h>\n\nrtk::XRadGeometryReader ::XRadGeometryReader()\n  : m_Geometry(nullptr)\n{}\n\nvoid\nrtk::XRadGeometryReader ::GenerateData()\n{\n  // Create new RTK geometry object\n  m_Geometry = GeometryType::New();\n  auto tmpGeo = GeometryType::New();\n\n  // Read image information which contains geometry information\n  rtk::XRadImageIOFactory::RegisterOneFactory();\n  itk::ImageIOBase::Pointer reader =\n    itk::ImageIOFactory::CreateImageIO(m_ImageFileName.c_str(), itk::ImageIOFactory::IOFileModeEnum::ReadMode);\n  if (!reader)\n    itkExceptionMacro(<< m_ImageFileName << \" is not an XRad file.\");\n  reader->SetFileName(m_ImageFileName);\n  reader->ReadImageInformation();\n\n  std::string sectionName, paramName;\n  using MetaDataStringType = itk::MetaDataObject<std::string>;\n  itk::MetaDataDictionary & dic = reader->GetMetaDataDictionary();\n\n  for (unsigned int i = 0; i < reader->GetDimensions(2); i++)\n  {\n    std::ostringstream os;\n    os << \"iView3D(Projection \" << i << \")\";\n    sectionName = os.str();\n\n    paramName = sectionName + \"_CBCT.ProjectionGeometryArray.u_axis\";\n    std::istringstream isu(dynamic_cast<MetaDataStringType *>(dic[paramName].GetPointer())->GetMetaDataObjectValue());\n    paramName = sectionName + \"_CBCT.ProjectionGeometryArray.v_axis\";\n    std::istringstream isv(dynamic_cast<MetaDataStringType *>(dic[paramName].GetPointer())->GetMetaDataObjectValue());\n    paramName = sectionName + \"_CBCT.ProjectionGeometryArray.focus\";\n    std::istringstream isfocus(\n      dynamic_cast<MetaDataStringType *>(dic[paramName].GetPointer())->GetMetaDataObjectValue());\n    paramName = sectionName + \"_CBCT.ProjectionGeometryArray.center\";\n    std::istringstream iscenter(\n      dynamic_cast<MetaDataStringType *>(dic[paramName].GetPointer())->GetMetaDataObjectValue());\n    itk::Vector<double, 3> u, v;\n    itk::Vector<double, 3> focus, center;\n    for (unsigned int j = 0; j < 3; j++)\n    {\n      isu >> u[j];\n      isv >> v[j];\n      isfocus >> focus[j];\n      iscenter >> center[j];\n\n      // cm to mm\n      focus[j] *= 10.;\n      center[j] *= 10.;\n    }\n\n    // Change of coordinate system to IEC\n    // The coordinate system of XRad is supposed to be illustrated in figure 1 of\n    // [Clarkson et al, Med Phys, 2011]. Real acquisition of a Playmobil have been\n    // actually used to be sure...\n    u[0] *= -1.;\n    v[0] *= -1.;\n    focus[0] *= -1.;\n    center[0] *= -1;\n    u[2] *= -1.;\n    v[2] *= -1.;\n    focus[2] *= -1.;\n    center[2] *= -1;\n    std::swap(u[1], u[2]);\n    std::swap(v[1], v[2]);\n    std::swap(focus[1], focus[2]);\n    std::swap(center[1], center[2]);\n\n    u.Normalize();\n    v.Normalize();\n    tmpGeo->AddProjection(&(focus[0]), &(center[0]), u, v);\n\n    paramName = sectionName + \"_CBCT.ProjectionGeometryArray.u_off\";\n    std::string suoff = dynamic_cast<MetaDataStringType *>(dic[paramName].GetPointer())->GetMetaDataObjectValue();\n    double      uoff = std::stod(suoff.c_str()) * reader->GetSpacing(0);\n\n    paramName = sectionName + \"_CBCT.ProjectionGeometryArray.v_off\";\n    std::string svoff = dynamic_cast<MetaDataStringType *>(dic[paramName].GetPointer())->GetMetaDataObjectValue();\n    double      voff = std::stod(svoff.c_str()) * reader->GetSpacing(1);\n\n    m_Geometry->AddProjectionInRadians(tmpGeo->GetSourceToIsocenterDistances()[i],\n                                       tmpGeo->GetSourceToDetectorDistances()[i],\n                                       tmpGeo->GetGantryAngles()[i],\n                                       tmpGeo->GetProjectionOffsetsX()[i] - uoff,\n                                       tmpGeo->GetProjectionOffsetsY()[i] - voff,\n                                       tmpGeo->GetOutOfPlaneAngles()[i],\n                                       tmpGeo->GetInPlaneAngles()[i],\n                                       tmpGeo->GetSourceOffsetsX()[i],\n                                       tmpGeo->GetSourceOffsetsY()[i]);\n  }\n}\n"
  },
  {
    "path": "src/rtkXRadImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkXRadImageIO.h\"\n#include <itkMetaDataObject.h>\n#include <itkByteSwapper.h>\n#include <itkRawImageIO.h>\n\n//--------------------------------------------------------------------\n// Read Image Information\nvoid\nrtk::XRadImageIO::ReadImageInformation()\n{\n  std::ifstream is;\n  is.open(m_FileName.c_str());\n\n  if (!is.is_open())\n    itkExceptionMacro(<< \"Could not open file \" << m_FileName);\n\n  SetNumberOfDimensions(3);\n  std::string section = \"\";\n  while (!is.eof())\n  {\n    std::string line;\n    std::getline(is, line);\n    if (line.find('[') != std::string::npos)\n    {\n      unsigned int pos1 = line.find('[');\n      unsigned int pos2 = line.find(']');\n      section = line.substr(pos1 + 1, pos2 - pos1 - 1);\n    }\n    if (line.find('=') != std::string::npos)\n    {\n      unsigned int pos = line.find('=');\n      std::string  paramName = line.substr(0, pos);\n      std::string  paramValue = line.substr(pos + 1, line.length() - pos - 1);\n\n      if (paramName == std::string(\"CBCT.DimensionalAttributes.IDim\"))\n        SetDimensions(0, std::stoi(paramValue.c_str()));\n      else if (paramName == std::string(\"CBCT.DimensionalAttributes.JDim\"))\n        SetDimensions(1, std::stoi(paramValue.c_str()));\n      else if (paramName == std::string(\"CBCT.DimensionalAttributes.KDim\"))\n        SetDimensions(2, std::stoi(paramValue.c_str()));\n      else if (paramName == std::string(\"CBCT.DimensionalAttributes.DataSize\"))\n      {\n        if (std::stoi(paramValue.c_str()) == 3)\n          SetComponentType(itk::ImageIOBase::IOComponentEnum::FLOAT);\n        if (std::stoi(paramValue.c_str()) == 6)\n          SetComponentType(itk::ImageIOBase::IOComponentEnum::USHORT);\n      }\n      else if (paramName == std::string(\"CBCT.DimensionalAttributes.PixelDimension_I_cm\"))\n      {\n        double spacing = 10 * std::stod(paramValue.c_str());\n        SetSpacing(0, (spacing == 0.) ? 1. : spacing);\n      }\n      else if (paramName == std::string(\"CBCT.DimensionalAttributes.PixelDimension_J_cm\"))\n      {\n        double spacing = 10 * std::stod(paramValue.c_str());\n        SetSpacing(1, (spacing == 0.) ? 1. : spacing);\n      }\n      else if (paramName == std::string(\"CBCT.DimensionalAttributes.PixelDimension_K_cm\"))\n      {\n        double spacing = 10 * std::stod(paramValue.c_str());\n        SetSpacing(2, (spacing == 0.) ? 1. : spacing);\n      }\n      else\n      {\n        paramName = section + std::string(\"_\") + paramName;\n        itk::EncapsulateMetaData<std::string>(this->GetMetaDataDictionary(), paramName.c_str(), paramValue);\n      }\n    }\n  }\n} ////\n\n//--------------------------------------------------------------------\n// Read Image Information\nbool\nrtk::XRadImageIO::CanReadFile(const char * FileNameToRead)\n{\n  std::string                  filename(FileNameToRead);\n  const std::string::size_type it = filename.find_last_of(\".\");\n  std::string                  fileExt(filename, it + 1, filename.length());\n\n  if (fileExt != std::string(\"header\"))\n    return false;\n  return true;\n} ////\n\n//--------------------------------------------------------------------\n// Read Image Content\nvoid\nrtk::XRadImageIO::Read(void * buffer)\n{\n  // Adapted from itkRawImageIO\n  std::string rawFileName(m_FileName, 0, m_FileName.size() - 6);\n  rawFileName += \"img\";\n\n  std::ifstream is(rawFileName.c_str(), std::ios::binary);\n  if (!is.is_open())\n    itkExceptionMacro(<< \"Could not open file \" << rawFileName);\n\n  unsigned long numberOfBytesToBeRead = GetComponentSize();\n  for (unsigned int i = 0; i < GetNumberOfDimensions(); i++)\n    numberOfBytesToBeRead *= GetDimensions(i);\n\n  if (!this->ReadBufferAsBinary(is, buffer, numberOfBytesToBeRead))\n  {\n    itkExceptionMacro(<< \"Read failed: Wanted \" << numberOfBytesToBeRead << \" bytes, but read \" << is.gcount()\n                      << \" bytes.\");\n  }\n  itkDebugMacro(<< \"Reading Done\");\n\n  const auto          componentType = this->GetComponentType();\n  const SizeValueType numberOfComponents = this->GetImageSizeInComponents();\n  ReadRawBytesAfterSwapping(componentType, buffer, m_ByteOrder, numberOfComponents);\n}\n\n//--------------------------------------------------------------------\n// Write Image Information\nvoid\nrtk::XRadImageIO::WriteImageInformation(bool itkNotUsed(keepOfStream))\n{}\n\n//--------------------------------------------------------------------\n// Write Image Information\nbool\nrtk::XRadImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n\n//--------------------------------------------------------------------\n// Write Image\nvoid\nrtk::XRadImageIO::Write(const void * itkNotUsed(buffer))\n{} ////\n"
  },
  {
    "path": "src/rtkXRadImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkXRadImageIOFactory.h\"\n\n//====================================================================\nrtk::XRadImageIOFactory::XRadImageIOFactory()\n{\n  this->RegisterOverride(\n    \"itkImageIOBase\", \"XRadImageIO\", \"XRad Image IO\", true, itk::CreateObjectFunction<XRadImageIO>::New());\n}\n\n// Undocumented API used to register during static initialization.\n// DO NOT CALL DIRECTLY.\n\nnamespace itk\n{\n\nstatic bool XRadImageIOFactoryHasBeenRegistered;\n\nvoid RTK_EXPORT\nXRadImageIOFactoryRegister__Private()\n{\n  if (!XRadImageIOFactoryHasBeenRegistered)\n  {\n    XRadImageIOFactoryHasBeenRegistered = true;\n    rtk::XRadImageIOFactory::RegisterOneFactory();\n  }\n}\n\n} // end namespace itk\n"
  },
  {
    "path": "src/rtkXimImageIO.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n// std include\n#include <cstdio>\n#include <numeric>\n\n#include \"rtkXimImageIO.h\"\n#include <itkMetaDataObject.h>\n\n#define PROPERTY_NAME_MAX_LENGTH 256\n\ntemplate <typename T>\nsize_t\nrtk::XimImageIO::SetPropertyValue(char * property_name, Int4 value_length, FILE * fp, Xim_header * xim)\n{\n  T      property_value;\n  T *    unused_property_value = nullptr;\n  size_t addNelements = 0;\n\n  if (value_length > 1)\n  {\n    unused_property_value = new T[value_length];\n    addNelements += fread((void *)unused_property_value, sizeof(T), value_length, fp);\n    delete[] unused_property_value;\n    return addNelements;\n  }\n\n  addNelements += fread((void *)&property_value, sizeof(T), value_length, fp);\n\n  if (strncmp(property_name, \"CouchLat\", 8) == 0)\n    xim->dCouchLat = property_value;\n  else if (strncmp(property_name, \"CouchLng\", 8) == 0)\n    xim->dCouchLng = property_value;\n  else if (strncmp(property_name, \"CouchVrt\", 8) == 0)\n    xim->dCouchVrt = property_value;\n  else if (strncmp(property_name, \"DataOffset\", 10) == 0)\n    xim->nPixelOffset = property_value;\n  else if (strncmp(property_name, \"KVSourceRtn\", 11) == 0)\n    xim->dCTProjectionAngle = property_value;\n  else if (strncmp(property_name, \"KVDetectorLat\", 13) == 0)\n    xim->dDetectorOffsetX = property_value;\n  else if (strncmp(property_name, \"KVDetectorLng\", 13) == 0)\n    xim->dDetectorOffsetY = property_value;\n  else if (strncmp(property_name, \"KVCollimatorX1\", 14) == 0)\n    xim->dCollX1 = property_value;\n  else if (strncmp(property_name, \"KVCollimatorX2\", 14) == 0)\n    xim->dCollX2 = property_value;\n  else if (strncmp(property_name, \"KVCollimatorY1\", 14) == 0)\n    xim->dCollY1 = property_value;\n  else if (strncmp(property_name, \"KVCollimatorY2\", 14) == 0)\n    xim->dCollY2 = property_value;\n  else if (strncmp(property_name, \"KVKiloVolts\", 11) == 0)\n    xim->dXRayKV = property_value;\n  else if (strncmp(property_name, \"KVMilliAmperes\", 14) == 0)\n    xim->dXRayMA = property_value;\n  else if (strncmp(property_name, \"KVNormChamber\", 13) == 0)\n    xim->dCTNormChamber = property_value;\n  else if (strncmp(property_name, \"MMTrackingRemainderX\", 20) == 0)\n    xim->dGating4DInfoX = property_value;\n  else if (strncmp(property_name, \"MMTrackingRemainderY\", 20) == 0)\n    xim->dGating4DInfoY = property_value;\n  else if (strncmp(property_name, \"MMTrackingRemainderZ\", 20) == 0)\n    xim->dGating4DInfoZ = property_value;\n  else if (strncmp(property_name, \"MVCollimatorRtn\", 15) == 0)\n    xim->dCollRtn = property_value;\n  else if (strncmp(property_name, \"MVCollimatorX1\", 14) == 0)\n    xim->dCollX1 = property_value;\n  else if (strncmp(property_name, \"MVCollimatorX2\", 14) == 0)\n    xim->dCollX2 = property_value;\n  else if (strncmp(property_name, \"MVCollimatorY1\", 14) == 0)\n    xim->dCollY1 = property_value;\n  else if (strncmp(property_name, \"MVCollimatorY2\", 14) == 0)\n    xim->dCollY2 = property_value;\n  else if (strncmp(property_name, \"MVDoseRate\", 10) == 0)\n    xim->dDoseRate = property_value;\n  else if (strncmp(property_name, \"MVEnergy\", 8) == 0)\n    xim->dEnergy = property_value;\n  else if (strncmp(property_name, \"PixelHeight\", 11) == 0)\n    xim->dIDUResolutionY = property_value * 10.0;\n  else if (strncmp(property_name, \"PixelWidth\", 10) == 0)\n    xim->dIDUResolutionX = property_value * 10.0;\n  return addNelements;\n}\n\n//--------------------------------------------------------------------\n// Read Image Information\nvoid\nrtk::XimImageIO::ReadImageInformation()\n{\n  Xim_header xim;\n  FILE *     fp = nullptr;\n\n  fp = fopen(m_FileName.c_str(), \"rb\");\n  if (fp == nullptr)\n    itkGenericExceptionMacro(<< \"Could not open file (for reading): \" << m_FileName);\n  size_t nelements = 0;\n  nelements += fread((void *)xim.sFileType, sizeof(char), 8, fp);\n  nelements += fread((void *)&xim.FileVersion, sizeof(Int4), 1, fp);\n  nelements += fread((void *)&xim.SizeX, sizeof(Int4), 1, fp);\n  nelements += fread((void *)&xim.SizeY, sizeof(Int4), 1, fp);\n\n  nelements += fread((void *)&xim.dBitsPerPixel, sizeof(Int4), 1, fp);\n  nelements += fread((void *)&xim.dBytesPerPixel, sizeof(Int4), 1, fp);\n  m_BytesPerPixel = xim.dBytesPerPixel;\n  nelements += fread((void *)&xim.dCompressionIndicator, sizeof(Int4), 1, fp);\n  m_ImageDataStart = ftell(fp);\n  if (xim.dCompressionIndicator == 1)\n  {\n    nelements += fread((void *)&xim.lookUpTableSize, sizeof(Int4), 1, fp);\n    fseek(fp, xim.lookUpTableSize, SEEK_CUR);\n    nelements += fread((void *)&xim.compressedPixelBufferSize, sizeof(Int4), 1, fp);\n    fseek(fp, xim.compressedPixelBufferSize, SEEK_CUR);\n    nelements += fread((void *)&xim.unCompressedPixelBufferSize, sizeof(Int4), 1, fp);\n    if (nelements != /*char*/ 8 + /*Int4*/ 9)\n      itkGenericExceptionMacro(<< \"Could not read header data in \" << m_FileName);\n  }\n  else\n  {\n    nelements += fread((void *)&xim.unCompressedPixelBufferSize, sizeof(Int4), 1, fp);\n    fseek(fp, xim.unCompressedPixelBufferSize, SEEK_CUR);\n    if (nelements != /*char*/ 8 + /*Int4*/ 7)\n      itkGenericExceptionMacro(<< \"Could not read header data in \" << m_FileName);\n  }\n\n  // Histogram Reading:\n  nelements += fread((void *)&xim.binsInHistogram, sizeof(Int4), 1, fp);\n  fseek(fp, xim.binsInHistogram * sizeof(Int4), SEEK_CUR);\n  /* // Replace the two lines above with this if you actually want the histogram:\n  int nhistElements = 0;\n  nhistElements += fread((void *)&xim.binsInHistogram, sizeof(Int4), 1, fp);\n\n  auto xim.histogramData = (int*) malloc(sizeof(int) * xim.binsInHistogram);\n\n  nhistElements += fread((void *)&xim.histogramData, sizeof(Int4), xim.binsInHistogram, fp);\n  if (nhistElements != (xim.binsInHistogram + 1))\n  {\n    itkGenericExceptionMacro(<< \"Could not read histogram from header data in \" << m_FileName);\n  }\n  // free(xim.histogramData); // <- Remember to put this after you are done with the histogram\n  */\n\n  // Properties Readding:\n  nelements += fread((void *)&xim.numberOfProperties, sizeof(Int4), 1, fp);\n  Int4   property_name_length = 0;\n  char   property_name[PROPERTY_NAME_MAX_LENGTH];\n  Int4   property_type = 0;\n  Int4   property_value_length = 0;\n  size_t theoretical_nelements = nelements; // Same as reseting\n\n  for (Int4 i = 0; i < xim.numberOfProperties; i++)\n  {\n    nelements += fread((void *)&property_name_length, sizeof(Int4), 1, fp);\n    if (property_name_length > PROPERTY_NAME_MAX_LENGTH)\n      itkGenericExceptionMacro(<< \"Property name is too long, i.e., \" << property_name_length);\n    nelements += fread((void *)&property_name, sizeof(char), property_name_length, fp);\n    nelements += fread((void *)&property_type, sizeof(Int4), 1, fp);\n    theoretical_nelements += property_name_length + 2;\n\n    switch (property_type)\n    {\n      case 0: // property_value type = uint32\n        nelements += SetPropertyValue<Int4>(property_name, 1, fp, &xim);\n        theoretical_nelements++;\n        break;\n      case 1: // property_value type = double\n        theoretical_nelements++;\n        nelements += SetPropertyValue<double>(property_name, 1, fp, &xim);\n        break;\n      case 2: // property_value type = length * char\n        nelements += fread((void *)&property_value_length, sizeof(Int4), 1, fp);\n        theoretical_nelements += property_value_length + 1;\n        nelements += SetPropertyValue<char>(property_name, property_value_length, fp, &xim);\n        break;\n      case 4: // property_value type = length * double\n        nelements += fread((void *)&property_value_length, sizeof(Int4), 1, fp);\n        nelements += SetPropertyValue<double>(property_name, property_value_length / 8, fp, &xim);\n        theoretical_nelements += property_value_length / 8 + 1;\n        break;\n      case 5: // property_value type = length * uint32\n        nelements += fread((void *)&property_value_length, sizeof(Int4), 1, fp);\n        nelements += SetPropertyValue<Int4>(property_name, property_value_length / 4, fp, &xim);\n        theoretical_nelements += property_value_length / 4 + 1;\n        break;\n      default:\n        std::cout << \"\\n\\nProperty name: \" << property_name << \", type: \" << property_type\n                  << \", is not supported! ABORTING decoding!\";\n        return;\n    }\n  }\n  if (nelements != theoretical_nelements)\n  {\n    std::cout << nelements << \" != \" << theoretical_nelements << std::endl;\n    itkGenericExceptionMacro(<< \"Could not read properties of \" << m_FileName);\n  }\n  if (fclose(fp) != 0)\n    itkGenericExceptionMacro(<< \"Could not close file: \" << m_FileName);\n\n  /* Convert xim to ITK image information */\n  this->SetNumberOfDimensions(2);\n  this->SetDimensions(0, xim.SizeX);\n  this->SetDimensions(1, xim.SizeY);\n\n  this->SetSpacing(0, xim.dIDUResolutionX); // set to PixelHeight/Width\n  this->SetSpacing(1, xim.dIDUResolutionY);\n  this->SetOrigin(0, -0.5 * (xim.SizeX - 1) * xim.dIDUResolutionX); // SR: assumed centered\n  this->SetOrigin(1, -0.5 * (xim.SizeY - 1) * xim.dIDUResolutionY); // SR: assumed centered\n\n  this->SetPixelType(itk::IOPixelEnum::SCALAR);\n  // We need 32 bytes, on many systems UINT seems to work, but on some it may not.\n  auto component_type = itk::ImageIOBase::IOComponentEnum::UINT;\n  SetComponentType(component_type);\n  if (GetComponentSize() < 4)\n  {\n    component_type = itk::ImageIOBase::IOComponentEnum::ULONG;\n    SetComponentType(component_type);\n    if (GetComponentSize() > 4)\n    {\n      itkGenericExceptionMacro(<< \"Could not find a 32bit unsigned integer type\");\n    }\n  }\n\n  /* Store important meta information in the meta data dictionary */\n  if (xim.SizeX * xim.SizeY != 0)\n  {\n    itk::EncapsulateMetaData<double>(this->GetMetaDataDictionary(), \"dCTProjectionAngle\", xim.dCTProjectionAngle);\n    itk::EncapsulateMetaData<double>(\n      this->GetMetaDataDictionary(), \"dDetectorOffsetX\", xim.dDetectorOffsetX * 10.0); // cm->mm Lat\n    itk::EncapsulateMetaData<double>(\n      this->GetMetaDataDictionary(), \"dDetectorOffsetY\", xim.dDetectorOffsetY * 10.0); // cm->mm Lng\n  }\n  else\n  {\n    itk::ImageIORegion ioreg;\n    ioreg.SetIndex(0, 0);\n    ioreg.SetIndex(1, 0);\n    ioreg.SetSize(0, 0);\n    ioreg.SetSize(1, 0);\n    this->SetIORegion(ioreg);\n    unsigned int imdim[] = { 0, 0 };\n    this->Resize(2, imdim);\n    itk::EncapsulateMetaData<double>(this->GetMetaDataDictionary(), \"dCTProjectionAngle\", 6000);\n  }\n}\n//--------------------------------------------------------------------\nbool\nrtk::XimImageIO::CanReadFile(const char * FileNameToRead)\n{\n  std::string                  filename(FileNameToRead);\n  const std::string::size_type it = filename.find_last_of('.');\n  std::string                  fileExt(filename, it + 1, filename.length());\n\n  if (fileExt != std::string(\"xim\"))\n    return false;\n\n  FILE * fp = nullptr;\n  fp = fopen(filename.c_str(), \"rb\");\n  if (fp == nullptr)\n  {\n    std::cerr << \"Could not open file (for reading): \" << m_FileName << std::endl;\n    return false;\n  }\n\n  size_t nelements = 0;\n  char   sfiletype[8];\n  Int4   fileversion = 0, sizex = 0, sizey = 0;\n\n  nelements += fread((void *)&sfiletype[0], sizeof(char), 8, fp);\n  nelements += fread((void *)&fileversion, sizeof(Int4), 1, fp);\n  nelements += fread((void *)&sizex, sizeof(Int4), 1, fp);\n  nelements += fread((void *)&sizey, sizeof(Int4), 1, fp);\n\n  if (nelements != 8 + 3)\n  {\n    std::cerr << \"Could not read initial header data in \" << m_FileName << std::endl;\n    fclose(fp);\n    return false;\n  }\n  if (sizex * sizey <= 0)\n  {\n    std::cerr << \"Imagedata was of size (x, y)=(\" << sizex << \", \" << sizey << \") in \" << filename << std::endl;\n    fclose(fp);\n    return false;\n  }\n\n  if (fclose(fp) != 0)\n  {\n    std::cerr << \"Could not close file (after reading): \" << m_FileName << std::endl;\n    return false;\n  }\n\n  return true;\n}\n\n//--------------------------------------------------------------------\ntemplate <typename T>\ninline T\nload_binary_char_as(const unsigned char * bin_vals, const size_t n_bytes)\n{\n  T tmp_val;\n  std::memcpy(&tmp_val, bin_vals, n_bytes);\n  return tmp_val;\n}\n\ntemplate <typename T>\ninline T\ncast_binary_char_to(const unsigned char * bin_vals, const size_t n_bytes)\n{\n  T out_val = 0;\n  switch (n_bytes)\n  {\n    case 1:\n      out_val = static_cast<T>(load_binary_char_as<int8_t>(bin_vals, n_bytes));\n      break;\n    case 2:\n      out_val = static_cast<T>(load_binary_char_as<int16_t>(bin_vals, n_bytes));\n      break;\n    case 4:\n      out_val = static_cast<T>(load_binary_char_as<int32_t>(bin_vals, n_bytes));\n      break;\n  }\n  return out_val;\n}\n\ninline size_t\nlut_to_bytes(const char val)\n{\n  switch (val)\n  {\n    case 0:\n      return 1;\n    case 1:\n      return 2;\n    case 2:\n      return 4;\n    default: // only 0, 1 & 2 should be possible\n      return 8;\n  }\n}\n\n// Read Image Content\nvoid\nrtk::XimImageIO::Read(void * buffer)\n{\n  FILE * fp = nullptr;\n  // Long is only garanteed to be AT LEAST 32 bits, it could be 64 bit\n  Int4 * buf = (Int4 *)buffer;\n\n  fp = fopen(m_FileName.c_str(), \"rb\");\n  if (fp == nullptr)\n    itkGenericExceptionMacro(<< \"Could not open file (for reading): \" << m_FileName);\n\n  if (fseek(fp, m_ImageDataStart, SEEK_SET) != 0)\n    itkGenericExceptionMacro(<< \"Could not seek to image data in: \" << m_FileName);\n\n  Int4 lookUpTableSize = 0;\n  // De\"compress\" image\n  if (1 != fread((void *)&lookUpTableSize, sizeof(Int4), 1, fp))\n  {\n    itkGenericExceptionMacro(<< \"Could not read LUT size from: \" << m_FileName);\n  }\n  auto m_lookup_table = std::vector<unsigned char>(lookUpTableSize);\n  if (lookUpTableSize != (Int4)fread((void *)&m_lookup_table[0], sizeof(unsigned char), lookUpTableSize, fp))\n  {\n    itkGenericExceptionMacro(<< \"Could not read lookup table from Xim file: \" << m_FileName);\n  }\n\n  Int4 compressedPixelBufferSize = 0;\n  if (1 != fread((void *)&compressedPixelBufferSize, sizeof(Int4), 1, fp))\n  {\n    itkGenericExceptionMacro(<< \"Could not get compressed pixel buffer size from: \" << m_FileName);\n  }\n\n  const auto xdim = GetDimensions(0);\n  const auto ydim = GetDimensions(1);\n  if (xdim * ydim == 0)\n  {\n    itkGenericExceptionMacro(<< \"Dimensions of image was 0 in: \" << m_FileName);\n  }\n\n  if ((xdim + 1) != fread(&buf[0], sizeof(Int4), xdim + 1, fp))\n    itkGenericExceptionMacro(<< \"Could not read first row +1 in: \" << m_FileName);\n\n  std::vector<unsigned char> byte_table(lookUpTableSize);\n  std::transform(m_lookup_table.begin(), m_lookup_table.end(), byte_table.begin(), [](const unsigned char & v) {\n    unsigned char bytes = 0;\n    bytes += lut_to_bytes(v & 0b00000011);        // 0x03\n    bytes += lut_to_bytes((v & 0b00001100) >> 2); // 0x0C\n    bytes += lut_to_bytes((v & 0b00110000) >> 4); // 0x30\n    bytes += lut_to_bytes((v & 0b11000000) >> 6); // 0xC0\n    return bytes;\n  });\n\n  const auto total_bytes = std::accumulate(std::begin(byte_table), std::end(byte_table), 0ull);\n\n  auto compr_img_buffer = std::vector<unsigned char>(total_bytes);\n  // total_bytes - 3 because the last two bits can be redundant (according to Xim docs)\n  if ((total_bytes - 3) > fread((void *)&compr_img_buffer[0], sizeof(unsigned char), total_bytes, fp))\n  {\n    itkGenericExceptionMacro(<< \"Could not read image buffer of Xim file: \" << m_FileName);\n  }\n\n  size_t j = 0U;\n  size_t i = xdim;\n  size_t iminxdim = 0;\n\n  for (auto lut_idx = 0U; lut_idx < static_cast<size_t>(lookUpTableSize); ++lut_idx)\n  {\n    const auto v = m_lookup_table[lut_idx];\n    auto       bytes = lut_to_bytes(v & 0b00000011); // 0x03\n    assert(bytes == 1 || bytes == 2 || bytes == 4);\n    auto diff1 = cast_binary_char_to<long long>(&compr_img_buffer[j], bytes);\n    j += bytes;\n\n    bytes = lut_to_bytes((v & 0b00001100) >> 2); // 0x0C\n    assert(bytes == 1 || bytes == 2 || bytes == 4);\n    auto diff2 = cast_binary_char_to<long long>(&compr_img_buffer[j], bytes);\n    j += bytes;\n\n    bytes = lut_to_bytes((v & 0b00110000) >> 4); // 0x30\n    assert(bytes == 1 || bytes == 2 || bytes == 4);\n    auto diff3 = cast_binary_char_to<long long>(&compr_img_buffer[j], bytes);\n    j += bytes;\n\n    bytes = lut_to_bytes((v & 0b11000000) >> 6); // 0xC0\n    assert(bytes == 1 || bytes == 2 || bytes == 4);\n    auto diff4 = cast_binary_char_to<long long>(&compr_img_buffer[j], bytes);\n    j += bytes;\n\n    buf[i + 1] = static_cast<Int4>(diff1 + buf[i] + buf[iminxdim + 1] - buf[iminxdim]);\n    buf[i + 2] = static_cast<Int4>(diff2 + buf[i + 1] + buf[iminxdim + 2] - buf[iminxdim + 1]);\n    buf[i + 3] = static_cast<Int4>(diff3 + buf[i + 2] + buf[iminxdim + 3] - buf[iminxdim + 2]);\n    if (i + 4 < xdim * ydim)\n    {\n      buf[i + 4] = static_cast<Int4>(diff4 + buf[i + 3] + buf[iminxdim + 4] - buf[iminxdim + 3]);\n    }\n\n    i += 4;\n    iminxdim += 4;\n  }\n\n  assert(j == total_bytes);\n  assert(i == (xdim * ydim));\n\n  if (fclose(fp) != 0)\n    itkGenericExceptionMacro(<< \"Could not close file: \" << m_FileName);\n}\n\n//--------------------------------------------------------------------\nbool\nrtk::XimImageIO::CanWriteFile(const char * itkNotUsed(FileNameToWrite))\n{\n  return false;\n}\n\n//--------------------------------------------------------------------\n// Write Image\nvoid\nrtk::XimImageIO::Write(const void * itkNotUsed(buffer))\n{\n  // TODO?\n}\n"
  },
  {
    "path": "src/rtkXimImageIOFactory.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkXimImageIOFactory.h\"\n\n#include <fstream>\n\n//====================================================================\nrtk::XimImageIOFactory::XimImageIOFactory()\n{\n  this->RegisterOverride(\n    \"itkImageIOBase\", \"XimImageIO\", \"Xim Image IO\", true, itk::CreateObjectFunction<XimImageIO>::New());\n}\n\n// Undocumented API used to register during static initialization.\n// DO NOT CALL DIRECTLY.\n\nnamespace itk\n{\n\nstatic bool XimImageIOFactoryHasBeenRegistered;\n\nvoid RTK_EXPORT\nXimImageIOFactoryRegister__Private()\n{\n  if (!XimImageIOFactoryHasBeenRegistered)\n  {\n    XimImageIOFactoryHasBeenRegistered = true;\n    rtk::XimImageIOFactory::RegisterOneFactory();\n  }\n}\n\n} // end namespace itk\n"
  },
  {
    "path": "test/Baseline/AmsterdamShroud/Amsterdam.mha.sha512",
    "content": "b676ecddf852315bc54a1c102dd93b1807371f2ecefdd0bc12edd5b128f0dad82e8476deed0074903c719325269287090942a4340764e42befac5692794152cd\n"
  },
  {
    "path": "test/Baseline/AmsterdamShroud/Amsterdam_crop.mha.sha512",
    "content": "b778fac482babff2e3dd59227606085f507473eab36e5398884dd2c38016017158f267b81690d478985d8070e44850cd022892724400c250bf0b7a001edf05c9\n"
  },
  {
    "path": "test/Baseline/Bioscan/geometry.xml.sha512",
    "content": "52639218df6ae671d9701f77c6c157891fcd6683f6b368c602af95e39b14b636dd21c9a971c44286dceba65f650f5994932fb37846f31111ecbcbc5f23c32285\n"
  },
  {
    "path": "test/Baseline/Digisens/attenuation.mha.sha512",
    "content": "a1110781e9c866bbf59f147e0dc664a0ef885999bf386607ffef6e7154c5d4fb9c06100c0753c8e2b34dbdaabf76b7b570d92b746c4e6dfa562acbf173aa15a3\n"
  },
  {
    "path": "test/Baseline/Digisens/geometry.xml.sha512",
    "content": "4909e61ccf98f292154b311b4511623f59070bb01cac1b7493260cf2a230484454be76f0e2258bc6e179235a0dd357a625de143184c296472dc228b127e48f56\n"
  },
  {
    "path": "test/Baseline/ESRF/attenuation.mha.sha512",
    "content": "5cb2e041c13bd2d5f03314da5b974e66762224c94dfaffc4fefde79ea6158735b1eaa07a3594cea0d28494dd124b6bde32323554ecc9ef71c31a675c330dc525\n"
  },
  {
    "path": "test/Baseline/Elekta/attenuation.mha.sha512",
    "content": "2cc6fda3b4b4fe3ef99d42d61caaca4a74278db6ad515a6ad976cde62511b9531bb85c2e92ae767035b7c12df844ab60524bdfa41fe23cc170f2e8d8d047e264\n"
  },
  {
    "path": "test/Baseline/Elekta/geometry.xml.sha512",
    "content": "2ef0f22bdcfd8019e8ea1c460c8dc5c7c2fcae42382a098edc3aab8ad613f19de929c5ec91e9d272c5039ea0e68433d245376941c638ae5bdf3b7602b624ad20\n"
  },
  {
    "path": "test/Baseline/Elekta/geometry5.xml.sha512",
    "content": "83a5e9670654442b35c24947dba4de7cde62ba6ba03da75e17b2ae39234a622f49dcf9463dd9bad496a71ec0761d23ff77f1780166158b717017f0a04f3805d5\n"
  },
  {
    "path": "test/Baseline/ImagX/attenuation.mha.sha512",
    "content": "53851357df0689a5b799dac03a8d80a8425906ebc5b5aab26337ee1b7bb8ffb331f2939fc38881dff33baa859502ebb3c4f59ad4db49d6392818835c53cd697e\n"
  },
  {
    "path": "test/Baseline/ImagX/attenuationDCM.mha.sha512",
    "content": "cd2d38c23c7444a5d5b3771f2d646431ac46fc86ef2c58ef7c03be7802bcd1c690c9e67e6bbcea53070b950b8f4b9335fb51e9c569d236708734c79f93f1df57\n"
  },
  {
    "path": "test/Baseline/ImagX/geo.xml.sha512",
    "content": "274c57224b13ab045d20f05202f7c68083293f8d446f8cba3fa6395ac9baafc1322f180150df44e48f53b9a52f24dc09ceee27708d033f95da9c675236451238\n"
  },
  {
    "path": "test/Baseline/Laplacian/Laplacian.mha.sha512",
    "content": "3fb1da009399645abafc6656f558249049fe28a448639346728aede004e9dd8582c209629708e46987980d86211f8b58e8e4d3f2f5e0c9f924d5734539f6051c\n"
  },
  {
    "path": "test/Baseline/Ora/attenuation.mha.sha512",
    "content": "99ecb36973b88a8166e849419d8c23155abb10ad9a023bb006f5f6608e765b41dc019fa87332078efbcd8110bdcd0dd73d726656da29a06d8f2289d9c98e4ed4\n"
  },
  {
    "path": "test/Baseline/Ora/geometry.xml.sha512",
    "content": "147b423ee00c22a35924b9da159ca91b8752a7b592f0cb9bbca344ca18543ed00d1fc053e73eb164e15ff3134a18419f3ea780745da93be866717797da1719fe\n"
  },
  {
    "path": "test/Baseline/Ora/geometry_optitrack.xml.sha512",
    "content": "5bab8df7a936505c56a94881b266791e65d4c4fde6a3ea96043efdb7f8a2a37ecb482d1b7158e843be2d0ee16878df4a3c6c97e7f61369b29334d86422b4f06c\n"
  },
  {
    "path": "test/Baseline/Ora/geometry_yawtilt.xml.sha512",
    "content": "9f56034b740d0765a507ee3a0d8dc7467cb569f35f80d737b11077d5ffd0f426b3e8d079e73658e19d278890a89ab746a6b85fdb7c86a035fbfce863947e2bbd\n"
  },
  {
    "path": "test/Baseline/Spectral/OneStep/newtonUpdate.mha.sha512",
    "content": "414e4d8a6b6fc7e484dc67f4d06baaa6e6daf0c4ac0ee9ddd3dfc48b9938635974f0a3a836f0cb8d674f5fa487dd18d3ed0a2db15705b232b516e76abafd7597\n"
  },
  {
    "path": "test/Baseline/Spectral/OneStep/out1.mha.sha512",
    "content": "6232d71a944ae3f464631ac26877e23c15099aebffe5340fce0192e5b71f98d9dc1d869afd891dc18389c0dabd08ea0c43428771abae605d18f4dcaceddb0b18\n"
  },
  {
    "path": "test/Baseline/Spectral/OneStep/out2.mha.sha512",
    "content": "43e3e3b5ac9c5c9eca2d69bb47b422e00f74f2ffabdb5a279580d858f0e042ad587d302ac0ae4d3b3896a214e19a43827ffe37a263b0c363bcc207dfd483aa3b\n"
  },
  {
    "path": "test/Baseline/Varian/attenuation.mha.sha512",
    "content": "f9f53b00f34ed5304088ab17a37e120ec98f32c7311be345c8ef0ee79e6e36807d1243ab9f6d8c93d8127feecae7d8061c3e32372aaf0dbc6d36cab9f8ee399a\n"
  },
  {
    "path": "test/Baseline/Varian/attenuationHnc.mha.sha512",
    "content": "6f25f2a5c495c874ce2827a011767dcbd6b7ef7825077963942ec4f2c058722795fde99b0335f2701673a1a4aea00deedd97689de2ba8862e6facb24915e898a\n"
  },
  {
    "path": "test/Baseline/Varian/attenuationProBeam.mha.sha512",
    "content": "8bcade37661a8f924a0f0446905ba262dc97dc1557a1912be328faabbb0013c2ab39d3f84a3fbbcfc0fb728a619dd7cda695229dbc858aa0ed09a5ee50cfdfce\n"
  },
  {
    "path": "test/Baseline/Varian/geometry.xml.sha512",
    "content": "b1c00fea4660d0cace9bbbc1b4e85517941b485881c3a03dc7c0351a3c532e355d20f79996cf6204b5dc70478a2dc32366a106a3f7fe653de20ce774125d37f6\n"
  },
  {
    "path": "test/Baseline/Varian/geometryHnc.xml.sha512",
    "content": "ca24856acf5b42cfb331f6428b4535036f548d77f8a5af4f4f53c15ddc333c824f8bcb8a5885ba7071aa26ec5a2d5564f18a5a5a44e3a1d7c36e7b080dc36bc5\n"
  },
  {
    "path": "test/Baseline/Varian/geometryProBeam.xml.sha512",
    "content": "854756ff7fc68c29a47dd304c068ec119d92c305553eeabd9137f4bb3395d43e1508e360f1ef0091c87068741cd87ffb1e863d98b1c679425eb12f0446ae7943\n"
  },
  {
    "path": "test/Baseline/XRad/attenuation.mha.sha512",
    "content": "c10191048355a89161dd64fc2a8b4dc1922cced0080cce9b40a6d9f0b5d82f42ee25ecb0d49a087c52dabe2cb532a1486fcce3fc213260fa3748da410e4e9680\n"
  },
  {
    "path": "test/Baseline/XRad/geometry.xml.sha512",
    "content": "ab8e49cbbdf164e8c5a2a25a15c44a6a394a79e7a7f879c5daea89bd4469bffd0dee1e65fd06607dcfea437b30d34a2f9f37f31d5a1b7e40450177a167f5ca51\n"
  },
  {
    "path": "test/CMakeLists.txt",
    "content": "configure_file (${CMAKE_CURRENT_SOURCE_DIR}/rtkTestConfiguration.h.in\n  ${RTK_BINARY_DIR}/include/rtkTestConfiguration.h)\n\n#-----------------------------------------------------------------------------\n# Find ITK.\n# Required to include ITK_USE_FILE in order to Register IO factories\n# Force requested modules to be RTK dependencies only, otherwise all\n# available factories will try to register themselves.\nif (NOT ITK_DIR)\n  set(ITK_DIR ${ITK_BINARY_DIR}/CMakeTmp)\nendif()\nfind_package(ITK REQUIRED COMPONENTS ${ITK_MODULE_RTK_DEPENDS})\ninclude(${ITK_USE_FILE})\n\n#-----------------------------------------------------------------------------\n# rtk_add_test(testname testfile [DATA{}])\n# Add regular test as opposed to tests depending on CUDA\nfunction(rtk_add_test testname testfile)\n  add_executable(${testname} ${testfile})\n  target_link_libraries( ${testname} ${RTK_LIBRARIES} ${ITK_LIBRARIES})\n  itk_add_test(NAME ${testname}\n    COMMAND itkTestDriver\n    $<TARGET_FILE:${testname}>\n    ${ARGN})\nendfunction()\n\n#-----------------------------------------------------------------------------\n# rtk_add_cuda_test(testname testfile [DATA{}])\n# Add test depending on CUDA\nfunction(rtk_add_cuda_test testname testfile)\n  if(RTK_USE_CUDA)\n    add_executable(${testname} ${testfile})\n    target_link_libraries( ${testname} ${RTK_LIBRARIES} ${ITK_LIBRARIES})\n    itk_add_test(NAME ${testname}\n      COMMAND itkTestDriver\n      $<TARGET_FILE:${testname}>\n      ${ARGN})\n    set_target_properties(${testname} PROPERTIES COMPILE_FLAGS -DUSE_CUDA)\n  endif()\nendfunction()\n\n\nitk_module_test()\n\n# Use sha512 algorithm to generate content link\nif(NOT ITK_SOURCE_DIR)\n  set(ExternalData_LINK_CONTENT SHA512)\nendif()\n\nrtk_add_test(rtkFDKTest rtkfdktest.cxx)\nrtk_add_cuda_test(rtkFDKCudaTest rtkfdktest.cxx)\n\nrtk_add_cuda_test(rtkFDKProjWeightCompCudaTest rtkfdkprojweightcompcudatest.cxx)\n\nrtk_add_test(rtkFBPParallelTest rtkfbpparalleltest.cxx)\n\nrtk_add_test(rtkImportTest rtkimporttest.cxx)\nrtk_add_cuda_test(rtkImportCudaTest rtkimporttest.cxx)\n\nrtk_add_cuda_test(rtkCropFilterCudaTest rtkcroptest.cxx)\n\nrtk_add_test(rtkMotionCompensatedFDKTest rtkmotioncompensatedfdktest.cxx)\n\nrtk_add_test(rtkDisplacedDetectorTest rtkdisplaceddetectortest.cxx)\nrtk_add_cuda_test(rtkDisplacedDetectorCudaTest rtkdisplaceddetectortest.cxx)\nrtk_add_cuda_test(rtkDisplacedDetectorCompCudaTest rtkdisplaceddetectorcompcudatest.cxx)\n\nrtk_add_test(rtkDisplacedDetectorCompOffsetTest rtkdisplaceddetectorcompoffsettest.cxx)\n\nrtk_add_test(rtkShortScanTest rtkshortscantest.cxx)\nrtk_add_cuda_test(rtkShortScanCudaTest rtkshortscantest.cxx)\nrtk_add_cuda_test(rtkShortScanCompCudaTest rtkshortscancompcudatest.cxx)\n\nrtk_add_test(rtkRampFilterTest rtkrampfiltertest.cxx)\nrtk_add_cuda_test(rtkRampFilterCudaTest rtkrampfiltertest.cxx)\n\nrtk_add_test(rtkRampFilterTest2 rtkrampfiltertest2.cxx)\nrtk_add_cuda_test(rtkRampFilterCudaTest2 rtkrampfiltertest2.cxx)\n\nrtk_add_test(rtkHilbertFilterTest rtkhilbertfiltertest.cxx)\n\nrtk_add_test(rtkScatterGlareFilterTest rtkscatterglarefiltertest.cxx)\nrtk_add_cuda_test(rtkScatterGlareFilterCudaTest rtkscatterglarefiltertest.cxx)\n\nrtk_add_test(rtkScatterGlareFilterNoFFTWTest rtkscatterglarefiltertest.cxx)\n\nrtk_add_test(rtkGainCorrectionTest rtkgaincorrectiontest.cxx)\nrtk_add_cuda_test(rtkGainCorrectionCudaTest rtkgaincorrectiontest.cxx)\n\nrtk_add_test(rtkForwardProjectionTest rtkforwardprojectiontest.cxx)\nrtk_add_cuda_test(rtkForwardProjectionCudaTest rtkforwardprojectiontest.cxx)\nrtk_add_test(rtkForwardAttenuatedProjectionTest rtkforwardattenuatedprojectiontest.cxx)\nrtk_add_test(rtkZengProjectionTest rtkzengforwardprojectiontest.cxx)\nrtk_add_test(rtkMaximumIntensityProjectionTest rtkmaximumintensityprojectiontest.cxx)\n\nrtk_add_test(rtkGeometryFileTest rtkgeometryfiletest.cxx)\n\nrtk_add_test(rtkReg23ProjectionGeometryTest rtkTestReg23ProjectionGeometry.cxx)\n\nrtk_add_test(rtkFOVTest rtkfovtest.cxx)\n\nrtk_add_test(rtkBinningTest rtkbinningtest.cxx)\n\nrtk_add_test(rtkl0GradientNormTest rtkl0gradientnormtest.cxx)\n\nrtk_add_test(rtkWaterPreCorrectionTest rtkwaterprecorrectiontest.cxx)\n\nrtk_add_test(rtkLUTBasedVarI0RawToAttTest rtklutbasedvarI0rawtoatttest.cxx)\n\nrtk_add_test(rtkDecomposeSpectralProjectionsTest rtkdecomposespectralprojectionstest.cxx\n  DATA{Input/Spectral/no_vector_incident_spectrum.mha}\n  DATA{Input/Spectral/detector_response.mha}\n  DATA{Input/Spectral/material_attenuations.mha}\n  DATA{Input/Spectral/incident_spectrum.mha})\n\nrtk_add_test(rtkSpectralOneStepTest rtkspectralonesteptest.cxx\n  DATA{Input/Spectral/OneStep/no_vector_incident_spectrum_64_rows.mha}\n  DATA{Input/Spectral/OneStep/incident_spectrum_64_rows.mha}\n  DATA{Input/Spectral/detector_response.mha}\n  DATA{Input/Spectral/material_attenuations.mha})\n\nrtk_add_test(rtkVectorImageConvertersTest rtkvectorimageconverterstest.cxx)\n\nrtk_add_test(rtkAmsterdamShroudTest rtkamsterdamshroudtest.cxx\n  DATA{Baseline/AmsterdamShroud/Amsterdam_crop.mha}\n  DATA{Baseline/AmsterdamShroud/Amsterdam.mha})\n\nrtk_add_test(rtkVarianTest rtkvariantest.cxx\n  DATA{Input/Varian/raw.hnd}\n  DATA{Input/Varian/acqui.xml}\n  DATA{Input/Varian/Proj_00000.xim}\n  DATA{Input/Varian/acqui_probeam.xml}\n  DATA{Input/Varian/image_00052.hnc}\n  DATA{Baseline/Varian/geometry.xml}\n  DATA{Baseline/Varian/attenuation.mha}\n  DATA{Baseline/Varian/geometryProBeam.xml}\n  DATA{Baseline/Varian/attenuationProBeam.mha}\n  DATA{Baseline/Varian/geometryHnc.xml}\n  DATA{Baseline/Varian/attenuationHnc.mha})\n\nrtk_add_test(rtkElektaTest rtkelektatest.cxx\n  DATA{Input/Elekta/IMAGE.DBF}\n  DATA{Input/Elekta/FRAME.DBF}\n  DATA{Input/Elekta/raw.his}\n  DATA{Input/Elekta/_Frames.xml}\n  DATA{Baseline/Elekta/geometry.xml}\n  DATA{Baseline/Elekta/attenuation.mha}\n  DATA{Baseline/Elekta/geometry5.xml})\n\nrtk_add_test(rtkLUTTest rtkluttest.cxx\n  DATA{Input/Elekta/raw.his}\n  DATA{Baseline/Elekta/attenuation.mha})\n\nrtk_add_test(rtkImagXTest rtkimagxtest.cxx\n  DATA{Input/ImagX/1.dcm}\n  DATA{Input/ImagX/calibration.xml}\n  DATA{Input/ImagX/room.xml}\n  DATA{Input/ImagX/raw.xml,raw.raw}\n  DATA{Baseline/ImagX/geo.xml}\n  DATA{Baseline/ImagX/attenuation.mha}\n  DATA{Baseline/ImagX/attenuationDCM.mha})\n\nrtk_add_test(rtkEdfTest rtkedftest.cxx\n  DATA{Input/ESRF/raw.edf,dark.edf,refHST0000.edf}\n  DATA{Baseline/ESRF/attenuation.mha})\n\nrtk_add_test(rtkDigisensTest rtkdigisenstest.cxx\n  DATA{Input/Digisens/calibration.cal}\n  DATA{Input/Digisens/ima0010.tif}\n  DATA{Baseline/Digisens/geometry.xml}\n  DATA{Baseline/Digisens/attenuation.mha})\n\nrtk_add_test(rtkXRadTest rtkxradtest.cxx\n  DATA{Input/XRad/SolidWater_HiGain1x1.header}\n  DATA{Input/XRad/SolidWater_HiGain1x1_firstProj.header,flat.header,flat.img,dark.header,dark.img,SolidWater_HiGain1x1_firstProj.img}\n  DATA{Baseline/XRad/geometry.xml}\n  DATA{Baseline/XRad/attenuation.mha})\n\nrtk_add_test(rtkProjectGeometricPhantomTest rtkprojectgeometricphantomtest.cxx\n  DATA{Input/GeometricPhantom/SheppLogan_forbild.txt})\n\nrtk_add_test(rtkDrawGeometricPhantomTest rtkdrawgeometricphantomtest.cxx\n  DATA{Input/GeometricPhantom/SheppLogan_forbild.txt}\n  DATA{Input/GeometricPhantom/Geometries_Forbild.txt})\n\nrtk_add_test(rtkWeidingerForwardModelTest rtkweidingerforwardmodeltest.cxx\n  DATA{Input/Spectral/OneStep/materialProjections.mha}\n  DATA{Input/Spectral/OneStep/photonCounts.mha}\n  DATA{Input/Spectral/OneStep/spectrum.mha}\n  DATA{Input/Spectral/OneStep/projOfOnes.mha}\n  DATA{Input/Spectral/OneStep/binnedDetectorResponse.csv}\n  DATA{Input/Spectral/OneStep/materialAttenuations.csv}\n  DATA{Baseline/Spectral/OneStep/out1.mha}\n  DATA{Baseline/Spectral/OneStep/out2.mha})\n\nrtk_add_test(rtkNewtonUpdateTest rtknewtonupdatetest.cxx\n  DATA{Input/Spectral/OneStep/gradient.mha}\n  DATA{Input/Spectral/OneStep/hessian.mha}\n  DATA{Baseline/Spectral/OneStep/newtonUpdate.mha})\n\nrtk_add_test(rtkSartTest rtksarttest.cxx)\nrtk_add_cuda_test(rtkSartCudaTest rtksarttest.cxx)\n\nrtk_add_test(rtkOsemTest rtkosemtest.cxx)\nrtk_add_cuda_test(rtkOsemCudaTest rtkosemtest.cxx)\n\nrtk_add_test(rtkFourDSartTest rtkfourdsarttest.cxx)\nrtk_add_cuda_test(rtkFourDSartCudaTest rtkfourdsarttest.cxx)\n\nrtk_add_test(rtkFourDConjugateGradientTest rtkfourdconjugategradienttest.cxx)\nrtk_add_cuda_test(rtkFourDConjugateGradientCudaTest rtkfourdconjugategradienttest.cxx)\n\nrtk_add_test(rtkWarpFourDToProjectionStackTest rtkwarpfourdtoprojectionstacktest.cxx)\nrtk_add_cuda_test(rtkWarpFourDToProjectionStackCudaTest rtkwarpfourdtoprojectionstacktest.cxx)\n\nrtk_add_test(rtkWarpProjectionStackToFourDTest rtkwarpprojectionstacktofourdtest.cxx)\nrtk_add_cuda_test(rtkWarpProjectionStackToFourDCudaTest rtkwarpprojectionstacktofourdtest.cxx)\n\nrtk_add_test(rtkCylindricalDetectorReconstructionTest rtkcylindricaldetectorreconstructiontest.cxx)\nrtk_add_cuda_test(rtkCylindricalDetectorReconstructionCudaTest rtkcylindricaldetectorreconstructiontest.cxx)\n\n\nrtk_add_test(rtkAdjointOperatorsTest rtkadjointoperatorstest.cxx)\nrtk_add_cuda_test(rtkAdjointOperatorsCudaTest rtkadjointoperatorstest.cxx)\n\nrtk_add_test(rtkFourDAdjointOperatorsTest rtkfourdadjointoperatorstest.cxx\n  DATA{Input/Phases/phases_slow.txt})\n\nrtk_add_test(rtkInterpolateSplatAdjointTest rtkinterpolatesplatadjointtest.cxx\n  DATA{Input/Phases/phases_slow.txt})\n\nrtk_add_test(rtkLaplacianTest rtklaplaciantest.cxx\n  DATA{Baseline/Laplacian/Laplacian.mha})\nrtk_add_cuda_test(rtkLaplacianCudaTest rtklaplaciantest.cxx\n  DATA{Baseline/Laplacian/Laplacian.mha})\n\nrtk_add_test(rtkTotalVariationTest rtktotalvariationtest.cxx)\n\nrtk_add_test(rtkGradientTest rtkgradienttest.cxx)\n\nrtk_add_test(rtkDivergenceTest rtkdivergencetest.cxx)\n\nrtk_add_test(rtkLagCorrectionTest rtklagcorrectiontest.cxx)\nrtk_add_cuda_test(rtkLagCorrectionCudaTest rtklagcorrectiontest.cxx)\n\nrtk_add_test(rtkConjugateGradientTest rtkconjugategradienttest.cxx)\n\nrtk_add_test(rtkWarpTest rtkwarptest.cxx)\n\nrtk_add_test(rtkI0EstimationTest rtkI0estimationtest.cxx)\n\nrtk_add_test(rtkSelectOneProjPerCycleTest rtkselectoneprojpercycletest.cxx)\n\n# We cannot compile these tests using CPU if GPU is present\n# This is because of rtkIterativeConeBeamReconstructionFilter\nif(NOT RTK_USE_CUDA)\n  rtk_add_test(rtkIterativeFDKTest rtkiterativefdktest.cxx)\n\n  rtk_add_test(rtkConjugateGradientReconstructionTest rtkconjugategradientreconstructiontest.cxx)\n\n  rtk_add_test(rtkFourDRoosterTest rtkfourdroostertest.cxx)\n\n  rtk_add_test(rtkADMMWaveletsTest rtkadmmwaveletstest.cxx)\n\n  rtk_add_test(rtkADMMTotalVariationTest rtkadmmtotalvariationtest.cxx\n    DATA{Input/Phases/phases.txt}\n    DATA{Input/Phases/phases_3projs.txt})\n\n  rtk_add_test(rtkRegularizedConjugateGradientTest rtkregularizedconjugategradienttest.cxx)\n\n  rtk_add_test(rtkCyclicDeformationTest rtkcyclicdeformationtest.cxx)\nendif()\n\nrtk_add_cuda_test(rtkIterativeFDKCudaTest rtkiterativefdktest.cxx)\nrtk_add_cuda_test(rtkConjugateGradientReconstructionCudaTest rtkconjugategradientreconstructiontest.cxx)\nrtk_add_cuda_test(rtkFourDRoosterCudaTest rtkfourdroostertest.cxx)\nrtk_add_cuda_test(rtkADMMWaveletsCudaTest rtkadmmwaveletstest.cxx)\nrtk_add_cuda_test(rtkADMMTotalVariationCudaTest rtkadmmtotalvariationtest.cxx\n  DATA{Input/Phases/phases.txt}\n  DATA{Input/Phases/phases_3projs.txt})\nrtk_add_cuda_test(rtkRegularizedConjugateGradientCudaTest rtkregularizedconjugategradienttest.cxx)\nrtk_add_cuda_test(rtkCudaRaycastAdjointOperatorsCudaTest rtkcudaraycastadjointoperatorstest.cxx)\nrtk_add_cuda_test(rtkCyclicDeformationCudaTest rtkcyclicdeformationtest.cxx)\n\nrtk_add_test(rtkWaveletsTest rtkwaveletstest.cxx)\n\n# Test the manager used to automatically clean up the gengetopt args_info structures\nrtk_add_test(rtkArgsInfoManagerTest rtkargsinfomanagertest.cxx)\n\nrtk_add_test(rtkGeometryCloneTest rtkgeometryclonetest.cxx)\nrtk_add_test(rtkGeometryFromMatrixTest rtkgeometryfrommatrixtest.cxx)\nrtk_add_test(rtkParallelGeometryFromMatrixTest rtkparallelgeometryfrommatrixtest.cxx)\n\nrtk_add_test(rtkOraTest rtkoratest.cxx\n  DATA{Input/Ora/0_afterLog.ora.xml,0_afterLog.mhd,0_afterLog.raw}\n  DATA{Baseline/Ora/geometry.xml}\n  DATA{Input/Ora/2006137_20220918183246810.ora.xml,2006137_20220918183246810.mhd}\n  DATA{Baseline/Ora/geometry_yawtilt.xml}\n  DATA{Baseline/Ora/geometry_optitrack.xml}\n  DATA{Baseline/Ora/attenuation.mha})\n\nrtk_add_test(rtkBioscanTest rtkbioscantest.cxx\n  DATA{Input/Bioscan/bioscan.dcm}\n  DATA{Baseline/Bioscan/geometry.xml})\n\nrtk_add_test(rtkVarianceReconstructionTest rtkvariancereconstructiontest.cxx)\n\n#-----------------------------------------------------------------------------\n# Test examples\nrtk_add_test(rtkFirstReconstructionExampleTest\n  ../examples/FirstReconstruction/FirstReconstruction.cxx\n  ${CMAKE_CURRENT_BINARY_DIR}/FirstReconstruction.mha\n  ${CMAKE_CURRENT_BINARY_DIR}/FirstReconstruction.xml\n)\nrtk_add_cuda_test(rtkFirstCudaReconstructionExampleTest\n  ../examples/FirstReconstruction/FirstCudaReconstruction.cxx\n  ${CMAKE_CURRENT_BINARY_DIR}/FirstCudaReconstruction.mha\n  ${CMAKE_CURRENT_BINARY_DIR}/FirstCudaReconstruction.xml\n)\nrtk_add_test(rtkInlineReconstructionExampleTest\n  ../examples/InlineReconstruction/InlineReconstruction.cxx)\nrtk_add_cuda_test(rtkCudaInlineReconstructionExampleTest\n  ../examples/InlineReconstruction/InlineReconstruction.cxx)\nrtk_add_test(rtkAddNoiseExampleTest\n  ../examples/AddNoise/AddNoise.cxx)\nrtk_add_test(rtkGeometricPhantomExampleTest\n  ../examples/GeometricPhantom/GeometricPhantom.cxx\n  DATA{Input/Forbild/Thorax}\n)\nrtk_add_test(rtkConjugateGradientExampleTest\n  ../examples/ConjugateGradient/ConjugateGradient.cxx\n  DATA{Input/Forbild/Thorax}\n)\n\nif(ITK_WRAP_PYTHON)\n  itk_python_add_test(NAME rtkMaximumIntensityPythonTest COMMAND rtkMaximumIntensity.py)\n  itk_python_add_test(NAME rtkOutputArgumentWrappingTest COMMAND rtkOutputArgumentWrapping.py)\nendif()\n"
  },
  {
    "path": "test/Input/Bioscan/bioscan.dcm.sha512",
    "content": "e173fd84d9afb6ef45c14e13df658f22641904cadf4f4b63f99d39a0c46a99cefc5fd2ba31751db12c1dc44af71b414c080e4d012e0c32292d4fa1b194f8ad15\n"
  },
  {
    "path": "test/Input/Digisens/calibration.cal.sha512",
    "content": "fe6498cad0c465af3c3199fd659fa02591f771245064bf86d1cc2bf5703435b0ce3a86546257f7cceb7e3eff6b5031b8c05167639a2908c5b8c7ddce4ad339a6\n"
  },
  {
    "path": "test/Input/Digisens/ima0010.tif.sha512",
    "content": "bf1429845800ae8edcf726bdab1722bbb54ea48c64d8888ed872d0d185b92523b672de2b63b94ed3a8be1fb12c6a3622b57b7ee4fb92cf04841357be352702d1\n"
  },
  {
    "path": "test/Input/ESRF/dark.edf.sha512",
    "content": "5b0e02cc08543adb30f0c2fa62c2f4ba9c3b1f956ee6efe2f4880408cccac6e0c1629d57f70914dce7db8c4b97fa62a22845907396bac06f5c671aac32e9d7e2\n"
  },
  {
    "path": "test/Input/ESRF/raw.edf.sha512",
    "content": "e233088b9fcdabc05b608612ae228e937395de1806fa823aca4c67cc420da6dbc3550317fcf0de120204123007c948af71ae9d009da5a87b267284b8ad23bbfd\n"
  },
  {
    "path": "test/Input/ESRF/refHST0000.edf.sha512",
    "content": "2638665bd0aa444e1683d3e67677fc2b92281c1b65f4c4e04b5888d7a54cb13e6a8ba441fdc573635cffe517d45b4d4e1ffc1d42996c4522e395022514287af4\n"
  },
  {
    "path": "test/Input/Elekta/FRAME.DBF.sha512",
    "content": "4508a1105ccf140c83049bebe2aa3cd066c59c5f210a20ff64ae2f9a2015e6ac7a44d102a3296b0d577b09f6d65e67f476d2916b9f0dbe5d4819c6410340e880\n"
  },
  {
    "path": "test/Input/Elekta/IMAGE.DBF.sha512",
    "content": "c791d5c783a5d2c5b69e8ac2ba058980f07be4340db6ab0f10174b3d3b2b1904e07cfc80556c6fa020abd0c361a4be4de5e44a2bef716e622e0c3a9298730516\n"
  },
  {
    "path": "test/Input/Elekta/_Frames.xml.sha512",
    "content": "abd3cd7c9d7f9511a381416ebd16f533c079c694e82fd9c21f39cf1aeb6fdfb3991a17d85a60d996043b5d8fb48e61bb5158bd2802dc733a30c642e827c3e00f\n"
  },
  {
    "path": "test/Input/Elekta/raw.his.sha512",
    "content": "2bd7d49c188a4d6a4b9ced8ee183d9ccd92ae71a675ccf3b24e7d36c4df154a399d38a8d32e9498f48ff689b168d9688fd2564f050b3b78f687e0eb81bd98d1f\n"
  },
  {
    "path": "test/Input/Forbild/Thorax.sha512",
    "content": "9cb246ae7fc7f905fc929767553d2771d19339c83b9a380a01d6bc66577acc133941610e185987fe0844295c7158fd593959fc1c091cfbba6395f805848bd1ee\n"
  },
  {
    "path": "test/Input/GeometricPhantom/Geometries.txt.sha512",
    "content": "269a5a8d8ad1eced55527d0bb98c7e28169db07d644b3c3cc80cca0151964992bd6715a5c3a3d3a27c3e8540f9a796e2c90b8d78bfbcc63e897337c3f7e21d4b\n"
  },
  {
    "path": "test/Input/GeometricPhantom/Geometries_Forbild.txt.sha512",
    "content": "5e3bbe5ef438b39294633058b13c583b822235613584fa01960614bf2af7a1c475e3c51f0cd84b25e65d811432409130513b450c9060cc487d140eda4995e56b\n"
  },
  {
    "path": "test/Input/GeometricPhantom/SheppLogan.txt.sha512",
    "content": "3c9792a4618be902703022bf222cefffa9996f279edfd76a792810763bc427a077a3991e0ead56844584e14f28dbb95380cd44ba251da77755e1512c50ab467f\n"
  },
  {
    "path": "test/Input/GeometricPhantom/SheppLogan_forbild.txt.sha512",
    "content": "fdb64bcc85ffed95ec161bf345bc3c4f0bded27d8c1c46c0186ca822017795edc2b6d4067bfa25d99f9e6c9d97705238f5c207b9286bbee2a2deac30d74bfa30"
  },
  {
    "path": "test/Input/ImagX/1.dcm.sha512",
    "content": "2293ea5f8e14ec534fbb2b8c4cfe221c99e18c764cd14a40484fba242c5a70b4fcdb5f3877014cd05533b7f03422f8f85f133ae7ceba38062cea215700a9272d\n"
  },
  {
    "path": "test/Input/ImagX/calibration.xml.sha512",
    "content": "54aedbc321d44eb62f5ea9c7fb1f7411c9123718fe8009171237dd676bd3ac5c5e6679e081fe96dcfebc17a76e6c83aa5dbe2be39dcce84ee3412364db9d5481\n"
  },
  {
    "path": "test/Input/ImagX/raw.raw.sha512",
    "content": "bb2bf9b98729e3f6ba119cb9269d38dc0c9a78adb9a6e6a0ac962a486966bc48fefd7d5199cddc4a645e5371172a9ac75cd538ef13e881444df78ee2c4b697a5\n"
  },
  {
    "path": "test/Input/ImagX/raw.xml.sha512",
    "content": "91c2f879e0d6d328a909baedbdd35543b21bf772ca0b20112e60d16c80b8da91c41818bdba2a2e60e467e7e7f06fcb59292f960518c3a6615d99df97c82e5502\n"
  },
  {
    "path": "test/Input/ImagX/room.xml.sha512",
    "content": "aa53dbf71663a2edc82d87c35770d52661f46b8ad8e8a41777fd0956aad1c53c725a68747b24a83a1ef7c6853dbe7da44e4452a5fec7ac4eb681e11f23b7a6c3\n"
  },
  {
    "path": "test/Input/Ora/084183_20211217170607335.mhd.sha512",
    "content": "5a0a6640cba5dcba82eb154fced8128b2a3ad23d8d34e4639d2ac516f2c590826e42a69c492ceaf224ca7d3ea4919cc35e40bc78623058bf4377a488ed24b8fd\n"
  },
  {
    "path": "test/Input/Ora/084183_20211217170607335.ora.xml.sha512",
    "content": "66237b2891db37192aa87ddf02fc5190b306c632fffa513c70b6a527167d157365088497936f5c8eb4b250747494b4fd5458730141a8420a92b8e90c45fac680\n"
  },
  {
    "path": "test/Input/Ora/0_afterLog.mhd.sha512",
    "content": "94011bf843c689b4ccb9fa03c7ed0558fe4b80078fa6e81f7783ef19769d35f9b6bb7a01653d495384b3a7e28d178cb385652ab49ab468e5fce06ff1c4513921\n"
  },
  {
    "path": "test/Input/Ora/0_afterLog.ora.xml.sha512",
    "content": "2471dd78dfddd692ac210f0f4751b6ee227201a649e758ce6ae7753f7fc9aec8c1f49e3d2d6bd04f146536d2be9c16a9373d8d6cae0fc52fccca95db8f6ee2dd\n"
  },
  {
    "path": "test/Input/Ora/0_afterLog.raw.sha512",
    "content": "08cd7a449a19f70c03984c7c2222b346b74f0bd0d229536ec48d6ad4b99389d0dae0085d8892cb9a8c775e454e6ef5852048c2abc933e74670e1b458451d368f\n"
  },
  {
    "path": "test/Input/Ora/2006137_20220918183246810.mhd.sha512",
    "content": "7dbe56d87d6026dfa9c350fe2f1f6e9558697044e5acf90c6dcb2a31eb106bb3b24a6a5ae39a32aa9ebe4532af4ec8e5b26cc7f3ad49c56e0eba289a2d39d6c8\n"
  },
  {
    "path": "test/Input/Ora/2006137_20220918183246810.ora.xml.sha512",
    "content": "20f97eb60e40586308bf576e4873e9d534aedbf7148151d2babb30a1556db61c76ba5c0c5c0fa29bb7c8bd93ad94761ddfe7cee7565006ed2fae15d6add2f4d3\n"
  },
  {
    "path": "test/Input/Phases/phases.txt.sha512",
    "content": "31c171ac561b30e972761892dae9192372ec4ea56675c361186609bd67f1d1fbbd219729fc9adcde1e175a47d6e848a113dbbfc3c1852f6619b21ce2712397c7\n"
  },
  {
    "path": "test/Input/Phases/phases_3projs.txt.sha512",
    "content": "f6aa3fb1ef036ba1502a68fdd8a086e75f621a43ccaee8309f78afd4448e1befd063b36c77ad5b5e0b8910a3c4c58806a02ce59a47b3446ebfbaeb6ab3d82f3e\n"
  },
  {
    "path": "test/Input/Phases/phases_slow.txt.sha512",
    "content": "f55deb6a7348b8fb56b4b2be31cb62815cb329ed5af4c2fded3b494a6d69881eb26914482a225ac83b111a369185a946e266908aad9c8dbb8a889dace66adec7\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/binnedDetectorResponse.csv.sha512",
    "content": "5eb9c478586aeec9688660fdea074426b11978f60cb489315cfa970fe9bf836883967ea733e38f166bafc599e7d329245b043a3af5edb62b509bebb872fde463\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/gradient.mha.sha512",
    "content": "ec9377f7aa5601e1d4914a438d6cffd48a65619118550239ec0d82d717117da237c2bf3988413788510654ffa761b72bcb274c0ce177d80455b0486ba8930b1a\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/hessian.mha.sha512",
    "content": "b2bcebfa4eb4d6c4e8080d68d3bdf86c4ff2941dc5d5136b1580a0a4a60fc3971ba434c535b73bdbf8c0b3fff4cc6addca78ab42ddd975bfa6efa02ad0f6771b\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/incident_spectrum_64_rows.mha.sha512",
    "content": "08e70c6da092fc1745c0e4da0796b25f05e78891a7174788e1ed9b4700c93339e6f0bb0e20d954566192ef670161b932bf52a64716a339d0e6e34a7bb0b71e18\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/materialAttenuations.csv.sha512",
    "content": "754aec176c5daa9830017b3b3e42a2260e176aae331687de89d53bea78937399cd3a9b4ddf7cf6c946bd93958179d490d39eca1ea4dc034b03dbe117f755a222\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/materialProjections.mha.sha512",
    "content": "0783778d6c6182d3b8d66887087620569eebda5c4d7e21e7f139faa81afc4aa3cf88b47d9a22390445f653f309ec2f8ef7b5a2496ef57f4823c19d610867935d\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/no_vector_incident_spectrum_64_rows.mha.sha512",
    "content": "c75509a192fbf61c94d9f1a874bf6f4883d07ecc0c319221c261a455bf95987705a32dd20348ac26aed3a259e4c9d3756cdbc8ce32d7a449e2bfdeb0452a5586\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/photonCounts.mha.sha512",
    "content": "9b33c713534c84f9b400a820b0779d438782af06035a3c3475ece55e721fe9de1217030b5f737909345936b2d5d659155607e0faf5ab3b4174c4ecc00a8e4ca5\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/projOfOnes.mha.sha512",
    "content": "328c922ef2f7f7bbaa5f75566ebedb9076464122b8e2dab37d07e9393ccbeb32e3d2b55f04dc3ac4299cff4f45a852862d6045e8acdb0af3f41cb6cc976473f2\n"
  },
  {
    "path": "test/Input/Spectral/OneStep/spectrum.mha.sha512",
    "content": "37b956d7ab8197033fb3522f679a444f8088ea0c859442fd92662992d9c4dbee3db1008e5f8ac9d653f397d2d8d678c5d1adf392d3caa669e2f4d8b518fbe005\n"
  },
  {
    "path": "test/Input/Spectral/detector_response.mha.sha512",
    "content": "123496abd20547cb8ac27b8b0806db56750e4f9ffd01cca6d83ffcb744052c8ebbbb53a51ffff192d81c565dd77e3992bb1040987b4c1e4e23e144151dd58c17\n"
  },
  {
    "path": "test/Input/Spectral/incident_spectrum.mha.sha512",
    "content": "315f410d858da64079b587826c5e8668c3ec0c41fc59a4c68a0f183d1678a89c6b240e39e1fbccdc0cedda20d53234f0c67761dfa7e04608009b44deee175dff\n"
  },
  {
    "path": "test/Input/Spectral/material_attenuations.mha.sha512",
    "content": "93e37f81d7b43bbcab7a0eedf9159f88b36feab98adff3873f0683cb55747c4f5a6691ff7ec7b36b6ca932e63a60174407623c74d01e8fabd364eea7db510bb2\n"
  },
  {
    "path": "test/Input/Spectral/no_vector_incident_spectrum.mha.sha512",
    "content": "167e2795613460a5da619a80c67275fd0aab364f1e32e03a94e76583abfbf61977360d3081388f6fd57d806f04fdb49f4b5832282934719d69aba58fed004e13\n"
  },
  {
    "path": "test/Input/Varian/Proj_00000.xim.sha512",
    "content": "c25a6440d27cc3fc44ce5e8dd2812df14ebb0bdec5b346d0d19f364dd9bdf9f8029ec337f6c484e42432d6ed750f96e8e5b9d36ead32c8722ec6519daefcc648\n"
  },
  {
    "path": "test/Input/Varian/acqui.xml.sha512",
    "content": "280e59f4c42a1382b54141b6a5a588cd67fc2dc928c8631ddd99343a417345538ea92fbe731b374b92d9c45c781d81f5d15e66b7a3fa17a937571437c8cfff91\n"
  },
  {
    "path": "test/Input/Varian/acqui_probeam.xml.sha512",
    "content": "a5068b48d77b9ad32dc265a07d34e097ec3c388e9dda4f08fe061217bde730e11f35eab5ed98edd131d05e1f7356b49ac0f9a7ba07a437a1214bd494da802c28\n"
  },
  {
    "path": "test/Input/Varian/image_00052.hnc.sha512",
    "content": "53b8ea2947c8c2cfe0922b990c2c821fccb905302b660a0de0d81107df9709b0aaa061b9f7b6a98a42032b2e25ee6f526006b07edcdec970c099f6614a4a03fd\n"
  },
  {
    "path": "test/Input/Varian/raw.hnd.sha512",
    "content": "585d03096e570a7296459ef2a9bc6f48ea5fd3ef16f648a16c35c42bcec7b1479f2201d078b8e893611f8819b8e4298e6ed9e6e3b076093e5af919ccff06a6ad\n"
  },
  {
    "path": "test/Input/XRad/SolidWater_HiGain1x1.header.sha512",
    "content": "a572a4d6ab576aa0536248269684f0e0659aae6f2186fa798d68fcae511e65753c8827c7c3d7d6fffd86b1b7d5c92beded531401f90d83a765a08de82d01ab83\n"
  },
  {
    "path": "test/Input/XRad/SolidWater_HiGain1x1_firstProj.header.sha512",
    "content": "d57c7a3e63fc8fb6ca563d4926d6c3739f8477879f4ff155ca81741123f5f4938f017eba50a0daecce5d95d32e28494f8cbf4672e4754dedbdb96494316312a0\n"
  },
  {
    "path": "test/Input/XRad/SolidWater_HiGain1x1_firstProj.img.sha512",
    "content": "5dd91814f6a47293c92f25d7a4380a142fcfb54f5ed6aee46c9bb90e2bbd6b695ba5421ef0ba7dc4ef5383667489f17e0fb2e492b9fe05437cf544b45041bb46\n"
  },
  {
    "path": "test/Input/XRad/dark.header.sha512",
    "content": "153871e194b0db10f7875fa093c6bf077226d5ea8caee8ea50f9173bfd01171d3ab842f9001606bf202a685ef7574833c50a41b70126f39cadf6ca04bb7101cb\n"
  },
  {
    "path": "test/Input/XRad/dark.img.sha512",
    "content": "5e90a786176289e3daf60231db696d5dc36ee670f7d58c94c37d6402ce1fbc2fa0643ed504b452ca185595568226f5b2181a38799724bed3d9ee88c28c838ecd\n"
  },
  {
    "path": "test/Input/XRad/flat.header.sha512",
    "content": "f655490965782fcbcaf020dbd34e3b6441e81ff123348747692d97effd6fb5e17268068e5095ca939cae4422326ae4ce7f376f2ecd4645f16e904a65cbedb023\n"
  },
  {
    "path": "test/Input/XRad/flat.img.sha512",
    "content": "8e52862ea17ec241199b6d326c6413477e916e915615b8339daa596d42a997f8639c0abd8177fba7603d1b80b8338c129f54a40529cce589b28da83ebfdf542d\n"
  },
  {
    "path": "test/rtkI0estimationtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkI0EstimationProjectionFilter.h\"\n#include <itkRandomImageSource.h>\n\n/**\n * \\file rtkI0estimationtest.cxx\n *\n * \\brief Test rtk::I0EstimationProjectionFilter\n *\n * \\author Sebastien Brousmiche\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::Image<unsigned short, Dimension>;\n\n  auto i0est = rtk::I0EstimationProjectionFilter<ImageType, ImageType, 3>::New();\n\n  // Constant image sources\n  auto                  size = itk::MakeSize(150, 150, 1);\n  ImageType::RegionType region;\n  region.SetSize(size);\n\n  auto randomSource = itk::RandomImageSource<ImageType>::New();\n  randomSource->SetSize(size);\n\n  i0est->SetExpectedI0(23);\n  i0est->SetLambda(0.9);\n\n  unsigned short minv = 0;\n  unsigned short maxv = 0;\n  for (unsigned int i = 0; i < 10; ++i)\n  {\n    minv = 3200 + 0 * i;\n    maxv = 3800 + 400 * i;\n\n    // std::cout << \"Average = \" << .5*(minv + maxv) << \" - \"<<minv <<\" to \"<<maxv<< std::endl;\n\n    randomSource->SetMin(minv);\n    randomSource->SetMax(maxv);\n    randomSource->Update();\n\n    i0est->SetInput(randomSource->GetOutput());\n    i0est->Update();\n  }\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkMaximumIntensity.py",
    "content": "#!/usr/bin/env python\nfrom __future__ import print_function\nimport itk\nfrom itk import RTK as rtk\n\ndef test_MaximumIntensity():\n    TImageType = itk.Image[itk.F, 3]\n    # Defines the RTK geometry object\n    geometry = rtk.ThreeDCircularProjectionGeometry.New()\n    numberOfProjections = 1\n    geometry.AddProjection(700, 800, 0)\n    # Constant image sources\n    # Create MIP Forward Projector volume\n    volInput = rtk.ConstantImageSource[TImageType].New()\n    origin = [0.0, 0.0, 0.0]\n    size = [64, 64, 64]\n    sizeOutput = [200, 200, numberOfProjections]\n    spacing = [4.0, 4.0, 4.0]\n    spacingOutput = [1.0, 1.0, 1.0]\n    volInput.SetOrigin(origin)\n    volInput.SetSpacing(spacing)\n    volInput.SetSize(size)\n    volInput.SetConstant(1.0)\n    volInput.UpdateOutputInformation()\n    volInputSource = volInput.GetOutput()\n    # Initialization Imager volume\n    projInput = rtk.ConstantImageSource[TImageType].New()\n    projInput.SetOrigin(origin)\n    projInput.SetSpacing(spacingOutput)\n    projInput.SetSize(sizeOutput)\n    projInput.SetConstant(0.0)\n    projInput.Update()\n    projInputSource = projInput.GetOutput()\n    # MIP Forward Projection filter\n    mip = rtk.MaximumIntensityProjectionImageFilter[TImageType, TImageType].New()\n    mip.SetGeometry(geometry)\n    mip.SetInput(volInputSource)\n    mip.SetInput(1, projInputSource)\n    mipImage = mip.GetOutput()\n"
  },
  {
    "path": "test/rtkOutputArgumentWrapping.py",
    "content": "import itk\nfrom itk import RTK as rtk\nimport math\n\n# Test for rtkConvexShape::IsIntersectedByRay\ndef test_IsIntersectedByRay():\n    q = rtk.QuadricShape.New()\n\n    # Define a sphere of radius 10\n    radius = 10\n    q.SetA(1)\n    q.SetB(1)\n    q.SetC(1)\n    q.SetJ(-(radius ** 2))\n\n    # Ray starting outside sphere aiming through center should intersect.\n    res = q.IsIntersectedByRay([-20, 0, 0], [1, 0, 0])\n    assert isinstance(res, (list, tuple)) and len(res) >= 3\n    intersects, t0, t1 = res[0], res[1], res[2]\n    assert intersects is True\n    # Expected param distances from start point x=-20 to entry at -10 (10 units) and exit at +10 (30 units)\n    assert math.isclose(t0, 10.0, rel_tol=1e-6, abs_tol=1e-6)\n    assert math.isclose(t1, 30.0, rel_tol=1e-6, abs_tol=1e-6)\n\n\n# Test for rtk::FieldOfViewImageFilter::ComputeFOVRadius\ndef test_ComputeFOVRadius():\n    geometry = rtk.ThreeDCircularProjectionGeometry.New()\n    numberOfProjections = 360\n    firstAngle = 0\n    angularArc = 360\n    sid = 600  # source to isocenter distance in mm\n    sdd = 1200  # source to detector distance in mm\n    isox = 0  # X coordinate on the projection image of isocenter\n    isoy = 0  # Y coordinate on the projection image of isocenter\n    for x in range(numberOfProjections):\n        angle = firstAngle + x * angularArc / numberOfProjections\n        geometry.AddProjection(sid, sdd, angle, isox, isoy)\n\n    constantImageSource = rtk.ConstantImageSource[itk.Image[itk.F, 3]].New()\n    origin = [-127.5, -127.5, 0.0]\n    sizeOutput = [256, 256, numberOfProjections]\n    spacing = [1.0, 1.0, 1.0]\n    constantImageSource.SetOrigin(origin)\n    constantImageSource.SetSpacing(spacing)\n    constantImageSource.SetSize(sizeOutput)\n    constantImageSource.SetConstant(0.0)\n    source = constantImageSource.GetOutput()\n\n    f = rtk.FieldOfViewImageFilter.New()\n    f.SetGeometry(geometry)\n    f.SetProjectionsStack(source)\n\n    res_inf = f.ComputeFOVRadius(f.FOVRadiusType_RADIUSINF)\n    success = res_inf[0]\n    rmin = res_inf[1]\n    rmax = res_inf[2]\n    rinf = res_inf[3]\n    assert success is True\n    # rmin and rmax are zero in this symmetric centered geometry\n    assert math.isclose(rmin, 0.0, abs_tol=1e-6)\n    assert math.isclose(rmax, 0.0, abs_tol=1e-6)\n    # Theoretical infinite-distance FOV radius: (detector_width/2) * sid / sdd = (256/2)*600/1200 = 64\n    expected = (sizeOutput[0] * spacing[0] / 2.0) * (sid / sdd)\n    # Allow small deviation (<2%) due to internal computations\n    rel_err = abs(rinf - expected) / expected\n    assert rel_err < 0.02\n\nif __name__ == \"__main__\":\n    test_IsIntersectedByRay()\n    test_ComputeFOVRadius()"
  },
  {
    "path": "test/rtkTest.h",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef rtkTest_h\n#define rtkTest_h\n\n#include <itkImageRegionConstIterator.h>\n#include <itkImageFileWriter.h>\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkTestConfiguration.h\"\n\n\ntemplate <class TImage>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckImageQuality(typename TImage::Pointer itkNotUsed(recon),\n                  typename TImage::Pointer itkNotUsed(ref),\n                  double                   itkNotUsed(ErrorPerPixelTolerance),\n                  double                   itkNotUsed(PSNRTolerance),\n                  double                   itkNotUsed(RefValueForPSNR))\n{}\n#else\nvoid\nCheckImageQuality(typename TImage::Pointer recon,\n                  typename TImage::Pointer ref,\n                  double                   ErrorPerPixelTolerance,\n                  double                   PSNRTolerance,\n                  double                   RefValueForPSNR)\n{\n  using ImageIteratorType = itk::ImageRegionConstIterator<TImage>;\n  ImageIteratorType itTest(recon, recon->GetBufferedRegion());\n  ImageIteratorType itRef(ref, ref->GetBufferedRegion());\n\n  using ErrorType = double;\n  ErrorType TestError = 0.;\n  ErrorType EnerError = 0.;\n\n  itTest.GoToBegin();\n  itRef.GoToBegin();\n\n  while (!itRef.IsAtEnd())\n  {\n    typename TImage::PixelType TestVal = itTest.Get();\n    typename TImage::PixelType RefVal = itRef.Get();\n    TestError += itk::Math::abs(RefVal - TestVal);\n    EnerError += std::pow(ErrorType(RefVal - TestVal), 2.);\n    ++itTest;\n    ++itRef;\n  }\n  // Error per Pixel\n  ErrorType ErrorPerPixel = TestError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"\\nError per Pixel = \" << ErrorPerPixel << std::endl;\n  // MSE\n  ErrorType MSE = EnerError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"MSE = \" << MSE << std::endl;\n  // PSNR\n  ErrorType PSNR = 20 * log10(RefValueForPSNR) - 10 * log10(MSE);\n  std::cout << \"PSNR = \" << PSNR << \"dB\" << std::endl;\n  // QI\n  ErrorType QI = (RefValueForPSNR - ErrorPerPixel) / RefValueForPSNR;\n  std::cout << \"QI = \" << QI << std::endl;\n\n  //   // It is often necessary to write the images and look at them\n  //   // to understand why a given test fails. This portion of code\n  //   // does that. It should be left here but commented out, since\n  //   // it is only useful in specific debugging tasks\n  //   using FileWriterType = itk::ImageFileWriter<TImage>;\n  //   typename FileWriterType::Pointer writer = FileWriterType::New();\n  //   writer->SetInput(recon);\n  //   writer->SetFileName(\"Reconstruction.mhd\");\n  //   writer->Update();\n  //   writer->SetInput(ref);\n  //   writer->SetFileName(\"Reference.mhd\");\n  //   writer->Update();\n  //   // End of results writing\n\n  // Checking results. As a comparison with NaN always returns false,\n  // this design allows to detect NaN results and cause test failure\n  if (!(ErrorPerPixel < ErrorPerPixelTolerance))\n  {\n    std::cerr << \"Test Failed, Error per pixel not valid! \" << ErrorPerPixel << \" instead of \" << ErrorPerPixelTolerance\n              << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  if (!(PSNR > PSNRTolerance))\n  {\n    std::cerr << \"Test Failed, PSNR not valid! \" << PSNR << \" instead of \" << PSNRTolerance << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif // FAST_TESTS_NO_CHECKS\n\ntemplate <class TImage>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckVectorImageQuality(typename TImage::Pointer itkNotUsed(recon),\n                        typename TImage::Pointer itkNotUsed(ref),\n                        double                   itkNotUsed(ErrorPerPixelTolerance),\n                        double                   itkNotUsed(PSNRTolerance),\n                        double                   itkNotUsed(RefValueForPSNR))\n{}\n#else\nvoid\nCheckVectorImageQuality(typename TImage::Pointer recon,\n                        typename TImage::Pointer ref,\n                        double                   ErrorPerPixelTolerance,\n                        double                   PSNRTolerance,\n                        double                   RefValueForPSNR)\n{\n  using ImageIteratorType = itk::ImageRegionConstIterator<TImage>;\n  ImageIteratorType itTest(recon, recon->GetBufferedRegion());\n  ImageIteratorType itRef(ref, ref->GetBufferedRegion());\n\n  using ErrorType = double;\n  ErrorType TestError = 0.;\n  ErrorType EnerError = 0.;\n\n  itTest.GoToBegin();\n  itRef.GoToBegin();\n\n  while (!itRef.IsAtEnd())\n  {\n    typename TImage::PixelType TestVal = itTest.Get();\n    typename TImage::PixelType RefVal = itRef.Get();\n    TestError += (RefVal - TestVal).GetNorm();\n    EnerError += (RefVal - TestVal).GetSquaredNorm();\n    ++itTest;\n    ++itRef;\n  }\n  // Error per Pixel\n  ErrorType ErrorPerPixel = TestError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"\\nError per Pixel = \" << ErrorPerPixel << std::endl;\n  // MSE\n  ErrorType MSE = EnerError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"MSE = \" << MSE << std::endl;\n  // PSNR\n  ErrorType PSNR = 20 * log10(RefValueForPSNR) - 10 * log10(MSE);\n  std::cout << \"PSNR = \" << PSNR << \"dB\" << std::endl;\n  // QI\n  ErrorType QI = (RefValueForPSNR - ErrorPerPixel) / RefValueForPSNR;\n  std::cout << \"QI = \" << QI << std::endl;\n\n  //   // It is often necessary to write the images and look at them\n  //   // to understand why a given test fails. This portion of code\n  //   // does that. It should be left here but commented out, since\n  //   // it is only useful in specific debugging tasks\n  //   using FileWriterType = itk::ImageFileWriter<TImage>;\n  //   typename FileWriterType::Pointer writer = FileWriterType::New();\n  //   writer->SetInput(recon);\n  //   writer->SetFileName(\"Reconstruction.mhd\");\n  //   writer->Update();\n  //   writer->SetInput(ref);\n  //   writer->SetFileName(\"Reference.mhd\");\n  //   writer->Update();\n  //   // End of results writing\n\n  // Checking results. As a comparison with NaN always returns false,\n  // this design allows to detect NaN results and cause test failure\n  if (!(ErrorPerPixel < ErrorPerPixelTolerance))\n  {\n    std::cerr << \"Test Failed, Error per pixel not valid! \" << ErrorPerPixel << \" instead of \" << ErrorPerPixelTolerance\n              << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  if (!(PSNR > PSNRTolerance))\n  {\n    std::cerr << \"Test Failed, PSNR not valid! \" << PSNR << \" instead of \" << PSNRTolerance << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif // FAST_TESTS_NO_CHECKS\n\n\ntemplate <class TImage>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckVariableLengthVectorImageQuality(typename TImage::Pointer itkNotUsed(recon),\n                                      typename TImage::Pointer itkNotUsed(ref),\n                                      double                   itkNotUsed(ErrorPerPixelTolerance),\n                                      double                   itkNotUsed(PSNRTolerance),\n                                      double                   itkNotUsed(RefValueForPSNR))\n{}\n#else\nvoid\nCheckVariableLengthVectorImageQuality(typename TImage::Pointer recon,\n                                      typename TImage::Pointer ref,\n                                      double                   ErrorPerPixelTolerance,\n                                      double                   PSNRTolerance,\n                                      double                   RefValueForPSNR)\n{\n  if (!(recon->GetVectorLength() == ref->GetVectorLength()))\n  {\n    std::cerr << \"Test Failed, image's vector length is \" << recon->GetVectorLength() << \" instead of \"\n              << ref->GetVectorLength() << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n  using ImageIteratorType = itk::ImageRegionConstIterator<TImage>;\n  ImageIteratorType itTest(recon, recon->GetBufferedRegion());\n  ImageIteratorType itRef(ref, ref->GetBufferedRegion());\n\n  using ErrorType = double;\n  ErrorType TestError = 0.;\n  ErrorType EnerError = 0.;\n\n  itTest.GoToBegin();\n  itRef.GoToBegin();\n\n  while (!itRef.IsAtEnd())\n  {\n    typename TImage::PixelType TestVec = itTest.Get();\n    typename TImage::PixelType RefVec = itRef.Get();\n    double                     accumulatedError = 0;\n    for (unsigned int channel = 0; channel < ref->GetVectorLength(); channel++)\n    {\n      accumulatedError += (RefVec[channel] - TestVec[channel]) * (RefVec[channel] - TestVec[channel]);\n    }\n    TestError += sqrt(accumulatedError);\n    EnerError += accumulatedError;\n    ++itTest;\n    ++itRef;\n  }\n  // Error per Pixel\n  ErrorType ErrorPerPixel = TestError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"\\nError per Pixel = \" << ErrorPerPixel << std::endl;\n  // MSE\n  ErrorType MSE = EnerError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"MSE = \" << MSE << std::endl;\n  // PSNR\n  ErrorType PSNR = 20 * log10(RefValueForPSNR) - 10 * log10(MSE);\n  std::cout << \"PSNR = \" << PSNR << \"dB\" << std::endl;\n  // QI\n  ErrorType QI = (RefValueForPSNR - ErrorPerPixel) / RefValueForPSNR;\n  std::cout << \"QI = \" << QI << std::endl;\n\n  //   // It is often necessary to write the images and look at them\n  //   // to understand why a given test fails. This portion of code\n  //   // does that. It should be left here but commented out, since\n  //   // it is only useful in specific debugging tasks\n  //   using FileWriterType = itk::ImageFileWriter<TImage>;\n  //   typename FileWriterType::Pointer writer = FileWriterType::New();\n  //   writer->SetInput(recon);\n  //   writer->SetFileName(\"Reconstruction.mhd\");\n  //   writer->Update();\n  //   writer->SetInput(ref);\n  //   writer->SetFileName(\"Reference.mhd\");\n  //   writer->Update();\n  //   // End of results writing\n\n  // Checking results. As a comparison with NaN always returns false,\n  // this design allows to detect NaN results and cause test failure\n  if (!(ErrorPerPixel < ErrorPerPixelTolerance))\n  {\n    std::cerr << \"Test Failed, Error per pixel not valid! \" << ErrorPerPixel << \" instead of \" << ErrorPerPixelTolerance\n              << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  if (!(PSNR > PSNRTolerance))\n  {\n    std::cerr << \"Test Failed, PSNR not valid! \" << PSNR << \" instead of \" << PSNRTolerance << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif // FAST_TESTS_NO_CHECKS\n\nvoid\nCheckGeometries(const rtk::ThreeDCircularProjectionGeometry * g1, const rtk::ThreeDCircularProjectionGeometry * g2)\n{\n  //  // It is often necessary to write the geometries and look at them\n  //  // to understand why a given test fails. This portion of code\n  //  // does that. It should be left here but commented out, since\n  //  // it is only useful in specific debugging tasks\n  //  rtk::ThreeDCircularProjectionGeometryXMLFileWriter::Pointer xmlWriter =\n  //    rtk::ThreeDCircularProjectionGeometryXMLFileWriter::New();\n  //  xmlWriter->SetFilename(\"g1.xml\");\n  //  xmlWriter->SetObject(g1);\n  //  xmlWriter->WriteFile();\n  //  xmlWriter->SetFilename(\"g2.xml\");\n  //  xmlWriter->SetObject(g2);\n  //  xmlWriter->WriteFile();\n  //  // End of results writing\n\n  const double       e = 1e-10;\n  const unsigned int nproj = g1->GetGantryAngles().size();\n  if (g2->GetGantryAngles().size() != nproj)\n  {\n    std::cerr << \"Unequal number of projections in the two geometries\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  if (e < itk::Math::abs(g1->GetRadiusCylindricalDetector() - g2->GetRadiusCylindricalDetector()))\n  {\n    std::cerr << \"Geometries don't have the same cylindrical detector radius\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n  for (unsigned int i = 0; i < nproj; i++)\n  {\n    // std::cout << g1->GetGantryAngles()[i] << \" \" << g2->GetGantryAngles()[i] << std::endl;\n    if (e < rtk::ThreeDCircularProjectionGeometry::ConvertAngleBetween0And2PIRadians(\n              itk::Math::abs(g1->GetGantryAngles()[i] - g2->GetGantryAngles()[i])) ||\n        e < rtk::ThreeDCircularProjectionGeometry::ConvertAngleBetween0And2PIRadians(\n              itk::Math::abs(g1->GetOutOfPlaneAngles()[i] - g2->GetOutOfPlaneAngles()[i])) ||\n        e < rtk::ThreeDCircularProjectionGeometry::ConvertAngleBetween0And2PIRadians(\n              itk::Math::abs(g1->GetInPlaneAngles()[i] - g2->GetInPlaneAngles()[i])) ||\n        e < itk::Math::abs(g1->GetSourceToIsocenterDistances()[i] - g2->GetSourceToIsocenterDistances()[i]) ||\n        e < itk::Math::abs(g1->GetSourceOffsetsX()[i] - g2->GetSourceOffsetsX()[i]) ||\n        e < itk::Math::abs(g1->GetSourceOffsetsY()[i] - g2->GetSourceOffsetsY()[i]) ||\n        e < itk::Math::abs(g1->GetSourceToDetectorDistances()[i] - g2->GetSourceToDetectorDistances()[i]) ||\n        e < itk::Math::abs(g1->GetProjectionOffsetsX()[i] - g2->GetProjectionOffsetsX()[i]) ||\n        e < itk::Math::abs(g1->GetProjectionOffsetsY()[i] - g2->GetProjectionOffsetsY()[i]) ||\n        e < itk::Math::abs(g1->GetCollimationUInf()[i] - g2->GetCollimationUInf()[i]) ||\n        e < itk::Math::abs(g1->GetCollimationVInf()[i] - g2->GetCollimationVInf()[i]) ||\n        e < itk::Math::abs(g1->GetCollimationUSup()[i] - g2->GetCollimationUSup()[i]) ||\n        e < itk::Math::abs(g1->GetCollimationVSup()[i] - g2->GetCollimationVSup()[i]))\n    {\n      std::cerr << \"Geometry of projection #\" << i << \" is unvalid.\" << std::endl;\n      exit(EXIT_FAILURE);\n    }\n  }\n}\n\n\ntemplate <class TImage1, class TImage2>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckScalarProducts(typename TImage1::Pointer itkNotUsed(im1A),\n                    typename TImage1::Pointer itkNotUsed(im1B),\n                    typename TImage2::Pointer itkNotUsed(im2A),\n                    typename TImage2::Pointer itkNotUsed(im2B))\n{}\n#else\nvoid\nCheckScalarProducts(typename TImage1::Pointer im1A,\n                    typename TImage1::Pointer im1B,\n                    typename TImage2::Pointer im2A,\n                    typename TImage2::Pointer im2B)\n{\n  using Image1IteratorType = itk::ImageRegionConstIterator<TImage1>;\n  using Image2IteratorType = itk::ImageRegionConstIterator<TImage2>;\n  Image1IteratorType itIm1A(im1A, im1A->GetLargestPossibleRegion());\n  Image1IteratorType itIm1B(im1B, im1B->GetLargestPossibleRegion());\n  Image2IteratorType itIm2A(im2A, im2A->GetLargestPossibleRegion());\n  Image2IteratorType itIm2B(im2B, im2B->GetLargestPossibleRegion());\n\n  typename TImage2::PixelType scalarProductT1, scalarProductT2;\n  scalarProductT1 = 0;\n  scalarProductT2 = 0;\n\n  while (!itIm1A.IsAtEnd())\n  {\n    scalarProductT1 += itIm1A.Get() * itIm1B.Get();\n    ++itIm1A;\n    ++itIm1B;\n  }\n\n  while (!itIm2A.IsAtEnd())\n  {\n    scalarProductT2 += itIm2A.Get() * itIm2B.Get();\n    ++itIm2A;\n    ++itIm2B;\n  }\n\n  // QI\n  double ratio = scalarProductT1 / scalarProductT2;\n  std::cout << \"1 - ratio = \" << 1 - ratio << std::endl;\n\n  //  // It is often necessary to write the images and look at them\n  //  // to understand why a given test fails. This portion of code\n  //  // does that. It should be left here but commented out, since\n  //  // it is only useful in specific debugging tasks\n  //  using FileWriterType1 = itk::ImageFileWriter<TImage1>;\n  //  typename FileWriterType1::Pointer writer = FileWriterType1::New();\n  //  writer->SetInput(im1A);\n  //  writer->SetFileName(\"im1A.mhd\");\n  //  writer->Update();\n  //  writer->SetInput(im1B);\n  //  writer->SetFileName(\"im1B.mhd\");\n  //  writer->Update();\n\n  //  using FileWriterType2 = itk::ImageFileWriter<TImage2>;\n  //  typename FileWriterType2::Pointer writer2 = FileWriterType2::New();\n  //  writer2->SetInput(im2A);\n  //  writer2->SetFileName(\"im2A.mhd\");\n  //  writer2->Update();\n  //  writer2->SetInput(im2B);\n  //  writer2->SetFileName(\"im2B.mhd\");\n  //  writer2->Update();\n  //  // End of results writing\n\n\n  // Checking results\n  if (!(itk::Math::abs(ratio - 1) < 0.001))\n  {\n    std::cerr << \"Test Failed, ratio not valid! \" << ratio << \" instead of 1 +/- 0.001\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif\n\ntemplate <class TImage1, class TImage2>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckVectorScalarProducts(typename TImage1::Pointer im1A,\n                          typename TImage1::Pointer im1B,\n                          typename TImage2::Pointer im2A,\n                          typename TImage2::Pointer im2B)\n{}\n#else\nvoid\nCheckVectorScalarProducts(typename TImage1::Pointer im1A,\n                          typename TImage1::Pointer im1B,\n                          typename TImage2::Pointer im2A,\n                          typename TImage2::Pointer im2B)\n{\n  using Image1IteratorType = itk::ImageRegionConstIterator<TImage1>;\n  using Image2IteratorType = itk::ImageRegionConstIterator<TImage2>;\n  Image1IteratorType itIm1A(im1A, im1A->GetLargestPossibleRegion());\n  Image1IteratorType itIm1B(im1B, im1B->GetLargestPossibleRegion());\n  Image2IteratorType itIm2A(im2A, im2A->GetLargestPossibleRegion());\n  Image2IteratorType itIm2B(im2B, im2B->GetLargestPossibleRegion());\n\n  typename itk::PixelTraits<typename TImage2::PixelType>::ValueType scalarProductT1, scalarProductT2;\n  scalarProductT1 = 0;\n  scalarProductT2 = 0;\n  unsigned int vectorLength = itk::PixelTraits<typename TImage2::PixelType>::Dimension;\n\n  while (!itIm1A.IsAtEnd())\n  {\n    for (unsigned int component = 0; component < vectorLength; component++)\n      scalarProductT1 += itIm1A.Get()[component] * itIm1B.Get()[component];\n    ++itIm1A;\n    ++itIm1B;\n  }\n\n  while (!itIm2A.IsAtEnd())\n  {\n    for (unsigned int component = 0; component < vectorLength; component++)\n      scalarProductT2 += itIm2A.Get()[component] * itIm2B.Get()[component];\n    ++itIm2A;\n    ++itIm2B;\n  }\n\n  // QI\n  double ratio = scalarProductT1 / scalarProductT2;\n  std::cout << \"1 - ratio = \" << 1 - ratio << std::endl;\n\n  //  // It is often necessary to write the images and look at them\n  //  // to understand why a given test fails. This portion of code\n  //  // does that. It should be left here but commented out, since\n  //  // it is only useful in specific debugging tasks\n  //  using FileWriterType1 = itk::ImageFileWriter<TImage1>;\n  //  typename FileWriterType1::Pointer writer = FileWriterType1::New();\n  //  writer->SetInput(im1A);\n  //  writer->SetFileName(\"im1A.mhd\");\n  //  writer->Update();\n  //  writer->SetInput(im1B);\n  //  writer->SetFileName(\"im1B.mhd\");\n  //  writer->Update();\n\n  //  using FileWriterType2 = itk::ImageFileWriter<TImage2>;\n  //  typename FileWriterType2::Pointer writer2 = FileWriterType2::New();\n  //  writer2->SetInput(im2A);\n  //  writer2->SetFileName(\"im2A.mhd\");\n  //  writer2->Update();\n  //  writer2->SetInput(im2B);\n  //  writer2->SetFileName(\"im2B.mhd\");\n  //  writer2->Update();\n  //  // End of results writing\n\n\n  // Checking results\n  if (!(itk::Math::abs(ratio - 1) < 0.001))\n  {\n    std::cerr << \"Test Failed, ratio not valid! \" << ratio << \" instead of 1 +/- 0.001\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif\n\n#endif // rtkTest_h\n"
  },
  {
    "path": "test/rtkTestConfiguration.h.in",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#ifndef __rtkTestConfiguration_h\n#define __rtkTestConfiguration_h\n//This file is interpreted by cmake, to define macros based on the cmake configuration options\n\n#define RTK_DATA_ROOT \"@RTK_DATA_ROOT@\"\n\n// Define if we want to have very fast tests and we do not want any functional\n// test, e.g., when one is doing valgrind or coverage tests\n#cmakedefine01 FAST_TESTS_NO_CHECKS\n\n#endif\n"
  },
  {
    "path": "test/rtkTestReg23ProjectionGeometry.cxx",
    "content": "//\n// std\n#include <cstdlib>\n#include <iostream>\n#include <vector>\n#include <cmath>\n// ITK\n#include <itkMersenneTwisterRandomVariateGenerator.h>\n#include <itkEuler3DTransform.h>\n#include <itkVector.h>\n#include <itkPoint.h>\n// RTK/ORA\n#include \"math.h\"\n\n#include \"rtkReg23ProjectionGeometry.h\"\n\n\n//\nbool Verbose = false; // spam the console\n#define VERBOSE(x) \\\n  if (Verbose)     \\\n    std::cout x;\n\n\n/** Print command line parameter help. **/\nvoid\nPrintHelp(char * binaryName)\n{\n  std::cerr << \"\\n\\n***** TEST: ora::Reg23ProjectionGeometry *****\\n\\n\";\n\n  if (binaryName)\n    std::cerr << binaryName;\n  else\n    std::cerr << \"<executable>\";\n  std::cerr << \" [options] \\n\\n\";\n\n  std::cerr << \"\\n available options:\\n\";\n  std::cerr << \"   -h or --help ... display this help and exit application\\n\";\n  std::cerr << \"   -v or --verbose ... verbose messages on std::cout\\n\";\n  std::cerr << \"\\n\\n***************************************************\\n\\n\";\n}\n\nusing GeometryType = rtk::Reg23ProjectionGeometry;\n\n/**\n * @brief Intersect detector plane with line between source and a specified\n * marker.\n * @param S source position\n * @param marker phantom marker\n * @param n normal of detector plane\n * @param detectorOrigin detector position\n * @param x returned intersection point in WCS\n * @return TRUE if successful intersection was detected\n */\nvoid\nIntersectPlaneWithLine(const GeometryType::PointType &  S,\n                       const GeometryType::PointType &  marker,\n                       const GeometryType::VectorType & n,\n                       const GeometryType::PointType &  detectorOrigin,\n                       GeometryType::VectorType &       x)\n{\n  double num = NAN, den = NAN;\n  double marker1[3];\n\n  marker1[0] = marker[0] - S[0];\n  marker1[1] = marker[1] - S[1];\n  marker1[2] = marker[2] - S[2];\n\n  num = (n[0] * detectorOrigin[0] + n[1] * detectorOrigin[1] + n[2] * detectorOrigin[2]) -\n        (n[0] * S[0] + n[1] * S[1] + n[2] * S[2]);\n  den = n[0] * marker1[0] + n[1] * marker1[1] + n[2] * marker1[2];\n\n  double t = num / den;\n  x[0] = S[0] + t * marker1[0];\n  x[1] = S[1] + t * marker1[1];\n  x[2] = S[2] + t * marker1[2];\n}\n\n\n/** @brief Unit test to check geometrical correctness of\n * ora::Reg23ProjectionGeometry utility class.\n * @author phil steininger\n * @version 1.0\n * @param argc run program with \"-h\" option in order to get more info\n * @param argv run program with \"-h\" option in order to get more info\n * @return EXIT_SUCCESS if the test approves correctness of the utility class\n */\nint\nmain(int argc, char * argv[])\n{\n  // parse cmdln args:\n  std::string sarg;\n  for (int i = 1; i < argc; i++)\n  {\n    sarg = std::string(argv[i]);\n    if (sarg == \"-h\" || sarg == \"--help\")\n    {\n      PrintHelp(argc > 0 ? argv[0] : nullptr);\n      return EXIT_SUCCESS;\n    }\n    if (sarg == \"-v\" || sarg == \"--verbose\")\n    {\n      Verbose = true;\n      continue;\n    }\n  }\n\n  bool ok = true;\n  bool lok = true;\n\n  VERBOSE(<< \"\\n\\nStart testing ora::Reg23ProjectionGeometry\\n\\n\")\n\n  using RandomType = itk::Statistics::MersenneTwisterRandomVariateGenerator;\n  using Point2DType = itk::Point<double, 2>;\n\n  GeometryType::PointType              sourcePosition;\n  GeometryType::PointType              detectorPosition;\n  GeometryType::VectorType             detectorRowDirection;\n  GeometryType::VectorType             detectorColumnDirection;\n  std::vector<GeometryType::PointType> phantomMarkers;\n\n  VERBOSE(<< \"  * Generating data sets ... \")\n  lok = true;\n  {\n    // determine a few random phantom markers around isocenter\n    constexpr int NUM_PHANTOM_MARKERS = 5;\n    auto          generator = RandomType::New();\n    generator->SetSeed(123456);\n    GeometryType::PointType p;\n    for (int i = 0; i < NUM_PHANTOM_MARKERS; i++)\n    {\n      for (int d = 0; d < 3; d++)\n        p[d] = generator->GetUniformVariate(-50, 50);\n      phantomMarkers.push_back(p);\n    }\n    // setup a basic REG23-like geometry imitating basically XVI at 0 deg w.r.t\n    // IEC CS (normally encapsulated in REG23's ora::ProjectionGeometry):\n    sourcePosition[0] = 0.;\n    sourcePosition[1] = 0.;\n    sourcePosition[2] = 1000.;\n    detectorPosition[0] = -(1024. * 0.4) / 2. + 0.4 / 2.;\n    detectorPosition[1] = -(1024. * 0.4) / 2. + 0.4 / 2.;\n    detectorPosition[2] = -536.;\n    detectorRowDirection[0] = 1.;\n    detectorRowDirection[1] = 0.;\n    detectorRowDirection[2] = 0.;\n    detectorColumnDirection[0] = 0.;\n    detectorColumnDirection[1] = 1.;\n    detectorColumnDirection[2] = 0.;\n  }\n  ok = ok && lok;\n  VERBOSE(<< (lok ? \"OK\" : \"FAILURE\") << \"\\n\")\n\n\n  VERBOSE(<< \"  * Swirl imaging device, compute reference projections and \"\n          << \"configure RTK projection list ... \")\n  lok = true;\n  std::vector<Point2DType>             referenceMarkerProjections;\n  std::vector<Point2DType>             rtkMarkerProjections;\n  std::vector<GeometryType::PointType> anglesList;\n  GeometryType::PointType              aaa;\n  auto                                 rtkProjectionsList = GeometryType::New();\n  {\n    const double degreesToRadians = atan(1.0) / 45.;\n\n    auto generator = RandomType::New();\n    generator->SetSeed(123456);\n\n    GeometryType::PointType             locSourcePosition;\n    GeometryType::PointType             locDetectorPosition;\n    GeometryType::VectorType            locDetectorPositionVec;\n    GeometryType::VectorType            locDetectorRowDirection;\n    GeometryType::VectorType            locDetectorColumnDirection;\n    GeometryType::VectorType            n;\n    GeometryType::VectorType            X;\n    Point2DType                         p2d;\n    GeometryType::MatrixType            rtkMatrix;\n    GeometryType::HomogeneousVectorType hv;\n    GeometryType::VectorType            tmp;\n\n    auto                eu = itk::Euler3DTransform<double>::New();\n    std::vector<double> gantryAngles;\n    std::vector<double> outOfPlaneAngles;\n    std::vector<double> inPlaneAngles;\n    std::vector<double> criticalAngles;\n\n    // create list of \"critical\" angles in general:\n    criticalAngles.push_back(-180);\n    criticalAngles.push_back(-90);\n    criticalAngles.push_back(-0);\n    criticalAngles.push_back(0);\n    criticalAngles.push_back(90);\n    criticalAngles.push_back(180);\n    // further potentially interesting angles:\n    criticalAngles.push_back(-150);\n    criticalAngles.push_back(-120);\n    criticalAngles.push_back(-60);\n    criticalAngles.push_back(-30);\n    criticalAngles.push_back(150);\n    criticalAngles.push_back(120);\n    criticalAngles.push_back(60);\n    criticalAngles.push_back(30);\n    inPlaneAngles.insert(inPlaneAngles.end(), criticalAngles.begin(), criticalAngles.end());\n    gantryAngles.insert(gantryAngles.end(), criticalAngles.begin(), criticalAngles.end());\n    outOfPlaneAngles.insert(outOfPlaneAngles.end(), criticalAngles.begin(), criticalAngles.end());\n    // randomly sample further angles in [-180;+180] deg range:\n    constexpr int NUM_RANDOM_ANGLES = 100;\n    for (int u = 0; u < NUM_RANDOM_ANGLES; u++)\n    {\n      inPlaneAngles.push_back(generator->GetUniformVariate(-180, 180));\n      gantryAngles.push_back(generator->GetUniformVariate(-180, 180));\n      outOfPlaneAngles.push_back(generator->GetUniformVariate(-180, 180));\n    }\n\n    for (const double gantryAngle : gantryAngles)\n    {\n      for (const double outOfPlaneAngle : outOfPlaneAngles)\n      {\n        for (const double inPlaneAngle : inPlaneAngles)\n        {\n          rtkProjectionsList->Clear(); // reduce required memory\n\n          // \"swirl\" the device around (not only circular trajectory, spherical):\n          eu->SetRotation(\n            outOfPlaneAngle * degreesToRadians, gantryAngle * degreesToRadians, inPlaneAngle * degreesToRadians);\n          locSourcePosition = eu->TransformPoint(sourcePosition);\n          locDetectorPosition = eu->TransformPoint(detectorPosition);\n          locDetectorRowDirection = eu->TransformVector(detectorRowDirection);\n          locDetectorColumnDirection = eu->TransformVector(detectorColumnDirection);\n\n          // offset detector and source randomly to make it more interesting:\n          for (int d = 0; d < 3; d++)\n          {\n            locSourcePosition[d] += generator->GetUniformVariate(-100, 100);\n            locDetectorPosition[d] += generator->GetUniformVariate(-100, 100);\n            locDetectorPositionVec[d] = locDetectorPosition[d]; // helper\n          }\n\n          // compute analytically the relative 2D projection position related to the\n          // detector position:\n          for (const GeometryType::PointType & phantomMarker : phantomMarkers)\n          {\n            n = itk::CrossProduct(locDetectorRowDirection, locDetectorColumnDirection);\n            IntersectPlaneWithLine(locSourcePosition, phantomMarker, n, locDetectorPosition, X);\n            p2d[0] = X * locDetectorRowDirection - locDetectorPositionVec * locDetectorRowDirection;\n            p2d[1] = X * locDetectorColumnDirection - locDetectorPositionVec * locDetectorColumnDirection;\n\n            referenceMarkerProjections.push_back(p2d);\n          }\n\n          // add to RTK projection list using the new method:\n          if (!rtkProjectionsList->AddReg23Projection(\n                locSourcePosition, locDetectorPosition, locDetectorRowDirection, locDetectorColumnDirection))\n          {\n            lok = false;\n          }\n\n          // compute RTK projection for each marker:\n          rtkMatrix = rtkProjectionsList->GetMatrices()[rtkProjectionsList->GetMatrices().size() - 1];\n          for (const GeometryType::PointType & phantomMarker : phantomMarkers)\n          {\n            hv[0] = phantomMarker[0];\n            hv[1] = phantomMarker[1];\n            hv[2] = phantomMarker[2];\n            hv[3] = 1.;\n            tmp = rtkMatrix * hv;\n            p2d[0] = tmp[0] / tmp[2]; // perspective divide\n            p2d[1] = tmp[1] / tmp[2];\n\n            rtkMarkerProjections.push_back(p2d);\n\n            // for possible error output later on:\n            aaa[0] = outOfPlaneAngle;\n            aaa[1] = gantryAngle;\n            aaa[2] = inPlaneAngle;\n            anglesList.push_back(aaa);\n          }\n        }\n      }\n    }\n  }\n  ok = ok && lok;\n  VERBOSE(<< (lok ? \"OK\" : \"FAILURE\") << \"\\n\")\n\n\n  VERBOSE(<< \"  * Check whether RTK projections match reference projections ... \")\n  lok = true;\n  {\n    const double EPSILON = 1e-3; // im unit is mm -> correct in um-range\n    std::size_t  fails = 0;\n    if (referenceMarkerProjections.size() == rtkMarkerProjections.size())\n    {\n      for (std::size_t i = 0; i < referenceMarkerProjections.size(); ++i)\n      {\n        if (itk::Math::abs(referenceMarkerProjections[i][0] - rtkMarkerProjections[i][0]) > EPSILON ||\n            itk::Math::abs(referenceMarkerProjections[i][1] - rtkMarkerProjections[i][1]) > EPSILON)\n        {\n          VERBOSE(<< \"\\nAngle-combination out-of-plane=\" << anglesList[i][0] << \", gantry=\" << anglesList[i][1]\n                  << \", in-plane=\" << anglesList[i][2] << \" failed:\\n\")\n          VERBOSE(<< \"  \" << referenceMarkerProjections[i] << \" vs. \" << rtkMarkerProjections[i] << \"\\n\")\n          lok = false;\n          fails++;\n        }\n      }\n      VERBOSE(<< \" [ok: \" << (rtkMarkerProjections.size() - fails) << \", fails: \" << fails << \"] \")\n    }\n    else\n    {\n      lok = false;\n    }\n  }\n  ok = ok && lok;\n  VERBOSE(<< (lok ? \"OK\" : \"FAILURE\") << \"\\n\")\n\n\n  VERBOSE(<< \"Test result: \")\n  if (ok)\n  {\n    VERBOSE(<< \"OK\\n\\n\")\n    return EXIT_SUCCESS;\n  }\n  else\n  {\n    VERBOSE(<< \"FAILURE\\n\\n\")\n    return EXIT_FAILURE;\n  }\n}\n"
  },
  {
    "path": "test/rtkadjointoperatorstest.cxx",
    "content": "#include \"rtkMacro.h\"\n#include \"rtkTest.h\"\n#include \"itkRandomImageSource.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkJosephBackProjectionImageFilter.h\"\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n#include \"rtkJosephBackAttenuatedProjectionImageFilter.h\"\n#include \"rtkJosephForwardAttenuatedProjectionImageFilter.h\"\n#include \"rtkZengBackProjectionImageFilter.h\"\n#include \"rtkZengForwardProjectionImageFilter.h\"\n#ifdef USE_CUDA\n#  include \"rtkCudaForwardProjectionImageFilter.h\"\n#  include \"rtkCudaRayCastBackProjectionImageFilter.h\"\n#endif\n\n/**\n * \\file rtkadjointoperatorstest.cxx\n *\n * \\brief Tests whether forward and back projectors are matched\n *\n * This test generates a random volume \"v\" and a random set of projections \"p\",\n * and compares the scalar products <Rv , p> and <v, R* p>, where R is either the\n * Joseph forward projector or the Cuda ray cast forward projector,\n * and R* is either the Joseph back projector or the Cuda ray cast back projector.\n * If R* is indeed the adjoint of R, these scalar products are equal.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n\n#ifdef USE_CUDA\n  using OutputPixelType = float;\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputPixelType = double;\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 60;\n#endif\n\n  // Random image sources\n  using RandomImageSourceType = itk::RandomImageSource<OutputImageType>;\n  auto randomVolumeSource = RandomImageSourceType::New();\n  auto randomProjectionsSource = RandomImageSourceType::New();\n\n  // Constant sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantVolumeSource = ConstantImageSourceType::New();\n  auto constantProjectionsSource = ConstantImageSourceType::New();\n  auto constantAttenuationSource = ConstantImageSourceType::New();\n\n  // Volume metadata\n  auto origin = itk::MakePoint(-128., -128., -128.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(252., 252., 252.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto size = itk::MakeSize(65, 65, 65);\n#endif\n  randomVolumeSource->SetOrigin(origin);\n  randomVolumeSource->SetSpacing(spacing);\n  randomVolumeSource->SetSize(size);\n  randomVolumeSource->SetMin(0.);\n  randomVolumeSource->SetMax(1.);\n  randomVolumeSource->SetNumberOfWorkUnits(2); // With 1, it's deterministic\n\n  constantVolumeSource->SetOrigin(origin);\n  constantVolumeSource->SetSpacing(spacing);\n  constantVolumeSource->SetSize(size);\n  constantVolumeSource->SetConstant(0.);\n\n  constantAttenuationSource->SetOrigin(origin);\n  constantAttenuationSource->SetSpacing(spacing);\n  constantAttenuationSource->SetSize(size);\n  constantAttenuationSource->SetConstant(0.0154);\n\n  // Projections metadata\n  origin = itk::MakePoint(-128., -128., -128.);\n#if FAST_TESTS_NO_CHECKS\n  spacing = itk::MakeVector(504., 504., 504.);\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n#else\n  spacing = itk::MakeVector(4., 4., 1.);\n  size = itk::MakeSize(65, 65, NumberOfProjectionImages);\n#endif\n  randomProjectionsSource->SetOrigin(origin);\n  randomProjectionsSource->SetSpacing(spacing);\n  randomProjectionsSource->SetSize(size);\n  randomProjectionsSource->SetMin(0.);\n  randomProjectionsSource->SetMax(100.);\n\n  constantProjectionsSource->SetOrigin(origin);\n  constantProjectionsSource->SetSpacing(spacing);\n  constantProjectionsSource->SetSize(size);\n  constantProjectionsSource->SetConstant(0.);\n\n  // Update all sources\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource->UpdateLargestPossibleRegion(););\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantVolumeSource->UpdateLargestPossibleRegion());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomProjectionsSource->UpdateLargestPossibleRegion());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantProjectionsSource->UpdateLargestPossibleRegion());\n\n  // Geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  for (unsigned int panel = 0; panel < 2; panel++)\n  {\n    if (panel == 0)\n      std::cout << \"\\n\\n****** Testing with flat panel ******\" << std::endl;\n    else\n    {\n      std::cout << \"\\n\\n****** Testing with cylindrical panel ******\" << std::endl;\n      geometry->SetRadiusCylindricalDetector(200);\n    }\n\n    std::cout << \"\\n\\n****** Joseph Forward projector ******\" << std::endl;\n\n    auto fw = rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType>::New();\n    fw->SetInput(0, constantProjectionsSource->GetOutput());\n    fw->SetInput(1, randomVolumeSource->GetOutput());\n    fw->SetGeometry(geometry);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(fw->Update());\n\n    std::cout << \"\\n\\n****** Joseph Back projector ******\" << std::endl;\n\n    auto bp = rtk::JosephBackProjectionImageFilter<OutputImageType, OutputImageType>::New();\n    bp->SetInput(0, constantVolumeSource->GetOutput());\n    bp->SetInput(1, randomProjectionsSource->GetOutput());\n    bp->SetGeometry(geometry.GetPointer());\n\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(bp->Update());\n\n    CheckScalarProducts<OutputImageType, OutputImageType>(\n      randomVolumeSource->GetOutput(), bp->GetOutput(), randomProjectionsSource->GetOutput(), fw->GetOutput());\n    std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n    using VectorImageType = itk::Image<itk::Vector<OutputPixelType, 3>, Dimension>;\n    auto vectorRandomProjections = VectorImageType::New();\n    auto vectorConstantProjections = VectorImageType::New();\n    auto vectorRandomVolume = VectorImageType::New();\n    auto vectorConstantVolume = VectorImageType::New();\n    vectorRandomProjections->CopyInformation(randomProjectionsSource->GetOutput());\n    vectorRandomProjections->SetRegions(randomProjectionsSource->GetOutput()->GetLargestPossibleRegion());\n    vectorRandomProjections->Allocate();\n    itk::ImageRegionIterator<VectorImageType> outIt1(vectorRandomProjections,\n                                                     vectorRandomProjections->GetLargestPossibleRegion());\n    itk::ImageRegionIterator<OutputImageType> inIt1(randomProjectionsSource->GetOutput(),\n                                                    randomProjectionsSource->GetOutput()->GetLargestPossibleRegion());\n    itk::Vector<OutputPixelType, 3>           temp;\n    while (!outIt1.IsAtEnd())\n    {\n      temp[0] = inIt1.Get();\n      temp[1] = inIt1.Get();\n      temp[2] = inIt1.Get();\n      outIt1.Set(temp);\n      ++outIt1;\n      ++inIt1;\n    }\n\n    constantVolumeSource->Update();\n    vectorConstantVolume->CopyInformation(constantVolumeSource->GetOutput());\n    vectorConstantVolume->SetRegions(constantVolumeSource->GetOutput()->GetLargestPossibleRegion());\n    vectorConstantVolume->Allocate();\n    itk::ImageRegionIterator<VectorImageType> outIt2(vectorConstantVolume,\n                                                     vectorConstantVolume->GetLargestPossibleRegion());\n    itk::ImageRegionIterator<OutputImageType> inIt2(constantVolumeSource->GetOutput(),\n                                                    constantVolumeSource->GetOutput()->GetLargestPossibleRegion());\n    while (!outIt2.IsAtEnd())\n    {\n      temp[0] = inIt2.Get();\n      temp[1] = inIt2.Get();\n      temp[2] = inIt2.Get();\n      outIt2.Set(temp);\n      ++outIt2;\n      ++inIt2;\n    }\n\n    constantProjectionsSource->Update();\n    vectorConstantProjections->CopyInformation(constantProjectionsSource->GetOutput());\n    vectorConstantProjections->SetRegions(constantProjectionsSource->GetOutput()->GetLargestPossibleRegion());\n    vectorConstantProjections->Allocate();\n    itk::ImageRegionIterator<VectorImageType> outIt3(vectorConstantProjections,\n                                                     vectorConstantProjections->GetLargestPossibleRegion());\n    itk::ImageRegionIterator<OutputImageType> inIt3(constantProjectionsSource->GetOutput(),\n                                                    constantProjectionsSource->GetOutput()->GetLargestPossibleRegion());\n    while (!outIt3.IsAtEnd())\n    {\n      temp[0] = inIt3.Get();\n      temp[1] = inIt3.Get();\n      temp[2] = inIt3.Get();\n      outIt3.Set(temp);\n      ++outIt3;\n      ++inIt3;\n    }\n\n    vectorRandomVolume->CopyInformation(randomVolumeSource->GetOutput());\n    vectorRandomVolume->SetRegions(randomVolumeSource->GetOutput()->GetLargestPossibleRegion());\n    vectorRandomVolume->Allocate();\n    itk::ImageRegionIterator<VectorImageType> outIt4(vectorRandomVolume,\n                                                     vectorRandomVolume->GetLargestPossibleRegion());\n    itk::ImageRegionIterator<OutputImageType> inIt4(randomVolumeSource->GetOutput(),\n                                                    randomVolumeSource->GetOutput()->GetLargestPossibleRegion());\n    while (!outIt4.IsAtEnd())\n    {\n      temp[0] = inIt4.Get();\n      temp[1] = inIt4.Get();\n      temp[2] = inIt4.Get();\n      outIt4.Set(temp);\n      ++outIt4;\n      ++inIt4;\n    }\n\n    std::cout << \"\\n\\n****** Joseph Vector Forward projector ******\" << std::endl;\n\n\n    auto vfw = rtk::JosephForwardProjectionImageFilter<VectorImageType, VectorImageType>::New();\n    vfw->SetInput(0, vectorConstantProjections);\n    vfw->SetInput(1, vectorRandomVolume);\n    vfw->SetGeometry(geometry);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(vfw->Update());\n\n    std::cout << \"\\n\\n****** Joseph Vector Back projector ******\" << std::endl;\n    auto vbp = rtk::JosephBackProjectionImageFilter<VectorImageType, VectorImageType>::New();\n    vbp->SetInput(0, vectorConstantVolume);\n    vbp->SetInput(1, vectorRandomProjections);\n    vbp->SetGeometry(geometry.GetPointer());\n\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(vbp->Update());\n\n    CheckVectorScalarProducts<VectorImageType, VectorImageType>(\n      vectorRandomVolume, vbp->GetOutput(), vectorRandomProjections, vfw->GetOutput());\n    std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n    std::cout << \"\\n\\n****** Attenuated Joseph Forward projector ******\" << std::endl;\n\n    auto attfw = rtk::JosephForwardAttenuatedProjectionImageFilter<OutputImageType, OutputImageType>::New();\n    attfw->SetInput(0, constantProjectionsSource->GetOutput());\n    attfw->SetInput(1, randomVolumeSource->GetOutput());\n    attfw->SetInput(2, constantAttenuationSource->GetOutput());\n    attfw->SetGeometry(geometry);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(attfw->Update());\n\n    std::cout << \"\\n\\n****** Attenuated Joseph Back projector ******\" << std::endl;\n\n    auto attbp = rtk::JosephBackAttenuatedProjectionImageFilter<OutputImageType, OutputImageType>::New();\n    attbp->SetInput(0, constantVolumeSource->GetOutput());\n    attbp->SetInput(1, randomProjectionsSource->GetOutput());\n    attbp->SetInput(2, constantAttenuationSource->GetOutput());\n    attbp->SetGeometry(geometry.GetPointer());\n\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(attbp->Update());\n\n    CheckScalarProducts<OutputImageType, OutputImageType>(\n      randomVolumeSource->GetOutput(), attbp->GetOutput(), randomProjectionsSource->GetOutput(), attfw->GetOutput());\n    std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n    std::cout << \"\\n\\n****** Cuda Ray Cast Forward projector ******\" << std::endl;\n\n    auto cfw = rtk::CudaForwardProjectionImageFilter<OutputImageType, OutputImageType>::New();\n    cfw->SetInput(0, constantProjectionsSource->GetOutput());\n    cfw->SetInput(1, randomVolumeSource->GetOutput());\n    cfw->SetGeometry(geometry);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cfw->Update());\n\n    std::cout << \"\\n\\n****** Cuda Ray Cast Back projector ******\" << std::endl;\n\n    auto cbp = rtk::CudaRayCastBackProjectionImageFilter::New();\n    cbp->SetInput(0, constantVolumeSource->GetOutput());\n    cbp->SetInput(1, randomProjectionsSource->GetOutput());\n    cbp->SetGeometry(geometry.GetPointer());\n    cbp->SetNormalize(false);\n\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cbp->Update());\n\n    CheckScalarProducts<OutputImageType, OutputImageType>(\n      randomVolumeSource->GetOutput(), cbp->GetOutput(), randomProjectionsSource->GetOutput(), cfw->GetOutput());\n    std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n  }\n\n  // Geometry parallel object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry_parallel = GeometryType::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry_parallel->AddProjection(500., 0., noProj * 360. / NumberOfProjectionImages, 8., -4.);\n\n\n  std::cout << \"\\n\\n******  Zeng Forward projector ******\" << std::endl;\n\n  using ZengForwardProjectorType = rtk::ZengForwardProjectionImageFilter<OutputImageType, OutputImageType>;\n  auto zfw = ZengForwardProjectorType::New();\n  zfw->SetInput(0, constantProjectionsSource->GetOutput());\n  zfw->SetInput(1, randomVolumeSource->GetOutput());\n  zfw->SetGeometry(geometry_parallel);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(zfw->Update());\n\n  std::cout << \"\\n\\n****** Zeng Back projector ******\" << std::endl;\n\n  using ZengBackProjectorType = rtk::ZengBackProjectionImageFilter<OutputImageType, OutputImageType>;\n  auto zbp = ZengBackProjectorType::New();\n  zbp->SetInput(0, constantVolumeSource->GetOutput());\n  zbp->SetInput(1, randomProjectionsSource->GetOutput());\n  zbp->SetGeometry(geometry_parallel);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(zbp->Update());\n\n  CheckScalarProducts<OutputImageType, OutputImageType>(\n    randomVolumeSource->GetOutput(), zbp->GetOutput(), randomProjectionsSource->GetOutput(), zfw->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n******  Attenuated Zeng Forward projector ******\" << std::endl;\n\n  using ZengForwardProjectorType = rtk::ZengForwardProjectionImageFilter<OutputImageType, OutputImageType>;\n  auto attzfw = ZengForwardProjectorType::New();\n  attzfw->SetInput(0, constantProjectionsSource->GetOutput());\n  attzfw->SetInput(1, randomVolumeSource->GetOutput());\n  attzfw->SetInput(2, constantAttenuationSource->GetOutput());\n  attzfw->SetGeometry(geometry_parallel);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(attzfw->Update());\n\n  std::cout << \"\\n\\n****** Attenuated Zeng Back projector ******\" << std::endl;\n\n  using ZengBackProjectorType = rtk::ZengBackProjectionImageFilter<OutputImageType, OutputImageType>;\n  auto attzbp = ZengBackProjectorType::New();\n  attzbp->SetInput(0, constantVolumeSource->GetOutput());\n  attzbp->SetInput(1, randomProjectionsSource->GetOutput());\n  attzbp->SetInput(2, constantAttenuationSource->GetOutput());\n  attzbp->SetGeometry(geometry_parallel);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(attzbp->Update());\n\n  CheckScalarProducts<OutputImageType, OutputImageType>(\n    randomVolumeSource->GetOutput(), attzbp->GetOutput(), randomProjectionsSource->GetOutput(), attzfw->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkadmmtotalvariationtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkADMMTotalVariationConeBeamReconstructionFilter.h\"\n#include \"rtkPhaseGatingImageFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n\n/**\n * \\file rtkadmmtotalvariationtest.cxx\n *\n * \\brief Functional test for ADMMTotalVariation reconstruction\n *\n * This test generates the projections of an ellipsoid and reconstructs the CT\n * image using the ADMMTotalVariation algorithm with different backprojectors (Voxel-Based,\n * Joseph). The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 3)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \" phases.txt phases_light.txt\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 90;\n#endif\n\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(252., 252., 252.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto size = itk::MakeSize(64, 64, 64);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  spacing = itk::MakeVector(504., 504., 504.);\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n#else\n  spacing = itk::MakeVector(8., 8., 8.);\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create ellipsoid PROJECTIONS\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::Pointer rei;\n\n  rei = REIType::New();\n  REIType::VectorType semiprincipalaxis, center;\n  semiprincipalaxis.Fill(90.);\n  center.Fill(0.);\n  rei->SetAngle(0.);\n  rei->SetDensity(1.);\n  rei->SetCenter(center);\n  rei->SetAxis(semiprincipalaxis);\n\n  rei->SetInput(projectionsSource->GetOutput());\n  rei->SetGeometry(geometry);\n\n  // Update\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n\n  // Create REFERENCE object (3D ellipsoid).\n  auto dsl = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // ADMMTotalVariation reconstruction filtering\n  using ADMMTotalVariationType = rtk::ADMMTotalVariationConeBeamReconstructionFilter<OutputImageType>;\n  auto admmtotalvariation = ADMMTotalVariationType::New();\n  admmtotalvariation->SetInput(tomographySource->GetOutput());\n  admmtotalvariation->SetInput(1, rei->GetOutput());\n  admmtotalvariation->SetGeometry(geometry);\n  admmtotalvariation->SetAlpha(100);\n  admmtotalvariation->SetBeta(1000);\n  admmtotalvariation->SetAL_iterations(3);\n  admmtotalvariation->SetCG_iterations(2);\n\n  // In all cases except CUDA, use the Joseph forward projector\n  admmtotalvariation->SetForwardProjectionFilter(ADMMTotalVariationType::FP_JOSEPH);\n\n  std::cout << \"\\n\\n****** Case 1: Voxel-Based Backprojector ******\" << std::endl;\n\n  admmtotalvariation->SetBackProjectionFilter(ADMMTotalVariationType::BP_VOXELBASED);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmtotalvariation->Update());\n\n  CheckImageQuality<OutputImageType>(admmtotalvariation->GetOutput(), dsl->GetOutput(), 0.05, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Joseph Backprojector ******\" << std::endl;\n\n  admmtotalvariation->SetBackProjectionFilter(ADMMTotalVariationType::BP_JOSEPH);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmtotalvariation->Update());\n\n  CheckImageQuality<OutputImageType>(admmtotalvariation->GetOutput(), dsl->GetOutput(), 0.05, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 3: CUDA Voxel-Based Backprojector and CUDA Forward projector ******\" << std::endl;\n\n  admmtotalvariation->SetForwardProjectionFilter(ADMMTotalVariationType::FP_CUDARAYCAST);\n  admmtotalvariation->SetBackProjectionFilter(ADMMTotalVariationType::BP_CUDAVOXELBASED);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmtotalvariation->Update());\n\n  CheckImageQuality<OutputImageType>(admmtotalvariation->GetOutput(), dsl->GetOutput(), 0.05, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  std::cout << \"\\n\\n****** Voxel-Based Backprojector and gating ******\" << std::endl;\n\n  admmtotalvariation->SetForwardProjectionFilter(ADMMTotalVariationType::FP_JOSEPH);\n  admmtotalvariation->SetBackProjectionFilter(ADMMTotalVariationType::BP_VOXELBASED);\n\n  // Generate arbitrary gating weights (select every third projection)\n  auto phaseGating = rtk::PhaseGatingImageFilter<OutputImageType>::New();\n#if FAST_TESTS_NO_CHECKS\n  phaseGating->SetPhasesFileName(argv[2]);\n#else\n  phaseGating->SetPhasesFileName(argv[1]);\n#endif\n  phaseGating->SetGatingWindowWidth(0.20);\n  phaseGating->SetGatingWindowShape(0); // Rectangular\n  phaseGating->SetGatingWindowCenter(0.70);\n  phaseGating->SetInputProjectionStack(rei->GetOutput());\n  phaseGating->SetInputGeometry(geometry);\n  phaseGating->Update();\n\n  admmtotalvariation->SetInput(1, phaseGating->GetOutput());\n  admmtotalvariation->SetGeometry(phaseGating->GetOutputGeometry());\n  admmtotalvariation->SetGatingWeights(phaseGating->GetGatingWeightsOnSelectedProjections());\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmtotalvariation->Update());\n\n  CheckImageQuality<OutputImageType>(admmtotalvariation->GetOutput(), dsl->GetOutput(), 0.05, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkadmmwaveletstest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n\n#include \"rtkTestConfiguration.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n// #include \"rtkNormalizedJosephBackProjectionImageFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n#include \"rtkADMMWaveletsConeBeamReconstructionFilter.h\"\n\ntemplate <class TImage>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckImageQuality(typename TImage::Pointer itkNotUsed(recon), typename TImage::Pointer itkNotUsed(ref))\n{}\n#else\nvoid\nCheckImageQuality(typename TImage::Pointer recon, typename TImage::Pointer ref)\n{\n  using ImageIteratorType = itk::ImageRegionConstIterator<TImage>;\n  ImageIteratorType itTest(recon, recon->GetBufferedRegion());\n  ImageIteratorType itRef(ref, ref->GetBufferedRegion());\n\n  using ErrorType = double;\n  ErrorType TestError = 0.;\n  ErrorType EnerError = 0.;\n\n  itTest.GoToBegin();\n  itRef.GoToBegin();\n\n  while (!itRef.IsAtEnd())\n  {\n    typename TImage::PixelType TestVal = itTest.Get();\n    typename TImage::PixelType RefVal = itRef.Get();\n    TestError += itk::Math::abs(RefVal - TestVal);\n    EnerError += std::pow(ErrorType(RefVal - TestVal), 2.);\n    ++itTest;\n    ++itRef;\n  }\n  // Error per Pixel\n  ErrorType ErrorPerPixel = TestError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"\\nError per Pixel = \" << ErrorPerPixel << std::endl;\n  // MSE\n  ErrorType MSE = EnerError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"MSE = \" << MSE << std::endl;\n  // PSNR\n  ErrorType PSNR = 20 * log10(2.0) - 10 * log10(MSE);\n  std::cout << \"PSNR = \" << PSNR << \"dB\" << std::endl;\n  // QI\n  ErrorType QI = (2.0 - ErrorPerPixel) / 2.0;\n  std::cout << \"QI = \" << QI << std::endl;\n\n  // Checking results\n  if (ErrorPerPixel > 0.032)\n  {\n    std::cerr << \"Test Failed, Error per pixel not valid! \" << ErrorPerPixel << \" instead of 0.08\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  if (PSNR < 28)\n  {\n    std::cerr << \"Test Failed, PSNR not valid! \" << PSNR << \" instead of 23\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif\n\n/**\n * \\file rtkadmmwaveletstest.cxx\n *\n * \\brief Functional test for ADMMWavelets reconstruction\n *\n * This test generates the projections of an ellipsoid and reconstructs the CT\n * image using the ADMMWavelets algorithm with different backprojectors (Voxel-Based,\n * Joseph). The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(252., 252., 252.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto size = itk::MakeSize(64, 64, 64);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  spacing = itk::MakeVector(504., 504., 504.);\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n#else\n  spacing = itk::MakeVector(8., 8., 8.);\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create ellipsoid PROJECTIONS\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::Pointer rei;\n\n  rei = REIType::New();\n  rei->SetAngle(0.);\n  rei->SetDensity(1.);\n  rei->SetCenter(itk::MakeVector(0., 0., 0.));\n  rei->SetAxis(itk::MakeVector(90., 90., 90.));\n\n  rei->SetInput(projectionsSource->GetOutput());\n  rei->SetGeometry(geometry);\n\n  // Update\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n\n  // Create REFERENCE object (3D ellipsoid).\n  auto dsl = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // ADMMWavelets reconstruction filtering\n  using ADMMWaveletsType = rtk::ADMMWaveletsConeBeamReconstructionFilter<OutputImageType>;\n  auto admmWavelets = ADMMWaveletsType::New();\n  admmWavelets->SetInput(tomographySource->GetOutput());\n  admmWavelets->SetInput(1, rei->GetOutput());\n  admmWavelets->SetGeometry(geometry);\n  admmWavelets->SetAlpha(10);\n  admmWavelets->SetBeta(1000);\n  admmWavelets->SetAL_iterations(3);\n  admmWavelets->SetCG_iterations(3);\n  admmWavelets->SetNumberOfLevels(3);\n  admmWavelets->SetOrder(3);\n\n  // In all cases, use the Joseph forward projector\n  admmWavelets->SetForwardProjectionFilter(ADMMWaveletsType::FP_JOSEPH);\n\n  std::cout << \"\\n\\n****** Case 1: Voxel-Based Backprojector ******\" << std::endl;\n\n  admmWavelets->SetBackProjectionFilter(ADMMWaveletsType::BP_VOXELBASED);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmWavelets->Update());\n\n  CheckImageQuality<OutputImageType>(admmWavelets->GetOutput(), dsl->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Joseph Backprojector ******\" << std::endl;\n\n  admmWavelets->SetBackProjectionFilter(ADMMWaveletsType::BP_JOSEPH);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmWavelets->Update());\n\n  CheckImageQuality<OutputImageType>(admmWavelets->GetOutput(), dsl->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 3: CUDA Voxel-Based Backprojector and CUDA Forward projector ******\" << std::endl;\n\n  admmWavelets->SetForwardProjectionFilter(ADMMWaveletsType::FP_CUDARAYCAST);\n  admmWavelets->SetBackProjectionFilter(ADMMWaveletsType::BP_CUDAVOXELBASED);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(admmWavelets->Update());\n\n  CheckImageQuality<OutputImageType>(admmWavelets->GetOutput(), dsl->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkamsterdamshroudtest.cxx",
    "content": "#include <itkImageFileReader.h>\n#include <itkPasteImageFilter.h>\n#include <itkConfigure.h>\n\n#include \"rtkTest.h\"\n#include \"rtkAmsterdamShroudImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkReg1DExtractShroudSignalImageFilter.h\"\n#include \"rtkDPExtractShroudSignalImageFilter.h\"\n#include \"rtkMacro.h\"\n#include \"rtkExtractPhaseImageFilter.h\"\n\n/**\n * \\file rtkamsterdamshroudtest.cxx\n *\n * \\brief Functional test for classes performing Amsterdam Shroud and breathing signal extraction algorithms\n *\n * This test generates an Amsterdam Shroud image from a moving simulated phantom\n * and extracts the breathing signal using two different methods, reg1D and D\n * algorithms. The generated results are compared to the expected results,\n * read from a baseline image in the MetaIO file format and hard-coded,\n * respectively.\n *\n * \\author Marc Vila\n */\nint\nmain(int argc, char * argv[])\n{\n  constexpr unsigned int Dimension = 3;\n  using reg1DPixelType = double;\n  using OutputImageType = itk::Image<float, Dimension>;\n  using reg1DImageType = itk::Image<reg1DPixelType, Dimension - 2>;\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 100;\n#endif\n\n  if (argc < 3)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \" croppedRefObject refObject \" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometryMain = GeometryType::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometryMain->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create a stack of empty projection images\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n\n  // Adjust size according to geometry and for just one projection\n  auto constantImageSourceSingleProjection = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-50., -50., -158.75);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(106., 106., 2.5);\n  auto size = itk::MakeSize(4, 4, 1);\n#else\n  auto spacing = itk::MakeVector(2.5, 2.5, 2.5);\n  auto size = itk::MakeSize(128, 128, 1);\n#endif\n  constantImageSourceSingleProjection->SetOrigin(origin);\n  constantImageSourceSingleProjection->SetSpacing(spacing);\n  constantImageSourceSingleProjection->SetSize(size);\n  constantImageSourceSingleProjection->SetConstant(0.);\n\n  // Adjust size according to geometry\n  auto constantImageSource = ConstantImageSourceType::New();\n  size[2] = NumberOfProjectionImages;\n  constantImageSource->SetOrigin(origin);\n  constantImageSource->SetSpacing(spacing);\n  constantImageSource->SetSize(size);\n  constantImageSource->SetConstant(0.);\n\n  OutputImageType::IndexType destinationIndex;\n  destinationIndex[0] = 0;\n  destinationIndex[1] = 0;\n  destinationIndex[2] = 0;\n\n  auto pasteFilter = itk::PasteImageFilter<OutputImageType, OutputImageType, OutputImageType>::New();\n\n  // Single projection\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  double                 reiSize = 80.;\n  double                 sinus = 0.;\n  constexpr unsigned int Cycles = 4;\n\n  OutputImageType::Pointer wholeImage = constantImageSource->GetOutput();\n  auto                     geometryFull = GeometryType::New();\n  for (unsigned int i = 1; i <= size[2]; i++)\n  {\n    // Geometry object\n    auto geometry = GeometryType::New();\n    geometry->AddProjection(1200., 1500., i * 360 / size[2]);\n    geometryFull->AddProjection(1200., 1500., i * 360 / size[2]);\n\n    // Ellipse 1\n    auto e1 = REIType::New();\n    e1->SetInput(constantImageSourceSingleProjection->GetOutput());\n    e1->SetGeometry(geometry);\n    e1->SetDensity(2.);\n    e1->SetAxis(itk::MakeVector(88.32, 115.2, 117.76));\n    e1->SetCenter(itk::MakeVector(0., 0., 0.));\n    e1->SetAngle(0.);\n    e1->InPlaceOff();\n    e1->Update();\n\n    // Ellipse 2\n    auto e2 = REIType::New();\n    e2->SetInput(e1->GetOutput());\n    e2->SetGeometry(geometry);\n    e2->SetDensity(-1.98);\n    e2->SetAxis(itk::MakeVector(35., reiSize - sinus, reiSize - sinus));\n    e2->SetCenter(itk::MakeVector(-37., 0., 0.));\n    e2->SetAngle(0.);\n    e2->Update();\n\n    // Ellipse 3\n    auto e3 = REIType::New();\n    e3->SetInput(e2->GetOutput());\n    e3->SetGeometry(geometry);\n    e3->SetDensity(-1.98);\n    e3->SetAxis(itk::MakeVector(35., reiSize - sinus, reiSize - sinus));\n    e3->SetCenter(itk::MakeVector(37., 0., 0.));\n    e3->SetAngle(0.);\n    e3->Update();\n\n    // Ellipse 4\n    auto e4 = REIType::New();\n    e4->SetInput(e3->GetOutput());\n    e4->SetGeometry(geometry);\n    e4->SetDensity(1.42);\n    e4->SetAxis(itk::MakeVector(8., 8., 8.));\n    e4->SetCenter(itk::MakeVector(-40., 0., 0.));\n    e4->SetAngle(0.);\n\n    // Creating movement\n    sinus = 15 * sin(i * 2 * itk::Math::pi / (size[2] / Cycles));\n\n    // Generating projection\n    e4->Update();\n\n    // Adding each projection to volume\n    pasteFilter->SetSourceImage(e4->GetOutput());\n    pasteFilter->SetDestinationImage(wholeImage);\n    pasteFilter->SetSourceRegion(e4->GetOutput()->GetLargestPossibleRegion());\n    pasteFilter->SetDestinationIndex(destinationIndex);\n    pasteFilter->Update();\n    wholeImage = pasteFilter->GetOutput();\n    destinationIndex[2]++;\n  }\n\n  std::cout << \"\\n\\n****** Case 0: Amsterdam Shroud Image with crop ******\" << std::endl;\n\n  // Amsterdam shroud\n  using ShroudFilterType = rtk::AmsterdamShroudImageFilter<OutputImageType>;\n  auto shroudFilter = ShroudFilterType::New();\n  shroudFilter->SetInput(pasteFilter->GetOutput());\n  shroudFilter->SetGeometry(geometryFull);\n  ShroudFilterType::PointType center(0.), offset1(-40), offset2(40);\n  center[0] = 37.;\n  center[1] = 80.;\n  for (int i = 0; i < 3; i++)\n  {\n    offset1[i] += center[i];\n    offset2[i] += center[i];\n  }\n  shroudFilter->SetCorner1(offset1);\n  shroudFilter->SetCorner2(offset2);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(shroudFilter->Update());\n\n  // Read reference object\n  auto reader2 = itk::ImageFileReader<ShroudFilterType::OutputImageType>::New();\n  reader2->SetFileName(argv[1]);\n  reader2->Update();\n\n  CheckImageQuality<ShroudFilterType::OutputImageType>(\n    shroudFilter->GetOutput(), reader2->GetOutput(), 1.20e-6, 185, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 1: Amsterdam Shroud Image without crop ******\" << std::endl;\n\n  // Amsterdam shroud\n  shroudFilter->SetGeometry(nullptr);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(shroudFilter->Update());\n\n  // Read reference object\n  reader2->SetFileName(argv[2]);\n  reader2->Update();\n\n  CheckImageQuality<ShroudFilterType::OutputImageType>(\n    shroudFilter->GetOutput(), reader2->GetOutput(), 1.20e-6, 185, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Breathing signal calculated by reg1D algorithm ******\\n\" << std::endl;\n\n  // Estimation of breathing signal\n  reg1DImageType::Pointer reg1DSignal;\n  auto                    reg1DFilter = rtk::Reg1DExtractShroudSignalImageFilter<reg1DPixelType, reg1DPixelType>::New();\n  reg1DFilter->SetInput(reader2->GetOutput());\n  reg1DFilter->Update();\n  reg1DSignal = reg1DFilter->GetOutput();\n\n  // Test Reference\n  float reg1D[100] = {\n    0.f,     4.5f,    8.625f,  12.25f, 15.f,     16.875f,  17.625f,  17.375f,  16.125f,  13.875f,  10.75f,   7.125f,\n    3.f,     -1.25f,  -5.375f, -9.f,   -12.125f, -14.25f,  -15.625f, -16.125f, -15.5f,   -13.75f,  -11.f,    -7.5f,\n    -3.375f, 1.125f,  5.5f,    9.5f,   13.f,     15.875f,  17.75f,   18.625f,  18.375f,  17.25f,   15.f,     11.875f,\n    8.125f,  3.875f,  -0.625f, -5.f,   -8.875f,  -12.125f, -14.25f,  -15.375f, -15.375f, -14.625f, -12.875f, -10.25f,\n    -6.875f, -2.75f,  1.625f,  6.f,    10.125f,  13.625f,  16.375f,  18.25f,   19.f,     18.75f,   17.5f,    15.25f,\n    12.125f, 8.5f,    4.375f,  0.125f, -4.f,     -7.625f,  -10.75f,  -12.875f, -14.25f,  -14.75f,  -14.125f, -12.375f,\n    -9.625f, -6.125f, -2.f,    2.5f,   6.875f,   10.875f,  14.375f,  17.25f,   19.125f,  20.f,     19.75f,   18.625f,\n    16.375f, 13.125f, 9.375f,  5.125f, 0.625f,   -3.75f,   -7.625f,  -10.875f, -13.f,    -14.125f, -14.125f, -13.375f,\n    -11.5f,  -8.875f, -5.375f, -1.25f\n  };\n\n  // Checking for possible errors\n  float                                         zeroValue = 1e-12;\n  float                                         sum = 0.;\n  unsigned int                                  i = 0;\n  itk::ImageRegionConstIterator<reg1DImageType> it(reg1DSignal, reg1DSignal->GetLargestPossibleRegion());\n  for (it.GoToBegin(); !it.IsAtEnd(); ++it, i++)\n    sum += itk::Math::abs(reg1D[i] - it.Get());\n\n  if (sum <= zeroValue)\n    std::cout << \"Test PASSED! \" << std::endl;\n  else\n  {\n    std::cerr << \"Test FAILED! \"\n              << \"Breathing signal does not match, absolute difference \" << sum << \" instead of 0.\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n  std::cout << \"\\n\\n****** Case 3: Breathing signal calculated by DP algorithm ******\\n\" << std::endl;\n\n  // Estimation of breathing signal\n  reg1DImageType::Pointer DPSignal;\n  auto                    DPFilter = rtk::DPExtractShroudSignalImageFilter<reg1DPixelType, reg1DPixelType>::New();\n  DPFilter->SetInput(reader2->GetOutput());\n  DPFilter->SetAmplitude(20.);\n  DPFilter->Update();\n  DPSignal = DPFilter->GetOutput();\n\n  // Test Reference\n  float DP[100] = { 2.5f,  7.5f,   12.5f,  15.f,   17.5f,  20.f,   20.f,   20.f,   20.f,   17.5f, 12.5f, 10.f,  5.f,\n                    0.f,   -5.f,   -7.5f,  -10.f,  -12.5f, -15.f,  -15.f,  -15.f,  -12.5f, -10.f, -7.5f, -2.5f, 2.5f,\n                    7.5f,  10.f,   15.f,   17.5f,  20.f,   20.f,   20.f,   17.5f,  15.f,   12.5f, 10.f,  5.f,   0.f,\n                    -5.f,  -7.5f,  -10.f,  -12.5f, -15.f,  -15.f,  -12.5f, -12.5f, -10.f,  -5.f,  0.f,   2.5f,  7.5f,\n                    12.5f, 15.f,   17.5f,  20.f,   20.f,   20.f,   20.f,   17.5f,  12.5f,  10.f,  5.f,   0.f,   -5.f,\n                    -7.5f, -10.f,  -12.5f, -15.f,  -15.f,  -15.f,  -12.5f, -10.f,  -7.5f,  -2.5f, 2.5f,  7.5f,  10.f,\n                    15.f,  17.5f,  20.f,   20.f,   20.f,   17.5f,  15.f,   12.5f,  10.f,   5.f,   0.f,   -5.f,  -7.5f,\n                    -10.f, -12.5f, -15.f,  -15.f,  -12.5f, -12.5f, -10.f,  -5.f,   0.f };\n\n  // Checking for possible errors\n  sum = 0.;\n  i = 0;\n  itk::ImageRegionConstIterator<reg1DImageType> itDP(DPSignal, DPSignal->GetLargestPossibleRegion());\n  for (itDP.GoToBegin(); !itDP.IsAtEnd(); ++itDP, i++)\n    sum += itk::Math::abs(DP[i] - itDP.Get());\n\n  if (sum <= zeroValue)\n    std::cout << \"Test PASSED! \" << std::endl;\n  else\n  {\n    std::cerr << \"Test FAILED! \"\n              << \"Breathing signal does not match, absolute difference \" << sum << \" instead of 0.\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n#if defined(USE_FFTWD)\n  std::cout << \"\\n\\n****** Extract phase from case 3 ******\\n\" << std::endl;\n\n  // Check phase\n  using PhaseType = rtk::ExtractPhaseImageFilter<reg1DImageType>;\n  auto phaseFilt = PhaseType::New();\n  phaseFilt->SetInput(DPSignal);\n  phaseFilt->SetUnsharpMaskSize(53);\n  std::cout << \"Unsharp mask size is \" << phaseFilt->GetUnsharpMaskSize() << std::endl;\n  phaseFilt->SetMovingAverageSize(3);\n  std::cout << \"Moving average size is \" << phaseFilt->GetMovingAverageSize() << std::endl;\n  phaseFilt->SetModel(PhaseType::LOCAL_PHASE);\n  phaseFilt->Update();\n  reg1DImageType * phase = phaseFilt->GetOutput();\n\n  // Checking for possible errors\n  float refLocalPhase[100] = { 0.76f, 0.80f, 0.85f, 0.89f, 0.94f, 0.98f, 0.02f, 0.06f, 0.10f, 0.14f, 0.18f, 0.22f,\n                               0.26f, 0.30f, 0.34f, 0.37f, 0.40f, 0.44f, 0.47f, 0.51f, 0.55f, 0.59f, 0.63f, 0.66f,\n                               0.70f, 0.75f, 0.78f, 0.82f, 0.86f, 0.90f, 0.95f, 0.99f, 0.03f, 0.07f, 0.11f, 0.14f,\n                               0.18f, 0.23f, 0.28f, 0.32f, 0.36f, 0.40f, 0.43f, 0.48f, 0.52f, 0.56f, 0.60f, 0.64f,\n                               0.68f, 0.72f, 0.76f, 0.79f, 0.83f, 0.87f, 0.91f, 0.95f, 0.98f, 0.02f, 0.06f, 0.11f,\n                               0.15f, 0.19f, 0.23f, 0.27f, 0.32f, 0.36f, 0.39f, 0.43f, 0.47f, 0.51f, 0.55f, 0.59f,\n                               0.63f, 0.67f, 0.71f, 0.75f, 0.79f, 0.82f, 0.86f, 0.90f, 0.94f, 0.98f, 0.01f, 0.05f,\n                               0.08f, 0.12f, 0.15f, 0.19f, 0.24f, 0.28f, 0.32f, 0.35f, 0.39f, 0.44f, 0.49f, 0.53f,\n                               0.58f, 0.63f, 0.68f, 0.72f };\n  itk::ImageRegionConstIterator<reg1DImageType> itPhaseLocal(phase, phase->GetLargestPossibleRegion());\n  for (sum = 0, i = 0; !itPhaseLocal.IsAtEnd(); ++itPhaseLocal, i++)\n    sum += itk::Math::abs(refLocalPhase[i] - itPhaseLocal.Get());\n  std::cout << \"LOCAL_PHASE... \";\n  if (sum <= 0.27)\n    std::cout << \"Test PASSED! \" << std::endl;\n  else\n  {\n    std::cerr << \"Test FAILED! Local phase does not match ref, absolute difference \" << sum << \" instead of 0.\"\n              << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n  phaseFilt->SetModel(PhaseType::LINEAR_BETWEEN_MAXIMA);\n  phaseFilt->Update();\n\n  float refMaxPhase[100] = { 0.77f, 0.81f, 0.85f, 0.88f, 0.92f, 0.96f, 0.00f, 0.04f, 0.08f, 0.12f, 0.15f, 0.19f, 0.23f,\n                             0.27f, 0.31f, 0.35f, 0.38f, 0.42f, 0.46f, 0.50f, 0.54f, 0.58f, 0.62f, 0.65f, 0.69f, 0.73f,\n                             0.77f, 0.81f, 0.85f, 0.88f, 0.92f, 0.96f, 0.00f, 0.04f, 0.08f, 0.12f, 0.16f, 0.20f, 0.24f,\n                             0.28f, 0.32f, 0.36f, 0.40f, 0.44f, 0.48f, 0.52f, 0.56f, 0.60f, 0.64f, 0.68f, 0.72f, 0.76f,\n                             0.80f, 0.84f, 0.88f, 0.92f, 0.96f, 0.00f, 0.04f, 0.08f, 0.12f, 0.16f, 0.20f, 0.24f, 0.28f,\n                             0.32f, 0.36f, 0.40f, 0.44f, 0.48f, 0.52f, 0.56f, 0.60f, 0.64f, 0.68f, 0.72f, 0.76f, 0.80f,\n                             0.84f, 0.88f, 0.92f, 0.96f, 0.00f, 0.04f, 0.08f, 0.12f, 0.16f, 0.20f, 0.24f, 0.28f, 0.32f,\n                             0.36f, 0.40f, 0.44f, 0.48f, 0.52f, 0.56f, 0.60f, 0.64f, 0.68f };\n\n  itk::ImageRegionConstIterator<reg1DImageType> itPhaseMax(phase, phase->GetLargestPossibleRegion());\n  for (sum = 0, i = 0; !itPhaseMax.IsAtEnd(); ++itPhaseMax, i++)\n    sum += itk::Math::abs(refMaxPhase[i] - itPhaseMax.Get());\n  std::cout << \"LINEAR_BETWEEN_MAXIMA... \";\n  if (sum <= 0.081)\n    std::cout << \"Test PASSED! \" << std::endl;\n  else\n  {\n    std::cerr << \"Test FAILED! Linear phase between max does not match ref, absolute difference \" << sum\n              << \" instead of 0.\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n  phaseFilt->SetModel(PhaseType::LINEAR_BETWEEN_MINIMA);\n  phaseFilt->Update();\n\n  float refMinPhase[100] = { 0.24f, 0.28f, 0.32f, 0.36f, 0.40f, 0.44f, 0.48f, 0.52f, 0.56f, 0.60f, 0.64f, 0.68f, 0.72f,\n                             0.76f, 0.80f, 0.84f, 0.88f, 0.92f, 0.96f, 0.00f, 0.04f, 0.08f, 0.12f, 0.16f, 0.20f, 0.24f,\n                             0.28f, 0.32f, 0.36f, 0.40f, 0.44f, 0.48f, 0.52f, 0.56f, 0.60f, 0.64f, 0.68f, 0.72f, 0.76f,\n                             0.80f, 0.84f, 0.88f, 0.92f, 0.96f, 0.00f, 0.04f, 0.08f, 0.12f, 0.16f, 0.20f, 0.24f, 0.28f,\n                             0.32f, 0.36f, 0.40f, 0.44f, 0.48f, 0.52f, 0.56f, 0.60f, 0.64f, 0.68f, 0.72f, 0.76f, 0.80f,\n                             0.84f, 0.88f, 0.92f, 0.96f, 0.00f, 0.04f, 0.08f, 0.12f, 0.17f, 0.21f, 0.25f, 0.29f, 0.33f,\n                             0.38f, 0.42f, 0.46f, 0.50f, 0.54f, 0.58f, 0.62f, 0.67f, 0.71f, 0.75f, 0.79f, 0.83f, 0.88f,\n                             0.92f, 0.96f, 0.00f, 0.04f, 0.08f, 0.12f, 0.17f, 0.21f, 0.25f };\n\n  itk::ImageRegionConstIterator<reg1DImageType> itPhaseMin(phase, phase->GetLargestPossibleRegion());\n  for (sum = 0, i = 0; !itPhaseMin.IsAtEnd(); ++itPhaseMin, i++)\n    sum += itk::Math::abs(refMinPhase[i] - itPhaseMin.Get());\n  std::cout << \"LINEAR_BETWEEN_MINIMA... \";\n  if (sum <= 0.076)\n    std::cout << \"Test PASSED! \" << std::endl;\n  else\n  {\n    std::cerr << \"Test FAILED! Linear phase between min does not match ref, absolute difference \" << sum\n              << \" instead of 0.\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n#endif\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkapplicationtest.py",
    "content": "#!/usr/bin/env python\nimport os\nimport shutil\nimport subprocess\nimport pytest\nfrom itk import RTK as rtk\n\n\n@pytest.fixture(scope=\"session\")\ndef rtk_reference(tmp_path_factory):\n\td = tmp_path_factory.mktemp(\"rtk_reference\")\n\tcwd = os.getcwd()\n\tos.chdir(d)\n\ttry:\n\t\tif not os.path.exists(\"geometry.xml\"):\n\t\t\trtk.rtksimulatedgeometry(\"-n 180 --sid 600 --sdd 1200 -o geometry.xml\")\n\t\tif not os.path.exists(\"projections.mha\"):\n\t\t\trtk.rtkprojectshepploganphantom(\"-g geometry.xml -o projections.mha --spacing 4 --size 64 --phantomscale 64\")\n\t\tif not os.path.exists(\"reference.mha\"):\n\t\t\trtk.rtkdrawshepploganphantom(\"--spacing 2 --size 64 -o reference.mha --phantomscale 64\")\n\tfinally:\n\t\tos.chdir(cwd)\n\treturn d\n\n\n@pytest.fixture()\ndef rtk_workdir(tmp_path, rtk_reference):\n\t\"\"\"Per-test working directory populated with cached geometry and projections.\"\"\"\n\tfor name in (\"geometry.xml\", \"projections.mha\", \"reference.mha\"):\n\t\tsrc = rtk_reference / name\n\t\tdst = tmp_path / name\n\t\tos.link(src, dst)\n\n\tcwd = os.getcwd()\n\tos.chdir(tmp_path)\n\tyield tmp_path\n\tos.chdir(cwd)\n\ndef test_fdk_application(rtk_workdir):\n\trtk.rtkfdk(\"-g geometry.xml -p . -r projections.mha -o fdk.mha --spacing 2 --size 64 --origin=-64\")\n\trtk.rtkcheckimagequality(\"-i reference.mha -j fdk.mha -t 200000\")\n\n\ndef test_application_invocation_modes(rtk_workdir):\n\t\"\"\"Validate rtkfdk equivalence across invocation styles\"\"\"\n\n\t# Keyword API baseline\n\trtk.rtkfdk(\n\t\tpath=\".\",\n\t\tregexp=\"projections.mha\",\n\t\toutput=\"fdk_kw.mha\",\n\t\tgeometry=\"geometry.xml\",\n\t\tspacing=\"2,2,2\",\n\t\tsize=[64, 64, 64],\n\t)\n\n\t# String API\n\trtk.rtkfdk(\"-p . -r projections.mha -o fdk_str.mha -g geometry.xml --spacing 2 --size 64\")\n\n\t# CLI\n\texe = shutil.which(\"rtkfdk\")\n\tcli_cmd = [exe, \"-p\", \".\", \"-r\", \"projections.mha\", \"-o\", \"fdk_cli.mha\", \"-g\", \"geometry.xml\", \"--spacing\", \"2\", \"--size\", \"64\"]\n\tsubprocess.run(cli_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n\n\trtk.rtkcheckimagequality(\"-i fdk_kw.mha -j fdk_str.mha -t 10\")\n\trtk.rtkcheckimagequality(\"-i fdk_kw.mha -j fdk_cli.mha -t 10\")\n\trtk.rtkcheckimagequality(\"-i fdk_str.mha -j fdk_cli.mha -t 10\")\n\n\ndef test_conjugategradient_application(rtk_workdir):\n\trtk.rtkconjugategradient(\"-g geometry.xml -p . -r projections.mha -o cg.mha --spacing 2 --size 64 -n 2\")\n\trtk.rtkcheckimagequality(\"-i reference.mha -j cg.mha -t 20000\")\n\n\ndef test_admmtotalvariation_application(rtk_workdir):\n\trtk.rtkadmmtotalvariation(\"-g geometry.xml -p . -r projections.mha -o admm.mha --spacing 2 --size 64 -n 1 --CGiter 2\")\n\trtk.rtkcheckimagequality(\"-i reference.mha -j admm.mha -t 20000\")\n"
  },
  {
    "path": "test/rtkargsinfomanagertest.cxx",
    "content": "#include <rtkGgoArgsInfoManager.h>\n#include <cstdlib>\n#include <iostream>\n\nclass args_info_test\n{\npublic:\n  int testVar{ true };\n  int verbose_flag{ 0 };\n  args_info_test() = default;\n};\n\nclass cleanup_functor\n{\npublic:\n  void\n  operator()(args_info_test * args_info)\n  {\n    args_info->testVar = false;\n  }\n};\n\nvoid\ncleanup_function(args_info_test * args_info)\n{\n  args_info->testVar = false;\n}\n\nint\nmain(int, char **)\n{\n  args_info_test args_info_1, args_info_2;\n\n  { // new scope - manager does cleanup on destruction\n    rtk::args_info_manager<args_info_test> manager_1(args_info_1, cleanup_function);\n\n    cleanup_functor                                         functor;\n    rtk::args_info_manager<args_info_test, cleanup_functor> manager_2(args_info_2, functor);\n  }\n\n  if (args_info_1.testVar)\n  {\n    std::cout << \"Test FAILED -- cleanup using a function didn't work.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  if (args_info_2.testVar)\n  {\n    std::cout << \"Test FAILED -- cleanup using a functor didn't work.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // otherwise\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkbinningtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n#include \"rtkConstantImageSource.h\"\n#include <itkBinShrinkImageFilter.h>\n\n/**\n * \\file rtkbinningtest.cxx\n *\n * \\brief Functional test for the classes performing binning\n *\n * This test perfoms a binning on a 2D image with binning factors 2x2. Compares\n * the obtained result with a reference image previously calculated.\n *\n * \\author Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 2;\n  using OutputImageType = itk::Image<unsigned short, Dimension>;\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n\n  // Create constant image of value 2 and reference image.\n  auto imgIn = ConstantImageSourceType::New();\n  auto imgRef = ConstantImageSourceType::New();\n\n  imgIn->SetOrigin(itk::MakePoint(-7, -7));\n  imgIn->SetSpacing(itk::MakeVector(1., 1.));\n  imgIn->SetSize(itk::MakeSize(8, 8));\n  imgIn->SetConstant(2);\n  imgIn->UpdateLargestPossibleRegion();\n\n  // Adapting reference for case 1\n  imgRef->SetOrigin(itk::MakePoint(-7, -7));\n  imgRef->SetSpacing(itk::MakeVector(2., 2.));\n  imgRef->SetSize(itk::MakeSize(4, 4));\n  imgRef->SetConstant(2);\n  imgRef->UpdateLargestPossibleRegion();\n\n  // Binning filter\n  auto bin = itk::BinShrinkImageFilter<OutputImageType, OutputImageType>::New();\n\n  std::cout << \"\\n\\n****** Case 1: binning 2x2 ******\" << std::endl;\n\n  // Update binning filter\n  bin->SetInput(imgIn->GetOutput());\n  bin->SetShrinkFactors(itk::MakeVector(2, 2));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(bin->UpdateLargestPossibleRegion());\n\n  CheckImageQuality<OutputImageType>(bin->GetOutput(), imgRef->GetOutput(), 0.001, 120, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: binning 1x2 ******\" << std::endl;\n\n  imgIn->UpdateLargestPossibleRegion();\n\n  // Adapting reference for case 2\n  imgRef->SetSpacing(itk::MakeVector(1., 2.));\n  imgRef->SetSize(itk::MakeSize(8, 4));\n  imgRef->UpdateLargestPossibleRegion();\n\n  // Update binning filter\n  bin->SetShrinkFactors(itk::MakeVector(1, 2));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(bin->UpdateLargestPossibleRegion());\n\n  CheckImageQuality<OutputImageType>(bin->GetOutput(), imgRef->GetOutput(), 0.001, 120, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 3: binning 2x1 ******\" << std::endl;\n\n  imgIn->UpdateLargestPossibleRegion();\n\n  // Adapting reference for case 3\n  imgRef->SetSpacing(itk::MakeVector(2., 1.));\n  imgRef->SetSize(itk::MakeSize(4, 8));\n  imgRef->UpdateLargestPossibleRegion();\n\n  // Update binning filter\n  bin->SetInput(imgIn->GetOutput());\n  bin->SetShrinkFactors(itk::MakeVector(2, 1));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(bin->UpdateLargestPossibleRegion());\n\n  CheckImageQuality<OutputImageType>(bin->GetOutput(), imgRef->GetOutput(), 0.001, 120, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkbioscantest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkBioscanGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\n/**\n * \\file rtkbioscantest.cxx\n *\n * \\brief Functional tests for classes managing Bioscan NanoSPECT/CT data\n *\n * This test reads and verifies the geometry from a bioscan projection.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 3)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \" bioscan.dcm refGeometry.xml\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  std::cout << \"Testing geometry...\" << std::endl;\n\n  // Ora geometry\n  std::vector<std::string> filenames;\n  filenames.emplace_back(argv[1]);\n  rtk::BioscanGeometryReader::Pointer geoTargReader;\n  geoTargReader = rtk::BioscanGeometryReader::New();\n  geoTargReader->SetProjectionsFileNames(filenames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader->UpdateOutputData());\n\n  // Reference geometry\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer geoRefReader;\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[2]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // Check geometries\n  CheckGeometries(geoTargReader->GetGeometry(), geoRefReader->GetOutputObject());\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkconjugategradientreconstructiontest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkConjugateGradientConeBeamReconstructionFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n\n/**\n * \\file rtkconjugategradientreconstructiontest.cxx\n *\n * \\brief Functional test for ConjugateGradient reconstruction\n *\n * This test generates the projections of an ellipsoid and reconstructs the CT\n * image using the ConjugateGradient algorithm with different backprojectors (Voxel-Based,\n * Joseph). The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(252., 252., 252.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto size = itk::MakeSize(64, 64, 64);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  spacing = itk::MakeVector(504., 504., 504.);\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n#else\n  spacing = itk::MakeVector(8., 8., 8.);\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create ellipsoid PROJECTIONS\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::Pointer rei;\n\n  rei = REIType::New();\n  rei->SetAngle(0.);\n  rei->SetDensity(1.);\n  rei->SetCenter(itk::MakeVector(0., 0., 0.));\n  rei->SetAxis(itk::MakeVector(90., 90., 90.));\n  rei->SetInput(projectionsSource->GetOutput());\n  rei->SetGeometry(geometry);\n\n  // Update\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n\n  // Create REFERENCE object (3D ellipsoid).\n  auto dsl = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // ConjugateGradient reconstruction filtering\n  using ConjugateGradientType = rtk::ConjugateGradientConeBeamReconstructionFilter<OutputImageType>;\n  auto conjugategradient = ConjugateGradientType::New();\n  conjugategradient->SetInput(tomographySource->GetOutput());\n  conjugategradient->SetInput(1, rei->GetOutput());\n  conjugategradient->SetGeometry(geometry);\n  conjugategradient->SetNumberOfIterations(5);\n\n  // In all cases, use the Joseph forward projector\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientType::FP_JOSEPH);\n  auto uniformWeightsSource = ConstantImageSourceType::New();\n  uniformWeightsSource->SetInformationFromImage(projectionsSource->GetOutput());\n  uniformWeightsSource->SetConstant(1.0);\n\n  std::cout << \"\\n\\n****** Case 1: Voxel-Based Backprojector ******\" << std::endl;\n\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientType::BP_VOXELBASED);\n  conjugategradient->SetInputWeights(uniformWeightsSource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<OutputImageType>(conjugategradient->GetOutput(), dsl->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Joseph Backprojector, laplacian and Tikhonov regularization ******\" << std::endl;\n\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientType::BP_JOSEPH);\n  conjugategradient->SetGamma(0.01);\n  conjugategradient->SetTikhonov(0.01);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<OutputImageType>(conjugategradient->GetOutput(), dsl->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 3: CUDA Voxel-Based Backprojector and CUDA Forward projector ******\" << std::endl;\n\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientType::FP_CUDARAYCAST);\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientType::BP_CUDAVOXELBASED);\n  conjugategradient->SetGamma(0);\n  conjugategradient->SetTikhonov(0);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<OutputImageType>(conjugategradient->GetOutput(), dsl->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  std::cout << \"\\n\\n****** Case 4: Joseph Backprojector, weighted least squares  ******\" << std::endl;\n\n  uniformWeightsSource->SetConstant(2.0);\n\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientType::BP_JOSEPH);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<OutputImageType>(conjugategradient->GetOutput(), dsl->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkconjugategradienttest.cxx",
    "content": "#include <itkRandomImageSource.h>\n#include <itkImageRegionIterator.h>\n\n#include \"rtkConstantImageSource.h\"\n#include \"rtkTestConfiguration.h\"\n#include \"rtkConjugateGradientImageFilter.h\"\n#include \"rtkDivergenceOfGradientConjugateGradientOperator.h\"\n#include \"rtkMacro.h\"\n#include \"rtkForwardDifferenceGradientImageFilter.h\"\n#include \"rtkBackwardDifferenceDivergenceImageFilter.h\"\n\n\ntemplate <class TImage1, class TImage2>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckImageQuality(typename TImage1::Pointer itkNotUsed(recon), typename TImage2::Pointer itkNotUsed(ref))\n{}\n#else\nvoid\nCheckImageQuality(typename TImage1::Pointer recon, typename TImage2::Pointer ref)\n{\n  itk::ImageRegionConstIterator<TImage1> itTest(recon, recon->GetBufferedRegion());\n  itk::ImageRegionConstIterator<TImage2> itRef(ref, ref->GetBufferedRegion());\n\n  // Compute the mean of the reference image (which cannot be recovered by inverting the gradient)\n  double mean = 0;\n  while (!itRef.IsAtEnd())\n  {\n    mean += itRef.Get();\n    ++itRef;\n  }\n  mean /= ref->GetBufferedRegion().GetNumberOfPixels();\n\n  using ErrorType = double;\n  ErrorType TestError = 0.;\n  ErrorType EnerError = 0.;\n\n  itTest.GoToBegin();\n  itRef.GoToBegin();\n\n  while (!itRef.IsAtEnd())\n  {\n    typename TImage1::PixelType TestVal = itTest.Get();\n    typename TImage2::PixelType RefVal = itRef.Get() - mean;\n\n    if (TestVal != RefVal)\n    {\n      TestError += itk::Math::abs(RefVal - TestVal);\n      EnerError += std::pow(ErrorType(RefVal - TestVal), 2.);\n    }\n    ++itTest;\n    ++itRef;\n  }\n  // Error per Pixel\n  ErrorType ErrorPerPixel = TestError / recon->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"\\nError per Pixel = \" << ErrorPerPixel << std::endl;\n  // MSE\n  ErrorType MSE = EnerError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"MSE = \" << MSE << std::endl;\n  // PSNR\n  ErrorType PSNR = 20 * log10(255.0) - 10 * log10(MSE);\n  std::cout << \"PSNR = \" << PSNR << \"dB\" << std::endl;\n  // QI\n  ErrorType QI = (255.0 - ErrorPerPixel) / 255.0;\n  std::cout << \"QI = \" << QI << std::endl;\n\n  // Checking results\n  if (ErrorPerPixel > 1.28)\n  {\n    std::cerr << \"Test Failed, Error per pixel not valid! \" << ErrorPerPixel << \" instead of 1.28\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  if (PSNR < 44.)\n  {\n    std::cerr << \"Test Failed, PSNR not valid! \" << PSNR << \" instead of 44\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif\n\n/**\n * \\file rtkconjugategradienttest.cxx\n *\n * \\brief Attempts to recover an image from its gradient using\n * conjugate gradient optimization\n *\n * This test generates a random volume and computes its gradient.\n * It attempts to recover the random volume (except for the DC component)\n * from its gradient. The optimizer attempts to solve\n * find f such that || grad(f) - g ||_2^2 is minimal\n * It searches for the zeros of the gradient of this quantity, i.e. for\n * f such that div( grad(f) - g ) = 0\n * which is equivalent to\n * div(grad(f)) = div(g)\n * Expressed in the canonical form AX=B, this means :\n * A = div(grad(.))\n * X = f\n * B = div(g)\n *\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Random and constant image sources\n  auto randomVolumeSource = itk::RandomImageSource<OutputImageType>::New();\n  auto constantVolumeSource = rtk::ConstantImageSource<OutputImageType>::New();\n\n  // Volume metadata\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(252., 252., 252.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto size = itk::MakeSize(64, 64, 64);\n#endif\n  randomVolumeSource->SetOrigin(origin);\n  randomVolumeSource->SetSpacing(spacing);\n  randomVolumeSource->SetSize(size);\n  randomVolumeSource->SetMin(0.);\n  randomVolumeSource->SetMax(1.);\n  randomVolumeSource->SetNumberOfWorkUnits(2); // With 1, it's deterministic\n\n  constantVolumeSource->SetOrigin(origin);\n  constantVolumeSource->SetSpacing(spacing);\n  constantVolumeSource->SetSize(size);\n  constantVolumeSource->SetConstant(0.);\n\n  // Update the sources\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantVolumeSource->Update());\n\n  // Create and set the gradient and divergence filters\n  using GradientFilterType = rtk::ForwardDifferenceGradientImageFilter<OutputImageType>;\n  auto gradientFilter = GradientFilterType::New();\n  gradientFilter->SetInput(randomVolumeSource->GetOutput());\n  bool dimsProcessed[Dimension];\n  for (bool & dimProcessed : dimsProcessed)\n  {\n    dimProcessed = true;\n  }\n  gradientFilter->SetDimensionsProcessed(dimsProcessed);\n  auto divergenceFilter = rtk::BackwardDifferenceDivergenceImageFilter<GradientFilterType::OutputImageType>::New();\n  divergenceFilter->SetInput(gradientFilter->GetOutput());\n\n  // Update the gradient and divergence filters\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(divergenceFilter->Update());\n\n  // Create and set the conjugate gradient optimizer\n  // It uses the operator DivergenceOfGradientConjugateGradientOperator\n  auto cg = rtk::ConjugateGradientImageFilter<OutputImageType>::New();\n\n  auto cg_op = rtk::DivergenceOfGradientConjugateGradientOperator<OutputImageType>::New();\n  cg->SetA(cg_op.GetPointer());\n  cg->SetX(constantVolumeSource->GetOutput());\n  cg->SetB(divergenceFilter->GetOutput());\n  cg->SetNumberOfIterations(30);\n\n  // Update the conjugate gradient filter\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(cg->Update());\n\n  CheckImageQuality<OutputImageType, OutputImageType>(cg->GetOutput(), randomVolumeSource->GetOutput());\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkcroptest.cxx",
    "content": "#include \"rtkTestConfiguration.h\"\n#include \"rtkCudaCropImageFilter.h\"\n\n/**\n * \\file rtkcroptest.cxx\n * \\brief Functional test for the classes performing crop filtering\n * \\author Julien Jomier\n */\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::CudaImage<float, Dimension>;\n\n  auto image = ImageType::New();\n  image->SetRegions(itk::MakeSize(50, 50, 50));\n  image->Allocate();\n  image->FillBuffer(12.3);\n\n  auto crop = rtk::CudaCropImageFilter::New();\n  crop->SetInput(image);\n  crop->SetLowerBoundaryCropSize(itk::MakeSize(1, 1, 1));\n  crop->SetUpperBoundaryCropSize(itk::MakeSize(10, 10, 10));\n\n  try\n  {\n    crop->Update();\n  }\n  catch (itk::ExceptionObject & err)\n  {\n    std::cerr << err << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n  ImageType::IndexType index;\n  index.Fill(2);\n\n  if (itk::Math::abs(crop->GetOutput()->GetPixel(index) - 12.3) > 0.0001)\n  {\n    std::cout << \"Output should be 12.3. Value Computed = \" << crop->GetOutput()->GetPixel(index) << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  std::cout << \"Done!\" << std::endl;\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkcudaraycastadjointoperatorstest.cxx",
    "content": "#include \"rtkMacro.h\"\n#include \"rtkTest.h\"\n#include \"itkRandomImageSource.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkCudaRayCastBackProjectionImageFilter.h\"\n#include \"rtkCudaForwardProjectionImageFilter.h\"\n\n/**\n * \\file rtkcudaraycastadjointoperatorstest.cxx\n *\n * \\brief Tests whether CUDA ray cast forward and back projectors are matched\n *\n * This test generates a random volume \"v\" and a random set of projections \"p\",\n * and compares the scalar products <Rv , p> and <v, R* p>, where R is the\n * CUDA ray cast forward projector and R* is the CUDA ray cast back projector. If R* is indeed\n * the adjoint of R, these scalar products are equal.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n\n  // Random image sources\n  using RandomImageSourceType = itk::RandomImageSource<OutputImageType>;\n  auto randomVolumeSource = RandomImageSourceType::New();\n  auto randomProjectionsSource = RandomImageSourceType::New();\n\n  // Constant sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto constantVolumeSource = ConstantImageSourceType::New();\n  auto constantProjectionsSource = ConstantImageSourceType::New();\n\n  // Volume metadata\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(252., 252., 252.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto size = itk::MakeSize(64, 64, 64);\n#endif\n  randomVolumeSource->SetOrigin(origin);\n  randomVolumeSource->SetSpacing(spacing);\n  randomVolumeSource->SetSize(size);\n  randomVolumeSource->SetMin(0.);\n  randomVolumeSource->SetMax(1.);\n\n  constantVolumeSource->SetOrigin(origin);\n  constantVolumeSource->SetSpacing(spacing);\n  constantVolumeSource->SetSize(size);\n  constantVolumeSource->SetConstant(0.);\n\n  // Projections metadata\n  origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  spacing = itk::MakeVector(504., 504., 504.);\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n#else\n  spacing = itk::MakeVector(8., 8., 8.);\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n#endif\n  randomProjectionsSource->SetOrigin(origin);\n  randomProjectionsSource->SetSpacing(spacing);\n  randomProjectionsSource->SetSize(size);\n  randomProjectionsSource->SetMin(0.);\n  randomProjectionsSource->SetMax(100.);\n\n  constantProjectionsSource->SetOrigin(origin);\n  constantProjectionsSource->SetSpacing(spacing);\n  constantProjectionsSource->SetSize(size);\n  constantProjectionsSource->SetConstant(0.);\n\n  // Update all sources\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantVolumeSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomProjectionsSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantProjectionsSource->Update());\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  std::cout << \"\\n\\n****** CUDA ray cast Forward projector, flat panel detector ******\" << std::endl;\n\n  auto fw = rtk::CudaForwardProjectionImageFilter<OutputImageType, OutputImageType>::New();\n  fw->SetInput(0, constantProjectionsSource->GetOutput());\n  fw->SetInput(1, randomVolumeSource->GetOutput());\n  fw->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fw->Update());\n\n  std::cout << \"\\n\\n****** CUDA ray cast Back projector, flat panel detector ******\" << std::endl;\n\n  auto bp = rtk::CudaRayCastBackProjectionImageFilter::New();\n  bp->SetInput(0, constantVolumeSource->GetOutput());\n  bp->SetInput(1, randomProjectionsSource->GetOutput());\n  bp->SetGeometry(geometry.GetPointer());\n  bp->SetNormalize(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(bp->Update());\n\n  CheckScalarProducts<OutputImageType, OutputImageType>(\n    randomVolumeSource->GetOutput(), bp->GetOutput(), randomProjectionsSource->GetOutput(), fw->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  // Start over with cylindrical detector\n  geometry->SetRadiusCylindricalDetector(200);\n  std::cout << \"\\n\\n****** CUDA ray cast Forward projector, cylindrical detector ******\" << std::endl;\n\n  fw->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fw->Update());\n\n  std::cout << \"\\n\\n****** CUDA ray cast Back projector, cylindrical detector ******\" << std::endl;\n\n  bp->SetGeometry(geometry.GetPointer());\n  bp->SetNormalize(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(bp->Update());\n\n  CheckScalarProducts<OutputImageType, OutputImageType>(\n    randomVolumeSource->GetOutput(), bp->GetOutput(), randomProjectionsSource->GetOutput(), fw->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkcyclicdeformationtest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n#include <itksys/SystemTools.hxx>\n\n#include \"rtkTest.h\"\n#include \"rtkConstantImageSource.h\"\n\n#ifdef USE_CUDA\n#  include \"rtkCudaCyclicDeformationImageFilter.h\"\n#else\n#  include \"rtkCyclicDeformationImageFilter.h\"\n#endif\n\n/**\n * \\file rtkcyclicdeformationtest.cxx\n *\n * \\brief Functional test for classes performing 4D conjugate gradient-based\n * reconstruction.\n *\n * This test generates the projections of a phantom, which consists of two\n * ellipsoids (one of them moving). The resulting moving phantom is\n * reconstructed using 4D conjugate gradient and the generated\n * result is compared to the expected results (analytical computation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = itk::CovariantVector<float, 3>;\n\n#ifdef USE_CUDA\n  using DVFSequenceImageType = itk::CudaImage<OutputPixelType, 4>;\n  using DVFImageType = itk::CudaImage<OutputPixelType, 3>;\n#else\n  using DVFSequenceImageType = itk::Image<OutputPixelType, 4>;\n  using DVFImageType = itk::Image<OutputPixelType, 3>;\n#endif\n\n  auto origin = itk::MakePoint(-63., -31., -63., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(8, 8, 8, 2);\n  auto spacing = itk::MakeVector(16., 8., 16., 1.);\n#else\n  auto size = itk::MakeSize(32, 16, 32, 8);\n  auto spacing = itk::MakeVector(4., 4., 4., 1.);\n#endif\n\n  DVFSequenceImageType::RegionType regionMotion;\n  regionMotion.SetSize(size);\n\n  auto deformationField = DVFSequenceImageType::New();\n  deformationField->SetRegions(regionMotion);\n  deformationField->SetOrigin(origin);\n  deformationField->SetSpacing(spacing);\n  deformationField->Allocate();\n\n  // Vector Field initilization\n  DVFImageType::PixelType                                 vec;\n  itk::ImageRegionIteratorWithIndex<DVFSequenceImageType> dvfIt(deformationField,\n                                                                deformationField->GetLargestPossibleRegion());\n\n  DVFSequenceImageType::OffsetType DVFCenter;\n  DVFSequenceImageType::IndexType  toCenter;\n  DVFCenter.Fill(0);\n  DVFCenter[0] = size[0] / 2;\n  DVFCenter[1] = size[1] / 2;\n  DVFCenter[2] = size[2] / 2;\n  while (!dvfIt.IsAtEnd())\n  {\n    vec.Fill(0.);\n    toCenter = dvfIt.GetIndex() - DVFCenter;\n\n    if (0.3 * toCenter[0] * toCenter[0] + toCenter[1] * toCenter[1] + toCenter[2] * toCenter[2] < 40)\n    {\n      if (dvfIt.GetIndex()[3] == 0)\n        vec[0] = -8.;\n      else\n        vec[0] = 8.;\n    }\n    dvfIt.Set(vec);\n\n    ++dvfIt;\n  }\n\n  // Signal\n#ifdef USE_CUDA\n  std::string signalFileName = \"signal_CyclicDeformation_cuda.txt\";\n#else\n  std::string signalFileName = \"signal_CyclicDeformation.txt\";\n#endif\n  std::ofstream signalFile(signalFileName.c_str());\n  signalFile << \"0.3\" << std::endl;\n  signalFile.close();\n\n  // Set the forward and back projection filters to be used\n\n  std::cout << \"\\n\\n****** Case 1: CPU cyclic deformation field ******\" << std::endl;\n\n  auto cyclic = rtk::CyclicDeformationImageFilter<DVFSequenceImageType, DVFImageType>::New();\n  cyclic->SetInput(deformationField);\n  cyclic->SetSignalFilename(signalFileName);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(cyclic->Update());\n\n  CheckVectorImageQuality<DVFImageType>(cyclic->GetOutput(), cyclic->GetOutput(), 0.4, 12, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 2: GPU cyclic deformation field ******\" << std::endl;\n\n  cyclic = rtk::CudaCyclicDeformationImageFilter::New();\n  cyclic->SetInput(deformationField);\n  cyclic->SetSignalFilename(signalFileName);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(cyclic->Update());\n\n  CheckVectorImageQuality<DVFImageType>(cyclic->GetOutput(), cyclic->GetOutput(), 0.4, 12, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#endif\n\n  itksys::SystemTools::RemoveFile(signalFileName.c_str());\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkcylindricaldetectorreconstructiontest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkConjugateGradientConeBeamReconstructionFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n#include \"itkTestingMacros.h\"\n\n/**\n * \\file rtkcylindricaldetectorreconstructiontest.cxx\n *\n * \\brief Functional test for conjugate gradient reconstruction with cylindrical-detector\n *\n * This test generates the projections of an ellipsoid onto a cylindrical detector,\n * and reconstructs the CT image using the conjugate gradient algorithm\n * with different backprojectors (Joseph, CudaRayCast). The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(252., 252., 252.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto size = itk::MakeSize(64, 64, 64);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  spacing = itk::MakeVector(504., 504., 504.);\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n#else\n  spacing = itk::MakeVector(8., 8., 8.);\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n  geometry->SetRadiusCylindricalDetector(200);\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create ellipsoid PROJECTIONS\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::Pointer rei;\n\n  rei = REIType::New();\n  rei->SetAngle(0.);\n  rei->SetDensity(1.);\n  rei->SetCenter(itk::MakeVector(0., 0., 0.));\n  rei->SetAxis(itk::MakeVector(90., 90., 90.));\n\n  rei->SetInput(projectionsSource->GetOutput());\n  rei->SetGeometry(geometry);\n\n  // Update\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n\n  // Create REFERENCE object (3D ellipsoid).\n  auto dsl = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // Define weights (for weighted least squares)\n  auto uniformWeightsSource = ConstantImageSourceType::New();\n  uniformWeightsSource->SetInformationFromImage(projectionsSource->GetOutput());\n  uniformWeightsSource->SetConstant(1.0);\n\n  // ConjugateGradient reconstruction filtering\n  using ConjugateGradientType = rtk::ConjugateGradientConeBeamReconstructionFilter<OutputImageType>;\n  auto conjugategradient = ConjugateGradientType::New();\n  conjugategradient->SetInput(tomographySource->GetOutput());\n  conjugategradient->SetInput(1, rei->GetOutput());\n  conjugategradient->SetInputWeights(uniformWeightsSource->GetOutput());\n  conjugategradient->SetGeometry(geometry);\n  conjugategradient->SetNumberOfIterations(5);\n  conjugategradient->SetDisableDisplacedDetectorFilter(true);\n\n  std::cout << \"\\n\\n****** Case 1: Joseph forward and back projectors ******\" << std::endl;\n\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientType::FP_JOSEPH);\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientType::BP_JOSEPH);\n#if defined(RTK_USE_CUDA) && !defined(USE_CUDA)\n  ITK_TRY_EXPECT_EXCEPTION(conjugategradient->Update());\n  conjugategradient->SetCudaConjugateGradient(false);\n#endif\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<OutputImageType>(conjugategradient->GetOutput(), dsl->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 2: CUDA ray cast forward and back projectors ******\" << std::endl;\n\n  conjugategradient->SetCudaConjugateGradient(true);\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientType::FP_CUDARAYCAST);\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientType::BP_CUDARAYCAST);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<OutputImageType>(conjugategradient->GetOutput(), dsl->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  std::cout << \"\\n\\n****** Case 3: Joseph forward projector, voxel-based back projector ******\" << std::endl;\n\n  // Only works with a cylindrical detector centered on the source, therefore a new geometry has to be simulated\n  geometry = GeometryType::New();\n  geometry->SetRadiusCylindricalDetector(1200);\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  conjugategradient->SetGeometry(geometry);\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientType::FP_JOSEPH);\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientType::BP_VOXELBASED);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<OutputImageType>(conjugategradient->GetOutput(), dsl->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 4: CUDA ray cast forward projection, CUDA voxel based back projection ******\"\n            << std::endl;\n\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientType::FP_CUDARAYCAST);\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientType::BP_CUDAVOXELBASED);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<OutputImageType>(conjugategradient->GetOutput(), dsl->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkdecomposespectralprojectionstest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkConfiguration.h\"\n#include \"rtkMacro.h\"\n#include \"rtkSimplexSpectralProjectionsDecompositionImageFilter.h\"\n#include \"rtkSpectralForwardModelImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include <itkImageFileReader.h>\n#include <itkCastImageFilter.h>\n\n/**\n * \\file rtkdecomposespectralprojectionstest.cxx\n *\n * \\brief Functional test for the filters performing spectral forward model and spectral projections' material\n * decomposition\n *\n * This test generates analytical projections of a small phantom made of cylinder of water,\n * iodine and gadolinium, computes the expected photon counts in each detector bin in the\n * noiseless case, and performs a material decomposition on the photon counts to recover\n * the analytical projections.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 4)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"  incident_spectrum  detector_response  material_attenuations\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  using PixelValueType = float;\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<PixelValueType, Dimension>;\n\n  using DecomposedProjectionsType = itk::VectorImage<PixelValueType, Dimension>;\n  using MeasuredProjectionsType = itk::VectorImage<PixelValueType, Dimension>;\n\n  using IncidentSpectrumImageType = itk::Image<PixelValueType, Dimension>;\n\n\n  // Cast filters to convert between vector image types\n  using CastDecomposedProjectionsFilterType =\n    itk::CastImageFilter<DecomposedProjectionsType, itk::Image<itk::Vector<PixelValueType, 3>, Dimension>>;\n  using CastMeasuredProjectionFilterType =\n    itk::CastImageFilter<MeasuredProjectionsType, itk::Image<itk::Vector<PixelValueType, 6>, Dimension>>;\n\n  // Read all inputs\n  auto incidentSpectrumReader = itk::ImageFileReader<IncidentSpectrumImageType>::New();\n  incidentSpectrumReader->SetFileName(argv[1]);\n  incidentSpectrumReader->Update();\n\n  auto detectorResponseReader = itk::ImageFileReader<itk::Image<PixelValueType, Dimension - 1>>::New();\n  detectorResponseReader->SetFileName(argv[2]);\n  detectorResponseReader->Update();\n\n  auto materialAttenuationsReader = itk::ImageFileReader<itk::Image<PixelValueType, Dimension - 1>>::New();\n  materialAttenuationsReader->SetFileName(argv[3]);\n  materialAttenuationsReader->Update();\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 1;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 64;\n#endif\n\n  // Constant image source for the analytical projections calculation\n\n  auto projectionsSource = rtk::ConstantImageSource<OutputImageType>::New();\n  auto origin = itk::MakePoint(-255., -0.5, -255.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(504., 504., 504.);\n  auto size = itk::MakeSize(2, 1, NumberOfProjectionImages);\n#else\n  auto spacing = itk::MakeVector(8., 1., 1.);\n  auto size = itk::MakeSize(64, 1, NumberOfProjectionImages);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Initialize the multi-materials projections\n  auto decomposed = DecomposedProjectionsType::New();\n  decomposed->SetVectorLength(3);\n  decomposed->SetOrigin(origin);\n  decomposed->SetSpacing(spacing);\n  DecomposedProjectionsType::RegionType region;\n  DecomposedProjectionsType::IndexType  index;\n  index.Fill(0);\n  region.SetSize(size);\n  region.SetIndex(index);\n  decomposed->SetRegions(region);\n  decomposed->Allocate();\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Generate 3 phantoms, one per material\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::Pointer rei;\n  rei = REIType::New();\n  for (unsigned int material = 0; material < 3; material++)\n  {\n    auto semiprincipalaxis = itk::MakeVector(10., 10., 10.);\n    auto center = itk::MakeVector(15., 0., 15.);\n    rei->SetAngle(0.);\n    if (material == 2) // water\n      rei->SetDensity(1.);\n    else // iodine and gadolinium\n      rei->SetDensity(0.01);\n    rei->SetCenter(center);\n    rei->SetAxis(semiprincipalaxis);\n\n    // Compute analytical projections through them\n    rei->SetInput(projectionsSource->GetOutput());\n    rei->SetGeometry(geometry);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n\n    // Merge these projections into the multi-material projections image\n    itk::ImageRegionConstIterator<OutputImageType> inIt(rei->GetOutput(), rei->GetOutput()->GetLargestPossibleRegion());\n    itk::ImageRegionIterator<DecomposedProjectionsType> outIt(decomposed, decomposed->GetLargestPossibleRegion());\n    outIt.GoToBegin();\n    while (!outIt.IsAtEnd())\n    {\n      itk::VariableLengthVector<PixelValueType> vector = outIt.Get();\n      vector[material] = inIt.Get();\n      outIt.Set(vector);\n      ++inIt;\n      ++outIt;\n    }\n  }\n\n  // Generate a set of zero-filled photon count projections\n  auto measuredProjections = MeasuredProjectionsType::New();\n  measuredProjections->CopyInformation(decomposed);\n  measuredProjections->SetVectorLength(6);\n  measuredProjections->SetRegions(region);\n  measuredProjections->Allocate();\n\n  // Generate the thresholds vector\n  itk::VariableLengthVector<unsigned int> thresholds;\n  thresholds.SetSize(7);\n  thresholds[0] = 25;\n  thresholds[1] = 40;\n  thresholds[2] = 55;\n  thresholds[3] = 70;\n  thresholds[4] = 85;\n  thresholds[5] = 100;\n  thresholds[6] = 180;\n\n  // Apply the forward model to the multi-material projections\n  auto forward = rtk::SpectralForwardModelImageFilter<DecomposedProjectionsType,\n                                                      MeasuredProjectionsType,\n                                                      IncidentSpectrumImageType>::New();\n  forward->SetInputDecomposedProjections(decomposed);\n  forward->SetInputMeasuredProjections(measuredProjections);\n  forward->SetInputIncidentSpectrum(incidentSpectrumReader->GetOutput());\n  forward->SetDetectorResponse(detectorResponseReader->GetOutput());\n  forward->SetMaterialAttenuations(materialAttenuationsReader->GetOutput());\n  forward->SetThresholds(thresholds);\n  forward->SetIsSpectralCT(true);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(forward->Update())\n\n  // Generate a set of decomposed projections as input for the simplex\n  auto initialDecomposedProjections = DecomposedProjectionsType::New();\n  initialDecomposedProjections->CopyInformation(decomposed);\n  initialDecomposedProjections->SetRegions(region);\n  initialDecomposedProjections->SetVectorLength(3);\n  initialDecomposedProjections->Allocate();\n  DecomposedProjectionsType::PixelType initPixel;\n  initPixel.SetSize(3);\n  initPixel[0] = 0.1;\n  initPixel[1] = 0.1;\n  initPixel[2] = 10;\n  initialDecomposedProjections->FillBuffer(initPixel);\n\n  // Create and set the simplex filter to perform the decomposition\n  auto simplex = rtk::SimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,\n                                                                         MeasuredProjectionsType,\n                                                                         IncidentSpectrumImageType>::New();\n  simplex->SetInputDecomposedProjections(initialDecomposedProjections);\n  simplex->SetInputMeasuredProjections(forward->GetOutput());\n  simplex->SetInputIncidentSpectrum(incidentSpectrumReader->GetOutput());\n  simplex->SetDetectorResponse(detectorResponseReader->GetOutput());\n  simplex->SetMaterialAttenuations(materialAttenuationsReader->GetOutput());\n  simplex->SetThresholds(thresholds);\n  simplex->SetNumberOfIterations(10000);\n  forward->SetIsSpectralCT(true);\n\n  std::cout << \"\\n\\n****** Case 1: User-provided initial values ******\" << std::endl;\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(simplex->Update())\n  CheckVectorImageQuality<DecomposedProjectionsType>(simplex->GetOutput(), decomposed, 0.0001, 15, 2.0);\n\n  std::cout << \"\\n\\n****** Case 2: Heuristically-determined initial values ******\" << std::endl;\n\n  simplex->SetGuessInitialization(true);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(simplex->Update())\n  CheckVectorImageQuality<DecomposedProjectionsType>(simplex->GetOutput(), decomposed, 0.0001, 15, 2.0);\n\n  std::cout << \"\\n\\n****** Case 3: Fixed-length vector image inputs ******\" << std::endl;\n\n  // measuredProjections has been consumed by forward, which is InPlace. Reallocate it\n  measuredProjections->SetRegions(region);\n  measuredProjections->Allocate();\n\n  auto castDecomposedProjections = CastDecomposedProjectionsFilterType::New();\n  auto castMeasuredProjections = CastMeasuredProjectionFilterType::New();\n  castDecomposedProjections->SetInput(decomposed);\n  castMeasuredProjections->SetInput(measuredProjections);\n  forward->SetInputDecomposedProjections(castDecomposedProjections->GetOutput());\n  forward->SetInputMeasuredProjections(castMeasuredProjections->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(forward->Update())\n\n  auto castDecomposedProjections2 = CastDecomposedProjectionsFilterType::New();\n  auto castMeasuredProjections2 = CastMeasuredProjectionFilterType::New();\n  castDecomposedProjections->SetInput(initialDecomposedProjections);\n  castMeasuredProjections->SetInput(forward->GetOutput());\n  simplex->SetInputDecomposedProjections(castDecomposedProjections->GetOutput());\n  simplex->SetInputMeasuredProjections(castMeasuredProjections->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(simplex->Update())\n\n  CheckVectorImageQuality<DecomposedProjectionsType>(simplex->GetOutput(), decomposed, 0.0001, 15, 2.0);\n\n#ifndef ITK_FUTURE_LEGACY_REMOVE\n  std::cout << \"\\n\\n****** Case 4: Legacy VectorImage type for incident spectrum ******\" << std::endl;\n\n  auto vectorSpectrumReader = itk::ImageFileReader<itk::VectorImage<PixelValueType, Dimension - 1>>::New();\n  vectorSpectrumReader->SetFileName(argv[4]);\n  vectorSpectrumReader->Update();\n  forward->SetInputIncidentSpectrum(vectorSpectrumReader->GetOutput());\n  simplex->SetInputIncidentSpectrum(vectorSpectrumReader->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(simplex->Update())\n  CheckVectorImageQuality<DecomposedProjectionsType>(simplex->GetOutput(), decomposed, 0.0001, 15, 2.0);\n#endif\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkdigisenstest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkDigisensGeometryReader.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\n\n/**\n * \\file rtkdigisenstest.cxx\n *\n * \\brief Functional tests for classes managing Digisens data\n *\n * This test reads a projection and the geometry of an acquisition from a\n * Digisens acquisition and compares it to the expected results, which are\n * read from a baseline image in the MetaIO file format and a geometry file in\n * the RTK format, respectively.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 5)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"  calibration.cal  projection.tif  geometry.xml  reference.mha\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Elekta geometry\n  rtk::DigisensGeometryReader::Pointer geoTargReader;\n  geoTargReader = rtk::DigisensGeometryReader::New();\n  geoTargReader->SetXMLFileName(argv[1]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader->UpdateOutputData());\n\n  // Reference geometry\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer geoRefReader;\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[3]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // 1. Check geometries\n  CheckGeometries(geoTargReader->GetGeometry(), geoRefReader->GetOutputObject());\n\n  // ******* COMPARING projections *******\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::Image<float, Dimension>;\n\n  // Tif projections reader\n  using ReaderType = rtk::ProjectionsReader<ImageType>;\n  auto                     reader = ReaderType::New();\n  std::vector<std::string> fileNames;\n  fileNames.emplace_back(argv[2]);\n  reader->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update());\n\n  // Reference projections reader\n  auto                     readerRef = ReaderType::New();\n  std::vector<std::string> fileNamesRef;\n  fileNamesRef.emplace_back(argv[4]);\n  readerRef->SetFileNames(fileNamesRef);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 2.31e-7, 100, 2.0);\n\n  // If both succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkdisplaceddetectorcompcudatest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkCudaDisplacedDetectorImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n\n#include <itkStreamingImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\n/**\n * \\file rtkdisplaceddetectorcompcudatest.cxx\n *\n * \\brief Test rtk::CudaDisplacedDetectorImageFilter vs rtk::DisplacedDetectorImageFilter\n *\n * This test compares weighted projections using CPU and Cuda implementations\n * of the filter for displaced detector handling in FBP.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::CudaImage<float, Dimension>;\n\n  // Constant image sources\n  auto projSource = rtk::ConstantImageSource<OutputImageType>::New();\n  projSource->SetOrigin(itk::MakePoint(-127., -3., 0.));\n  projSource->SetSpacing(itk::MakeVector(2., 2., 2.));\n  projSource->SetSize(itk::MakeSize(128, 4, 4));\n\n  // Geometry\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  geometry->AddProjection(600., 700., 0., 84., 35, 23, 15, 21, 26);\n  geometry->AddProjection(500., 800., 45., 21., 12, 16, 546, 14, 41);\n  geometry->AddProjection(700., 900., 90., 68., 68, 54, 38, 35, 56);\n  geometry->AddProjection(900., 1000., 135., 48., 35, 84, 10, 84, 59);\n\n  // Projections\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  for (int inPlace = 0; inPlace < 2; inPlace++)\n  {\n    std::cout << \"\\n\\n****** Case \" << inPlace * 2 << \": no streaming, \";\n    if (!inPlace)\n      std::cout << \"not\";\n    std::cout << \" in place ******\" << std::endl;\n\n    using CUDADDFType = rtk::CudaDisplacedDetectorImageFilter;\n    auto cudaddf = CUDADDFType::New();\n    cudaddf->SetInput(slp->GetOutput());\n    cudaddf->SetGeometry(geometry);\n    cudaddf->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cudaddf->Update());\n\n    using CPUDDFType = rtk::DisplacedDetectorImageFilter<OutputImageType>;\n    auto cpuddf = CPUDDFType::New();\n    cpuddf->SetInput(slp->GetOutput());\n    cpuddf->SetGeometry(geometry);\n    cpuddf->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cpuddf->Update());\n\n    CheckImageQuality<OutputImageType>(cudaddf->GetOutput(), cpuddf->GetOutput(), 1.e-5, 100, 1.);\n\n    std::cout << \"\\n\\n****** Case \" << inPlace * 2 + 1 << \": with streaming, \";\n    if (!inPlace)\n      std::cout << \"not\";\n    std::cout << \" in place ******\" << std::endl;\n\n    // Idem with streaming\n    cudaddf = CUDADDFType::New();\n    cudaddf->SetInput(slp->GetOutput());\n    cudaddf->SetGeometry(geometry);\n    cudaddf->InPlaceOff();\n\n    using StreamingType = itk::StreamingImageFilter<OutputImageType, OutputImageType>;\n    auto streamingCUDA = StreamingType::New();\n    streamingCUDA->SetInput(cudaddf->GetOutput());\n    streamingCUDA->SetNumberOfStreamDivisions(4);\n    auto splitter = itk::ImageRegionSplitterDirection::New();\n    splitter->SetDirection(2); // Splitting along direction 1, NOT 2\n    streamingCUDA->SetRegionSplitter(splitter);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamingCUDA->Update());\n\n    cpuddf = CPUDDFType::New();\n    cpuddf->SetInput(slp->GetOutput());\n    cpuddf->SetGeometry(geometry);\n    cpuddf->InPlaceOff();\n\n    auto streamingCPU = StreamingType::New();\n    streamingCPU->SetInput(cpuddf->GetOutput());\n    streamingCPU->SetNumberOfStreamDivisions(2);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamingCPU->Update());\n\n    CheckImageQuality<OutputImageType>(streamingCUDA->GetOutput(), streamingCPU->GetOutput(), 1.e-5, 100, 1.);\n  }\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkdisplaceddetectorcompoffsettest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkDisplacedDetectorImageFilter.h\"\n#include \"rtkDisplacedDetectorForOffsetFieldOfViewImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n\n#include <itkStreamingImageFilter.h>\n\n/**\n * \\file rtkdisplaceddetectorcompcudatest.cxx\n *\n * \\brief Test rtk::CudaDisplacedDetectorImageFilter vs rtk::DisplacedDetectorImageFilter\n *\n * This test compares weighted projections using CPU and Cuda implementations\n * of the filter for displaced detector handling in FBP.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Constant image sources\n  auto projSource = rtk::ConstantImageSource<OutputImageType>::New();\n  projSource->SetOrigin(itk::MakePoint(-508., -3., 0.));\n  projSource->SetSpacing(itk::MakeVector(8., 2., 2.));\n  projSource->SetSize(itk::MakeSize(128, 4, 4));\n\n  // Geometry\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  geometry->AddProjection(600., 560., 0., 3., 0., 0., 0., 2., 0.);\n  geometry->AddProjection(500., 545., 90., 2., 0., 0., 0., 4., 0.);\n  geometry->AddProjection(700., 790., 180., 8., 0., 0., 0., 5., 0.);\n  geometry->AddProjection(900., 935., 270., 4., 0., 0., 0., 8., 0.);\n\n  // Projections\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  for (int inPlace = 0; inPlace < 2; inPlace++)\n  {\n    std::cout << \"\\n\\n****** Case \" << inPlace * 2 << \": no streaming, \";\n    if (!inPlace)\n      std::cout << \"not\";\n    std::cout << \" in place ******\" << std::endl;\n\n    using OffsetDDFType = rtk::DisplacedDetectorForOffsetFieldOfViewImageFilter<OutputImageType>;\n    auto cudaddf = OffsetDDFType::New();\n    cudaddf->SetInput(slp->GetOutput());\n    cudaddf->SetGeometry(geometry);\n    cudaddf->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cudaddf->Update());\n\n    using CPUDDFType = rtk::DisplacedDetectorImageFilter<OutputImageType>;\n    auto cpuddf = CPUDDFType::New();\n    cpuddf->SetInput(slp->GetOutput());\n    cpuddf->SetGeometry(geometry);\n    cpuddf->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cpuddf->Update());\n\n    CheckImageQuality<OutputImageType>(cudaddf->GetOutput(), cpuddf->GetOutput(), 1.e-6, 100, 1.);\n\n    std::cout << \"\\n\\n****** Case \" << inPlace * 2 + 1 << \": with streaming, \";\n    if (!inPlace)\n      std::cout << \"not\";\n    std::cout << \" in place ******\" << std::endl;\n\n    // Idem with streaming\n    cudaddf = OffsetDDFType::New();\n    cudaddf->SetInput(slp->GetOutput());\n    cudaddf->SetGeometry(geometry);\n    cudaddf->InPlaceOff();\n\n    using StreamingType = itk::StreamingImageFilter<OutputImageType, OutputImageType>;\n    auto streamingCUDA = StreamingType::New();\n    streamingCUDA->SetInput(cudaddf->GetOutput());\n    streamingCUDA->SetNumberOfStreamDivisions(2);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamingCUDA->Update());\n\n    cpuddf = CPUDDFType::New();\n    cpuddf->SetInput(slp->GetOutput());\n    cpuddf->SetGeometry(geometry);\n    cpuddf->InPlaceOff();\n\n    auto streamingCPU = StreamingType::New();\n    streamingCPU->SetInput(cpuddf->GetOutput());\n    streamingCPU->SetNumberOfStreamDivisions(2);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamingCPU->Update());\n\n    CheckImageQuality<OutputImageType>(streamingCUDA->GetOutput(), streamingCPU->GetOutput(), 1.e-6, 100, 1.);\n  }\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkdisplaceddetectortest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n\n#include \"rtkTest.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#ifdef USE_CUDA\n#  include \"rtkCudaDisplacedDetectorImageFilter.h\"\n#else\n#  include \"rtkDisplacedDetectorImageFilter.h\"\n#endif\n\n/**\n * \\file rtkdisplaceddetectortest.cxx\n *\n * \\brief Functional test for classes performing FDK reconstructions with a\n * displaced detector/source\n *\n * This test generates the projections of a simulated Shepp-Logan phantom and\n * different sets of geometries with different displaced detectors and sources.\n * Images are then reconstructed from the generated projection images and\n * compared to the expected results which is analytically computed.\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(254., 254., 254.);\n#else\n  auto size = itk::MakeSize(128, 128, 128);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(508., 508., 508.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  auto projectionsSource = ConstantImageSourceType::New();\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Shepp Logan projections filter\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projectionsSource->GetOutput());\n\n  // Displaced detector weighting\n#ifdef USE_CUDA\n  using DDFType = rtk::CudaDisplacedDetectorImageFilter;\n#else\n  using DDFType = rtk::DisplacedDetectorImageFilter<OutputImageType>;\n#endif\n  auto ddf = DDFType::New();\n  ddf->SetInput(slp->GetOutput());\n\n  // Create a reference object (in this case a 3D phantom reference).\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update());\n\n  // FDK reconstruction filtering\n  auto feldkamp = rtk::FDKConeBeamReconstructionFilter<OutputImageType>::New();\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, ddf->GetOutput());\n\n  std::cout << \"\\n\\n****** Case 1: positive offset in geometry ******\" << std::endl;\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n  slp->SetGeometry(geometry);\n  ddf->SetGeometry(geometry);\n  feldkamp->SetGeometry(geometry);\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 120., 0.);\n  slp->Update();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 0.061, 24, 2.0);\n\n  std::cout << \"\\n\\n****** Case 2: negative offset in geometry ******\" << std::endl;\n  geometry = GeometryType::New();\n  slp->SetGeometry(geometry);\n  ddf->SetGeometry(geometry);\n  feldkamp->SetGeometry(geometry);\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, -120., 0.);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 0.061, 24, 2.0);\n\n  std::cout << \"\\n\\n****** Case 3: no displacement ******\" << std::endl;\n  geometry = GeometryType::New();\n  slp->SetGeometry(geometry);\n  ddf->SetGeometry(geometry);\n  feldkamp->SetGeometry(geometry);\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n  projectionsSource->SetOrigin(origin);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 0.061, 24, 2.0);\n\n  std::cout << \"\\n\\n****** Case 4: negative offset in origin ******\" << std::endl;\n  geometry = GeometryType::New();\n  slp->SetGeometry(geometry);\n  ddf->SetGeometry(geometry);\n  feldkamp->SetGeometry(geometry);\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n  projectionsSource->SetOrigin(itk::MakePoint(-400., -254., -254.));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 0.061, 24, 2.0);\n\n  std::cout << \"\\n\\n****** Case 5: positive offset in origin ******\" << std::endl;\n  projectionsSource->SetOrigin(itk::MakePoint(-100., -254., -254.));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 0.061, 24, 2.0);\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkdivergencetest.cxx",
    "content": "#include <itkRandomImageSource.h>\n#include <itkConstantBoundaryCondition.h>\n#include <itkImageFileReader.h>\n#include <itkImageFileWriter.h>\n#include <itkMultiplyImageFilter.h>\n\n#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n\n#include \"rtkBackwardDifferenceDivergenceImageFilter.h\"\n#include \"rtkForwardDifferenceGradientImageFilter.h\"\n\n/**\n * \\file rtkdivergencetest.cxx\n *\n * \\brief Tests whether the divergence filter behaves as expected\n *\n * Tests whether MINUS the divergence is the adjoint of the forward\n * difference gradient. The exact definition of\n * the divergence desired can be found in\n * Chambolle, Antonin. “An Algorithm for Total Variation\n * Minimization and Applications.” J. Math. Imaging Vis. 20,\n * no. 1–2 (January 2004): 89–97\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = double;\n\n  using CovVecType = itk::CovariantVector<OutputPixelType, 2>;\n#ifdef USE_CUDA\n  using ImageType = itk::CudaImage<OutputPixelType, Dimension>;\n  using GradientImageType = itk::CudaImage<CovVecType, Dimension>;\n#else\n  using ImageType = itk::Image<OutputPixelType, Dimension>;\n  using GradientImageType = itk::Image<CovVecType, Dimension>;\n#endif\n\n  // Random image sources\n  using RandomImageSourceType = itk::RandomImageSource<ImageType>;\n  auto randomVolumeSource1 = RandomImageSourceType::New();\n  auto randomVolumeSource2 = RandomImageSourceType::New();\n\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(252., 252., 252.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto size = itk::MakeSize(64, 64, 64);\n#endif\n  randomVolumeSource1->SetOrigin(origin);\n  randomVolumeSource1->SetSpacing(spacing);\n  randomVolumeSource1->SetSize(size);\n  randomVolumeSource1->SetMin(-7.);\n  randomVolumeSource1->SetMax(1.);\n\n  randomVolumeSource2->SetOrigin(origin);\n  randomVolumeSource2->SetSpacing(spacing);\n  randomVolumeSource2->SetSize(size);\n  randomVolumeSource2->SetMin(-3.);\n  randomVolumeSource2->SetMax(2.);\n\n  // Update all sources\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource1->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource2->Update());\n\n  // Set the dimensions along which gradient and divergence\n  // should be computed\n  bool computeGradientAlongDim[Dimension];\n  computeGradientAlongDim[0] = true;\n  computeGradientAlongDim[1] = false;\n  computeGradientAlongDim[2] = true;\n\n  // Compute the gradient of both volumes\n  using GradientFilterType =\n    rtk::ForwardDifferenceGradientImageFilter<ImageType, OutputPixelType, OutputPixelType, GradientImageType>;\n  auto grad1 = GradientFilterType::New();\n  grad1->SetInput(randomVolumeSource1->GetOutput());\n  grad1->SetDimensionsProcessed(computeGradientAlongDim);\n\n  auto grad2 = GradientFilterType::New();\n  grad2->SetInput(randomVolumeSource2->GetOutput());\n  grad2->SetDimensionsProcessed(computeGradientAlongDim);\n\n  // Now compute MINUS the divergence of grad2\n  auto div = rtk::BackwardDifferenceDivergenceImageFilter<GradientImageType, ImageType>::New();\n  div->SetInput(grad2->GetOutput());\n  div->SetDimensionsProcessed(computeGradientAlongDim);\n\n  auto multiply = itk::MultiplyImageFilter<ImageType>::New();\n  multiply->SetInput1(div->GetOutput());\n  multiply->SetConstant2(-1);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(multiply->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(grad1->Update());\n\n  CheckScalarProducts<GradientImageType, ImageType>(\n    grad1->GetOutput(), grad2->GetOutput(), randomVolumeSource1->GetOutput(), multiply->GetOutput());\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkdrawgeometricphantomtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkDrawGeometricPhantomImageFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkDrawCylinderImageFilter.h\"\n#include \"rtkDrawConeImageFilter.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\nusing GeometryType = rtk::ThreeDCircularProjectionGeometry;\n\n/**\n * \\file rtkdrawgeometricphantomtest.cxx\n *\n * \\brief Functional test for the class that creates a geometric phantom\n * specified in a config file.\n *\n * This test generates several phantoms with different geometrical shapes\n * (Cone, Cylinder, Shepp-Logan...) specified by configuration files.\n * The generated results are compared to the expected results, which are\n * created through hard-coded geometric parameters.\n *\n * \\author Marc Vila\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 3)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"  SheppLoganConfig.txt GeometryConfig.txt\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Constant image sources\n  auto tomographySource = rtk::ConstantImageSource<OutputImageType>::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto spacing = itk::MakeVector(254., 254., 254.);\n  auto size = itk::MakeSize(2, 2, 2);\n#else\n  auto spacing = itk::MakeVector(2., 2., 2.);\n  auto size = itk::MakeSize(128, 128, 128);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  //////////////////////////////////\n  // Part 1: Shepp Logan\n  //////////////////////////////////\n\n  // Shepp Logan reference filter\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  dsl->SetPhantomScale(128.);\n  dsl->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update());\n\n  // Shepp Logan reference filter from Configuration File\n  auto dgp = rtk::DrawGeometricPhantomImageFilter<OutputImageType, OutputImageType>::New();\n  dgp->SetInput(tomographySource->GetOutput());\n  dgp->InPlaceOff();\n  dgp->SetConfigFile(argv[1]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dgp->Update());\n\n  CheckImageQuality<OutputImageType>(dsl->GetOutput(), dgp->GetOutput(), 0.0005, 90, 255.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  //////////////////////////////////\n  // Part 2: other geometries than ellipsoid\n  //////////////////////////////////\n\n  // New Geometries from Configuration File\n  dgp->SetInput(tomographySource->GetOutput());\n  dgp->SetConfigFile(argv[2]);\n  dgp->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dgp->Update());\n\n  //    // Create Reference\n  //    std::vector< double > axis;\n  //    axis.push_back(100.);\n  //    axis.push_back(0.);\n  //    axis.push_back(100.);\n\n  //    std::vector< double > center;\n  //    center.push_back(2.);\n  //    center.push_back(2.);\n  //    center.push_back(2.);\n\n  // Draw CYLINDER\n  auto dcl = rtk::DrawCylinderImageFilter<OutputImageType, OutputImageType>::New();\n\n  dcl->SetInput(tomographySource->GetOutput());\n  dcl->SetAxis(itk::MakeVector(100., 0., 100.));\n  dcl->SetCenter(itk::MakeVector(2., 2., 2.));\n  dcl->SetAngle(0.);\n  dcl->SetDensity(2.);\n  dcl->InPlaceOff();\n\n  // Draw CONE\n  auto dco = rtk::DrawConeImageFilter<OutputImageType, OutputImageType>::New();\n  dco->SetInput(tomographySource->GetOutput());\n  dco->SetAxis(itk::MakeVector(25., -50., 25.));\n  dco->SetCenter(itk::MakeVector(2., 2., 2.));\n  dco->SetAngle(0.);\n  dco->SetDensity(-0.54);\n\n  // Add Image Filter used to concatenate the different figures obtained on each iteration\n  auto addFilter = itk::AddImageFilter<OutputImageType, OutputImageType, OutputImageType>::New();\n\n  addFilter->SetInput1(dcl->GetOutput());\n  addFilter->SetInput2(dco->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(addFilter->Update());\n\n  CheckImageQuality<OutputImageType>(dgp->GetOutput(), addFilter->GetOutput(), 0.0005, 90, 255.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkedftest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkMacro.h\"\n\n/**\n * \\file rtkedftest.cxx\n *\n * \\brief Functional test for classes managing ESRF/Edf data\n *\n * This test reads a projection of an acquisition of ESRF/Edf type\n * and compares it to the expected results, which are read from a baseline\n * image in the MetaIO file format.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 3)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"  projection.edf  reference.mha\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::Image<float, Dimension>;\n\n  // 1. ESRF / Edf projections reader\n  using ReaderType = rtk::ProjectionsReader<ImageType>;\n  auto                     reader = ReaderType::New();\n  std::vector<std::string> fileNames;\n  fileNames.emplace_back(argv[1]);\n  reader->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update());\n\n  // Reference projections reader\n  auto readerRef = ReaderType::New();\n  fileNames.clear();\n  fileNames.emplace_back(argv[2]);\n  readerRef->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 0.00000001, 100, 2.0);\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkelektatest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkMacro.h\"\n#include \"rtkElektaSynergyGeometryReader.h\"\n#include \"rtkElektaXVI5GeometryXMLFileReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\n/**\n * \\file rtkelektatest.cxx\n *\n * \\brief Functional tests for classes managing Elekta Synergy data\n *\n * This test reads a projection and the geometry of an acquisition from an\n * Elekta Synergy acquisition and compares it to the expected results, which are\n * read from a baseline image in the MetaIO file format and a geometry file in\n * the RTK format, respectively.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 8)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0]\n              << \"  image.DBF frame.DBF proj.his elektaGeometry.xml refGeometry.xml reference.mha refElektaGeometry.xml\"\n              << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  std::cout << \"Testing geometry with FRAME.DBF...\" << std::endl;\n\n  // Elekta geometry\n  rtk::ElektaSynergyGeometryReader::Pointer geoTargReader;\n  geoTargReader = rtk::ElektaSynergyGeometryReader::New();\n  geoTargReader->SetDicomUID(\"1.3.46.423632.135428.1351013645.166\");\n  geoTargReader->SetImageDbfFileName(argv[1]);\n  geoTargReader->SetFrameDbfFileName(argv[2]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader->UpdateOutputData());\n\n  // Reference geometry\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer geoRefReader;\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[5]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  std::cout << \"Testing geometry with _Frames.xml...\" << std::endl;\n\n  // Elekta geometry XVI v5\n  rtk::ElektaXVI5GeometryXMLFileReader::Pointer geo5TargReader;\n  geo5TargReader = rtk::ElektaXVI5GeometryXMLFileReader::New();\n  geo5TargReader->SetFilename(argv[4]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geo5TargReader->GenerateOutputInformation());\n\n  // Reference geometry v5\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer geo5RefReader;\n  geo5RefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geo5RefReader->SetFilename(argv[7]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geo5RefReader->GenerateOutputInformation())\n\n  // 1. Check geometries\n  CheckGeometries(geoTargReader->GetGeometry(), geoRefReader->GetOutputObject());\n  CheckGeometries(geo5TargReader->GetGeometry(), geo5RefReader->GetOutputObject());\n\n  std::cout << \"Testing his file processing...\" << std::endl;\n\n  // ******* COMPARING projections *******\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::Image<float, Dimension>;\n\n  // Elekta projections reader\n  using ReaderType = rtk::ProjectionsReader<ImageType>;\n  auto                     reader = ReaderType::New();\n  std::vector<std::string> fileNames;\n  fileNames.emplace_back(argv[3]);\n  reader->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update());\n\n  // Reference projections reader\n  auto readerRef = ReaderType::New();\n  fileNames.clear();\n  fileNames.emplace_back(argv[6]);\n  readerRef->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 1.6e-7, 100, 2.0);\n\n  // ******* Test split of lookup table ******\n  using InputImageType = itk::Image<unsigned short, 3>;\n  auto r = itk::ImageFileReader<InputImageType>::New();\n  r->SetFileName(argv[3]);\n  r->Update();\n\n  auto full = rtk::ElektaSynergyLookupTableImageFilter<ImageType>::New();\n  full->SetInput(r->GetOutput());\n  full->Update();\n\n  auto raw = rtk::ElektaSynergyRawLookupTableImageFilter<InputImageType, InputImageType>::New();\n  raw->SetInput(r->GetOutput());\n  raw->Update();\n\n  auto log = rtk::LUTbasedVariableI0RawToAttenuationImageFilter<InputImageType, ImageType>::New();\n  log->SetInput(raw->GetOutput());\n  log->SetI0(log->GetI0() + 1.);\n  log->Update();\n\n  // Compare the result of the full lut with the split lut\n  CheckImageQuality<ImageType>(full->GetOutput(), log->GetOutput(), 1.6e-7, 100, 2.0);\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkfbpparalleltest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkStreamingImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\n#include \"rtkTest.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"rtkCudaFDKConeBeamReconstructionFilter.h\"\n#else\n#  include \"rtkFDKConeBeamReconstructionFilter.h\"\n#endif\n\n/**\n * \\file rtkfdktest.cxx\n *\n * \\brief Functional test for classes performing parallel FBP\n *\n * This test generates the projections of a simulated Shepp-Logan phantom.\n * A CT image is reconstructed from each set of generated projection images\n * using the FDK algorithm and the reconstructed CT image is compared to the\n * expected results which is analytically computed.\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(32, 32, 32);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#else\n  auto size = itk::MakeSize(128, 128, 128);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  auto tomographySource = ConstantImageSourceType::New();\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  size[2] = NumberOfProjectionImages;\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 0., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n  // Shepp Logan projections filter\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projectionsSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  // Create a reference object (in this case a 3D phantom reference).\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  dsl->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // FDK reconstruction filtering\n#ifdef USE_CUDA\n  using FDKType = rtk::CudaFDKConeBeamReconstructionFilter;\n#else\n  using FDKType = rtk::FDKConeBeamReconstructionFilter<OutputImageType>;\n#endif\n  auto feldkamp = FDKType::New();\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, slp->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n\n\n  // FOV\n  auto fov = rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType>::New();\n  fov->SetInput(0, feldkamp->GetOutput());\n  fov->SetProjectionsStack(slp->GetOutput());\n  fov->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fov->Update());\n\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput(), 0.03, 26, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkfdkprojweightcompcudatest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkCudaFDKWeightProjectionFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\n#include <itkStreamingImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\n/**\n * \\file rtkfdkprojweightcompcudatest.cxx\n *\n * \\brief Test rtk::CudaFDKWeightProjectionFilter vs rtk::FDKWeightProjectionFilter\n *\n * This test compares CUDA and CPU implementations of the projection weighting\n * for FDK reconstruction.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::CudaImage<float, Dimension>;\n\n\n  // Constant image sources\n  auto projSource = rtk::ConstantImageSource<OutputImageType>::New();\n  projSource->SetOrigin(itk::MakePoint(-127., -3., 0.));\n  projSource->SetSpacing(itk::MakeVector(2., 2., 2.));\n  projSource->SetSize(itk::MakeSize(128, 4, 4));\n\n  // Geometry\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  geometry->AddProjection(600., 700., 0., 84., 35, 23, 15, 21, 26);\n  geometry->AddProjection(500., 800., 45., 21., 12, 16, 546, 14, 41);\n  geometry->AddProjection(700., 900., 90., 68., 68, 54, 38, 35, 56);\n  geometry->AddProjection(900., 1000., 135., 48., 35, 84, 10, 84, 59);\n\n  // Projections\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  for (int inPlace = 0; inPlace < 2; inPlace++)\n  {\n    std::cout << \"\\n\\n****** Case \" << inPlace * 2 << \": no streaming, \";\n    if (!inPlace)\n      std::cout << \"not\";\n    std::cout << \" in place ******\" << std::endl;\n\n    using CUDAFDKWFType = rtk::CudaFDKWeightProjectionFilter;\n    auto cudafdkwf = CUDAFDKWFType::New();\n    cudafdkwf->SetInput(slp->GetOutput());\n    cudafdkwf->SetGeometry(geometry);\n    cudafdkwf->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cudafdkwf->Update());\n\n    using CPUFDKWFType = rtk::FDKWeightProjectionFilter<OutputImageType>;\n    auto cpufdkwf = CPUFDKWFType::New();\n    cpufdkwf->SetInput(slp->GetOutput());\n    cpufdkwf->SetGeometry(geometry);\n    cpufdkwf->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cpufdkwf->Update());\n\n    CheckImageQuality<OutputImageType>(cudafdkwf->GetOutput(), cpufdkwf->GetOutput(), 1.e-5, 95, 1.);\n\n    std::cout << \"\\n\\n****** Case \" << inPlace * 2 + 1 << \": with streaming, \";\n    if (!inPlace)\n      std::cout << \"not\";\n    std::cout << \" in place ******\" << std::endl;\n\n    // Idem with streaming\n    cudafdkwf = CUDAFDKWFType::New();\n    cudafdkwf->SetInput(slp->GetOutput());\n    cudafdkwf->SetGeometry(geometry);\n    cudafdkwf->InPlaceOff();\n\n    using StreamingType = itk::StreamingImageFilter<OutputImageType, OutputImageType>;\n    auto streamingCUDA = StreamingType::New();\n    streamingCUDA->SetInput(cudafdkwf->GetOutput());\n    streamingCUDA->SetNumberOfStreamDivisions(4);\n    auto splitter = itk::ImageRegionSplitterDirection::New();\n    splitter->SetDirection(2); // Splitting along direction 1, NOT 2\n    streamingCUDA->SetRegionSplitter(splitter);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamingCUDA->Update());\n\n    cpufdkwf = CPUFDKWFType::New();\n    cpufdkwf->SetInput(slp->GetOutput());\n    cpufdkwf->SetGeometry(geometry);\n    cpufdkwf->InPlaceOff();\n\n    auto streamingCPU = StreamingType::New();\n    streamingCPU->SetInput(cpufdkwf->GetOutput());\n    streamingCPU->SetNumberOfStreamDivisions(2);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamingCPU->Update());\n\n    CheckImageQuality<OutputImageType>(streamingCUDA->GetOutput(), streamingCPU->GetOutput(), 1.e-5, 95, 1.);\n  }\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkfdktest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkStreamingImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\n#include \"rtkTest.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"rtkCudaFDKConeBeamReconstructionFilter.h\"\n#else\n#  include \"rtkFDKConeBeamReconstructionFilter.h\"\n#endif\n\n/**\n * \\file rtkfdktest.cxx\n *\n * \\brief Functional test for classes performing FDK reconstructions\n *\n * This test generates the projections of a simulated Shepp-Logan phantom.\n * A CT image is reconstructed from each set of generated projection images\n * using the FDK algorithm and the reconstructed CT image is compared to the\n * expected results which is analytically computed.\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(32, 32, 32);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#else\n  auto size = itk::MakeSize(128, 128, 128);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  auto tomographySource = ConstantImageSourceType::New();\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(32, 32, NumberOfProjectionImages);\n  spacing = itk::MakeVector(32., 32., 32.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  auto projectionsSource = ConstantImageSourceType::New();\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  std::cout << \"\\n\\n****** Case 1: No streaming ******\" << std::endl;\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n  // Shepp Logan projections filter\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projectionsSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  // Create a reference object (in this case a 3D phantom reference).\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  dsl->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // FDK reconstruction filtering\n#ifdef USE_CUDA\n  using FDKType = rtk::CudaFDKConeBeamReconstructionFilter;\n#else\n  using FDKType = rtk::FDKConeBeamReconstructionFilter<OutputImageType>;\n#endif\n  auto feldkamp = FDKType::New();\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, slp->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n\n\n  // FOV\n  auto fov = rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType>::New();\n  fov->SetInput(0, feldkamp->GetOutput());\n  fov->SetProjectionsStack(slp->GetOutput());\n  fov->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fov->Update());\n\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput(), 0.03, 26, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: perpendicular direction ******\" << std::endl;\n\n  ConstantImageSourceType::OutputImageType::DirectionType direction;\n  direction[0][0] = 0;\n  direction[0][1] = 1;\n  direction[0][2] = 0;\n  direction[1][0] = -1;\n  direction[1][1] = 0;\n  direction[1][2] = 0;\n  direction[2][0] = 0;\n  direction[2][1] = 0;\n  direction[2][2] = 1;\n  tomographySource->SetDirection(direction);\n  tomographySource->SetOrigin(itk::MakePoint(-127., 127., -127.));\n  fov->GetOutput()->ResetPipeline();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fov->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput(), 0.03, 26, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 3: 45 degree tilt direction ******\" << std::endl;\n\n  direction[0][0] = 0.70710678118;\n  direction[0][1] = -0.70710678118;\n  direction[0][2] = 0.70710678118;\n  direction[1][0] = 0.70710678118;\n  direction[1][1] = 0;\n  direction[1][2] = 0;\n  direction[2][0] = 0;\n  direction[2][1] = 0;\n  direction[2][2] = 1;\n  tomographySource->SetDirection(direction);\n  tomographySource->SetOrigin(itk::MakePoint(-127., -127., -127.));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fov->Update());\n\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput(), 0.03, 26, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 4: streaming ******\" << std::endl;\n\n  // Make sure that the data will be recomputed by releasing them\n  fov->GetOutput()->ReleaseData();\n\n  auto streamer = itk::StreamingImageFilter<OutputImageType, OutputImageType>::New();\n  streamer->SetInput(0, fov->GetOutput());\n  streamer->SetNumberOfStreamDivisions(8);\n  auto splitter = itk::ImageRegionSplitterDirection::New();\n  splitter->SetDirection(2); // Prevent splitting along z axis. As a result, splitting will be performed along y axis\n  streamer->SetRegionSplitter(splitter);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(streamer->Update());\n\n  CheckImageQuality<OutputImageType>(streamer->GetOutput(), dsl->GetOutput(), 0.03, 26, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 5: small ROI ******\" << std::endl;\n  tomographySource->SetOrigin(itk::MakePoint(-5., -13., -20.));\n  tomographySource->SetSize(itk::MakeSize(64, 64, 64));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fov->UpdateLargestPossibleRegion());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->UpdateLargestPossibleRegion())\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput(), 0.03, 26, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkforbildtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkDrawGeometricPhantomImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkProjectGeometricPhantomImageFilter.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n\n/**\n * \\file rtkforbildtest.cxx\n *\n * \\brief Functional test for Forbild phantom\n *\n * This test reads in a phantom file in the Forbild format, creates projections,\n * reconstructs them and compares the result to the drawing.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 45;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-29., -29., -29.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(6, 6, 6);\n  auto spacing = itk::MakeVector(10., 10., 10.);\n#else\n  auto size = itk::MakeSize(30, 30, 30);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-29., -29., 0.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(6, 6, NumberOfProjectionImages);\n#else\n  size = itk::MakeSize(30, 30, NumberOfProjectionImages);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Rotation matrix\n  rtk::ThreeDCircularProjectionGeometry::Matrix3x3Type rotMat;\n  rotMat.Fill(0.);\n  rotMat[0][0] = 1.;\n  rotMat[1][2] = 1.;\n  rotMat[2][1] = -1.;\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 0., noProj * 360. / NumberOfProjectionImages);\n\n  std::string configFileName = std::string(RTK_DATA_ROOT) + std::string(\"/Input/Forbild/Thorax\");\n\n  // Shepp Logan projections filter\n  std::cout << \"\\n\\n****** Projecting ******\" << std::endl;\n  auto pgp = rtk::ProjectGeometricPhantomImageFilter<OutputImageType, OutputImageType>::New();\n  pgp->SetInput(projectionsSource->GetOutput());\n  pgp->SetGeometry(geometry);\n  pgp->SetPhantomScale(1.2);\n  pgp->SetConfigFile(configFileName);\n  pgp->SetRotationMatrix(rotMat);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(pgp->Update());\n\n  // Create a reference object (in this case a 3D phantom reference).\n  std::cout << \"\\n\\n****** Drawing ******\" << std::endl;\n  auto dgp = rtk::DrawGeometricPhantomImageFilter<OutputImageType, OutputImageType>::New();\n  dgp->SetInput(tomographySource->GetOutput());\n  dgp->SetPhantomScale(1.2);\n  dgp->SetConfigFile(configFileName);\n  dgp->SetRotationMatrix(rotMat);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dgp->Update())\n\n  // FDK reconstruction filtering\n  std::cout << \"\\n\\n****** Reconstructing ******\" << std::endl;\n  auto feldkamp = rtk::FDKConeBeamReconstructionFilter<OutputImageType>::New();\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, pgp->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dgp->GetOutput(), 0.065, 24, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkforwardattenuatedprojectiontest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkJosephForwardAttenuatedProjectionImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include <itkStreamingImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n#include <itkSubtractImageFilter.h>\n#include <itkCenteredEuler3DTransform.h>\n#include <itkPasteImageFilter.h>\n#include <cmath>\n#include <itkMemoryUsageObserver.h>\n\n\n#ifdef USE_CUDA\n#  include \"rtkCudaForwardProjectionImageFilter.h\"\n#else\n#  include \"rtkJosephForwardAttenuatedProjectionImageFilter.h\"\n#endif\n\n/**\n * \\file rtkforwardattenuatedprojectiontest.cxx\n *\n * \\brief Functional test for forward projection\n *\n * The test projects a volume filled with ones. The forward projector should\n * then return the intersection of the ray with the box and it is compared\n * with the analytical intersection of a box with a ray.\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 45;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  constexpr double att = 0.0154;\n\n  // Create Joseph Forward Projector volume input.\n  auto volInput = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-126., -126., -126.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(252., 252., 252.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  volInput->SetOrigin(origin);\n  volInput->SetSpacing(spacing);\n  volInput->SetSize(size);\n  volInput->SetConstant(0.);\n  volInput->UpdateOutputInformation();\n\n  // Create Joseph Forward Projector attenuation map.\n  auto attenuationInput = ConstantImageSourceType::New();\n\n  attenuationInput->SetOrigin(origin);\n  attenuationInput->SetSpacing(spacing);\n  attenuationInput->SetSize(size);\n  attenuationInput->SetConstant(0);\n\n  auto deif = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  auto axis_vol = itk::MakeVector(50., 50., 50.);\n  auto center_vol = itk::MakeVector(0., 0., -30.);\n  deif->SetInput(volInput->GetOutput());\n  deif->SetCenter(center_vol);\n  deif->SetAxis(axis_vol);\n  deif->SetDensity(1);\n  deif->Update();\n\n  typename OutputImageType::Pointer attenuationMap, volumeSource;\n  volumeSource = deif->GetOutput();\n  volumeSource->DisconnectPipeline();\n  deif->SetCenter(itk::MakeVector(0., 0., 0.));\n  deif->SetAxis(itk::MakeVector(90, 90, 90));\n  deif->SetDensity(att);\n  deif->Update();\n  attenuationMap = deif->GetOutput();\n  attenuationMap->DisconnectPipeline();\n\n  // Initialization Volume, it is used in the Joseph Forward Projector and in the\n  // Ray Box Intersection Filter in order to initialize the stack of projections.\n  auto projInput = ConstantImageSourceType::New();\n  size[2] = 1;\n  projInput->SetOrigin(origin);\n  projInput->SetSpacing(spacing);\n  projInput->SetSize(size);\n  projInput->SetConstant(0.);\n  projInput->Update();\n\n  auto projTotal = ConstantImageSourceType::New();\n  size[2] = NumberOfProjectionImages;\n  projTotal->SetOrigin(origin);\n  projTotal->SetSpacing(spacing);\n  projTotal->SetSize(size);\n  projTotal->SetConstant(0.);\n  projTotal->Update();\n\n  // Joseph Forward Projection filter\n#ifdef USE_CUDA\n  using JFPType = rtk::CudaForwardProjectionImageFilter<OutputImageType, OutputImageType>;\n#else\n  using JFPType = rtk::JosephForwardAttenuatedProjectionImageFilter<OutputImageType, OutputImageType>;\n#endif\n  auto jfp = JFPType::New();\n  jfp->InPlaceOff();\n  jfp->SetInput(projTotal->GetOutput());\n  jfp->SetInput(1, volumeSource);\n  jfp->SetInput(2, attenuationMap);\n\n#ifdef USE_CUDA\n  jfp->SetStepSize(10);\n#endif\n  // Geometry\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto   geometry_projection = GeometryType::New();\n  double angle = 0;\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::PointType  center_transform;\n  REIType::VectorType clip_plane_direction_init, clip_plane_direction;\n  clip_plane_direction_init[0] = 0.;\n  clip_plane_direction_init[1] = 0.;\n  clip_plane_direction_init[2] = 1.;\n  auto transform = itk::CenteredEuler3DTransform<double>::New();\n  auto subtractImageFilter = itk::SubtractImageFilter<OutputImageType, OutputImageType>::New();\n  typename OutputImageType::IndexType indexSlice;\n  typename OutputImageType::Pointer   pimg;\n  indexSlice.Fill(0);\n  auto pasteImageFilter = itk::PasteImageFilter<OutputImageType, OutputImageType>::New();\n  pasteImageFilter->SetDestinationImage(projTotal->GetOutput());\n\n  int count = 0;\n  for (unsigned int i = 0; i < NumberOfProjectionImages; i++)\n  {\n    angle = i * 360. / NumberOfProjectionImages;\n    geometry_projection->AddProjection(500, 0., angle);\n    transform->SetRotation(0., angle * itk::Math::pi / 180, 0.);\n    clip_plane_direction = transform->GetMatrix() * clip_plane_direction_init;\n    center_transform = transform->GetMatrix() * center_vol;\n    auto sphere_attenuation = REIType::New();\n    sphere_attenuation->SetAngle(0);\n    sphere_attenuation->SetDensity(1);\n    sphere_attenuation->SetCenter(itk::MakeVector(0., 0., 0.));\n    sphere_attenuation->SetAxis(itk::MakeVector(90, 90, 90));\n    sphere_attenuation->SetInput(projInput->GetOutput());\n    auto sphere_emission = REIType::New();\n    sphere_emission->SetAngle(0);\n    sphere_emission->SetDensity(1);\n    sphere_emission->SetCenter(center_vol);\n    sphere_emission->SetAxis(axis_vol);\n    sphere_emission->SetInput(projInput->GetOutput());\n    sphere_attenuation->AddClipPlane(clip_plane_direction, center_transform[2]);\n    sphere_attenuation->SetGeometry(geometry_projection);\n    sphere_emission->AddClipPlane(clip_plane_direction, center_transform[2]);\n    sphere_emission->SetGeometry(geometry_projection);\n    indexSlice[2] = count;\n    sphere_attenuation->Update();\n    sphere_emission->Update();\n    subtractImageFilter->SetInput1(sphere_attenuation->GetOutput());\n    subtractImageFilter->SetInput2(sphere_emission->GetOutput());\n    subtractImageFilter->Update();\n    pasteImageFilter->SetSourceImage(subtractImageFilter->GetOutput());\n    pasteImageFilter->SetSourceRegion(subtractImageFilter->GetOutput()->GetLargestPossibleRegion());\n    pasteImageFilter->SetDestinationIndex(indexSlice);\n    pasteImageFilter->Update();\n    pimg = pasteImageFilter->GetOutput();\n    pimg->DisconnectPipeline();\n    pasteImageFilter->SetDestinationImage(pimg);\n    geometry_projection->Clear();\n    count += 1;\n  }\n\n  // Streaming filter to test for unusual regions\n  auto stream = itk::StreamingImageFilter<OutputImageType, OutputImageType>::New();\n  stream->SetInput(jfp->GetOutput());\n\n  stream->SetNumberOfStreamDivisions(9);\n  auto splitter = itk::ImageRegionSplitterDirection::New();\n  splitter->SetDirection(2); // Splitting along direction 1, NOT 2\n  stream->SetRegionSplitter(splitter);\n\n  std::cout << \"\\n\\n****** Case 1: inner ray source ******\" << std::endl;\n\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n  for (unsigned int i = 0; i < NumberOfProjectionImages; i++)\n  {\n    geometry->AddProjection(500, 0., i * 360. / NumberOfProjectionImages);\n  }\n  projTotal->Update();\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  auto rei = REIType::New();\n  rei->InPlaceOff();\n  rei->SetAngle(0);\n  rei->SetDensity(1);\n  rei->SetCenter(center_vol);\n  rei->SetAxis(axis_vol);\n  rei->SetInput(projTotal->GetOutput());\n  rei->SetGeometry(geometry);\n  rei->Update();\n\n  auto customBinaryFilter = itk::BinaryGeneratorImageFilter<OutputImageType, OutputImageType, OutputImageType>::New();\n  // Set Lambda function\n  auto customLambda = [&](const typename OutputImageType::PixelType & input1,\n                          const typename OutputImageType::PixelType & input2) -> typename OutputImageType::PixelType {\n    return static_cast<typename OutputImageType::PixelType>((1 - std::exp(-input1 * att)) / att *\n                                                            std::exp(-input2 * att));\n  };\n  customBinaryFilter->SetFunctor(customLambda);\n  customBinaryFilter->SetInput1(rei->GetOutput());\n  customBinaryFilter->SetInput2(pimg);\n  customBinaryFilter->Update();\n  jfp->SetGeometry(geometry);\n  stream->Update();\n\n  CheckImageQuality<OutputImageType>(stream->GetOutput(), customBinaryFilter->GetOutput(), 1.28, 44.0, 255.0);\n  std::cout << \"\\n\\nTest  PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkforwardprojectiontest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkRayBoxIntersectionImageFilter.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkConstantImageSource.h\"\n\n#include <itkStreamingImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\n#ifdef USE_CUDA\n#  include \"rtkCudaForwardProjectionImageFilter.h\"\n#else\n#  include \"rtkJosephForwardProjectionImageFilter.h\"\n#endif\n\n/**\n * \\file rtkforwardprojectiontest.cxx\n *\n * \\brief Functional test for forward projection\n *\n * The test projects a volume filled with ones. The forward projector should\n * then return the intersection of the ray with the box and it is compared\n * with the analytical intersection of a box with a ray.\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 45;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  // Create Joseph Forward Projector volume input.\n  auto volInput = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-126., -126., -126.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(252., 252., 252.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  volInput->SetOrigin(origin);\n  volInput->SetSpacing(spacing);\n  volInput->SetSize(size);\n  volInput->SetConstant(1.);\n  volInput->UpdateOutputInformation();\n\n  // Initialization Volume, it is used in the Joseph Forward Projector and in the\n  // Ray Box Intersection Filter in order to initialize the stack of projections.\n  auto projInput = ConstantImageSourceType::New();\n  size[2] = NumberOfProjectionImages;\n  projInput->SetOrigin(origin);\n  projInput->SetSpacing(spacing);\n  projInput->SetSize(size);\n  projInput->SetConstant(0.);\n  projInput->Update();\n\n  // Joseph Forward Projection filter\n#ifdef USE_CUDA\n  using JFPType = rtk::CudaForwardProjectionImageFilter<OutputImageType, OutputImageType>;\n#else\n  using JFPType = rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType>;\n#endif\n  auto jfp = JFPType::New();\n  jfp->InPlaceOff();\n  jfp->SetInput(projInput->GetOutput());\n  jfp->SetInput(1, volInput->GetOutput());\n\n  // Ray Box Intersection filter (reference)\n#ifdef USE_CUDA\n  jfp->SetStepSize(10);\n#endif\n  auto rbi = rtk::RayBoxIntersectionImageFilter<OutputImageType, OutputImageType>::New();\n  rbi->InPlaceOff();\n  rbi->SetInput(projInput->GetOutput());\n  rbi->SetBoxMin(itk::MakeVector(-126.0, -126.0, -126.0));\n  rbi->SetBoxMax(itk::MakeVector(126.0, 126.0, 47.6));\n\n  // Streaming filter to test for unusual regions\n  auto stream = itk::StreamingImageFilter<OutputImageType, OutputImageType>::New();\n  stream->SetInput(jfp->GetOutput());\n\n  stream->SetNumberOfStreamDivisions(9);\n  auto splitter = itk::ImageRegionSplitterDirection::New();\n  splitter->SetDirection(2); // Splitting along direction 1, NOT 2\n  stream->SetRegionSplitter(splitter);\n\n  std::cout << \"\\n\\n****** Case 1: inner ray source ******\" << std::endl;\n  // The circle is divided in 4 quarters\n  for (int q = 0; q < 4; q++)\n  {\n    // Geometry\n    using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n    auto geometry = GeometryType::New();\n    for (unsigned int i = 0; i < NumberOfProjectionImages; i++)\n    {\n      const double angle = -45. + i * 2.;\n      geometry->AddProjection(47.6 / std::cos(angle * itk::Math::pi / 180.), 1000., q * 90 + angle);\n    }\n\n    if (q == 0)\n    {\n      rbi->SetGeometry(geometry);\n      rbi->Update();\n    }\n\n    jfp->SetGeometry(geometry);\n    stream->Update();\n\n    CheckImageQuality<OutputImageType>(stream->GetOutput(), rbi->GetOutput(), 1.28, 44.0, 255.0);\n    std::cout << \"\\n\\nTest of quarter #\" << q << \" PASSED! \" << std::endl;\n  }\n\n#ifdef USE_CUDA\n  jfp->SetStepSize(1);\n#endif\n\n  std::cout << \"\\n\\n****** Case 2: outer ray source ******\" << std::endl;\n  rbi->SetBoxMax(itk::MakeVector(126.0, 126.0, 126.0));\n\n  // Geometry\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n  for (unsigned int i = 0; i < NumberOfProjectionImages; i++)\n    geometry->AddProjection(500., 1000., i * 8.);\n\n  rbi->SetGeometry(geometry);\n  rbi->Update();\n\n  jfp->SetGeometry(geometry);\n  stream->Update();\n\n  CheckImageQuality<OutputImageType>(stream->GetOutput(), rbi->GetOutput(), 1.28, 44.0, 255.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 3: Shepp-Logan, outer ray source ******\" << std::endl;\n\n  // Create Shepp Logan reference projections\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->InPlaceOff();\n  slp->SetInput(projInput->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->Update();\n\n  // Create a Shepp Logan reference volume (finer resolution)\n  origin.Fill(-127);\n  size.Fill(128);\n  spacing.Fill(2.);\n  volInput->SetOrigin(origin);\n  volInput->SetSpacing(spacing);\n  volInput->SetSize(size);\n  volInput->SetConstant(0.);\n\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->InPlaceOff();\n  dsl->SetInput(volInput->GetOutput());\n  dsl->Update();\n\n  // Forward projection\n  jfp->SetInput(1, dsl->GetOutput());\n  stream->Update();\n\n  CheckImageQuality<OutputImageType>(stream->GetOutput(), slp->GetOutput(), 1.28, 44, 255.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 4: Shepp-Logan, outer ray source, cylindrical detector ******\" << std::endl;\n  geometry->SetRadiusCylindricalDetector(600);\n\n  slp->SetGeometry(geometry);\n  slp->Update();\n\n  jfp->SetGeometry(geometry);\n  stream->Update();\n\n  CheckImageQuality<OutputImageType>(stream->GetOutput(), slp->GetOutput(), 1.28, 44, 255.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 5: Shepp-Logan, inner ray source ******\" << std::endl;\n  geometry = GeometryType::New();\n  for (unsigned int i = 0; i < NumberOfProjectionImages; i++)\n    geometry->AddProjection(120., 1000., i * 8.);\n\n  slp->SetGeometry(geometry);\n  slp->Update();\n\n  jfp->SetGeometry(geometry);\n  stream->Update();\n\n  CheckImageQuality<OutputImageType>(stream->GetOutput(), slp->GetOutput(), 1.28, 44, 255.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkfourdadjointoperatorstest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"itkRandomImageSource.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkProjectionStackToFourDImageFilter.h\"\n#include \"rtkFourDToProjectionStackImageFilter.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n#include \"rtkJosephBackProjectionImageFilter.h\"\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n#include \"rtkMacro.h\"\n\n#include <itkImageFileReader.h>\n\n/**\n * \\file rtkfourdadjointoperatorstest.cxx\n *\n * \\brief Tests whether ProjectionStackToFourDImageFilter and FourDToProjectionStackImageFilter\n * are the adjoint of one another.\n *\n * This test generates a random 4D volume \"v\" and a random set of projections \"p\",\n * and compares the scalar products <Rv , p> and <v, R* p>, where R is the\n * FourDToProjectionStack filter and R* is the ProjectionStackToFourD. If R* is indeed\n * the adjoint of R, these scalar products are equal.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 2)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \" phases.txt\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef RTK_USE_CUDA\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, Dimension>;\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, Dimension + 1>;\n#else\n  using ProjectionStackType = itk::Image<OutputPixelType, Dimension>;\n  using VolumeSeriesType = itk::Image<OutputPixelType, Dimension + 1>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 64;\n#endif\n\n\n  // Random image sources\n  auto randomProjectionStackSource = itk::RandomImageSource<ProjectionStackType>::New();\n\n  auto randomVolumeSeriesSource = itk::RandomImageSource<VolumeSeriesType>::New();\n\n  // Constant sources\n  auto constantProjectionStackSource = rtk::ConstantImageSource<ProjectionStackType>::New();\n\n  auto constantVolumeSeriesSource = rtk::ConstantImageSource<VolumeSeriesType>::New();\n\n  // Volume metadata\n  auto fourDOrigin = itk::MakePoint(-127., -127., -127., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto fourDSize = itk::MakeSize(2, 2, 2, 2);\n  auto fourDSpacing = itk::MakeVector(252., 252., 252., 1.);\n#else\n  auto fourDSize = itk::MakeSize(64, 64, 64, 5);\n  auto fourDSpacing = itk::MakeVector(4., 4., 4., 1.);\n#endif\n  randomVolumeSeriesSource->SetOrigin(fourDOrigin);\n  randomVolumeSeriesSource->SetSpacing(fourDSpacing);\n  randomVolumeSeriesSource->SetSize(fourDSize);\n  randomVolumeSeriesSource->SetMin(0.);\n  randomVolumeSeriesSource->SetMax(1.);\n\n  constantVolumeSeriesSource->SetOrigin(fourDOrigin);\n  constantVolumeSeriesSource->SetSpacing(fourDSpacing);\n  constantVolumeSeriesSource->SetSize(fourDSize);\n  constantVolumeSeriesSource->SetConstant(0.);\n\n  // Projections metadata\n  auto origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  auto spacing = itk::MakeVector(504., 504., 504.);\n#else\n  auto size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#endif\n  randomProjectionStackSource->SetOrigin(origin);\n  randomProjectionStackSource->SetSpacing(spacing);\n  randomProjectionStackSource->SetSize(size);\n  randomProjectionStackSource->SetMin(0.);\n  randomProjectionStackSource->SetMax(1.);\n\n  constantProjectionStackSource->SetOrigin(origin);\n  constantProjectionStackSource->SetSpacing(spacing);\n  constantProjectionStackSource->SetSize(size);\n  constantProjectionStackSource->SetConstant(0.);\n\n  // Update all sources\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSeriesSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantVolumeSeriesSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomProjectionStackSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantProjectionStackSource->Update());\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Read the phases file\n  auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n  phaseReader->SetFileName(argv[1]);\n  phaseReader->SetNumberOfReconstructedFrames(fourDSize[3]);\n  phaseReader->Update();\n\n  std::cout << \"\\n\\n****** 4D to projection stack ******\" << std::endl;\n\n  auto jfw = rtk::JosephForwardProjectionImageFilter<ProjectionStackType, ProjectionStackType>::New();\n\n  auto fw = rtk::FourDToProjectionStackImageFilter<ProjectionStackType, VolumeSeriesType>::New();\n  fw->SetInputProjectionStack(constantProjectionStackSource->GetOutput());\n  fw->SetInputVolumeSeries(randomVolumeSeriesSource->GetOutput());\n  fw->SetForwardProjectionFilter(jfw.GetPointer());\n  fw->SetGeometry(geometry);\n  fw->SetWeights(phaseReader->GetOutput());\n  fw->SetSignal(rtk::ReadSignalFile(argv[1]));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fw->Update());\n\n  std::cout << \"\\n\\n****** Projection stack to 4D ******\" << std::endl;\n\n  auto jbp = rtk::JosephBackProjectionImageFilter<ProjectionStackType, ProjectionStackType>::New();\n\n  auto bp = rtk::ProjectionStackToFourDImageFilter<VolumeSeriesType, ProjectionStackType>::New();\n  bp->SetInputVolumeSeries(constantVolumeSeriesSource->GetOutput());\n  bp->SetInputProjectionStack(randomProjectionStackSource->GetOutput());\n  bp->SetBackProjectionFilter(jbp.GetPointer());\n  bp->SetGeometry(geometry.GetPointer());\n  bp->SetWeights(phaseReader->GetOutput());\n  bp->SetSignal(rtk::ReadSignalFile(argv[1]));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(bp->Update());\n\n  CheckScalarProducts<VolumeSeriesType, ProjectionStackType>(\n    randomVolumeSeriesSource->GetOutput(), bp->GetOutput(), randomProjectionStackSource->GetOutput(), fw->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkfourdconjugategradienttest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkPasteImageFilter.h>\n#include <itksys/SystemTools.hxx>\n#include <itkJoinSeriesImageFilter.h>\n\n#include \"rtkTest.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n#include \"rtkFourDConjugateGradientConeBeamReconstructionFilter.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n\n/**\n * \\file rtkfourdconjugategradienttest.cxx\n *\n * \\brief Functional test for classes performing 4D conjugate gradient-based\n * reconstruction.\n *\n * This test generates the projections of a phantom, which consists of two\n * ellipsoids (one of them moving). The resulting moving phantom is\n * reconstructed using 4D conjugate gradient and the generated\n * result is compared to the expected results (analytical computation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n  using VolumeType = itk::CudaImage<OutputPixelType, 3>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n  using VolumeType = itk::Image<OutputPixelType, 3>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 5;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 64;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<VolumeType>;\n\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-63., -31., -63.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(8, 8, 8);\n  auto spacing = itk::MakeVector(16., 8., 16.);\n#else\n  auto size = itk::MakeSize(32, 16, 32);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto fourdSource = rtk::ConstantImageSource<VolumeSeriesType>::New();\n  auto fourDOrigin = itk::MakePoint(-63., -31., -63., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto fourDSize = itk::MakeSize(8, 8, 8, 2);\n  auto fourDSpacing = itk::MakeVector(16., 8., 16., 1.);\n#else\n  auto fourDSize = itk::MakeSize(32, 16, 32, 8);\n  auto fourDSpacing = itk::MakeVector(4., 4., 4., 1.);\n#endif\n  fourdSource->SetOrigin(fourDOrigin);\n  fourdSource->SetSpacing(fourDSpacing);\n  fourdSource->SetSize(fourDSize);\n  fourdSource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(32, 32, NumberOfProjectionImages);\n  spacing = itk::MakeVector(32., 32., 32.);\n#else\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n  spacing = itk::MakeVector(8., 8., 1.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  auto oneProjectionSource = ConstantImageSourceType::New();\n  size[2] = 1;\n  oneProjectionSource->SetOrigin(origin);\n  oneProjectionSource->SetSpacing(spacing);\n  oneProjectionSource->SetSize(size);\n  oneProjectionSource->SetConstant(0.);\n\n  // Geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n\n  // Projections\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<VolumeType, ProjectionStackType>;\n  auto destinationIndex = itk::MakeIndex(0, 0, 0);\n  auto pasteFilter = itk::PasteImageFilter<ProjectionStackType, ProjectionStackType, ProjectionStackType>::New();\n  pasteFilter->SetDestinationImage(projectionsSource->GetOutput());\n\n#ifdef USE_CUDA\n  std::string signalFileName = \"signal_4DConjugatedGradient_cuda.txt\";\n#else\n  std::string signalFileName = \"signal_4DConjugatedGradient.txt\";\n#endif\n\n  std::ofstream signalFile(signalFileName.c_str());\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n  {\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Geometry object\n    auto oneProjGeometry = GeometryType::New();\n    oneProjGeometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Ellipse 1\n    auto e1 = REIType::New();\n    auto semiprincipalaxis = itk::MakeVector(60., 30., 60.);\n    auto center = itk::MakeVector(0., 0., 0.);\n    e1->SetInput(oneProjectionSource->GetOutput());\n    e1->SetGeometry(oneProjGeometry);\n    e1->SetDensity(2.);\n    e1->SetAxis(semiprincipalaxis);\n    e1->SetCenter(center);\n    e1->SetAngle(0.);\n    e1->InPlaceOff();\n    e1->Update();\n\n    // Ellipse 2\n    auto e2 = REIType::New();\n    semiprincipalaxis.Fill(8.);\n    center[0] = 4 * (itk::Math::abs((4 + noProj) % 8 - 4.) - 2.);\n    center[1] = 0.;\n    center[2] = 0.;\n    e2->SetInput(e1->GetOutput());\n    e2->SetGeometry(oneProjGeometry);\n    e2->SetDensity(-1.);\n    e2->SetAxis(semiprincipalaxis);\n    e2->SetCenter(center);\n    e2->SetAngle(0.);\n    e2->Update();\n\n    // Adding each projection to the projection stack\n    if (noProj > 0) // After the first projection, we use the output as input\n    {\n      ProjectionStackType::Pointer wholeImage = pasteFilter->GetOutput();\n      wholeImage->DisconnectPipeline();\n      pasteFilter->SetDestinationImage(wholeImage);\n    }\n    pasteFilter->SetSourceImage(e2->GetOutput());\n    pasteFilter->SetSourceRegion(e2->GetOutput()->GetLargestPossibleRegion());\n    pasteFilter->SetDestinationIndex(destinationIndex);\n    pasteFilter->UpdateLargestPossibleRegion();\n    destinationIndex[2]++;\n\n    // Signal\n    signalFile << (noProj % 8) / 8. << std::endl;\n  }\n  signalFile.close();\n\n  // Ground truth\n  auto * Volumes = new VolumeType::Pointer[fourDSize[3]];\n  auto   join = itk::JoinSeriesImageFilter<VolumeType, VolumeSeriesType>::New();\n\n  for (itk::SizeValueType n = 0; n < fourDSize[3]; n++)\n  {\n    // Ellipse 1\n    using DEType = rtk::DrawEllipsoidImageFilter<VolumeType, VolumeType>;\n    auto de1 = DEType::New();\n    de1->SetInput(tomographySource->GetOutput());\n    de1->SetDensity(2.);\n    DEType::VectorType axis;\n    axis.Fill(60.);\n    axis[1] = 30;\n    de1->SetAxis(axis);\n    DEType::VectorType center;\n    center.Fill(0.);\n    de1->SetCenter(center);\n    de1->SetAngle(0.);\n    de1->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(de1->Update())\n\n    // Ellipse 2\n    auto de2 = DEType::New();\n    de2->SetInput(de1->GetOutput());\n    de2->SetDensity(-1.);\n    DEType::VectorType axis2;\n    axis2.Fill(8.);\n    de2->SetAxis(axis2);\n    DEType::VectorType center2;\n    center2[0] = 4 * (itk::Math::abs((4 + n) % 8 - 4.) - 2.);\n    center2[1] = 0.;\n    center2[2] = 0.;\n    de2->SetCenter(center2);\n    de2->SetAngle(0.);\n    de2->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(de2->Update());\n\n    Volumes[n] = de2->GetOutput();\n    Volumes[n]->DisconnectPipeline();\n    join->SetInput(n, Volumes[n]);\n  }\n  join->Update();\n\n  // Read the phases file\n  auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n  phaseReader->SetFileName(signalFileName);\n  phaseReader->SetNumberOfReconstructedFrames(fourDSize[3]);\n  phaseReader->Update();\n\n  // Set the forward and back projection filters to be used\n  using ConjugateGradientFilterType =\n    rtk::FourDConjugateGradientConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  auto conjugategradient = ConjugateGradientFilterType::New();\n  conjugategradient->SetInputVolumeSeries(fourdSource->GetOutput());\n  conjugategradient->SetInputProjectionStack(pasteFilter->GetOutput());\n  conjugategradient->SetGeometry(geometry);\n  conjugategradient->SetNumberOfIterations(3);\n  conjugategradient->SetWeights(phaseReader->GetOutput());\n  conjugategradient->SetSignal(rtk::ReadSignalFile(signalFileName));\n\n  std::cout\n    << \"\\n\\n****** Case 1: Joseph forward projector, Voxel-Based back projector, CPU interpolation and splat ******\"\n    << std::endl;\n\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientFilterType::BP_VOXELBASED);\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientFilterType::FP_JOSEPH);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<VolumeSeriesType>(conjugategradient->GetOutput(), join->GetOutput(), 0.4, 12, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 2: CUDA ray cast forward projector, CUDA Voxel-Based back projector, GPU interpolation \"\n               \"and splat ******\"\n            << std::endl;\n\n  conjugategradient->SetBackProjectionFilter(ConjugateGradientFilterType::BP_CUDAVOXELBASED);\n  conjugategradient->SetForwardProjectionFilter(ConjugateGradientFilterType::FP_CUDARAYCAST);\n  conjugategradient->SetCudaConjugateGradient(true);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(conjugategradient->Update());\n\n  CheckImageQuality<VolumeSeriesType>(conjugategradient->GetOutput(), join->GetOutput(), 0.4, 12, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  itksys::SystemTools::RemoveFile(signalFileName.c_str());\n  delete[] Volumes;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkfourdroostertest.cxx",
    "content": "#include <itkPasteImageFilter.h>\n#include <itksys/SystemTools.hxx>\n#include <itkJoinSeriesImageFilter.h>\n\n#include \"rtkTest.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n#include \"rtkCyclicDeformationImageFilter.h\"\n#include \"rtkFourDROOSTERConeBeamReconstructionFilter.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n\n/**\n * \\file rtkfourdroostertest.cxx\n *\n * \\brief Functional test for classes performing 4D ROOSTER\n * reconstruction.\n *\n * This test generates the projections of a phantom, which consists of two\n * ellipsoids (one of them moving). The resulting moving phantom is\n * reconstructed using the 4D ROOSTER algorithm and the generated\n * result is compared to the expected results (analytical computation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n\n  using DVFVectorType = itk::CovariantVector<OutputPixelType, 3>;\n\n#ifdef USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n  using VolumeType = itk::CudaImage<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n  using VolumeType = itk::Image<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 5;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 64;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<VolumeType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-63., -31., -63.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(8, 8, 8);\n  auto spacing = itk::MakeVector(16., 8., 16.);\n#else\n  auto size = itk::MakeSize(32, 16, 32);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto fourdSource = rtk::ConstantImageSource<VolumeSeriesType>::New();\n  auto fourDOrigin = itk::MakePoint(-63., -31., -63., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto fourDSize = itk::MakeSize(8, 8, 8, 2);\n  auto fourDSpacing = itk::MakeVector(16., 8., 16., 1.);\n#else\n  auto fourDSize = itk::MakeSize(32, 16, 32, 8);\n  auto fourDSpacing = itk::MakeVector(4., 4., 4., 1.);\n#endif\n  fourdSource->SetOrigin(fourDOrigin);\n  fourdSource->SetSpacing(fourDSpacing);\n  fourdSource->SetSize(fourDSize);\n  fourdSource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(32, 32, NumberOfProjectionImages);\n  spacing = itk::MakeVector(32., 32., 32.);\n#else\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n  spacing = itk::MakeVector(8., 8., 1.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  auto oneProjectionSource = ConstantImageSourceType::New();\n  size[2] = 1;\n  oneProjectionSource->SetOrigin(origin);\n  oneProjectionSource->SetSpacing(spacing);\n  oneProjectionSource->SetSize(size);\n  oneProjectionSource->SetConstant(0.);\n\n  // Geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n\n  // Projections\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<VolumeType, ProjectionStackType>;\n  auto destinationIndex = itk::MakeIndex(0, 0, 0);\n  auto pasteFilter = itk::PasteImageFilter<ProjectionStackType, ProjectionStackType, ProjectionStackType>::New();\n  pasteFilter->SetDestinationImage(projectionsSource->GetOutput());\n\n#ifdef USE_CUDA\n  std::string signalFileName = \"signal_4DRooster_cuda.txt\";\n#else\n  std::string signalFileName = \"signal_4DRooster.txt\";\n#endif\n\n  std::ofstream signalFile(signalFileName.c_str());\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n  {\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Geometry object\n    auto oneProjGeometry = GeometryType::New();\n    oneProjGeometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Ellipse 1\n    auto e1 = REIType::New();\n    auto semiprincipalaxis = itk::MakeVector(60., 30., 60.);\n    auto center = itk::MakeVector(0., 0., 0.);\n    e1->SetInput(oneProjectionSource->GetOutput());\n    e1->SetGeometry(oneProjGeometry);\n    e1->SetDensity(2.);\n    e1->SetAxis(semiprincipalaxis);\n    e1->SetCenter(center);\n    e1->SetAngle(0.);\n    e1->InPlaceOff();\n    e1->Update();\n\n    // Ellipse 2\n    auto e2 = REIType::New();\n    semiprincipalaxis.Fill(8.);\n    center[0] = 4 * (itk::Math::abs((4 + noProj) % 8 - 4.) - 2.);\n    center[1] = 0.;\n    center[2] = 0.;\n    e2->SetInput(e1->GetOutput());\n    e2->SetGeometry(oneProjGeometry);\n    e2->SetDensity(-1.);\n    e2->SetAxis(semiprincipalaxis);\n    e2->SetCenter(center);\n    e2->SetAngle(0.);\n    e2->Update();\n\n    // Adding each projection to the projection stack\n    if (noProj > 0) // After the first projection, we use the output as input\n    {\n      ProjectionStackType::Pointer wholeImage = pasteFilter->GetOutput();\n      wholeImage->DisconnectPipeline();\n      pasteFilter->SetDestinationImage(wholeImage);\n    }\n    pasteFilter->SetSourceImage(e2->GetOutput());\n    pasteFilter->SetSourceRegion(e2->GetOutput()->GetLargestPossibleRegion());\n    pasteFilter->SetDestinationIndex(destinationIndex);\n    pasteFilter->UpdateLargestPossibleRegion();\n    destinationIndex[2]++;\n\n    // Signal\n    signalFile << (noProj % 8) / 8. << std::endl;\n  }\n  signalFile.close();\n\n  // Create a vector field and its (very rough) inverse\n  using IteratorType = itk::ImageRegionIteratorWithIndex<DVFSequenceImageType>;\n\n  auto deformationField = DVFSequenceImageType::New();\n  auto inverseDeformationField = DVFSequenceImageType::New();\n\n  auto                             sizeMotion = itk::MakeSize(fourDSize[0], fourDSize[1], fourDSize[2], 2);\n  auto                             originMotion = itk::MakePoint(-63., -31., -63., 0.);\n  DVFSequenceImageType::RegionType regionMotion;\n  regionMotion.SetSize(sizeMotion);\n\n  auto spacingMotion = itk::MakeVector(fourDSpacing[0], fourDSpacing[1], fourDSpacing[2], fourDSpacing[3]);\n  deformationField->SetRegions(regionMotion);\n  deformationField->SetOrigin(originMotion);\n  deformationField->SetSpacing(spacingMotion);\n  deformationField->Allocate();\n\n  inverseDeformationField->SetRegions(regionMotion);\n  inverseDeformationField->SetOrigin(originMotion);\n  inverseDeformationField->SetSpacing(spacingMotion);\n  inverseDeformationField->Allocate();\n\n  // Vector Field initilization\n  DVFVectorType vec;\n  IteratorType  dvfIt(deformationField, deformationField->GetLargestPossibleRegion());\n  IteratorType  idvfIt(inverseDeformationField, inverseDeformationField->GetLargestPossibleRegion());\n\n  DVFSequenceImageType::OffsetType DVFCenter;\n  DVFSequenceImageType::IndexType  toCenter;\n  DVFCenter.Fill(0);\n  DVFCenter[0] = sizeMotion[0] / 2;\n  DVFCenter[1] = sizeMotion[1] / 2;\n  DVFCenter[2] = sizeMotion[2] / 2;\n  while (!dvfIt.IsAtEnd())\n  {\n    vec.Fill(0.);\n    toCenter = dvfIt.GetIndex() - DVFCenter;\n\n    if (0.3 * toCenter[0] * toCenter[0] + toCenter[1] * toCenter[1] + toCenter[2] * toCenter[2] < 40)\n    {\n      if (dvfIt.GetIndex()[3] == 0)\n        vec[0] = -8.;\n      else\n        vec[0] = 8.;\n    }\n    dvfIt.Set(vec);\n    idvfIt.Set(-vec);\n\n    ++dvfIt;\n    ++idvfIt;\n  }\n\n  // Ground truth\n  auto * Volumes = new VolumeType::Pointer[fourDSize[3]];\n  auto   join = itk::JoinSeriesImageFilter<VolumeType, VolumeSeriesType>::New();\n\n  for (itk::SizeValueType n = 0; n < fourDSize[3]; n++)\n  {\n    // Ellipse 1\n    using DEType = rtk::DrawEllipsoidImageFilter<VolumeType, VolumeType>;\n    auto de1 = DEType::New();\n    de1->SetInput(tomographySource->GetOutput());\n    de1->SetDensity(2.);\n    DEType::VectorType axis;\n    axis.Fill(60.);\n    axis[1] = 30;\n    de1->SetAxis(axis);\n    DEType::VectorType center;\n    center.Fill(0.);\n    de1->SetCenter(center);\n    de1->SetAngle(0.);\n    de1->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(de1->Update())\n\n    // Ellipse 2\n    auto de2 = DEType::New();\n    de2->SetInput(de1->GetOutput());\n    de2->SetDensity(-1.);\n    DEType::VectorType axis2;\n    axis2.Fill(8.);\n    de2->SetAxis(axis2);\n    DEType::VectorType center2;\n    center2[0] = 4 * (itk::Math::abs((4 + n) % 8 - 4.) - 2.);\n    center2[1] = 0.;\n    center2[2] = 0.;\n    de2->SetCenter(center2);\n    de2->SetAngle(0.);\n    de2->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(de2->Update());\n\n    Volumes[n] = de2->GetOutput();\n    Volumes[n]->DisconnectPipeline();\n    join->SetInput(n, Volumes[n]);\n  }\n  join->Update();\n\n  // ROI\n  using DEType = rtk::DrawEllipsoidImageFilter<VolumeType, VolumeType>;\n  auto roi = DEType::New();\n  roi->SetInput(tomographySource->GetOutput());\n  roi->SetDensity(1.);\n  DEType::VectorType axis;\n  axis.Fill(15.);\n  axis[0] = 20;\n  roi->SetAxis(axis);\n  DEType::VectorType center;\n  center.Fill(0.);\n  roi->SetCenter(center);\n  roi->SetAngle(0.);\n  roi->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(roi->Update())\n\n  // Read the phases file\n  auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n  phaseReader->SetFileName(signalFileName);\n  phaseReader->SetNumberOfReconstructedFrames(fourDSize[3]);\n  phaseReader->Update();\n\n  // Set the forward and back projection filters to be used\n  using ROOSTERFilterType = rtk::FourDROOSTERConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  auto rooster = ROOSTERFilterType::New();\n  rooster->SetInputVolumeSeries(fourdSource->GetOutput());\n  rooster->SetInputProjectionStack(pasteFilter->GetOutput());\n  rooster->SetGeometry(geometry);\n  rooster->SetWeights(phaseReader->GetOutput());\n  rooster->SetSignal(rtk::ReadSignalFile(signalFileName));\n  rooster->SetGeometry(geometry);\n  rooster->SetCG_iterations(2);\n  rooster->SetMainLoop_iterations(2);\n\n  rooster->SetTV_iterations(3);\n  rooster->SetGammaTVSpace(1);\n  rooster->SetGammaTVTime(0.1);\n\n  rooster->SetSoftThresholdWavelets(0.1);\n  rooster->SetOrder(3);\n  rooster->SetNumberOfLevels(3);\n\n  rooster->SetLambdaL0Time(0.1);\n  rooster->SetL0_iterations(5);\n\n  std::cout << \"\\n\\n****** Case 1: Joseph forward projector, voxel-based back projector, positivity, motion mask, \"\n               \"wavelets spatial denoising, TV temporal denoising, no warping ******\"\n            << std::endl;\n\n  rooster->SetBackProjectionFilter(ROOSTERFilterType::BP_VOXELBASED);\n  rooster->SetForwardProjectionFilter(ROOSTERFilterType::FP_JOSEPH);\n\n  rooster->SetPerformPositivity(true);\n  rooster->SetPerformMotionMask(true);\n  rooster->SetMotionMask(roi->GetOutput());\n  rooster->SetPerformTVSpatialDenoising(false);\n  rooster->SetPerformWaveletsSpatialDenoising(true);\n  rooster->SetPerformTVTemporalDenoising(true);\n  rooster->SetPerformL0TemporalDenoising(false);\n  rooster->SetPerformWarping(false);\n  rooster->SetComputeInverseWarpingByConjugateGradient(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rooster->Update());\n\n  CheckImageQuality<VolumeSeriesType>(rooster->GetOutput(), join->GetOutput(), 0.25, 15, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Joseph forward projector, voxel-based back projector, positivity, no motion mask, \"\n               \"TV spatial denoising, L0 temporal denoising, motion compensation (nearest neighbor interpolation). \"\n               \"Inverse warping by conjugate gradient ******\"\n            << std::endl;\n\n  rooster->SetBackProjectionFilter(ROOSTERFilterType::BP_VOXELBASED);\n  rooster->SetForwardProjectionFilter(ROOSTERFilterType::FP_JOSEPH);\n\n  rooster->SetPerformPositivity(true);\n  rooster->SetPerformMotionMask(false);\n  rooster->SetPerformTVSpatialDenoising(true);\n  rooster->SetPerformWaveletsSpatialDenoising(false);\n  rooster->SetPerformTVTemporalDenoising(false);\n  rooster->SetPerformL0TemporalDenoising(true);\n  rooster->SetPerformWarping(true);\n  rooster->SetDisplacementField(deformationField);\n  rooster->SetComputeInverseWarpingByConjugateGradient(true);\n  rooster->SetUseNearestNeighborInterpolationInWarping(true);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rooster->Update());\n\n  CheckImageQuality<VolumeSeriesType>(rooster->GetOutput(), join->GetOutput(), 0.25, 15, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 3: Joseph forward projector, voxel-based back projector, no positivity, motion mask, \"\n               \"no spatial denoising, motion compensation and temporal TV denoising. Inverse warping by warping with \"\n               \"approximate inverse DVF ******\"\n            << std::endl;\n\n  rooster->SetBackProjectionFilter(ROOSTERFilterType::BP_VOXELBASED);\n  rooster->SetForwardProjectionFilter(ROOSTERFilterType::FP_JOSEPH);\n\n  rooster->SetPerformPositivity(false);\n  rooster->SetPerformMotionMask(true);\n  rooster->SetMotionMask(roi->GetOutput());\n  rooster->SetPerformTVSpatialDenoising(false);\n  rooster->SetPerformWaveletsSpatialDenoising(false);\n  rooster->SetPerformTVTemporalDenoising(true);\n  rooster->SetPerformL0TemporalDenoising(false);\n  rooster->SetPerformWarping(true);\n  rooster->SetDisplacementField(deformationField);\n  rooster->SetComputeInverseWarpingByConjugateGradient(false);\n  rooster->SetInverseDisplacementField(inverseDeformationField);\n  rooster->SetUseNearestNeighborInterpolationInWarping(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rooster->Update());\n\n  CheckImageQuality<VolumeSeriesType>(rooster->GetOutput(), join->GetOutput(), 0.25, 15, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 4: CUDA forward and back projectors, only L0 temporal denoising ******\" << std::endl;\n\n  rooster->SetBackProjectionFilter(ROOSTERFilterType::BP_CUDAVOXELBASED); // Cuda voxel based\n  rooster->SetForwardProjectionFilter(ROOSTERFilterType::FP_CUDARAYCAST); // Cuda ray cast\n\n  rooster->SetPerformPositivity(false);\n  rooster->SetPerformMotionMask(false);\n  rooster->SetPerformTVSpatialDenoising(false);\n  rooster->SetPerformWaveletsSpatialDenoising(false);\n  rooster->SetPerformTVTemporalDenoising(false);\n  rooster->SetPerformL0TemporalDenoising(true);\n  rooster->SetPerformWarping(false);\n  rooster->SetComputeInverseWarpingByConjugateGradient(false);\n  rooster->SetUseNearestNeighborInterpolationInWarping(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rooster->Update());\n\n  CheckImageQuality<VolumeSeriesType>(rooster->GetOutput(), join->GetOutput(), 0.25, 15, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  itksys::SystemTools::RemoveFile(signalFileName.c_str());\n  delete[] Volumes;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkfourdsarttest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkPasteImageFilter.h>\n#include <itksys/SystemTools.hxx>\n#include <itkJoinSeriesImageFilter.h>\n\n#include \"rtkTest.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n#include \"rtkCyclicDeformationImageFilter.h\"\n#include \"rtkFourDSARTConeBeamReconstructionFilter.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n\n/**\n * \\file rtkfourdsarttest.cxx\n *\n * \\brief Functional test for classes performing 4D SART\n * reconstruction.\n *\n * This test generates the projections of a phantom, which consists of two\n * ellipsoids (one of them moving). The resulting moving phantom is\n * reconstructed using 4D SART and the generated\n * result is compared to the expected results (analytical computation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n  using VolumeType = itk::CudaImage<OutputPixelType, 3>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n  using VolumeType = itk::Image<OutputPixelType, 3>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 5;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 64;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<VolumeType>;\n  ConstantImageSourceType::PointType   origin;\n  ConstantImageSourceType::SizeType    size;\n  ConstantImageSourceType::SpacingType spacing;\n\n  using FourDSourceType = rtk::ConstantImageSource<VolumeSeriesType>;\n  FourDSourceType::PointType   fourDOrigin;\n  FourDSourceType::SizeType    fourDSize;\n  FourDSourceType::SpacingType fourDSpacing;\n\n  auto tomographySource = ConstantImageSourceType::New();\n  origin[0] = -63.;\n  origin[1] = -31.;\n  origin[2] = -63.;\n#if FAST_TESTS_NO_CHECKS\n  size[0] = 8;\n  size[1] = 8;\n  size[2] = 8;\n  spacing[0] = 16.;\n  spacing[1] = 8.;\n  spacing[2] = 16.;\n#else\n  size[0] = 32;\n  size[1] = 16;\n  size[2] = 32;\n  spacing[0] = 4.;\n  spacing[1] = 4.;\n  spacing[2] = 4.;\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto fourdSource = FourDSourceType::New();\n  fourDOrigin[0] = -63.;\n  fourDOrigin[1] = -31.;\n  fourDOrigin[2] = -63.;\n  fourDOrigin[3] = 0;\n#if FAST_TESTS_NO_CHECKS\n  fourDSize[0] = 8;\n  fourDSize[1] = 8;\n  fourDSize[2] = 8;\n  fourDSize[3] = 2;\n  fourDSpacing[0] = 16.;\n  fourDSpacing[1] = 8.;\n  fourDSpacing[2] = 16.;\n  fourDSpacing[3] = 1.;\n#else\n  fourDSize[0] = 32;\n  fourDSize[1] = 16;\n  fourDSize[2] = 32;\n  fourDSize[3] = 8;\n  fourDSpacing[0] = 4.;\n  fourDSpacing[1] = 4.;\n  fourDSpacing[2] = 4.;\n  fourDSpacing[3] = 1.;\n#endif\n  fourdSource->SetOrigin(fourDOrigin);\n  fourdSource->SetSpacing(fourDSpacing);\n  fourdSource->SetSize(fourDSize);\n  fourdSource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin[0] = -254.;\n  origin[1] = -254.;\n  origin[2] = -254.;\n#if FAST_TESTS_NO_CHECKS\n  size[0] = 32;\n  size[1] = 32;\n  size[2] = NumberOfProjectionImages;\n  spacing[0] = 32.;\n  spacing[1] = 32.;\n  spacing[2] = 32.;\n#else\n  size[0] = 64;\n  size[1] = 64;\n  size[2] = NumberOfProjectionImages;\n  spacing[0] = 8.;\n  spacing[1] = 8.;\n  spacing[2] = 1.;\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  auto oneProjectionSource = ConstantImageSourceType::New();\n  size[2] = 1;\n  oneProjectionSource->SetOrigin(origin);\n  oneProjectionSource->SetSpacing(spacing);\n  oneProjectionSource->SetSize(size);\n  oneProjectionSource->SetConstant(0.);\n\n  // Geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n\n  // Projections\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<VolumeType, ProjectionStackType>;\n  ProjectionStackType::IndexType destinationIndex;\n  destinationIndex[0] = 0;\n  destinationIndex[1] = 0;\n  destinationIndex[2] = 0;\n  auto pasteFilter = itk::PasteImageFilter<ProjectionStackType, ProjectionStackType, ProjectionStackType>::New();\n  pasteFilter->SetDestinationImage(projectionsSource->GetOutput());\n\n#ifdef USE_CUDA\n  std::string signalFileName = \"signal_4DSART_cuda.txt\";\n#else\n  std::string signalFileName = \"signal_4DSART.txt\";\n#endif\n\n  std::ofstream signalFile(signalFileName.c_str());\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n  {\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Geometry object\n    auto oneProjGeometry = GeometryType::New();\n    oneProjGeometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Ellipse 1\n    auto e1 = REIType::New();\n    auto semiprincipalaxis = itk::MakeVector(60., 30., 60.);\n    auto center = itk::MakeVector(0., 0., 0.);\n    e1->SetInput(oneProjectionSource->GetOutput());\n    e1->SetGeometry(oneProjGeometry);\n    e1->SetDensity(2.);\n    e1->SetAxis(semiprincipalaxis);\n    e1->SetCenter(center);\n    e1->SetAngle(0.);\n    e1->InPlaceOff();\n    e1->Update();\n\n    // Ellipse 2\n    auto e2 = REIType::New();\n    semiprincipalaxis.Fill(8.);\n    center[0] = 4 * (itk::Math::abs((4 + noProj) % 8 - 4.) - 2.);\n    center[1] = 0.;\n    center[2] = 0.;\n    e2->SetInput(e1->GetOutput());\n    e2->SetGeometry(oneProjGeometry);\n    e2->SetDensity(-1.);\n    e2->SetAxis(semiprincipalaxis);\n    e2->SetCenter(center);\n    e2->SetAngle(0.);\n    e2->Update();\n\n    // Adding each projection to the projection stack\n    if (noProj > 0) // After the first projection, we use the output as input\n    {\n      ProjectionStackType::Pointer wholeImage = pasteFilter->GetOutput();\n      wholeImage->DisconnectPipeline();\n      pasteFilter->SetDestinationImage(wholeImage);\n    }\n    pasteFilter->SetSourceImage(e2->GetOutput());\n    pasteFilter->SetSourceRegion(e2->GetOutput()->GetLargestPossibleRegion());\n    pasteFilter->SetDestinationIndex(destinationIndex);\n    pasteFilter->UpdateLargestPossibleRegion();\n    destinationIndex[2]++;\n\n    // Signal\n    signalFile << (noProj % 8) / 8. << std::endl;\n  }\n  signalFile.close();\n\n  // Ground truth\n  auto * Volumes = new VolumeType::Pointer[fourDSize[3]];\n  auto   join = itk::JoinSeriesImageFilter<VolumeType, VolumeSeriesType>::New();\n\n  for (itk::SizeValueType n = 0; n < fourDSize[3]; n++)\n  {\n    // Ellipse 1\n    using DEType = rtk::DrawEllipsoidImageFilter<VolumeType, VolumeType>;\n    auto de1 = DEType::New();\n    de1->SetInput(tomographySource->GetOutput());\n    de1->SetDensity(2.);\n    DEType::VectorType axis;\n    axis.Fill(60.);\n    axis[1] = 30;\n    de1->SetAxis(axis);\n    DEType::VectorType center;\n    center.Fill(0.);\n    de1->SetCenter(center);\n    de1->SetAngle(0.);\n    de1->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(de1->Update())\n\n    // Ellipse 2\n    auto de2 = DEType::New();\n    de2->SetInput(de1->GetOutput());\n    de2->SetDensity(-1.);\n    DEType::VectorType axis2;\n    axis2.Fill(8.);\n    de2->SetAxis(axis2);\n    DEType::VectorType center2;\n    center2[0] = 4 * (itk::Math::abs((4 + n) % 8 - 4.) - 2.);\n    center2[1] = 0.;\n    center2[2] = 0.;\n    de2->SetCenter(center2);\n    de2->SetAngle(0.);\n    de2->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(de2->Update());\n\n    Volumes[n] = de2->GetOutput();\n    Volumes[n]->DisconnectPipeline();\n    join->SetInput(n, Volumes[n]);\n  }\n  join->Update();\n\n  // Read the phases file\n  auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n  phaseReader->SetFileName(signalFileName);\n  phaseReader->SetNumberOfReconstructedFrames(fourDSize[3]);\n  phaseReader->Update();\n\n  // Set the forward and back projection filters to be used\n  using FourDSARTFilterType = rtk::FourDSARTConeBeamReconstructionFilter<VolumeSeriesType, ProjectionStackType>;\n  auto fourdsart = FourDSARTFilterType::New();\n  fourdsart->SetInputVolumeSeries(fourdSource->GetOutput());\n  fourdsart->SetInputProjectionStack(pasteFilter->GetOutput());\n  fourdsart->SetGeometry(geometry);\n  fourdsart->SetNumberOfIterations(3);\n  fourdsart->SetWeights(phaseReader->GetOutput());\n  fourdsart->SetSignal(rtk::ReadSignalFile(signalFileName));\n  fourdsart->SetEnforcePositivity(true);\n\n  std::cout\n    << \"\\n\\n****** Case 1: Joseph forward projector, Voxel-Based back projector, CPU interpolation and splat ******\"\n    << std::endl;\n\n  fourdsart->SetBackProjectionFilter(FourDSARTFilterType::BP_VOXELBASED);\n  fourdsart->SetForwardProjectionFilter(FourDSARTFilterType::FP_JOSEPH);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fourdsart->Update());\n\n  CheckImageQuality<VolumeSeriesType>(fourdsart->GetOutput(), join->GetOutput(), 0.22, 12, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Joseph forward projector, Voxel-Based back projector, CPU interpolation and splat, \"\n               \"2 projections per subset ******\"\n            << std::endl;\n\n  fourdsart->SetBackProjectionFilter(FourDSARTFilterType::BP_VOXELBASED);\n  fourdsart->SetForwardProjectionFilter(FourDSARTFilterType::FP_JOSEPH);\n  fourdsart->SetNumberOfProjectionsPerSubset(2);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fourdsart->Update());\n\n  CheckImageQuality<VolumeSeriesType>(fourdsart->GetOutput(), join->GetOutput(), 0.35, 12, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 3: CUDA ray cast forward projector, CUDA Voxel-Based back projector, GPU interpolation \"\n               \"and splat ******\"\n            << std::endl;\n\n  fourdsart->SetBackProjectionFilter(FourDSARTFilterType::BP_CUDAVOXELBASED);\n  fourdsart->SetForwardProjectionFilter(FourDSARTFilterType::FP_CUDARAYCAST);\n  fourdsart->SetNumberOfProjectionsPerSubset(1);\n  fourdsart->SetNumberOfIterations(3);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fourdsart->Update());\n\n  CheckImageQuality<VolumeSeriesType>(fourdsart->GetOutput(), join->GetOutput(), 0.22, 12, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  itksys::SystemTools::RemoveFile(signalFileName.c_str());\n  delete[] Volumes;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkfovtest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkBinaryThresholdImageFilter.h>\n\n#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n\n/**\n * \\file rtkfovtest.cxx\n *\n * \\brief Functional test for classes in charge of creating a FOV (Field Of\n * View) mask\n *\n * This test generates a FOV mask that can be used after a reconstruction.\n * The generated results are compared to the expected results, which are\n * created with a threshold in the backprojection images of the volume.\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n\n  // FOV filter Input Volume, it is used as the input to create the fov mask.\n  auto fovInput = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(254., 254., 254.);\n#else\n  auto size = itk::MakeSize(128, 128, 128);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n\n\n  fovInput->SetOrigin(origin);\n  fovInput->SetSpacing(spacing);\n  fovInput->SetSize(size);\n  fovInput->SetConstant(1.);\n\n  // BP volume\n  auto bpInput = ConstantImageSourceType::New();\n  bpInput->SetOrigin(origin);\n  bpInput->SetSpacing(spacing);\n  bpInput->SetSize(size);\n\n  // BackProjection Input Projections, it is used as the input to create the fov mask.\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin.Fill(-254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(508., 508., 508.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(1.);\n\n  std::cout << \"\\n\\n****** Case 1: centered detector ******\" << std::endl;\n\n  // Geometry\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600, 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // FOV\n  auto fov = rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType>::New();\n  fov->SetInput(0, fovInput->GetOutput());\n  fov->SetProjectionsStack(projectionsSource->GetOutput());\n  fov->SetGeometry(geometry);\n  fov->Update();\n\n  // Backprojection reconstruction filter\n  auto bp = rtk::BackProjectionImageFilter<OutputImageType, OutputImageType>::New();\n  bp->SetInput(0, bpInput->GetOutput());\n  bp->SetInput(1, projectionsSource->GetOutput());\n  bp->SetGeometry(geometry.GetPointer());\n\n  // Thresholded to the number of projections\n  auto threshold = itk::BinaryThresholdImageFilter<OutputImageType, OutputImageType>::New();\n  threshold->SetInput(bp->GetOutput());\n  threshold->SetOutsideValue(0.);\n  threshold->SetLowerThreshold(NumberOfProjectionImages - 0.01);\n  threshold->SetUpperThreshold(NumberOfProjectionImages + 0.01);\n  threshold->SetInsideValue(1.);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(threshold->Update());\n\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), threshold->GetOutput(), 0.02, 23.5, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: offset detector ******\" << std::endl;\n\n  origin[0] = -54.;\n  projectionsSource->SetOrigin(origin);\n  size[0] = 78;\n  projectionsSource->SetSize(size);\n  projectionsSource->UpdateOutputInformation();\n  projectionsSource->UpdateLargestPossibleRegion();\n  fov->SetDisplacedDetector(true);\n  fov->Update();\n\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), threshold->GetOutput(), 0.02, 23.5, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkgaincorrectiontest.cxx",
    "content": "/*=========================================================================\n *\n *  Copyright RTK Consortium\n *\n *  Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *         https://www.apache.org/licenses/LICENSE-2.0.txt\n *\n *  Unless required by applicable law or agreed to in writing, software\n *  distributed under the License is distributed on an \"AS IS\" BASIS,\n *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *  See the License for the specific language governing permissions and\n *  limitations under the License.\n *\n *=========================================================================*/\n\n#include \"rtkTest.h\"\n#include \"rtkTestConfiguration.h\"\n#include \"rtkMacro.h\"\n\n#include <cmath>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n\n#ifdef USE_CUDA\n#  include \"rtkCudaPolynomialGainCorrectionImageFilter.h\"\n#else\n#  include \"rtkPolynomialGainCorrectionImageFilter.h\"\n#endif\n\n#include \"rtkTestConfiguration.h\"\n\n/**\n * \\file rtkgaincorrectiontest.cxx\n *\n * \\brief Functional test for the polynomial gain correction filter\n *\n * \\author Sebastien Brousmiche\n */\n\nconstexpr unsigned int Dimension = 3;\n#ifdef USE_CUDA\nusing InputImageType = itk::CudaImage<unsigned short, Dimension>;\nusing OutputImageType = itk::CudaImage<float, Dimension>;\n#else\nusing InputImageType = itk::Image<unsigned short, Dimension>;\nusing OutputImageType = itk::Image<float, Dimension>;\n#endif\n\nconstexpr int modelOrder = 3;\nconstexpr int sizeI = 100;\n\nInputImageType::Pointer\ncreateDarkImage()\n{\n  auto size = itk::MakeSize(sizeI, sizeI, 1);\n  auto spacing = itk::MakeVector(1.f, 1.f, 1.f);\n\n  InputImageType::RegionType region;\n  region.SetSize(size);\n\n  auto darkImage = InputImageType::New();\n  darkImage->SetRegions(region);\n  darkImage->SetSpacing(spacing);\n  darkImage->Allocate();\n  darkImage->FillBuffer(0.0f);\n\n  float orig_x = -static_cast<float>(size[0] - 1) / 2.f;\n  float orig_y = -static_cast<float>(size[1] - 1) / 2.f;\n\n  itk::ImageRegionIteratorWithIndex<InputImageType> itIn(darkImage, darkImage->GetLargestPossibleRegion());\n  itIn.GoToBegin();\n  while (!itIn.IsAtEnd())\n  {\n    InputImageType::IndexType idx = itIn.GetIndex();\n    float                     xx = static_cast<float>(idx[0]) + orig_x;\n    float                     yy = static_cast<float>(idx[1]) + orig_y;\n    float                     rr = std::sqrt(xx * xx + yy * yy);\n    itIn.Set(static_cast<unsigned short>(rr));\n    ++itIn;\n  }\n\n  return darkImage;\n}\n\nOutputImageType::Pointer\ncreateGainImage()\n{\n  auto size = itk::MakeSize(sizeI, sizeI, modelOrder);\n  auto spacing = itk::MakeVector(1.f, 1.f, 1.f);\n\n  OutputImageType::RegionType region;\n  region.SetSize(size);\n\n  auto gainImage = OutputImageType::New();\n  gainImage->SetRegions(region);\n  gainImage->SetSpacing(spacing);\n  gainImage->Allocate();\n  gainImage->FillBuffer(0.0f);\n\n  itk::ImageRegionIteratorWithIndex<OutputImageType> itIn(gainImage, gainImage->GetLargestPossibleRegion());\n  itIn.GoToBegin();\n  while (!itIn.IsAtEnd())\n  {\n    InputImageType::IndexType idx = itIn.GetIndex();\n    float                     value = 0.f;\n    if (idx[2] == 0)\n      value = 1.2f;\n    else if (idx[2] == 1)\n      value = 0.016f;\n    else if (idx[2] == 3)\n      value = -0.003f;\n\n    itIn.Set(value);\n    ++itIn;\n  }\n\n  return gainImage;\n}\n\nInputImageType::Pointer\ncreateInputImage()\n{\n  auto size = itk::MakeSize(sizeI, sizeI, 1);\n  auto spacing = itk::MakeVector(1.f, 1.f, 1.f);\n\n  InputImageType::RegionType region;\n  region.SetSize(size);\n\n  auto inputImage = InputImageType::New();\n  inputImage->SetRegions(region);\n  inputImage->SetSpacing(spacing);\n  inputImage->Allocate();\n  inputImage->FillBuffer(32000.0f);\n\n  return inputImage;\n}\n\nOutputImageType::Pointer\ngenerateExpectedOutput(InputImageType::Pointer  inputImage,\n                       float                    K,\n                       InputImageType::Pointer  darkImage,\n                       OutputImageType::Pointer gainImage)\n{\n  auto size = itk::MakeSize(sizeI, sizeI, 1);\n  auto spacing = itk::MakeVector(1.f, 1.f, 1.f);\n\n  OutputImageType::RegionType region;\n  region.SetSize(size);\n\n  auto expectedOutput = OutputImageType::New();\n  expectedOutput->SetRegions(region);\n  expectedOutput->SetSpacing(spacing);\n  expectedOutput->Allocate();\n  expectedOutput->FillBuffer(0.0f);\n\n  itk::ImageRegionConstIterator<InputImageType> itIn(inputImage, inputImage->GetLargestPossibleRegion());\n  itk::ImageRegionIterator<OutputImageType>     itOut(expectedOutput, expectedOutput->GetLargestPossibleRegion());\n\n  InputImageType::RegionType darkRegion = inputImage->GetLargestPossibleRegion();\n  darkRegion.SetSize(2, 1);\n  darkRegion.SetIndex(2, 0);\n  itk::ImageRegionConstIterator<InputImageType> itDark(darkImage, darkRegion);\n\n  // Get gain map buffer\n  const float * gainBuffer = gainImage->GetBufferPointer();\n\n  itIn.GoToBegin();\n  itOut.GoToBegin();\n  itDark.GoToBegin();\n\n  float sizeI2 = sizeI * sizeI;\n  for (int j = 0; j < sizeI; ++j)\n  {\n    for (int i = 0; i < sizeI; ++i)\n    {\n      int darkx = static_cast<int>(itDark.Get());\n      int px = static_cast<int>(itIn.Get()) - darkx;\n      px = (px >= 0) ? px : 0;\n\n      float correctedValue = 0.f;\n      auto  powValue = static_cast<float>(px);\n      for (int m = 0; m < modelOrder; ++m)\n      {\n        int   gainidx = m * sizeI2 + j * sizeI + i;\n        float Aij = gainBuffer[gainidx];\n        correctedValue += Aij * powValue;\n        powValue *= powValue;\n      }\n      correctedValue *= K;\n\n      itOut.Set(static_cast<float>(correctedValue));\n\n      ++itIn;\n      ++itOut;\n      ++itDark;\n    }\n  }\n\n  return expectedOutput;\n}\n\n\nint\nmain(int, char **)\n{\n  const float K = 0.5f;\n#ifdef USE_CUDA\n  using GainCorrectionType = rtk::CudaPolynomialGainCorrectionImageFilter;\n#else\n  using GainCorrectionType = rtk::PolynomialGainCorrectionImageFilter<InputImageType, OutputImageType>;\n#endif\n  auto gainfilter = GainCorrectionType::New();\n\n  // Set filter inputs\n  InputImageType::Pointer darkImage = createDarkImage();\n  gainfilter->SetDarkImage(darkImage);\n\n  OutputImageType::Pointer gainImage = createGainImage();\n  gainfilter->SetGainCoefficients(gainImage);\n\n  gainfilter->SetK(K);\n\n  InputImageType::Pointer testImage = createInputImage();\n  gainfilter->SetInput(testImage);\n\n  // Apply correction\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(gainfilter->Update())\n  OutputImageType::Pointer outputImage = gainfilter->GetOutput();\n\n  // Generate expected output\n  OutputImageType::Pointer expectedOutput = generateExpectedOutput(testImage, K, darkImage, gainImage);\n\n  // Compare\n  itk::ImageRegionConstIterator<OutputImageType> itExp(expectedOutput, expectedOutput->GetLargestPossibleRegion());\n  itk::ImageRegionConstIterator<OutputImageType> itOut(outputImage, outputImage->GetLargestPossibleRegion());\n\n  itExp.GoToBegin();\n  itOut.GoToBegin();\n  float diffValue = 0.f;\n  while (!itExp.IsAtEnd())\n  {\n    diffValue += itk::Math::abs(itExp.Get() - itOut.Get());\n    ++itExp;\n    ++itOut;\n  }\n  diffValue /= static_cast<float>(sizeI * sizeI);\n  std::cout << diffValue << std::endl;\n  if (!(diffValue < 1.f))\n  {\n    std::cerr << \"Test Failed! \" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkgeometryclonetest.cxx",
    "content": "// RTK\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n#include \"rtkTest.h\"\n\nint\nmain(int, char **)\n{\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry1, geometry2;\n  geometry1 = rtk::ThreeDCircularProjectionGeometry::New();\n\n  for (double oa = -60.; oa < 65.; oa += 60.)\n    for (double ia = -60.; ia < 65.; ia += 60.)\n      for (double ga = 0.; ga < 360.; ga += 45.)\n        for (double sx = -50.; sx < 55.; sx += 25.)\n          for (double sy = -50.; sy < 55.; sy += 25.)\n            for (double px = -50.; px < 55.; px += 25.)\n              for (double py = -50.; py < 55.; py += 25.)\n                for (double sdd = 200.; sdd < 405.; sdd += 200.)\n                  for (double sid = 100.; sid < 200.; sid += 200.)\n                  {\n                    geometry1->AddProjection(sid, sdd, ga, px, py, oa, ia, sx, sy);\n                    geometry1->SetCollimationOfLastProjection(px * 0.3, px * 0.1, py * 0.4, py * 0.2);\n                  }\n  geometry1->SetRadiusCylindricalDetector(300.);\n  geometry2 = geometry1->Clone();\n  CheckGeometries(geometry1, geometry2);\n  std::cout << \"Test PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkgeometryfiletest.cxx",
    "content": "#include \"rtkTestConfiguration.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkMacro.h\"\n#include <itksys/SystemTools.hxx>\n\nusing GeometryType = rtk::ThreeDCircularProjectionGeometry;\n\nvoid\nWriteReadAndCheck(GeometryType * geometry)\n{\n  const char   fileName[] = \"rtkgeometryfiletest.out\";\n  const double epsilon = 1e-13;\n\n  auto xmlWriter = rtk::ThreeDCircularProjectionGeometryXMLFileWriter::New();\n  xmlWriter->SetFilename(fileName);\n  xmlWriter->SetObject(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(xmlWriter->WriteFile())\n\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer xmlReader;\n  xmlReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  xmlReader->SetFilename(fileName);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(xmlReader->GenerateOutputInformation())\n\n  itksys::SystemTools::RemoveFile(fileName);\n\n  GeometryType * geoRead = xmlReader->GetOutputObject();\n  for (unsigned int i = 0; i < geometry->GetGantryAngles().size(); i++)\n  {\n#define CHECK_GEOMETRY_PARAMETER(paramName)                                                   \\\n  {                                                                                           \\\n    double val1 = geoRead->Get##paramName()[i];                                               \\\n    double val2 = geometry->Get##paramName()[i];                                              \\\n    if (itk::Math::abs(val1 - val2) > epsilon)                                                \\\n    {                                                                                         \\\n      std::cerr << #paramName \" differ [\" << val1 << \"] read from written file vs. [\" << val2 \\\n                << \"] for the reference, difference=[\" << val1 - val2 << \"].\" << std::endl;   \\\n      exit(1);                                                                                \\\n    }                                                                                         \\\n  }\n\n    CHECK_GEOMETRY_PARAMETER(GantryAngles);\n    CHECK_GEOMETRY_PARAMETER(OutOfPlaneAngles);\n    CHECK_GEOMETRY_PARAMETER(InPlaneAngles);\n    CHECK_GEOMETRY_PARAMETER(SourceToIsocenterDistances);\n    CHECK_GEOMETRY_PARAMETER(SourceOffsetsX);\n    CHECK_GEOMETRY_PARAMETER(SourceOffsetsY);\n    CHECK_GEOMETRY_PARAMETER(SourceToDetectorDistances);\n    CHECK_GEOMETRY_PARAMETER(ProjectionOffsetsX);\n    CHECK_GEOMETRY_PARAMETER(ProjectionOffsetsY);\n  }\n}\n\n/**\n * \\file rtkgeometryfiletest.cxx\n *\n * \\brief Functional tests for classes managing RTK geometry data\n *\n * This test creates different RTK geometries and compares the result to\n * to the expected one, read from a baseline .txt file in the RTK format.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  // Create a geometry object with 1 projection\n  auto geometry = GeometryType::New();\n  geometry->AddProjection(615., 548., 36., 1.3, 1.57, 15.4, 13.48, 5.42, 7.56);\n  WriteReadAndCheck(geometry);\n\n  // Create a geometry object with 5 projections with similar geometry parameters\n  geometry = GeometryType::New();\n  for (int i = 0; i < 5; i++)\n    geometry->AddProjection(615., 548., 36., 1.3, 1.57, 15.4, 13.48, 5.42, 7.56);\n  WriteReadAndCheck(geometry);\n\n  // Create a geometry object with 5 projections with different geometry parameters\n  geometry = GeometryType::New();\n  geometry->AddProjection(615., 15., -8., 1.3, 1.57, 15.4, 13.48, 5.42, 7.56);\n  geometry->AddProjection(354., 873., 3218., 354.4, 6587.1, .483, 384.4, 6874.4, 384.4);\n  geometry->AddProjection(1869., 6987., 684., 681., -45.1, 6548.1, 6547., .214, .217);\n  geometry->AddProjection(1532., 3218., 98732., -184.5, 548.1, -659.4, 123.4, 87.4, -15476.);\n  geometry->AddProjection(578., 68., 9879., -38.4, 2158.4, -158.4, -43.3, 3218.4, 325.4);\n  WriteReadAndCheck(geometry);\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkgeometryfrommatrixtest.cxx",
    "content": "// RTK\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\n\nint\nmain(int, char **)\n{\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry1, geometry2;\n  geometry1 = rtk::ThreeDCircularProjectionGeometry::New();\n  geometry2 = rtk::ThreeDCircularProjectionGeometry::New();\n\n  for (double oa = -60.; oa < 65.; oa += 60.)\n    for (double ia = -60.; ia < 65.; ia += 60.)\n      for (double ga = 0.; ga < 360.; ga += 45.)\n        for (double sx = -50.; sx < 55.; sx += 25.)\n          for (double sy = -50.; sy < 55.; sy += 25.)\n            for (double px = -50.; px < 55.; px += 25.)\n              for (double py = -50.; py < 55.; py += 25.)\n                for (double sdd = 200.; sdd < 405.; sdd += 200.)\n                  for (double sid = 100.; sid < 200.; sid += 200.)\n                  {\n                    geometry1->AddProjection(sid, sdd, ga, px, py, oa, ia, sx, sy);\n                    geometry2->AddProjection(geometry1->GetMatrices().back());\n\n                    double d = geometry1->GetGantryAngles().back() - geometry2->GetGantryAngles().back();\n                    d = itk::Math::abs(geometry1->ConvertAngleBetweenMinusAndPlusPIRadians(d));\n                    if (d > 0.01)\n                    {\n                      std::cerr << \"ERROR: GantryAngles 1 is \" << geometry1->GetGantryAngles().back()\n                                << \" and GantryAngles 2 is \" << geometry2->GetGantryAngles().back();\n                      return EXIT_FAILURE;\n                    }\n\n                    d = geometry1->GetInPlaneAngles().back() - geometry2->GetInPlaneAngles().back();\n                    d = itk::Math::abs(geometry1->ConvertAngleBetweenMinusAndPlusPIRadians(d));\n                    if (d > 0.01)\n                    {\n                      std::cerr << \"ERROR: InPlaneAngles 1 is \" << geometry1->GetInPlaneAngles().back()\n                                << \" and InPlaneAngles 2 is \" << geometry2->GetInPlaneAngles().back();\n                      return EXIT_FAILURE;\n                    }\n\n                    d = geometry1->GetOutOfPlaneAngles().back() - geometry2->GetOutOfPlaneAngles().back();\n                    d = itk::Math::abs(geometry1->ConvertAngleBetweenMinusAndPlusPIRadians(d));\n                    if (d > 0.01)\n                    {\n                      std::cerr << \"ERROR: OutOfPlaneAngle 1 is \" << geometry1->GetOutOfPlaneAngles().back()\n                                << \" and OutOfPlaneAngle 2 is \" << geometry2->GetOutOfPlaneAngles().back();\n                      return EXIT_FAILURE;\n                    }\n\n                    if (itk::Math::abs(geometry1->GetProjectionOffsetsY().back() -\n                                       geometry2->GetProjectionOffsetsY().back()) > 0.01)\n                    {\n                      std::cerr << \"ERROR: ProjectionOffsetsY 1 is \" << geometry1->GetProjectionOffsetsY().back()\n                                << \" and ProjectionOffsetsY 2 is \" << geometry2->GetProjectionOffsetsY().back();\n                      return EXIT_FAILURE;\n                    }\n\n                    if (itk::Math::abs(geometry1->GetProjectionOffsetsX().back() -\n                                       geometry2->GetProjectionOffsetsX().back()) > 0.01)\n                    {\n                      std::cerr << \"ERROR: ProjectionOffsetsX 1 is \" << geometry1->GetProjectionOffsetsX().back()\n                                << \" and ProjectionOffsetsX 2 is \" << geometry2->GetProjectionOffsetsX().back();\n                      return EXIT_FAILURE;\n                    }\n\n                    if (itk::Math::abs(geometry1->GetSourceToIsocenterDistances().back() -\n                                       geometry2->GetSourceToIsocenterDistances().back()) > 0.01)\n                    {\n                      std::cerr << \"ERROR: GetSourceToIsocenterDistances 1 is \"\n                                << geometry1->GetSourceToIsocenterDistances().back()\n                                << \" and GetSourceToIsocenterDistances 2 is \"\n                                << geometry2->GetSourceToIsocenterDistances().back();\n                      return EXIT_FAILURE;\n                    }\n\n                    if (itk::Math::abs(geometry1->GetSourceToDetectorDistances().back() -\n                                       geometry2->GetSourceToDetectorDistances().back()) > 0.01)\n                    {\n                      std::cerr << \"ERROR: GetSourceToDetectorDistances 1 is \"\n                                << geometry1->GetSourceToDetectorDistances().back()\n                                << \" and GetSourceToDetectorDistances 2 is \"\n                                << geometry2->GetSourceToDetectorDistances().back();\n                      return EXIT_FAILURE;\n                    }\n\n                    if (itk::Math::abs(geometry1->GetSourceOffsetsY().back() - geometry2->GetSourceOffsetsY().back()) >\n                        0.01)\n                    {\n                      std::cerr << \"ERROR: SourceOffsetsY 1 is \" << geometry1->GetSourceOffsetsY().back()\n                                << \" and SourceOffsetsY 2 is \" << geometry2->GetSourceOffsetsY().back();\n                      return EXIT_FAILURE;\n                    }\n\n                    if (itk::Math::abs(geometry1->GetSourceOffsetsX().back() - geometry2->GetSourceOffsetsX().back()) >\n                        0.01)\n                    {\n                      std::cerr << \"ERROR: SourceOffsetsX 1 is \" << geometry1->GetSourceOffsetsX().back()\n                                << \" and SourceOffsetsX 2 is \" << geometry2->GetSourceOffsetsX().back();\n                      return EXIT_FAILURE;\n                    }\n                  }\n  std::cout << \"Test PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkgradienttest.cxx",
    "content": "#include \"math.h\"\n#include <itkImageRegionConstIterator.h>\n\n#include \"rtkMacro.h\"\n\n#include \"rtkTestConfiguration.h\"\n#include \"itkRandomImageSource.h\"\n#include \"rtkForwardDifferenceGradientImageFilter.h\"\n\ntemplate <class TImage, class TGradient>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckGradient(typename TImage::Pointer    itkNotUsed(im),\n              typename TGradient::Pointer itkNotUsed(grad),\n              bool *                      itkNotUsed(dimensionsProcessed))\n{}\n#else\nvoid\nCheckGradient(typename TImage::Pointer im, typename TGradient::Pointer grad, const bool * dimensionsProcessed)\n{\n  // Generate a list of indices of the dimensions to process\n  std::vector<int> dimsToProcess;\n  for (unsigned int dim = 0; dim < TImage::ImageDimension; dim++)\n  {\n    if (dimensionsProcessed[dim])\n      dimsToProcess.push_back(dim);\n  }\n\n  itk::ImageRegionConstIterator<TGradient> itGrad(grad, grad->GetBufferedRegion());\n\n  const int ImageDimension = TImage::ImageDimension;\n\n  itk::Size<ImageDimension> radius;\n  radius.Fill(1);\n\n  itk::ConstNeighborhoodIterator<TImage> iit(radius, im, im->GetLargestPossibleRegion());\n  auto *                                 boundaryCondition = new itk::ZeroFluxNeumannBoundaryCondition<TImage>;\n  iit.OverrideBoundaryCondition(boundaryCondition);\n\n  auto   c = (itk::SizeValueType)(iit.Size() / 2);         // get offset of center pixel\n  auto * strides = new itk::SizeValueType[ImageDimension]; // get offsets to access neighboring pixels\n  for (int dim = 0; dim < ImageDimension; dim++)\n  {\n    strides[dim] = iit.GetStride(dim);\n  }\n\n  double AbsDiff = NAN;\n  double epsilon = 1e-7;\n\n  // Run through the image\n  while (!iit.IsAtEnd())\n  {\n    for (std::vector<int>::size_type k = 0; k < dimsToProcess.size(); k++)\n    {\n      AbsDiff = itk::Math::abs(iit.GetPixel(c + strides[dimsToProcess[k]]) - iit.GetPixel(c) -\n                               itGrad.Get()[k] * grad->GetSpacing()[k]);\n\n      // Checking results\n      if (AbsDiff > epsilon)\n      {\n        std::cerr << \"Test Failed: output of gradient filter not equal to finite difference image.\" << std::endl;\n        std::cerr << \"Problem at pixel \" << iit.GetIndex() << std::endl;\n        std::cerr << \"Absolute difference = \" << AbsDiff << \" instead of \" << epsilon << std::endl;\n        exit(EXIT_FAILURE);\n      }\n    }\n    ++iit;\n    ++itGrad;\n  }\n}\n#endif\n\n/**\n * \\file rtkgradienttest.cxx\n *\n * \\brief Tests whether the gradient filter behaves as expected\n *\n * Tests whether the gradient filter compute uncentered forward\n * differences with ZeroFluxNeumann boundary conditions. The exact\n * definition of the gradient desired can be found in\n * Chambolle, Antonin. “An Algorithm for Total Variation\n * Minimization and Applications.” J. Math. Imaging Vis. 20,\n * no. 1–2 (January 2004): 89–97\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = double;\n\n  using CovVecType = itk::CovariantVector<OutputPixelType, 2>;\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n  using GradientImageType = itk::CudaImage<CovVecType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n  using GradientImageType = itk::Image<CovVecType, Dimension>;\n#endif\n\n  // Random image sources\n  auto randomVolumeSource = itk::RandomImageSource<OutputImageType>::New();\n\n  // Volume metadata\n  auto origin = itk::MakePoint<OutputPixelType>(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize<itk::SizeValueType>(2, 2, 2);\n  auto spacing = itk::MakeVector<OutputPixelType>(252., 252., 252.);\n#else\n  auto size = itk::MakeSize<itk::SizeValueType>(64, 64, 64);\n  auto spacing = itk::MakeVector<OutputPixelType>(4., 4., 4.);\n#endif\n  randomVolumeSource->SetOrigin(origin);\n  randomVolumeSource->SetSpacing(spacing);\n  randomVolumeSource->SetSize(size);\n  randomVolumeSource->SetMin(0.);\n  randomVolumeSource->SetMax(1.);\n\n  // Update all sources\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource->Update());\n\n  using GradientFilterType =\n    rtk::ForwardDifferenceGradientImageFilter<OutputImageType, OutputPixelType, OutputPixelType, GradientImageType>;\n  auto grad = GradientFilterType::New();\n  grad->SetInput(randomVolumeSource->GetOutput());\n\n  bool computeGradientAlongDim[Dimension];\n  computeGradientAlongDim[0] = true;\n  computeGradientAlongDim[1] = false;\n  computeGradientAlongDim[2] = true;\n\n  grad->SetDimensionsProcessed(computeGradientAlongDim);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(grad->Update());\n\n  CheckGradient<OutputImageType, GradientFilterType::OutputImageType>(\n    randomVolumeSource->GetOutput(), grad->GetOutput(), computeGradientAlongDim);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkheadertestfooter.cxx",
    "content": "/**\n * \\file rtkheadertestfooter.cxx\n *\n * \\brief This test includes all headers for coverage and style purposed.\n *\n * This is the footer only of the file, the rest is generated by cmake and\n * includes all headers in the code subdirectory.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkhilbertfiltertest.cxx",
    "content": "#include \"rtkTest.h\"\n\n#include \"rtkFFTHilbertImageFilter.h\"\n/**\n * \\file rtkhilbertfiltertest.cxx\n *\n * \\brief Functional test for the FFT Hilbert filter.\n *\n * This test computes the FFT Hilbert transform of the signal t -> sin(20*pi*t).\n * The computed Hilbert transform is compared against the known analytic Hilbert transform of the signal.\n *\n * \\author Aurélien Coussat\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  OutputImageType::SizeType size;\n  size[0] = 500;\n  size[1] = size[2] = 1;\n\n  OutputImageType::SpacingType spacing;\n  spacing[0] = spacing[1] = spacing[2] = .001;\n\n  OutputImageType::IndexType ix;\n\n  // Build the signal t -> sin(20*pi*t)\n  auto signal = OutputImageType::New();\n  signal->SetSpacing(spacing);\n  signal->SetRegions(size);\n  signal->Allocate();\n\n  itk::ImageRegionIterator<OutputImageType> signalIt(signal, signal->GetLargestPossibleRegion());\n\n  while (!signalIt.IsAtEnd())\n  {\n    ix = signalIt.GetIndex();\n    double t = ix[0] * spacing[0];\n    double v = sin(20 * itk::Math::pi * t);\n    signalIt.Set(v);\n    ++signalIt;\n  }\n\n  // Build the analytic Hilbert transform of the signal\n  // It is t -> -cos(20*pi*t)\n  auto analyticHilbertSignal = OutputImageType::New();\n  analyticHilbertSignal->SetSpacing(spacing);\n  analyticHilbertSignal->SetRegions(size);\n  analyticHilbertSignal->Allocate();\n\n  itk::ImageRegionIterator<OutputImageType> analyticHilbertSignalIt(analyticHilbertSignal,\n                                                                    analyticHilbertSignal->GetLargestPossibleRegion());\n\n  while (!analyticHilbertSignalIt.IsAtEnd())\n  {\n    ix = analyticHilbertSignalIt.GetIndex();\n    double t = ix[0] * spacing[0];\n    double v = -cos(20 * itk::Math::pi * t);\n    analyticHilbertSignalIt.Set(v);\n    ++analyticHilbertSignalIt;\n  }\n\n  // Compute the Hilbert transform of the signal using rtkFFTHilbertImageFilter\n  using HilbertType = rtk::FFTHilbertImageFilter<OutputImageType>;\n  auto hilbert = HilbertType::New();\n  hilbert->SetInput(signal);\n\n  HilbertType::ZeroPadFactorsType zeroPadFactors;\n  zeroPadFactors.Fill(1);\n  hilbert->SetZeroPadFactors(zeroPadFactors);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(hilbert->Update());\n\n  CheckImageQuality<OutputImageType>(hilbert->GetOutput(), analyticHilbertSignal, .035, 27.3, 0.96);\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkimagxtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkImagXGeometryReader.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\n/**\n * \\file rtkimagxtest.cxx\n *\n * \\brief Functional tests for classes managing iMagX data\n *\n * This test reads projections and the geometry of an acquisition from an\n * IBA CBCT acquisition and compares it to the expected results, which are\n * read from a baseline image in the MetaIO file format.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 8)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0]\n              << \"  projection.dcm calibration.xml room.xml imagX.xml geometry.xml reference.mha DCMreference.mha\"\n              << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::Image<float, Dimension>;\n\n  // Generate projections names\n  std::vector<std::string> FileNames;\n  FileNames.emplace_back(argv[1]);\n\n  // Create geometry reader\n  auto imagxReader = rtk::ImagXGeometryReader<ImageType>::New();\n  imagxReader->SetProjectionsFileNames(FileNames);\n  imagxReader->SetCalibrationXMLFileName(argv[2]);\n  imagxReader->SetRoomXMLFileName(argv[3]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(imagxReader->UpdateOutputData());\n\n  // Reference geometry\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer geoRefReader;\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[5]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // Check geometries\n  CheckGeometries(imagxReader->GetGeometry(), geoRefReader->GetOutputObject());\n\n  std::cout << \"Checking one projection in xml format...\" << std::endl;\n\n  // ImagX projections reader\n  using ReaderType = rtk::ProjectionsReader<ImageType>;\n  ReaderType::ShrinkFactorsType binning;\n  binning.Fill(2);\n  binning[2] = 1;\n  ReaderType::OutputImageSizeType crop;\n  crop.Fill(4);\n  crop[2] = 0;\n  auto                     reader = ReaderType::New();\n  std::vector<std::string> fileNames;\n  fileNames.emplace_back(argv[4]);\n  reader->SetFileNames(fileNames);\n  reader->SetShrinkFactors(binning);\n  reader->SetLowerBoundaryCropSize(crop);\n  reader->SetUpperBoundaryCropSize(crop);\n  reader->SetNonNegativityConstraintThreshold(20);\n  reader->SetI0(0);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update());\n\n  // Reference projections reader\n  auto readerRef = ReaderType::New();\n  fileNames.clear();\n  fileNames.emplace_back(argv[6]);\n  readerRef->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 1e-8, 100, 2.0);\n\n  std::cout << std::endl << std::endl << \"Checking one projection in dcm format...\" << std::endl;\n  fileNames.clear();\n  fileNames.emplace_back(argv[1]);\n  reader->SetFileNames(fileNames);\n  reader->SetShrinkFactors(binning);\n  reader->SetLowerBoundaryCropSize(crop);\n  reader->SetUpperBoundaryCropSize(crop);\n  reader->SetNonNegativityConstraintThreshold(20);\n  reader->SetI0(0);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update());\n\n  // Reference projections reader\n  fileNames.clear();\n  fileNames.emplace_back(argv[7]);\n  readerRef->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 1e-8, 100, 2.0);\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkimporttest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkImportImageFilter.h\"\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n\n/**\n * \\file rtkimporttest.cxx\n *\n * \\brief Functional test for the classes performing an import\n *\n * This test perfoms an import of several vector types.\n * Compares the obtained result with the reference raw vector.\n *\n * \\author Marc Vila\n */\n\ntemplate <class TImage>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckError(typename TImage::Pointer     itkNotUsed(recon),\n           typename TImage::PixelType * itkNotUsed(ref),\n           double                       itkNotUsed(ErrorPerPixelTolerance),\n           double                       itkNotUsed(PSNRTolerance),\n           double                       itkNotUsed(RefValueForPSNR))\n{}\n#else\nvoid\nCheckError(typename TImage::Pointer     recon,\n           typename TImage::PixelType * ref,\n           double                       ErrorPerPixelTolerance,\n           double                       PSNRTolerance,\n           double                       RefValueForPSNR)\n{\n  itk::ImageRegionConstIterator<TImage> itTest(recon, recon->GetBufferedRegion());\n\n  using ErrorType = double;\n  ErrorType TestError = 0.;\n  ErrorType EnerError = 0.;\n\n  unsigned int k = 0;\n  itTest.GoToBegin();\n  while (!itTest.IsAtEnd())\n  {\n    typename TImage::PixelType TestVal = itTest.Get();\n    TestError += itk::Math::abs(ErrorType(ref[k] - TestVal));\n    EnerError += std::pow(ErrorType(ref[k] - TestVal), 2.);\n    ++itTest;\n    ++k;\n  }\n  // Error per Pixel\n  ErrorType ErrorPerPixel = TestError / recon->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"\\nError per Pixel = \" << ErrorPerPixel << std::endl;\n  // MSE\n  ErrorType MSE = EnerError / recon->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"MSE = \" << MSE << std::endl;\n  // PSNR\n  ErrorType PSNR = 20 * log10(RefValueForPSNR) - 10 * log10(MSE);\n  std::cout << \"PSNR = \" << PSNR << \"dB\" << std::endl;\n  // QI\n  ErrorType QI = (RefValueForPSNR - ErrorPerPixel) / RefValueForPSNR;\n  std::cout << \"QI = \" << QI << std::endl;\n\n  // Checking results. As a comparison with NaN always returns false,\n  // this design allows to detect NaN results and cause test failure\n  if (!(ErrorPerPixel < ErrorPerPixelTolerance))\n  {\n    std::cerr << \"Test Failed, Error per pixel not valid! \" << ErrorPerPixel << \" instead of \" << ErrorPerPixelTolerance\n              << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  if (!(PSNR > PSNRTolerance))\n  {\n    std::cerr << \"Test Failed, PSNR not valid! \" << PSNR << \" instead of \" << PSNRTolerance << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif // FAST_TESTS_NO_CHECKS\n\nint\nmain(int, char **)\n{\n  // Raw vectors\n  auto * vec_uint_2d = new unsigned int[10 * 10];\n  int *  vec_int_2d = new int[10 * 10];\n  auto * vec_float_2d = new float[10 * 10];\n  auto * vec_double_2d = new double[10 * 10];\n\n  // Initializing values\n  for (unsigned int i = 0; i < 10 * 10; i++)\n  {\n    vec_uint_2d[i] = i;\n    vec_int_2d[i] = i;\n    vec_float_2d[i] = i * 1.01f;\n    vec_double_2d[i] = i * 1.01;\n  }\n\n  std::cout << \"\\n\\n****** Case 1: unsigned short ******\" << std::endl;\n\n  // Update median filter\n  // Import\n  rtk::ImportImageFilter<itk::Image<unsigned int, 2>>::RegionType volRegion;\n\n  rtk::ImportImageFilter<itk::Image<unsigned int, 2>>::RegionType::IndexType volIndex;\n  volIndex.Fill(0.0);\n  volRegion.SetIndex(volIndex);\n\n  rtk::ImportImageFilter<itk::Image<unsigned int, 2>>::RegionType::SizeType volSize;\n  volSize.Fill(10);\n  volRegion.SetSize(volSize);\n\n  auto vol = rtk::ImportImageFilter<itk::Image<unsigned int, 2>>::New();\n  vol->SetRegion(volRegion);\n  vol->SetSpacing(itk::MakeVector(1.0, 1.0));\n  vol->SetImportPointer(vec_uint_2d, 10 * 10, false);\n  vol->Update();\n\n  CheckError<itk::Image<unsigned int, 2>>(vol->GetOutput(), &(vec_uint_2d[0]), 0.5, 2.0, 999.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  auto volCuda = rtk::ImportImageFilter<itk::CudaImage<unsigned int, 2>>::New();\n  volCuda->SetRegion(volRegion);\n  volCuda->SetSpacing(itk::MakeVector(1.0, 1.0));\n  volCuda->SetImportPointer(vec_uint_2d, 10 * 10, false);\n  volCuda->Update();\n\n  CheckError<itk::CudaImage<unsigned int, 2>>(volCuda->GetOutput(), &(vec_uint_2d[0]), 0.5, 2.0, 999.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n  delete[] vec_uint_2d;\n\n  std::cout << \"\\n\\n****** Case 2: int ******\" << std::endl;\n\n  // Update median filter\n  // Import\n  rtk::ImportImageFilter<itk::Image<int, 2>>::RegionType volIntRegion;\n\n  rtk::ImportImageFilter<itk::Image<int, 2>>::RegionType::IndexType volIntIndex;\n  volIntIndex.Fill(0.0);\n  volIntRegion.SetIndex(volIntIndex);\n\n  rtk::ImportImageFilter<itk::Image<int, 2>>::RegionType::SizeType volIntSize;\n  volIntSize.Fill(10);\n  volIntRegion.SetSize(volIntSize);\n\n  auto volInt = rtk::ImportImageFilter<itk::Image<int, 2>>::New();\n  volInt->SetRegion(volIntRegion);\n  volInt->SetSpacing(itk::MakeVector(1.0, 1.0));\n  volInt->SetImportPointer(vec_int_2d, 10 * 10, false);\n  volInt->Update();\n\n  CheckError<itk::Image<int, 2>>(volInt->GetOutput(), &(vec_int_2d[0]), 0.5, 2.0, 999.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  auto volIntCuda = rtk::ImportImageFilter<itk::CudaImage<int, 2>>::New();\n  volIntCuda->SetRegion(volIntRegion);\n  volIntCuda->SetSpacing(itk::MakeVector(1.0, 1.0));\n  volIntCuda->SetImportPointer(vec_int_2d, 10 * 10, false);\n  volIntCuda->Update();\n\n  CheckError<itk::CudaImage<int, 2>>(volIntCuda->GetOutput(), &(vec_int_2d[0]), 0.5, 2.0, 999.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n  delete[] vec_int_2d;\n\n  std::cout << \"\\n\\n****** Case 3: float ******\" << std::endl;\n\n  // Update median filter\n  // Import\n  rtk::ImportImageFilter<itk::Image<float, 2>>::RegionType volFloatRegion;\n\n  rtk::ImportImageFilter<itk::Image<float, 2>>::RegionType::IndexType volFloatIndex;\n  volFloatIndex.Fill(0.0);\n  volFloatRegion.SetIndex(volFloatIndex);\n\n  rtk::ImportImageFilter<itk::Image<float, 2>>::RegionType::SizeType volFloatSize;\n  volFloatSize.Fill(10);\n  volFloatRegion.SetSize(volFloatSize);\n\n  auto volFloat = rtk::ImportImageFilter<itk::Image<float, 2>>::New();\n  volFloat->SetRegion(volFloatRegion);\n  volFloat->SetSpacing(itk::MakeVector(1.0, 1.0));\n  volFloat->SetImportPointer(vec_float_2d, 10 * 10, false);\n  volFloat->Update();\n\n  CheckError<itk::Image<float, 2>>(volFloat->GetOutput(), &(vec_float_2d[0]), 0.5, 2.0, 1008.99);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  auto volFloatCuda = rtk::ImportImageFilter<itk::CudaImage<float, 2>>::New();\n  volFloatCuda->SetRegion(volFloatRegion);\n  volFloatCuda->SetSpacing(itk::MakeVector(1.0, 1.0));\n  volFloatCuda->SetImportPointer(vec_float_2d, 10 * 10, false);\n  volFloatCuda->Update();\n\n  CheckError<itk::CudaImage<float, 2>>(volFloatCuda->GetOutput(), &(vec_float_2d[0]), 0.5, 2.0, 1008.99);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n  delete[] vec_float_2d;\n\n  std::cout << \"\\n\\n****** Case 4: double ******\" << std::endl;\n\n  // Update median filter\n  // Import\n  rtk::ImportImageFilter<itk::Image<double, 2>>::RegionType volDoubleRegion;\n\n  rtk::ImportImageFilter<itk::Image<double, 2>>::RegionType::IndexType volDoubleIndex;\n  volDoubleIndex.Fill(0.0);\n  volDoubleRegion.SetIndex(volDoubleIndex);\n\n  rtk::ImportImageFilter<itk::Image<double, 2>>::RegionType::SizeType volDoubleSize;\n  volDoubleSize.Fill(10);\n  volDoubleRegion.SetSize(volDoubleSize);\n\n  auto volDouble = rtk::ImportImageFilter<itk::Image<double, 2>>::New();\n  volDouble->SetRegion(volDoubleRegion);\n  volDouble->SetSpacing(itk::MakeVector(1.0, 1.0));\n  volDouble->SetImportPointer(vec_double_2d, 10 * 10, false);\n  volDouble->Update();\n\n  CheckError<itk::Image<double, 2>>(volDouble->GetOutput(), &(vec_double_2d[0]), 0.5, 2.0, 1008.99);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  auto volDoubleCuda = rtk::ImportImageFilter<itk::CudaImage<double, 2>>::New();\n  volDoubleCuda->SetRegion(volDoubleRegion);\n  volDoubleCuda->SetSpacing(itk::MakeVector(1.0, 1.0));\n  volDoubleCuda->SetImportPointer(vec_double_2d, 10 * 10, false);\n  volDoubleCuda->Update();\n\n  CheckError<itk::CudaImage<double, 2>>(volDoubleCuda->GetOutput(), &(vec_double_2d[0]), 0.5, 2.0, 1008.99);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n  delete[] vec_double_2d;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkinterpolatesplatadjointtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"itkRandomImageSource.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkInterpolatorWithKnownWeightsImageFilter.h\"\n#include \"rtkSplatWithKnownWeightsImageFilter.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n#include \"rtkJosephBackProjectionImageFilter.h\"\n#include \"rtkJosephForwardProjectionImageFilter.h\"\n#include \"rtkMacro.h\"\n\n#include <itkImageFileReader.h>\n\n/**\n * \\file rtkinterpolatesplatadjointtest.cxx\n *\n * \\brief Tests whether InterpolatorWithKnownWeightsImageFilter and\n * SplatWithKnownWeightsImageFilter are the adjoint of one another.\n *\n * This test generates a random 4D volume \"f\" and a random 3D volume \"v\",\n * and compares the scalar products <Sf , v> and <f, S* v>, where S is the\n * interpolation operator and S* is the splat operator. If S* is indeed\n * the adjoint of S, these scalar products are equal.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 2)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \" phases.txt\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n  using VolumeType = itk::Image<OutputPixelType, Dimension>;\n  using VolumeSeriesType = itk::Image<OutputPixelType, Dimension + 1>;\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfSlices = 2;\n#else\n  constexpr unsigned int NumberOfSlices = 64;\n#endif\n\n\n  // Random image sources\n  auto randomVolumeSource = itk::RandomImageSource<VolumeType>::New();\n\n  auto randomVolumeSeriesSource = itk::RandomImageSource<VolumeSeriesType>::New();\n\n  // Constant sources\n  auto constantVolumeSource = rtk::ConstantImageSource<VolumeType>::New();\n\n  auto constantVolumeSeriesSource = rtk::ConstantImageSource<VolumeSeriesType>::New();\n\n  // Volume metadata\n  auto fourDOrigin = itk::MakePoint(-127., -127., -127., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto fourDSize = itk::MakeSize(2, 2, NumberOfSlices, 2);\n  auto fourDSpacing = itk::MakeVector(252., 252., 252., 1.);\n#else\n  auto fourDSize = itk::MakeSize(64, 64, NumberOfSlices, 5);\n  auto fourDSpacing = itk::MakeVector(4., 4., 4., 1.);\n#endif\n  randomVolumeSeriesSource->SetOrigin(fourDOrigin);\n  randomVolumeSeriesSource->SetSpacing(fourDSpacing);\n  randomVolumeSeriesSource->SetSize(fourDSize);\n  randomVolumeSeriesSource->SetMin(0.);\n  randomVolumeSeriesSource->SetMax(1.);\n\n  constantVolumeSeriesSource->SetOrigin(fourDOrigin);\n  constantVolumeSeriesSource->SetSpacing(fourDSpacing);\n  constantVolumeSeriesSource->SetSize(fourDSize);\n  constantVolumeSeriesSource->SetConstant(0.);\n\n  // Volume metadata\n  auto origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, NumberOfSlices);\n  auto spacing = itk::MakeVector(504., 504., 504.);\n#else\n  auto size = itk::MakeSize(64, 64, NumberOfSlices);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#endif\n  randomVolumeSource->SetOrigin(origin);\n  randomVolumeSource->SetSpacing(spacing);\n  randomVolumeSource->SetSize(size);\n  randomVolumeSource->SetMin(0.);\n  randomVolumeSource->SetMax(1.);\n\n  constantVolumeSource->SetOrigin(origin);\n  constantVolumeSource->SetSpacing(spacing);\n  constantVolumeSource->SetSize(size);\n  constantVolumeSource->SetConstant(0.);\n\n  // Update all sources\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSeriesSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantVolumeSeriesSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(constantVolumeSource->Update());\n\n  // Read the phases file\n  auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n  phaseReader->SetFileName(argv[1]);\n  phaseReader->SetNumberOfReconstructedFrames(fourDSize[3]);\n  phaseReader->Update();\n\n  std::cout << \"\\n\\n****** 4D to 3D (interpolation) ******\" << std::endl;\n\n  auto interp = rtk::InterpolatorWithKnownWeightsImageFilter<VolumeType, VolumeSeriesType>::New();\n  interp->SetInputVolume(constantVolumeSource->GetOutput());\n  interp->SetInputVolumeSeries(randomVolumeSeriesSource->GetOutput());\n  interp->SetWeights(phaseReader->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(interp->Update());\n\n  std::cout << \"\\n\\n****** 3D to 4D (splat) ******\" << std::endl;\n\n  auto splat = rtk::SplatWithKnownWeightsImageFilter<VolumeSeriesType, VolumeType>::New();\n  splat->SetInputVolumeSeries(constantVolumeSeriesSource->GetOutput());\n  splat->SetInputVolume(randomVolumeSource->GetOutput());\n  splat->SetWeights(phaseReader->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(splat->Update());\n\n  CheckScalarProducts<VolumeSeriesType, VolumeType>(\n    randomVolumeSeriesSource->GetOutput(), splat->GetOutput(), randomVolumeSource->GetOutput(), interp->GetOutput());\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkiterativefdktest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkStreamingImageFilter.h>\n\n#include \"rtkConfiguration.h\"\n#include \"rtkTestConfiguration.h\"\n#include \"rtkTest.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"rtkCudaIterativeFDKConeBeamReconstructionFilter.h\"\n#else\n#  include \"rtkIterativeFDKConeBeamReconstructionFilter.h\"\n#endif\n\n/**\n * \\file rtkiterativefdktest.cxx\n *\n * \\brief Functional test for iterative FDK reconstruction\n *\n * This test generates the projections of a simulated Shepp-Logan phantom.\n * A CT image is reconstructed from the set of generated projection images\n * using the iterative FDK algorithm and the reconstructed CT image is compared\n * to the expected results which is analytically computed.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(32, 32, 32);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#else\n  auto size = itk::MakeSize(128, 128, 128);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(32, 32, NumberOfProjectionImages);\n  spacing = itk::MakeVector(32., 32., 32.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n  // Shepp Logan projections filter\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projectionsSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  // Create a reference object (in this case a 3D phantom reference).\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  dsl->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // FDK reconstruction filtering\n#ifdef USE_CUDA\n  using FDKType = rtk::CudaIterativeFDKConeBeamReconstructionFilter;\n#else\n  using FDKType = rtk::IterativeFDKConeBeamReconstructionFilter<OutputImageType>;\n#endif\n  auto ifdk = FDKType::New();\n  ifdk->SetInput(0, tomographySource->GetOutput());\n  ifdk->SetInput(1, slp->GetOutput());\n  ifdk->SetGeometry(geometry);\n  ifdk->SetNumberOfIterations(3);\n#ifdef USE_CUDA\n  ifdk->SetForwardProjectionFilter(FDKType::FP_CUDARAYCAST);\n#else\n  ifdk->SetForwardProjectionFilter(FDKType::FP_JOSEPH);\n#endif\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(ifdk->Update());\n\n  // FOV\n  auto fov = rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType>::New();\n  fov->SetInput(0, ifdk->GetOutput());\n  fov->SetProjectionsStack(slp->GetOutput());\n  fov->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fov->Update());\n\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput(), 0.027, 27, 2.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkl0gradientnormtest.cxx",
    "content": "#include <itkPasteImageFilter.h>\n#include <itksys/SystemTools.hxx>\n#include <itkJoinSeriesImageFilter.h>\n\n#include \"rtkTest.h\"\n#include <itkImageRegionIteratorWithIndex.h>\n#include \"rtkLastDimensionL0GradientDenoisingImageFilter.h\"\n\n/**\n * \\file rtkl0gradientnormtest.cxx\n *\n * \\brief Test for the denoising filter that minimizes the L0 norm of the gradient\n * along the last dimension.\n *\n * This test generates a known 4D image, degrades it with noise,\n * runs L0 gradient norm denoising, and compares the L0 norm of the\n * gradient along the last dimension before and after the regularization\n *\n * \\author Cyril Mory\n */\n\ntemplate <class TInputImage>\nstatic unsigned int\nComputeL0NormAlongLastDimension(typename TInputImage::Pointer in)\n{\n\n  // Create a slice to iterate on\n  typename TInputImage::RegionType largest = in->GetLargestPossibleRegion();\n  typename TInputImage::RegionType FirstFrameRegion = largest;\n  FirstFrameRegion.SetSize(TInputImage::ImageDimension - 1, 1);\n  itk::ImageRegionIteratorWithIndex<TInputImage> FakeIterator(in, FirstFrameRegion);\n\n  // Useful\n  unsigned int length = largest.GetSize(TInputImage::ImageDimension - 1);\n\n  // Create a single-voxel region traversing last dimension\n  typename TInputImage::RegionType SingleVoxelRegion = largest;\n  for (unsigned int dim = 0; dim < TInputImage::ImageDimension - 1; dim++)\n  {\n    SingleVoxelRegion.SetSize(dim, 1);\n    SingleVoxelRegion.SetIndex(dim, 0);\n  }\n\n  unsigned int norm = 0;\n  auto *       oned = new typename TInputImage::PixelType[length];\n\n  // Walk the first frame, and for each voxel, set the whole sequence the way we want it\n  while (!FakeIterator.IsAtEnd())\n  {\n    // Configure the SingleVoxelRegion correctly to follow the FakeIterator\n    // It is the only purpose of this FakeIterator\n    SingleVoxelRegion.SetIndex(FakeIterator.GetIndex());\n\n    // Walk the input along last dimension for this voxel, filling it with the values we want\n    itk::ImageRegionConstIterator<TInputImage> inputIterator(in, SingleVoxelRegion);\n\n    unsigned int i = 0;\n    while (!inputIterator.IsAtEnd())\n    {\n      oned[i] = inputIterator.Get();\n      i++;\n      ++inputIterator;\n    }\n\n    for (unsigned int j = 0; j < length; j++)\n    {\n      unsigned int next = (j + 1) % length;\n      if (oned[j] != oned[next])\n        norm++;\n      i++;\n    }\n\n    ++FakeIterator;\n  }\n  delete[] oned;\n  return (norm);\n}\n\ntemplate <class TInputImage>\nvoid\nCheckL0NormOfGradient(typename TInputImage::Pointer before, typename TInputImage::Pointer after)\n{\n  unsigned int normBefore = 0;\n  unsigned int normAfter = 0;\n\n  normBefore = ComputeL0NormAlongLastDimension<TInputImage>(before);\n  std::cout << \"L0 norm of the gradient before denoising is \" << normBefore << std::endl;\n\n  normAfter = ComputeL0NormAlongLastDimension<TInputImage>(after);\n  std::cout << \"L0 norm of the gradient after denoising is \" << normAfter << std::endl;\n\n  // Checking results\n  if (normBefore / 2 < normAfter)\n  {\n    std::cerr << \"Test Failed: L0 norm of the gradient was not reduced enough\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n\n  // Constant image sources\n  auto origin = itk::MakePoint(-63., -31., -63., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(8, 8, 8, 12);\n  auto spacing = itk::MakeVector(16., 8., 16., 1.);\n#else\n  auto size = itk::MakeSize(32, 16, 32, 12);\n  auto spacing = itk::MakeVector(4., 4., 4., 1.);\n#endif\n  // Initialize the largest possible region for the input image\n  VolumeSeriesType::RegionType largest;\n  largest.SetSize(size);\n\n  // Initialize the input image\n  auto input = VolumeSeriesType::New();\n  input->SetOrigin(origin);\n  input->SetSpacing(spacing);\n  input->SetRegions(largest);\n  input->Allocate();\n\n  ////////////////////////////////////////////////\n  // Fill the input image with the values we want\n\n  // Determine the values we want\n  auto   length = largest.GetSize(VolumeSeriesType::ImageDimension - 1);\n  auto * signal = new OutputPixelType[length]; // Should be an array of 12 floats, since size[3] = 12\n  signal[0] = 0;\n  signal[1] = 1;\n  signal[2] = 1;\n  signal[3] = 1;\n  signal[4] = 0.5;\n  signal[5] = 0;\n  signal[6] = -0.5;\n  signal[7] = -1;\n  signal[8] = -1;\n  signal[9] = -1;\n  signal[10] = 0.5;\n  signal[11] = 0;\n\n  // Create a slice to iterate on\n  VolumeSeriesType::RegionType FirstFrameRegion = largest;\n  FirstFrameRegion.SetSize(VolumeSeriesType::ImageDimension - 1, 1);\n  itk::ImageRegionIteratorWithIndex<VolumeSeriesType> FakeIterator(input, FirstFrameRegion);\n\n  // Create a single-voxel region traversing last dimension\n  VolumeSeriesType::RegionType SingleVoxelRegion = largest;\n  for (unsigned int dim = 0; dim < VolumeSeriesType::ImageDimension - 1; dim++)\n  {\n    SingleVoxelRegion.SetSize(dim, 1);\n    SingleVoxelRegion.SetIndex(dim, 0);\n  }\n\n  // Walk the first frame, and for each voxel, set the whole sequence the way we want it\n  while (!FakeIterator.IsAtEnd())\n  {\n    // Configure the SingleVoxelRegion correctly to follow the FakeIterator\n    // It is the only purpose of this FakeIterator\n    SingleVoxelRegion.SetIndex(FakeIterator.GetIndex());\n\n    // Walk the input along last dimension for this voxel, filling it with the values we want\n    itk::ImageRegionIterator<VolumeSeriesType> inputIterator(input, SingleVoxelRegion);\n\n    unsigned int i = 0;\n    while (!inputIterator.IsAtEnd())\n    {\n      float randomNoise = rand() % 10000;\n      randomNoise -= 5000;\n      randomNoise /= 25000;\n\n      inputIterator.Set(signal[i] + randomNoise);\n      i++;\n      ++inputIterator;\n    }\n    ++FakeIterator;\n  }\n  delete[] signal;\n\n  // Perform regularization\n  auto denoising = rtk::LastDimensionL0GradientDenoisingImageFilter<VolumeSeriesType>::New();\n  denoising->SetInput(input);\n  denoising->SetLambda(0.3);\n  denoising->SetNumberOfIterations(5);\n  denoising->SetInPlace(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(denoising->Update());\n\n  CheckL0NormOfGradient<VolumeSeriesType>(input, denoising->GetOutput());\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtklagcorrectiontest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkTestConfiguration.h\"\n#include \"rtkMacro.h\"\n#ifdef USE_CUDA\n#  include \"rtkCudaLagCorrectionImageFilter.h\"\n#else\n#  include \"rtkLagCorrectionImageFilter.h\"\n#endif\n\n#include <vector>\n\n/**\n * \\file rtklagcorrectiontest.cxx\n *\n * \\brief Test the lag correction filter\n *\n * \\author Sebastien Brousmiche\n */\n\nconst unsigned ModelOrder = 4;\nconst unsigned Nprojections = 10;\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n\n  using VectorType = itk::Vector<float, ModelOrder>; // Parameter type always float/double\n#ifdef USE_CUDA\n  using PixelType = unsigned short;\n  using ImageType = itk::CudaImage<PixelType, Dimension>;\n  using LCImageFilterType = rtk::CudaLagCorrectionImageFilter;\n#else\n  using PixelType = float;\n  using ImageType = itk::Image<PixelType, Dimension>;\n  using LCImageFilterType = rtk::LagCorrectionImageFilter<ImageType, ModelOrder>;\n#endif\n\n  auto lagcorr = LCImageFilterType::New();\n\n  auto size = itk::MakeSize(650, 700, 1);\n\n  ImageType::RegionType region;\n  region.SetSize(size);\n\n  VectorType a;\n  a[0] = 0.7055f;\n  a[1] = 0.1141f;\n  a[2] = 0.0212f;\n  a[3] = 0.0033f;\n\n  VectorType b;\n  b[0] = 2.911e-3f;\n  b[1] = 0.4454e-3f;\n  b[2] = 0.0748e-3f;\n  b[3] = 0.0042e-3f;\n\n  lagcorr->SetCoefficients(a, b);\n\n  for (unsigned i = 0; i < Nprojections; ++i)\n  {\n    auto inputI = ImageType::New();\n    inputI->SetRegions(region);\n    inputI->Allocate();\n    inputI->FillBuffer(1.0f);\n\n    lagcorr->SetInput(inputI.GetPointer());\n\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(lagcorr->Update())\n  }\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtklaplaciantest.cxx",
    "content": "#include \"itkRandomImageSource.h\"\n#include \"rtkLaplacianImageFilter.h\"\n#include \"rtkMacro.h\"\n#include \"rtkTest.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"itkImageFileReader.h\"\n#include \"rtkConstantImageSource.h\"\n\n#ifdef USE_CUDA\n#  include \"rtkCudaLaplacianImageFilter.h\"\n#endif\n\n/**\n * \\file rtklaplaciantest.cxx\n *\n * \\brief Tests whether the computation of the laplacian actually works\n *\n * This test generates a random volume and computes its laplacian.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 2)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \" reference.mha\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n  // Constant image sources\n  auto tomographySource = rtk::ConstantImageSource<OutputImageType>::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(254., 254., 254.);\n#else\n  auto size = itk::MakeSize(32, 32, 32);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  // Generate a shepp logan phantom\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  dsl->SetPhantomScale(128.);\n  dsl->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update());\n\n\n  // Read a reference image\n  auto readerRef = itk::ImageFileReader<OutputImageType>::New();\n  readerRef->SetFileName(argv[1]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n\n  std::cout << \"\\n\\n****** Case 1: CPU laplacian ******\" << std::endl;\n\n  // Create and set the laplacian filter\n  auto laplacian = rtk::LaplacianImageFilter<OutputImageType>::New();\n  laplacian->SetInput(dsl->GetOutput());\n\n  // Compute the laplacian of the shepp logan\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(laplacian->Update());\n\n  // Compare the result with the reference\n  CheckImageQuality<OutputImageType>(laplacian->GetOutput(), readerRef->GetOutput(), 0.00001, 15, 2.0);\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 2: CUDA laplacian ******\" << std::endl;\n\n  // Create and set the laplacian filter\n  typedef rtk::CudaLaplacianImageFilter CUDALaplacianFilterType;\n  auto                                  cudaLaplacian = CUDALaplacianFilterType::New();\n  cudaLaplacian->SetInput(dsl->GetOutput());\n\n  // Compute the laplacian of the shepp logan\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(cudaLaplacian->Update());\n\n  // Compare the result with the reference\n  CheckImageQuality<OutputImageType>(cudaLaplacian->GetOutput(), readerRef->GetOutput(), 0.00001, 15, 2.0);\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtklutbasedvarI0rawtoatttest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkLUTbasedVariableI0RawToAttenuationImageFilter.h\"\n#include <itkImageRegionIterator.h>\n\n/**\n * \\file rtklutbasedvarI0rawtoatttest.cxx\n *\n * \\brief Test rtk::LUTbasedVariableI0RawToAttenuationImageFilter\n *\n * \\author Sebastien Brousmiche\n */\n\nusing ShortImageType = itk::Image<unsigned short, 2>;\n\nvoid\nfillImageWithRawData(ShortImageType::Pointer image, unsigned short I0)\n{\n  itk::ImageRegionIterator<ShortImageType> it(image, image->GetLargestPossibleRegion());\n  it.GoToBegin();\n  unsigned short i = 0;\n  while (!it.IsAtEnd())\n  {\n    unsigned short I = (i % I0) + 1;\n    it.Set(I);\n    ++it;\n    ++i;\n  }\n}\n\nint\nmain(int, char **)\n{\n  auto convert = rtk::LUTbasedVariableI0RawToAttenuationImageFilter<ShortImageType, itk::Image<float, 2>>::New();\n\n  // Constant image sources\n  ShortImageType::RegionType region;\n  region.SetSize(itk::MakeSize(10, 10));\n\n  auto rawImage = ShortImageType::New();\n  rawImage->SetRegions(region);\n  rawImage->SetSpacing(itk::MakeVector(1.0, 1.0));\n  rawImage->Allocate();\n\n  convert->SetInput(rawImage);\n\n  for (unsigned short i = 0; i < 10; ++i)\n  {\n    unsigned short I0 = 10 * i + 1;\n\n    fillImageWithRawData(rawImage, I0);\n\n    convert->SetI0(I0 / 2);\n    convert->Update();\n  }\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkluttest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkMacro.h\"\n#include <itkRegularExpressionSeriesFileNames.h>\n#include <itkCastImageFilter.h>\n\n/**\n * \\file rtkluttest.cxx\n *\n * \\brief Test rtk::LookupTableImageFilter\n *\n * This test float and double lookup table filters. It compares the output of\n * the Elekta lookup table with the values of the same lut casted to float and\n * double.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 2)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \" ElektaProjections \" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Elekta projections reader\n  using ShortImageType = itk::Image<unsigned short, 3>;\n  auto                     r = rtk::ProjectionsReader<ShortImageType>::New();\n  std::vector<std::string> fileNames;\n  fileNames.emplace_back(argv[1]);\n  r->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(r->Update());\n\n  /***** Float *****/\n  using FloatImageType = itk::Image<float, 3>;\n  using ShortFloatLUTType = rtk::ElektaSynergyLookupTableImageFilter<FloatImageType>;\n  auto sflut = ShortFloatLUTType::New();\n  sflut->SetInput(r->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(sflut->Update());\n\n  auto fCast = itk::CastImageFilter<ShortImageType, FloatImageType>::New();\n  fCast->SetInput(r->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fCast->Update());\n\n  auto flCast = itk::CastImageFilter<ShortFloatLUTType::LookupTableType, itk::Image<float, 1>>::New();\n  flCast->SetInput(sflut->GetLookupTable());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(flCast->Update());\n\n  auto flut = rtk::LookupTableImageFilter<FloatImageType, FloatImageType>::New();\n  flut->SetInput(fCast->GetOutput());\n  flut->SetLookupTable(flCast->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(flut->Update());\n\n  CheckImageQuality<FloatImageType>(flut->GetOutput(), sflut->GetOutput(), 1.6e-7, 100, 2.0);\n\n  /***** Double *****/\n  using DoubleImageType = itk::Image<float, 3>;\n  using ShortDoubleLUTType = rtk::ElektaSynergyLookupTableImageFilter<DoubleImageType>;\n  auto sdlut = ShortDoubleLUTType::New();\n  sdlut->SetInput(r->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(sdlut->Update());\n\n  auto dCast = itk::CastImageFilter<ShortImageType, DoubleImageType>::New();\n  dCast->SetInput(r->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dCast->Update());\n\n  auto dlCast = itk::CastImageFilter<ShortDoubleLUTType::LookupTableType, itk::Image<float, 1>>::New();\n  dlCast->SetInput(sdlut->GetLookupTable());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dlCast->Update());\n\n  auto dlut = rtk::LookupTableImageFilter<DoubleImageType, DoubleImageType>::New();\n  dlut->SetInput(dCast->GetOutput());\n  dlut->SetLookupTable(dlCast->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dlut->Update());\n\n  CheckImageQuality<DoubleImageType>(dlut->GetOutput(), sdlut->GetOutput(), 1.6e-7, 100, 2.0);\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkmaximumintensityprojectiontest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkRayBoxIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkMaximumIntensityProjectionImageFilter.h\"\n#include <itkImageRegionSplitterDirection.h>\n#include <itkImageRegionIterator.h>\n#include <itkImageFileWriter.h>\n#include <itkShiftScaleImageFilter.h>\n#include <cmath>\n\n\n/**\n * \\file rtkmaximumintensityprojectiontest.cxx\n *\n * \\brief Functional test for MIP forward filter\n *\n * The test projects a volume filled with ones.\n *\n * \\author Mikhail Polkovnikov\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n  constexpr unsigned int NumberOfProjectionImages = 1;\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  // Create MIP Forward Projector volume input.\n  auto volInput = ConstantImageSourceType::New();\n\n  auto origin = itk::MakePoint(0., 0., 0.);\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  auto sizeOutput = itk::MakeSize(200, 200, 200);\n  auto spacingOutput = itk::MakeVector(1., 1., 1.);\n\n  volInput->SetOrigin(origin);\n  volInput->SetSpacing(spacing);\n  volInput->SetSize(size);\n  volInput->SetConstant(1.);\n  volInput->UpdateOutputInformation();\n\n  // Initialization Imager Volume\n  auto projInput = ConstantImageSourceType::New();\n  sizeOutput[2] = NumberOfProjectionImages;\n  projInput->SetOrigin(origin);\n  projInput->SetSpacing(spacingOutput);\n  projInput->SetSize(sizeOutput);\n  projInput->SetConstant(0.);\n  projInput->Update();\n\n  // MIP Forward Projection filter\n  auto mipfp = rtk::MaximumIntensityProjectionImageFilter<OutputImageType, OutputImageType>::New();\n  mipfp->SetInput(projInput->GetOutput());\n  mipfp->SetInput(1, volInput->GetOutput());\n\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  geometry->AddProjection(700, 800, 0);\n\n  mipfp->SetGeometry(geometry);\n  mipfp->Update();\n\n  itk::ImageRegionConstIterator<OutputImageType> inputIt(mipfp->GetOutput(), mipfp->GetOutput()->GetRequestedRegion());\n\n  inputIt.GoToBegin();\n\n  bool res = false;\n  while (!inputIt.IsAtEnd())\n  {\n    OutputPixelType pixel = inputIt.Get();\n    if (pixel < 4. || pixel > 4.25)\n    {\n      res = true;\n    }\n    ++inputIt;\n  }\n  if (res)\n  {\n    return EXIT_FAILURE;\n  }\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkmotioncompensatedfdktest.cxx",
    "content": "#include <itkPasteImageFilter.h>\n#include <itksys/SystemTools.hxx>\n\n#include \"rtkTest.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n#include \"rtkFDKWarpBackProjectionImageFilter.h\"\n#include \"rtkCyclicDeformationImageFilter.h\"\n\n/**\n * \\file rtkmotioncompensatedfdktest.cxx\n *\n * \\brief Functional tests for classes performing a motion compensated FDK\n * reconstruction.\n *\n * This test generates the projections of a phantom, which consists of two\n * ellipsoids (one of them moving). The resulting moving phantom is\n * reconstructed using motion compensation techniques and these generated\n * results are compared to the expected results (analytical computation).\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 128;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-63., -31., -63.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(32, 32, 32);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#else\n  auto size = itk::MakeSize(64, 32, 64);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(32, 32, NumberOfProjectionImages);\n  spacing = itk::MakeVector(32., 32., 32.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  auto oneProjectionSource = ConstantImageSourceType::New();\n  size[2] = 1;\n  oneProjectionSource->SetOrigin(origin);\n  oneProjectionSource->SetSpacing(spacing);\n  oneProjectionSource->SetSize(size);\n  oneProjectionSource->SetConstant(0.);\n\n  // Geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n\n  // Projections\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  auto destinationIndex = itk::MakeIndex(0, 0, 0);\n  auto pasteFilter = itk::PasteImageFilter<OutputImageType, OutputImageType, OutputImageType>::New();\n\n  std::ofstream            signalFile(\"signal.txt\");\n  OutputImageType::Pointer wholeImage = projectionsSource->GetOutput();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n  {\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Geometry object\n    auto oneProjGeometry = GeometryType::New();\n    oneProjGeometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Ellipse 1\n    auto e1 = REIType::New();\n    auto semiprincipalaxis = itk::MakeVector(60., 60., 60.);\n    auto center = itk::MakeVector(0., 0., 0.);\n    e1->SetInput(oneProjectionSource->GetOutput());\n    e1->SetGeometry(oneProjGeometry);\n    e1->SetDensity(2.);\n    e1->SetAxis(semiprincipalaxis);\n    e1->SetCenter(center);\n    e1->SetAngle(0.);\n    e1->InPlaceOff();\n    e1->Update();\n\n    // Ellipse 2\n    auto e2 = REIType::New();\n    semiprincipalaxis.Fill(8.);\n    e2->SetInput(e1->GetOutput());\n    e2->SetGeometry(oneProjGeometry);\n    e2->SetDensity(-1.);\n    e2->SetAxis(itk::MakeVector(8., 8., 8.));\n    e2->SetCenter(itk::MakeVector(4 * (itk::Math::abs((4 + noProj) % 8 - 4.) - 2.), 0., 0.));\n    e2->SetAngle(0.);\n    e2->Update();\n\n    // Adding each projection to volume\n    pasteFilter->SetSourceImage(e2->GetOutput());\n    pasteFilter->SetDestinationImage(wholeImage);\n    pasteFilter->SetSourceRegion(e2->GetOutput()->GetLargestPossibleRegion());\n    pasteFilter->SetDestinationIndex(destinationIndex);\n    pasteFilter->Update();\n    wholeImage = pasteFilter->GetOutput();\n    destinationIndex[2]++;\n\n    // Signal\n    signalFile << (noProj % 8) / 8. << std::endl;\n  }\n  signalFile.close();\n\n  // Create vector field\n  using DVFPixelType = itk::Vector<float, 3>;\n  using DeformationType = rtk::CyclicDeformationImageFilter<itk::Image<DVFPixelType, 4>, itk::Image<DVFPixelType, 3>>;\n\n  DeformationType::InputImageType::Pointer deformationField;\n  deformationField = DeformationType::InputImageType::New();\n\n  auto                                       sizeMotion = itk::MakeSize(64, 64, 64, 2);\n  DeformationType::InputImageType::PointType originMotion;\n  originMotion[0] = (sizeMotion[0] - 1) * (-0.5); // size along X\n  originMotion[1] = (sizeMotion[1] - 1) * (-0.5); // size along Y\n  originMotion[2] = (sizeMotion[2] - 1) * (-0.5); // size along Z\n  originMotion[3] = 0.;\n  DeformationType::InputImageType::RegionType regionMotion;\n  regionMotion.SetSize(sizeMotion);\n  deformationField->SetRegions(regionMotion);\n  deformationField->SetOrigin(originMotion);\n  deformationField->Allocate();\n\n  // Vector Field initilization\n  DVFPixelType vec;\n  vec.Fill(0.);\n  itk::ImageRegionIteratorWithIndex<DeformationType::InputImageType> inputIt(\n    deformationField, deformationField->GetLargestPossibleRegion());\n  for (inputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt)\n  {\n    if (inputIt.GetIndex()[3] == 0)\n      vec[0] = -8.;\n    else\n      vec[0] = 8.;\n    inputIt.Set(vec);\n  }\n\n  // Create cyclic deformation\n  auto def = DeformationType::New();\n  def->SetInput(deformationField);\n  auto bp = rtk::FDKWarpBackProjectionImageFilter<OutputImageType, OutputImageType, DeformationType>::New();\n  bp->SetDeformation(def);\n  bp->SetGeometry(geometry.GetPointer());\n\n  // FDK reconstruction filtering\n#ifdef USE_CUDA\n  using FDKType = rtk::CudaFDKConeBeamReconstructionFilter;\n#else\n  using FDKType = rtk::FDKConeBeamReconstructionFilter<OutputImageType>;\n#endif\n  auto feldkamp = FDKType::New();\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, wholeImage);\n  feldkamp->SetGeometry(geometry);\n  def->SetSignalFilename(\"signal.txt\");\n  feldkamp.GetPointer()->SetBackProjectionFilter(bp.GetPointer());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n\n  // FOV\n  auto fov = rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType>::New();\n  fov->SetInput(0, feldkamp->GetOutput());\n  fov->SetProjectionsStack(wholeImage.GetPointer());\n  fov->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(fov->Update());\n\n  // Create a reference object (in this case a 3D phantom reference).\n  // Ellipse 1\n  using DEType = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>;\n  auto e1 = DEType::New();\n  e1->SetInput(tomographySource->GetOutput());\n  e1->SetDensity(2.);\n  e1->SetAxis(itk::MakeVector(60., 60., 60.));\n  e1->SetCenter(itk::MakeVector(0., 0., 0.));\n  e1->SetAngle(0.);\n  e1->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(e1->Update())\n\n  // Ellipse 2\n  auto e2 = DEType::New();\n  e2->SetInput(e1->GetOutput());\n  e2->SetDensity(-1.);\n  e2->SetAxis(itk::MakeVector(8., 8., 8.));\n  e2->SetCenter(itk::MakeVector(0., 0., 0.));\n  e2->SetAngle(0.);\n  e2->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(e2->Update())\n\n  CheckImageQuality<OutputImageType>(fov->GetOutput(), e2->GetOutput(), 0.05, 22, 2.0);\n\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  itksys::SystemTools::RemoveFile(\"signal.txt\");\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtknewtonupdatetest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include <itkImageFileReader.h>\n#include \"rtkGetNewtonUpdateImageFilter.h\"\n#include <itkCSVArray2DFileReader.h>\n\n/**\n * \\file rtknewtonupdatetest.cxx\n *\n * \\brief Test for the filter rtkNewtonUpdateImageFilter\n *\n * This test reads gradient and hessian, runs rtkNewtonUpdateImageFilter\n * to get the update computed by Newton's method, and compares its outputs\n * to the expected one (computed with Matlab)\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 4)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \" gradient.mha hessian.mha reference.mha\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Define types\n  constexpr unsigned int nMaterials = 3;\n  using dataType = double;\n  using TGradient = itk::Image<itk::Vector<dataType, nMaterials>, 3>;\n  using THessian = itk::Image<itk::Vector<dataType, nMaterials * nMaterials>, 3>;\n\n  // Define, instantiate, set and update readers\n  auto gradientReader = itk::ImageFileReader<TGradient>::New();\n  gradientReader->SetFileName(argv[1]);\n  gradientReader->Update();\n\n  auto hessianReader = itk::ImageFileReader<THessian>::New();\n  hessianReader->SetFileName(argv[2]);\n  hessianReader->Update();\n\n  auto outputReader = itk::ImageFileReader<TGradient>::New();\n  outputReader->SetFileName(argv[3]);\n  outputReader->Update();\n\n  // Create the filter\n  auto newtonUpdate = rtk::GetNewtonUpdateImageFilter<TGradient, THessian>::New();\n\n  // Set its inputs\n  newtonUpdate->SetInputGradient(gradientReader->GetOutput());\n  newtonUpdate->SetInputHessian(hessianReader->GetOutput());\n\n  // Update the filter\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(newtonUpdate->Update());\n\n  // 2. Compare read projections\n  CheckVectorImageQuality<TGradient>(newtonUpdate->GetOutput(), outputReader->GetOutput(), 1.e-9, 200, 2000.0);\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkoratest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkOraGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkMaskCollimationImageFilter.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\n/**\n * \\file rtkoratest.cxx\n *\n * \\brief Functional tests for classes managing Ora data (radART / medPhoton)\n *\n * This test reads and verifies the geometry from an ora projection.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 5)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"oraGeometry.xml refGeometry.xml\"\n              << \" oraGeometry_yawtilt.xml refGeometry_yawtilt.xml\"\n              << \" oraGeometry_yaw.xml refGeometry_yaw.xml\"\n              << \" refGeometry_optitrack.xml\"\n              << \" reference.mha\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  std::cout << \"Testing geometry...\" << std::endl;\n\n  // Ora geometry\n  std::vector<std::string> filenames;\n  filenames.emplace_back(argv[1]);\n  rtk::OraGeometryReader::Pointer geoTargReader;\n  geoTargReader = rtk::OraGeometryReader::New();\n  geoTargReader->SetProjectionsFileNames(filenames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader->UpdateOutputData());\n\n  // Reference geometry\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer geoRefReader;\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[2]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // Check geometries\n  CheckGeometries(geoTargReader->GetGeometry(), geoRefReader->GetOutputObject());\n\n  std::cout << \"Testing geometry with tilt and yaw...\" << std::endl;\n\n  // Ora geometry\n  std::vector<std::string> filenames_yawtilt;\n  filenames_yawtilt.emplace_back(argv[3]);\n  rtk::OraGeometryReader::Pointer geoTargReader_yawtilt;\n  geoTargReader_yawtilt = rtk::OraGeometryReader::New();\n  geoTargReader_yawtilt->SetProjectionsFileNames(filenames_yawtilt);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader_yawtilt->UpdateOutputData());\n\n  // Reference geometry\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[4]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // Check geometries\n  CheckGeometries(geoTargReader_yawtilt->GetGeometry(), geoRefReader->GetOutputObject());\n\n  std::cout << \"Testing geometry with optitrack...\" << std::endl;\n\n  // Ora geometry\n  std::vector<std::string> filenames_opti;\n  filenames_opti.emplace_back(argv[3]);\n  rtk::OraGeometryReader::Pointer geoTargReader_opti;\n  geoTargReader_opti = rtk::OraGeometryReader::New();\n  geoTargReader_opti->SetProjectionsFileNames(filenames_opti);\n  geoTargReader_opti->SetOptiTrackObjectID(2);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader_opti->UpdateOutputData());\n\n  // Reference geometry\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[5]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // Check geometries\n  CheckGeometries(geoTargReader_opti->GetGeometry(), geoRefReader->GetOutputObject());\n\n  // ******* COMPARING projections *******\n  std::cout << \"Testing attenuation conversion...\" << std::endl;\n\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::Image<float, Dimension>;\n\n  // Projections reader\n  using ReaderType = rtk::ProjectionsReader<ImageType>;\n  auto reader = ReaderType::New();\n  reader->SetFileNames(filenames);\n  ReaderType::OutputImageSpacingType spacing;\n  spacing[0] = 1.;\n  spacing[1] = 2.;\n  spacing[2] = 1.;\n  reader->SetSpacing(spacing);\n  reader->SetOrigin(itk::MakePoint(0., 0., 0.));\n  ReaderType::OutputImageDirectionType direction;\n  direction.SetIdentity();\n  reader->SetDirection(direction);\n\n  // Create projection image filter\n  auto ofm = rtk::MaskCollimationImageFilter<ImageType, ImageType>::New();\n  ofm->SetInput(reader->GetOutput());\n  ofm->SetGeometry(geoTargReader->GetModifiableGeometry());\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(ofm->Update());\n\n  // Reference projections reader\n  auto readerRef = ReaderType::New();\n  filenames.clear();\n  filenames.emplace_back(argv[6]);\n  readerRef->SetFileNames(filenames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(ofm->GetOutput(), readerRef->GetOutput(), 1.e-10, 100000, 2000.0);\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkosemtest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n\n#include \"rtkTest.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"itkMaskImageFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n#include \"rtkOSEMConeBeamReconstructionFilter.h\"\n\n/**\n * \\file rtkosemtest.cxx\n *\n * \\brief Functional test for OSEM reconstruction\n *\n * This test generates the projections of an ellipsoid and reconstructs the CT\n * image using the OSEM algorithm with different backprojectors (Voxel-Based,\n * Joseph and CUDA Voxel-Based). The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Antoine Robert\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 60;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  constexpr double att = 0.0154;\n\n  auto tomographySource = ConstantImageSourceType::New();\n  auto volumeSource = ConstantImageSourceType::New();\n  auto attenuationInput = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-67., -67., -67.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(252., 252., 252.);\n#else\n  auto size = itk::MakeSize(34, 34, 34);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n  volumeSource->SetOrigin(origin);\n  volumeSource->SetSpacing(spacing);\n  volumeSource->SetSize(size);\n  volumeSource->SetConstant(1.);\n  attenuationInput->SetOrigin(origin);\n  attenuationInput->SetSpacing(spacing);\n  attenuationInput->SetSize(size);\n  attenuationInput->SetConstant(att);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-135., -135., -135.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(504., 504., 504.);\n#else\n  size = itk::MakeSize(34, 34, NumberOfProjectionImages);\n  spacing = itk::MakeVector(8., 8., 8.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create ellipsoid PROJECTIONS\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::Pointer rei;\n\n  auto semiprincipalaxis = itk::MakeVector(60., 60., 60.);\n  auto center = itk::MakeVector(0., 0., 0.);\n  rei = REIType::New();\n  rei->SetAngle(0.);\n  rei->SetDensity(1.);\n  rei->SetCenter(center);\n  rei->SetAxis(semiprincipalaxis);\n\n  rei->SetInput(projectionsSource->GetOutput());\n  rei->SetGeometry(geometry);\n\n  // Update\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n\n  // Create REFERENCE object (3D ellipsoid).\n  auto dsl = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  dsl->SetAxis(semiprincipalaxis);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update());\n\n  // Create attenuation map according to the reference object\n  auto maskFilter = itk::MaskImageFilter<OutputImageType, OutputImageType>::New();\n  maskFilter->SetInput(attenuationInput->GetOutput());\n  maskFilter->SetMaskImage(dsl->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(maskFilter->Update());\n\n  // OSEM reconstruction filtering\n  using OSEMType = rtk::OSEMConeBeamReconstructionFilter<OutputImageType>;\n  auto osem = OSEMType::New();\n  osem->SetInput(0, volumeSource->GetOutput());\n  osem->SetInput(1, rei->GetOutput());\n  osem->SetGeometry(geometry);\n\n  std::cout << \"\\n\\n****** Case 1: Voxel-Based Backprojector, ML-EM 10 iterations ******\" << std::endl;\n\n  osem->SetNumberOfIterations(10);\n  osem->SetBackProjectionFilter(OSEMType::BP_VOXELBASED);\n  osem->SetForwardProjectionFilter(OSEMType::FP_JOSEPH);\n  osem->SetNumberOfProjectionsPerSubset(NumberOfProjectionImages);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(osem->Update());\n\n  CheckImageQuality<OutputImageType>(osem->GetOutput(), dsl->GetOutput(), 0.047, 25.0, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout\n    << \"\\n\\n****** Case 2: Joseph-Based Backprojector, OS-EM with 10 projections per subset and 4 iterations******\"\n    << std::endl;\n\n  osem->SetNumberOfIterations(3);\n  osem->SetBackProjectionFilter(OSEMType::BP_JOSEPH);\n  osem->SetForwardProjectionFilter(OSEMType::FP_JOSEPH);\n  osem->SetNumberOfProjectionsPerSubset(10);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(osem->Update());\n\n  CheckImageQuality<OutputImageType>(osem->GetOutput(), dsl->GetOutput(), 0.032, 25.0, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout\n    << \"\\n\\n****** Case 3: Voxel-Based Backprojector, OS-EM with 10 projections per subset and 3 iterations******\"\n    << std::endl;\n\n  osem->SetNumberOfIterations(3);\n  osem->SetBackProjectionFilter(OSEMType::BP_VOXELBASED);\n  osem->SetForwardProjectionFilter(OSEMType::FP_JOSEPH);\n  osem->SetNumberOfProjectionsPerSubset(10);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(osem->Update());\n\n  CheckImageQuality<OutputImageType>(osem->GetOutput(), dsl->GetOutput(), 0.032, 25, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 4: CUDA Voxel-Based Backprojector ******\" << std::endl;\n\n  osem->SetBackProjectionFilter(OSEMType::BP_CUDAVOXELBASED);\n  osem->SetForwardProjectionFilter(OSEMType::FP_CUDARAYCAST);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(osem->Update());\n\n  CheckImageQuality<OutputImageType>(osem->GetOutput(), dsl->GetOutput(), 0.032, 26, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  itk::ImageRegionIterator<OutputImageType> itRei(rei->GetOutput(), rei->GetOutput()->GetBufferedRegion());\n\n  itRei.GoToBegin();\n\n  while (!itRei.IsAtEnd())\n  {\n    typename OutputImageType::PixelType RefVal = itRei.Get();\n    if (att == 0)\n      itRei.Set(RefVal);\n    else\n      itRei.Set((1 - exp(-RefVal * att)) / (att));\n    ++itRei;\n  }\n  osem->SetInput(1, rei->GetOutput());\n  osem->SetInput(2, maskFilter->GetOutput());\n\n  std::cout\n    << \"\\n\\n****** Case 5: Joseph Attenuated Backprojector, OS-EM with 10 projections per subset and 3 iterations******\"\n    << std::endl;\n\n  osem->SetNumberOfIterations(3);\n  osem->SetBackProjectionFilter(OSEMType::BP_JOSEPHATTENUATED);\n  osem->SetForwardProjectionFilter(OSEMType::FP_JOSEPHATTENUATED);\n  osem->SetNumberOfProjectionsPerSubset(10);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(osem->Update());\n\n  CheckImageQuality<OutputImageType>(osem->GetOutput(), dsl->GetOutput(), 0.032, 25.0, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkparallelgeometryfrommatrixtest.cxx",
    "content": "// RTK\n#include \"rtkThreeDCircularProjectionGeometry.h\"\n\n\nint\nmain(int, char **)\n{\n  rtk::ThreeDCircularProjectionGeometry::Pointer geometry1, geometry2;\n  geometry1 = rtk::ThreeDCircularProjectionGeometry::New();\n  geometry2 = rtk::ThreeDCircularProjectionGeometry::New();\n\n  const double sid = 1000.;\n  const double sdd = 0.; // Parallel geometry\n  for (double oa = -60.; oa < 65.; oa += 60.)\n  {\n    for (double ia = -360.; ia < 360.; ia += 60.)\n    {\n      for (double ga = -360.; ga < 360.; ga += 45.)\n      {\n        for (double px = -50.; px < 55.; px += 25.)\n        {\n          for (double py = -50.; py < 55.; py += 25.)\n          {\n            geometry1->AddProjection(sid, sdd, ga, px, py, oa, ia);\n            geometry2->AddProjection(geometry1->GetMatrices().back());\n\n            double g1 = geometry1->GetGantryAngles().back();\n            double g2 = geometry2->GetGantryAngles().back();\n            double d = g1 - g2;\n            d = itk::Math::abs(geometry1->ConvertAngleBetweenMinusAndPlusPIRadians(d));\n            if (d > 0.01)\n            {\n              std::cerr << \"ERROR: GantryAngles 1 is \" << g1 << \" and GantryAngles 2 is \" << g2;\n              return EXIT_FAILURE;\n            }\n\n            double ia1 = geometry1->GetInPlaneAngles().back();\n            double ia2 = geometry2->GetInPlaneAngles().back();\n            d = ia1 - ia2;\n            d = itk::Math::abs(geometry1->ConvertAngleBetweenMinusAndPlusPIRadians(d));\n            if (d > 0.01)\n            {\n              std::cerr << \"ERROR: InPlaneAngles 1 is \" << ia1 << \" and InPlaneAngles 2 is \" << ia2;\n              return EXIT_FAILURE;\n            }\n\n            double oa1 = geometry1->GetOutOfPlaneAngles().back();\n            double oa2 = geometry2->GetOutOfPlaneAngles().back();\n            d = oa1 - oa2;\n            d = itk::Math::abs(geometry1->ConvertAngleBetweenMinusAndPlusPIRadians(d));\n            if (d > 0.01)\n            {\n              std::cerr << \"ERROR: OutOfPlaneAngle 1 is \" << oa1 << \" and OutOfPlaneAngle 2 is \" << oa2;\n              return EXIT_FAILURE;\n            }\n\n            double py1 = geometry1->GetProjectionOffsetsY().back();\n            double py2 = geometry2->GetProjectionOffsetsY().back();\n            d = itk::Math::abs(py1 - py2);\n            if (d > 0.01)\n            {\n              std::cerr << \"ERROR: ProjectionOffsetsY 1 is \" << py1 << \" and ProjectionOffsetsY 2 is \" << py2;\n              return EXIT_FAILURE;\n            }\n\n            double px1 = geometry1->GetProjectionOffsetsX().back();\n            double px2 = geometry2->GetProjectionOffsetsX().back();\n            d = itk::Math::abs(px1 - px2);\n            if (d > 0.01)\n            {\n              std::cerr << \"ERROR: ProjectionOffsetsX 1 is \" << px1 << \" and ProjectionOffsetsX 2 is \" << px2;\n              return EXIT_FAILURE;\n            }\n\n            double sid1 = geometry1->GetSourceToIsocenterDistances().back();\n            double sid2 = geometry2->GetSourceToIsocenterDistances().back();\n            d = itk::Math::abs(sid1 - sid2);\n            if (d > 0.01)\n            {\n              std::cerr << \"ERROR: GetSourceToIsocenterDistances 1 is \" << sid1\n                        << \" and GetSourceToIsocenterDistances 2 is \" << sid2;\n              return EXIT_FAILURE;\n            }\n\n            double sdd1 = geometry1->GetSourceToDetectorDistances().back();\n            double sdd2 = geometry2->GetSourceToDetectorDistances().back();\n            d = itk::Math::abs(sdd1 - sdd2);\n            if (d > 0.01)\n            {\n              std::cerr << \"ERROR: GetSourceToDetectorDistances 1 is \" << sdd1\n                        << \" and GetSourceToDetectorDistances 2 is \" << sdd2;\n              return EXIT_FAILURE;\n            }\n          }\n        }\n      }\n    }\n  }\n  std::cout << \"Test PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkprojectgeometricphantomtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkProjectGeometricPhantomImageFilter.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\n/**\n * \\file rtkprojectgeometricphantomtest.cxx\n *\n * \\brief Functional test for the class that projects a geometric phantom\n * specified in a config file.\n *\n * This test generates the projections of a Shepp-Logan phantom which are\n * specified by a configuration file located at the Baseline folder.\n * The generated results are compared to the expected results, which are\n * created through hard-coded geometric parameters.\n *\n * \\author Marc Vila\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 2)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"  ConfigFile.txt\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n\n  // Constant image sources\n  auto projectionsSource = rtk::ConstantImageSource<OutputImageType>::New();\n  auto origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  auto spacing = itk::MakeVector(508., 508., 508.);\n#else\n  auto size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Shepp Logan projections filter\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projectionsSource->GetOutput());\n  slp->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  // Shepp Logan projections filter from Configuration File\n  auto pgp = rtk::ProjectGeometricPhantomImageFilter<OutputImageType, OutputImageType>::New();\n  pgp->SetInput(projectionsSource->GetOutput());\n  pgp->SetGeometry(geometry);\n  pgp->SetConfigFile(argv[1]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(pgp->Update());\n\n  CheckImageQuality<OutputImageType>(slp->GetOutput(), pgp->GetOutput(), 0.00055, 88, 255.0);\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkrampfiltertest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n\n#include \"rtkTestConfiguration.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkAdditiveGaussianNoiseImageFilter.h\"\n#include \"rtkTest.h\"\n\n#ifdef USE_CUDA\n#  include \"rtkCudaFDKConeBeamReconstructionFilter.h\"\n#else\n#  include \"rtkFDKConeBeamReconstructionFilter.h\"\n#endif\n\n/**\n * \\file rtkrampfiltertest.cxx\n *\n * \\brief Functional test for the ramp filter of the FDK reconstruction.\n *\n * This test generates the projections of a simulated Shepp-Logan phantom in\n * different reconstruction scenarios (noise, truncation).\n * CT images are reconstructed from each set of projection images using the\n * FDK algorithm with different configuration of the ramp filter in order to\n * reduce the possible artifacts. The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(254., 254., 254.);\n#else\n  auto size = itk::MakeSize(128, 128, 128);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(508., 508., 508.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Shepp Logan projections filter\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projectionsSource->GetOutput());\n  slp->SetGeometry(geometry);\n\n  std::cout << \"\\n\\n****** Test 1: add noise and test Hann window ******\" << std::endl;\n\n  // Add noise\n  auto noisy = rtk::AdditiveGaussianNoiseImageFilter<OutputImageType>::New();\n  noisy->SetInput(slp->GetOutput());\n  noisy->SetMean(0.0);\n  noisy->SetStandardDeviation(1.);\n\n  // Create a reference object (in this case a 3D phantom reference).\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update());\n\n  // FDK reconstruction filtering\n#ifdef USE_CUDA\n  using FDKType = rtk::CudaFDKConeBeamReconstructionFilter;\n#else\n  using FDKType = rtk::FDKConeBeamReconstructionFilter<OutputImageType>;\n#endif\n  auto feldkamp = FDKType::New();\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, noisy->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  feldkamp->GetRampFilter()->SetHannCutFrequency(0.8);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 0.72, 22.4, 2.);\n\n  std::cout << \"\\n\\n****** Test 1.5: add noise and test HannY window ******\" << std::endl;\n  feldkamp->GetRampFilter()->SetHannCutFrequencyY(0.8);\n  feldkamp->Modified();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 0.74, 21.8, 2.);\n\n  std::cout << \"\\n\\n****** Test 2: smaller detector and test data padding for truncation ******\" << std::endl;\n\n  size[0] = 114;\n  projectionsSource->SetSize(size);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->UpdateLargestPossibleRegion());\n\n  auto feldkampCropped = FDKType::New();\n  feldkampCropped->SetInput(0, tomographySource->GetOutput());\n  feldkampCropped->SetInput(1, slp->GetOutput());\n  feldkampCropped->SetGeometry(geometry);\n  feldkampCropped->GetRampFilter()->SetTruncationCorrection(0.1);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkampCropped->Update());\n\n  CheckImageQuality<OutputImageType>(feldkampCropped->GetOutput(), dsl->GetOutput(), 0.12, 20.8, 2.);\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkrampfiltertest2.cxx",
    "content": "#include \"rtkTestConfiguration.h\"\n\n#include \"itkImageFileWriter.h\"\n\n#ifdef USE_CUDA\n#  include \"rtkCudaFFTRampImageFilter.h\"\n#else\n#  include \"rtkFFTRampImageFilter.h\"\n#endif\n\n/**\n * \\file rtkrampfiltertest.cxx\n *\n * \\brief Functional test for the ramp filter of the FDK reconstruction.\n *\n * \\author Julien JOmier\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using PixelType = float;\n#ifdef USE_CUDA\n  using ImageType = itk::CudaImage<PixelType, Dimension>;\n  using RampFilterType = rtk::CudaFFTRampImageFilter;\n#else\n  using ImageType = itk::Image<PixelType, Dimension>;\n  using RampFilterType = rtk::FFTRampImageFilter<ImageType, ImageType>;\n#endif\n\n  auto                  image = ImageType::New();\n  ImageType::RegionType region;\n  region.SetSize(itk::MakeSize(64, 64, 64));\n  image->SetRegions(region);\n  image->Allocate();\n  image->FillBuffer(10);\n\n  auto rampFilter = RampFilterType::New();\n  rampFilter->SetInput(image);\n\n  try\n  {\n    rampFilter->Update();\n  }\n  catch (itk::ExceptionObject & err)\n  {\n    std::cerr << err << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n\n  // Check the results\n  auto  index = itk::MakeIndex(3, 21, 26);\n  float value = 0.132652;\n  if (itk::Math::abs(rampFilter->GetOutput()->GetPixel(index) - value) > 0.000001)\n  {\n    std::cout << \"Output value #0 should be \" << value << \" found \" << rampFilter->GetOutput()->GetPixel(index)\n              << \" instead.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Testing the HannCutFrequency\n  rampFilter->SetHannCutFrequency(0.8);\n  rampFilter->Update();\n  value = 0.149724;\n  if (itk::Math::abs(rampFilter->GetOutput()->GetPixel(index) - value) > 0.000001)\n  {\n    std::cout << \"Output value #1 should be \" << value << \" found \" << rampFilter->GetOutput()->GetPixel(index)\n              << \" instead.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Testing the HanncutFrequencyY\n  rampFilter->SetHannCutFrequencyY(0.1);\n  rampFilter->Update();\n  value = 0.150181;\n  if (itk::Math::abs(rampFilter->GetOutput()->GetPixel(index) - value) > 0.000001)\n  {\n    std::cout << \"Output value #2 should be \" << value << \" found \" << rampFilter->GetOutput()->GetPixel(index)\n              << \" instead.\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  std::cout << \"Test PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkregularizedconjugategradienttest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkRegularizedConjugateGradientConeBeamReconstructionFilter.h\"\n\n#include <itkAdditiveGaussianNoiseImageFilter.h>\n\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n\n/**\n * \\file rtkregularizedconjugategradienttest.cxx\n *\n * \\brief Functional test for ADMMTotalVariation reconstruction\n *\n * This test generates the projections of an ellipsoid and reconstructs the CT\n * image using the ADMMTotalVariation algorithm with different backprojectors (Voxel-Based,\n * Joseph). The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 90;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(252., 252., 252.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(504., 504., 504.);\n#else\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n  spacing = itk::MakeVector(8., 8., 8.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create ellipsoid PROJECTIONS\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::Pointer rei;\n\n  rei = REIType::New();\n  rei->SetAngle(0.);\n  rei->SetDensity(1.);\n  rei->SetCenter(itk::MakeVector(0., 0., 0.));\n  rei->SetAxis(itk::MakeVector(90., 90., 90.));\n  rei->SetInput(projectionsSource->GetOutput());\n  rei->SetGeometry(geometry);\n\n  // Update\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n\n  // Create REFERENCE object (3D ellipsoid).\n  auto dsl = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // Create the weights map\n  auto uniformWeightsSource = ConstantImageSourceType::New();\n  uniformWeightsSource->SetInformationFromImage(projectionsSource->GetOutput());\n  uniformWeightsSource->SetConstant(1.0);\n\n  // Regularized CG reconstruction filter\n  using RegularizedCGType = rtk::RegularizedConjugateGradientConeBeamReconstructionFilter<OutputImageType>;\n  auto regularizedConjugateGradient = RegularizedCGType::New();\n  regularizedConjugateGradient->SetInputVolume(tomographySource->GetOutput());\n  regularizedConjugateGradient->SetInputProjectionStack(rei->GetOutput());\n  regularizedConjugateGradient->SetInputWeights(uniformWeightsSource->GetOutput());\n  regularizedConjugateGradient->SetPreconditioned(false);\n  regularizedConjugateGradient->SetGeometry(geometry);\n  regularizedConjugateGradient->SetMainLoop_iterations(2);\n  regularizedConjugateGradient->SetCudaConjugateGradient(false);\n\n  regularizedConjugateGradient->SetGammaTV(1);\n  regularizedConjugateGradient->SetTV_iterations(3);\n\n  regularizedConjugateGradient->SetSoftThresholdWavelets(0.1);\n  regularizedConjugateGradient->SetOrder(3);\n  regularizedConjugateGradient->SetNumberOfLevels(3);\n\n  // In all cases except CUDA, use the Joseph forward projector and Voxel-based back projector\n  regularizedConjugateGradient->SetForwardProjectionFilter(RegularizedCGType::FP_JOSEPH);\n  regularizedConjugateGradient->SetBackProjectionFilter(RegularizedCGType::BP_VOXELBASED);\n\n  std::cout << \"\\n\\n****** Case 1: Positivity + TV regularization ******\" << std::endl;\n\n  regularizedConjugateGradient->SetPerformPositivity(true);\n  regularizedConjugateGradient->SetPerformTVSpatialDenoising(true);\n  regularizedConjugateGradient->SetPerformWaveletsSpatialDenoising(false);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(regularizedConjugateGradient->Update());\n\n  CheckImageQuality<OutputImageType>(regularizedConjugateGradient->GetOutput(), dsl->GetOutput(), 0.05, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Wavelets ******\" << std::endl;\n\n  regularizedConjugateGradient->SetPerformPositivity(false);\n  regularizedConjugateGradient->SetPerformTVSpatialDenoising(false);\n  regularizedConjugateGradient->SetPerformWaveletsSpatialDenoising(true);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(regularizedConjugateGradient->Update());\n\n  CheckImageQuality<OutputImageType>(regularizedConjugateGradient->GetOutput(), dsl->GetOutput(), 0.05, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 3: CUDA Voxel-Based Backprojector and CUDA Forward projector, all regularization steps \"\n               \"on ******\"\n            << std::endl;\n\n  regularizedConjugateGradient->SetForwardProjectionFilter(RegularizedCGType::FP_CUDARAYCAST);\n  regularizedConjugateGradient->SetBackProjectionFilter(RegularizedCGType::BP_CUDAVOXELBASED);\n  regularizedConjugateGradient->SetCudaConjugateGradient(true);\n  regularizedConjugateGradient->SetPerformPositivity(true);\n  regularizedConjugateGradient->SetPerformTVSpatialDenoising(true);\n  regularizedConjugateGradient->SetPerformWaveletsSpatialDenoising(true);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(regularizedConjugateGradient->Update());\n\n  CheckImageQuality<OutputImageType>(regularizedConjugateGradient->GetOutput(), dsl->GetOutput(), 0.05, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  std::cout << \"\\n\\n****** Image-domain sparsity ******\" << std::endl;\n\n  // Replace the ellise with a very small one\n  rei->SetAxis(itk::MakeVector(9., 9., 9.));\n  dsl->SetAxis(itk::MakeVector(9., 9., 9.));\n\n  // Add gaussian noise on the projections\n  auto gaussian = itk::AdditiveGaussianNoiseImageFilter<OutputImageType>::New();\n  gaussian->SetStandardDeviation(1);\n  gaussian->SetMean(0.);\n  gaussian->SetInput(rei->GetOutput());\n\n  regularizedConjugateGradient->SetInputProjectionStack(gaussian->GetOutput());\n  regularizedConjugateGradient->SetPerformPositivity(false);\n  regularizedConjugateGradient->SetPerformTVSpatialDenoising(false);\n  regularizedConjugateGradient->SetPerformWaveletsSpatialDenoising(false);\n  regularizedConjugateGradient->SetPerformSoftThresholdOnImage(true);\n  regularizedConjugateGradient->SetSoftThresholdOnImage(0.01);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(regularizedConjugateGradient->Update());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update());\n\n  CheckImageQuality<OutputImageType>(regularizedConjugateGradient->GetOutput(), dsl->GetOutput(), 0.004, 47, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtksarttest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n\n#include \"rtkTest.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n#include \"rtkSARTConeBeamReconstructionFilter.h\"\n\n/**\n * \\file rtksarttest.cxx\n *\n * \\brief Functional test for SART reconstruction\n *\n * This test generates the projections of an ellipsoid and reconstructs the CT\n * image using the SART algorithm with different backprojectors (Voxel-Based,\n * Joseph and CUDA Voxel-Based). The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 180;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(252., 252., 252.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-255., -255., -255.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(504., 504., 504.);\n#else\n  size = itk::MakeSize(64, 64, NumberOfProjectionImages);\n  spacing = itk::MakeVector(8., 8., 8.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create ellipsoid PROJECTIONS\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  REIType::Pointer rei;\n\n  rei = REIType::New();\n  rei->SetAngle(0.);\n  rei->SetDensity(1.);\n  rei->SetCenter(itk::MakeVector(0., 0., 0.));\n  rei->SetAxis(itk::MakeVector(90., 90., 90.));\n\n  rei->SetInput(projectionsSource->GetOutput());\n  rei->SetGeometry(geometry);\n\n  // Update\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n\n  // Create REFERENCE object (3D ellipsoid).\n  auto dsl = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // SART reconstruction filtering\n  using SARTType = rtk::SARTConeBeamReconstructionFilter<OutputImageType>;\n  auto sart = SARTType::New();\n  sart->SetInput(tomographySource->GetOutput());\n  sart->SetInput(1, rei->GetOutput());\n  sart->SetGeometry(geometry);\n  sart->SetNumberOfIterations(1);\n  sart->SetLambda(0.5);\n\n  std::cout << \"\\n\\n****** Case 1: Voxel-Based Backprojector ******\" << std::endl;\n\n  sart->SetBackProjectionFilter(SARTType::BP_VOXELBASED);\n  sart->SetForwardProjectionFilter(SARTType::FP_JOSEPH);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(sart->Update());\n\n  CheckImageQuality<OutputImageType>(sart->GetOutput(), dsl->GetOutput(), 0.032, 28.6, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Voxel-Based Backprojector, OS-SART with 2 projections per subset ******\"\n            << std::endl;\n\n  sart->SetBackProjectionFilter(SARTType::BP_VOXELBASED);\n  sart->SetForwardProjectionFilter(SARTType::FP_JOSEPH);\n  sart->SetNumberOfProjectionsPerSubset(2);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(sart->Update());\n\n  CheckImageQuality<OutputImageType>(sart->GetOutput(), dsl->GetOutput(), 0.032, 28.6, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 3: Joseph Backprojector ******\" << std::endl;\n  sart->SetNumberOfProjectionsPerSubset(1);\n  sart->SetBackProjectionFilter(SARTType::BP_JOSEPH);\n  sart->SetForwardProjectionFilter(SARTType::FP_JOSEPH);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(sart->Update());\n\n  CheckImageQuality<OutputImageType>(sart->GetOutput(), dsl->GetOutput(), 0.032, 28.6, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 4: CUDA Voxel-Based Backprojector ******\" << std::endl;\n\n  sart->SetBackProjectionFilter(SARTType::BP_CUDAVOXELBASED);\n  sart->SetForwardProjectionFilter(SARTType::FP_CUDARAYCAST);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(sart->Update());\n\n  CheckImageQuality<OutputImageType>(sart->GetOutput(), dsl->GetOutput(), 0.032, 28.6, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  std::cout << \"\\n\\n****** Case 5: Voxel-Based Backprojector and gating ******\" << std::endl;\n\n  sart->SetBackProjectionFilter(SARTType::BP_VOXELBASED);\n  sart->SetForwardProjectionFilter(SARTType::FP_JOSEPH);\n\n  // Generate arbitrary gating weights (select every third projection)\n  std::vector<float> gatingWeights;\n  for (unsigned int i = 0; i < NumberOfProjectionImages; i++)\n  {\n    if ((i % 3) == 0)\n      gatingWeights.push_back(1);\n    else\n      gatingWeights.push_back(0);\n  }\n  sart->SetGatingWeights(gatingWeights);\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(sart->Update());\n\n  CheckImageQuality<OutputImageType>(sart->GetOutput(), dsl->GetOutput(), 0.05, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkscatterglarefiltertest.cxx",
    "content": "\n#ifdef RAMP_FILTER_TEST_WITHOUT_FFTW\n#  include \"rtkConfiguration.h\"\n#  include <itkImageToImageFilter.h>\n#  if defined(ITK_USE_FFTWF)\n#    undef ITK_USE_FFTWF\n#  endif\n#  if defined(ITK_USE_FFTWD)\n#    undef ITK_USE_FFTWD\n#  endif\n#  if defined(USE_FFTWF)\n#    undef USE_FFTWF\n#  endif\n#  if defined(USE_FFTWD)\n#    undef USE_FFTWD\n#  endif\n#endif\n\n#include \"rtkTest.h\"\n#include \"rtkTestConfiguration.h\"\n#include \"rtkMacro.h\"\n\n#include <cmath>\n#include <itkImageRegionConstIterator.h>\n#include <itkImageRegionIteratorWithIndex.h>\n\n#ifdef USE_CUDA\n#  include \"rtkCudaScatterGlareCorrectionImageFilter.h\"\n#else\n#  include \"rtkScatterGlareCorrectionImageFilter.h\"\n#endif\n\n#include \"rtkTestConfiguration.h\"\n\n/**\n * \\file rtkscatterglarefiltertest.cxx\n *\n * \\brief Functional test for the scatter glare correction filter\n *\n * \\author Sebastien Brousmiche\n */\n\nconstexpr unsigned int Dimension = 3;\n#ifdef USE_CUDA\nusing ImageType = itk::CudaImage<float, Dimension>;\n#else\nusing ImageType = itk::Image<float, Dimension>;\n#endif\n\nconstexpr float spikeValue = 12.341;\n\nImageType::Pointer\ncreateInputImage(const std::vector<float> & coef)\n{\n  auto                  spacing = itk::MakeVector(0.296, 0.296, 1.);\n  auto                  size = itk::MakeSize(650, 700, 1);\n  ImageType::RegionType region;\n  region.SetSize(size);\n\n  auto inputI = ImageType::New();\n  inputI->SetRegions(region);\n  inputI->SetSpacing(spacing);\n  inputI->Allocate();\n  inputI->FillBuffer(1.0f);\n\n  float a3 = coef[0];\n  float b3 = coef[1];\n  float b3sq = b3 * b3;\n  float dx = spacing[0];\n  float dy = spacing[1];\n\n  itk::ImageRegionIteratorWithIndex<ImageType> itK(inputI, inputI->GetLargestPossibleRegion());\n  itK.GoToBegin();\n  ImageType::IndexType idx;\n  while (!itK.IsAtEnd())\n  {\n    idx = itK.GetIndex();\n    float xx = (float)idx[0] - (float)size[0] / 2.0f;\n    float yy = (float)idx[1] - (float)size[1] / 2.0f;\n    float rr2 = (xx * xx + yy * yy);\n    float g = (a3 * dx * dy / (2.0f * itk::Math::pi * b3sq)) * 1.0f / std::pow((1.0f + rr2 / b3sq), 1.5f);\n    if ((2 * idx[0] == (ImageType::IndexValueType)size[0]) && ((2 * idx[1] == (ImageType::IndexValueType)size[1])))\n    {\n      g += (1 - a3);\n    }\n    g = spikeValue * g; // The image is a spike at the central pixel convolved with the scatter PSF\n    itK.Set(g);\n    ++itK;\n  }\n  return inputI;\n}\n\nint\nmain(int, char **)\n{\n#ifdef USE_CUDA\n  using ScatterCorrectionType = rtk::CudaScatterGlareCorrectionImageFilter;\n#else\n  using ScatterCorrectionType = rtk::ScatterGlareCorrectionImageFilter<ImageType, ImageType, float>;\n#endif\n  auto SFilter = ScatterCorrectionType::New();\n\n  std::vector<float> coef;\n  coef.push_back(0.0787f);\n  coef.push_back(106.244f);\n\n  SFilter->SetTruncationCorrection(0.5);\n  SFilter->SetCoefficients(coef);\n\n  ImageType::Pointer testImage = createInputImage(coef);\n  SFilter->SetInput(testImage);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(SFilter->Update())\n\n  ImageType::Pointer                       outputI = SFilter->GetOutput();\n  ImageType::SizeType                      size = outputI->GetLargestPossibleRegion().GetSize();\n  itk::ImageRegionConstIterator<ImageType> itO(outputI, outputI->GetLargestPossibleRegion());\n  itO.GoToBegin();\n\n  ImageType::IndexType idx;\n  float                sumBng = 0.0f;\n  float                spikeValueOut = 0.0f;\n  while (!itO.IsAtEnd())\n  {\n    idx = itO.GetIndex();\n    if ((2 * idx[0] == (ImageType::IndexValueType)size[0]) && ((2 * idx[1] == (ImageType::IndexValueType)size[1])))\n    {\n      spikeValueOut += itO.Get();\n    }\n    else\n    {\n      sumBng += itO.Get();\n    }\n    ++itO;\n  }\n\n  if (!((itk::Math::abs(spikeValueOut - spikeValue) < 1e-2) && (itk::Math::abs(sumBng) < 1e-2)))\n  {\n    std::cerr << \"Test Failed! \" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkselectoneprojpercycletest.cxx",
    "content": "#include <itksys/SystemTools.hxx>\n\n#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkSelectOneProjectionPerCycleImageFilter.h\"\n\n/**\n * \\file rtkmotioncompensatedfdktest.cxx\n *\n * \\brief Check that the correct projection is selected in 3 cycles\n *\n * The test generates projections of 3 cycles and the corresponding signal\n * and check that rtk::SelectOneProjectionPerCycleImageFilter does a proper job.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n  constexpr unsigned int NumberOfProjectionImages = 24;\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto projectionsSource = ConstantImageSourceType::New();\n  auto projectionsSourceRef = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-254., -254., -254.);\n  auto size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n  size[2] = 3;\n  projectionsSourceRef->SetOrigin(origin);\n  projectionsSourceRef->SetSpacing(spacing);\n  projectionsSourceRef->SetSize(size);\n  projectionsSourceRef->SetConstant(0.);\n\n  auto oneProjectionSource = ConstantImageSourceType::New();\n  size[2] = 1;\n  oneProjectionSource->SetOrigin(origin);\n  oneProjectionSource->SetSpacing(spacing);\n  oneProjectionSource->SetSize(size);\n  oneProjectionSource->SetConstant(0.);\n\n  // Geometry objects\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n  auto geometryRef = GeometryType::New();\n\n  // Projections\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<OutputImageType, OutputImageType>;\n  OutputImageType::IndexType destinationIndex, destinationIndexRef;\n  destinationIndex.Fill(0);\n  destinationIndexRef.Fill(0);\n  auto pasteFilter = itk::PasteImageFilter<OutputImageType, OutputImageType, OutputImageType>::New();\n\n  std::string              signalFileName = \"signal_SelectOneProjPerCycle.txt\";\n  std::ofstream            signalFile(signalFileName.c_str());\n  OutputImageType::Pointer wholeImage = projectionsSource->GetOutput();\n  OutputImageType::Pointer wholeImageRef = projectionsSourceRef->GetOutput();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n  {\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n    if (noProj % 8 == 3)\n      geometryRef->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Geometry object\n    auto oneProjGeometry = GeometryType::New();\n    oneProjGeometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Ellipse 1\n    auto e1 = REIType::New();\n    auto semiprincipalaxis = itk::MakeVector(60., 60., 60.);\n    auto center = itk::MakeVector(0., 0., 0.);\n    e1->SetInput(oneProjectionSource->GetOutput());\n    e1->SetGeometry(oneProjGeometry);\n    e1->SetDensity(2.);\n    e1->SetAxis(semiprincipalaxis);\n    e1->SetCenter(center);\n    e1->SetAngle(0.);\n    e1->InPlaceOff();\n    e1->Update();\n\n    // Ellipse 2\n    auto e2 = REIType::New();\n    semiprincipalaxis.Fill(8.);\n    center[0] = 4 * (itk::Math::abs((4 + noProj) % 8 - 4.) - 2.);\n    center[1] = 0.;\n    center[2] = 0.;\n    e2->SetInput(e1->GetOutput());\n    e2->SetGeometry(oneProjGeometry);\n    e2->SetDensity(-1.);\n    e2->SetAxis(semiprincipalaxis);\n    e2->SetCenter(center);\n    e2->SetAngle(0.);\n    e2->Update();\n\n    // Adding each projection to volume\n    pasteFilter->SetSourceImage(e2->GetOutput());\n    pasteFilter->SetDestinationImage(wholeImage);\n    pasteFilter->SetSourceRegion(e2->GetOutput()->GetLargestPossibleRegion());\n    pasteFilter->SetDestinationIndex(destinationIndex);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(pasteFilter->UpdateLargestPossibleRegion());\n    wholeImage = pasteFilter->GetOutput();\n    wholeImage->DisconnectPipeline();\n    destinationIndex[2]++;\n\n    if (noProj % 8 == 3)\n    {\n      // Adding each projection to volume ref\n      pasteFilter->SetSourceImage(e2->GetOutput());\n      pasteFilter->SetDestinationImage(wholeImageRef);\n      pasteFilter->SetSourceRegion(e2->GetOutput()->GetLargestPossibleRegion());\n      pasteFilter->SetDestinationIndex(destinationIndexRef);\n      TRY_AND_EXIT_ON_ITK_EXCEPTION(pasteFilter->UpdateLargestPossibleRegion(););\n      wholeImageRef = pasteFilter->GetOutput();\n      wholeImageRef->DisconnectPipeline();\n      destinationIndexRef[2]++;\n    }\n\n    // Signal\n    signalFile << (noProj % 8) / 8. << std::endl;\n  }\n  signalFile.close();\n\n  // Select\n  auto select = rtk::SelectOneProjectionPerCycleImageFilter<OutputImageType>::New();\n  select->SetInput(wholeImage);\n  select->SetInputGeometry(geometry);\n  select->SetPhase(0.4);\n  select->SetSignalFilename(signalFileName);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(select->Update());\n\n  CheckImageQuality<OutputImageType>(select->GetOutput(), wholeImageRef, 1e-12, 1e20, 1 - 1e-12);\n  CheckGeometries(select->GetOutputGeometry(), geometryRef);\n\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  itksys::SystemTools::RemoveFile(signalFileName.c_str());\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkshortscancompcudatest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include \"rtkCudaParkerShortScanImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n\n#include <itkStreamingImageFilter.h>\n#include <itkImageRegionSplitterDirection.h>\n\n/**\n * \\file rtkshortscancompcudatest.cxx\n *\n * \\brief Test rtk::CudaParkerShortScanImageFilter vs rtk::ParkerShortScanImageFilter\n *\n * This test compares weighted projections using CPU and Cuda implementations\n * of the filter for short scan handling in FBP.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::CudaImage<float, Dimension>;\n\n\n  // Constant image sources\n  auto projSource = rtk::ConstantImageSource<OutputImageType>::New();\n  auto origin = itk::MakePoint(-127., -3., 0.);\n  auto size = itk::MakeSize(128, 4, 4);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n\n  projSource->SetOrigin(origin);\n  projSource->SetSpacing(spacing);\n  projSource->SetSize(size);\n\n  // Geometry\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  geometry->AddProjection(600., 700., 0., 84., 35, 23, 15, 21, 26);\n  geometry->AddProjection(500., 800., 45., 21., 12, 16, 546, 14, 41);\n  geometry->AddProjection(700., 900., 90., 68., 68, 54, 38, 35, 56);\n  geometry->AddProjection(900., 1000., 135., 48., 35, 84, 10, 84, 59);\n\n  // Projections\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  for (int inPlace = 0; inPlace < 2; inPlace++)\n  {\n    std::cout << \"\\n\\n****** Case \" << inPlace * 2 << \": no streaming, \";\n    if (!inPlace)\n      std::cout << \"not\";\n    std::cout << \" in place ******\" << std::endl;\n\n    using CUDASSFType = rtk::CudaParkerShortScanImageFilter;\n    auto cudassf = CUDASSFType::New();\n    cudassf->SetInput(slp->GetOutput());\n    cudassf->SetGeometry(geometry);\n    cudassf->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cudassf->Update());\n\n    using CPUSSFType = rtk::ParkerShortScanImageFilter<OutputImageType>;\n    auto cpussf = CPUSSFType::New();\n    cpussf->SetInput(slp->GetOutput());\n    cpussf->SetGeometry(geometry);\n    cpussf->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(cpussf->Update());\n\n    CheckImageQuality<OutputImageType>(cudassf->GetOutput(), cpussf->GetOutput(), 1.e-5, 100, 1.);\n\n    std::cout << \"\\n\\n****** Case \" << inPlace * 2 + 1 << \": with streaming, \";\n    if (!inPlace)\n      std::cout << \"not\";\n    std::cout << \" in place ******\" << std::endl;\n\n    // Idem with streaming\n    cudassf = CUDASSFType::New();\n    cudassf->SetInput(slp->GetOutput());\n    cudassf->SetGeometry(geometry);\n    cudassf->InPlaceOff();\n\n    using StreamingType = itk::StreamingImageFilter<OutputImageType, OutputImageType>;\n    auto streamingCUDA = StreamingType::New();\n    streamingCUDA->SetInput(cudassf->GetOutput());\n    streamingCUDA->SetNumberOfStreamDivisions(4);\n    auto splitter = itk::ImageRegionSplitterDirection::New();\n    splitter->SetDirection(2); // Splitting along direction 1, NOT 2\n    streamingCUDA->SetRegionSplitter(splitter);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamingCUDA->Update());\n\n    cpussf = CPUSSFType::New();\n    cpussf->SetInput(slp->GetOutput());\n    cpussf->SetGeometry(geometry);\n    cpussf->InPlaceOff();\n\n    auto streamingCPU = StreamingType::New();\n    streamingCPU->SetInput(cpussf->GetOutput());\n    streamingCPU->SetNumberOfStreamDivisions(2);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(streamingCPU->Update());\n\n    CheckImageQuality<OutputImageType>(streamingCUDA->GetOutput(), streamingCPU->GetOutput(), 1.e-5, 100, 1.);\n  }\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkshortscantest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n\n#include \"rtkTest.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#ifdef USE_CUDA\n#  include \"rtkCudaParkerShortScanImageFilter.h\"\n#else\n#  include \"rtkParkerShortScanImageFilter.h\"\n#endif\n\n/**\n * \\file rtkshortscantest.cxx\n *\n * \\brief Functional test for FDK reconstruction from short scan\n *\n * This test generates the projections of a simulated Shepp-Logan phantom with\n * a short scan geometry. The corresponding CT image is reconstructed using\n * FDK with Parker weighting. The generated results are compared to the\n * expected results (analytical calculation).\n *\n * \\author Simon Rit and Marc Vila\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 110;\n#endif\n  constexpr double ArcSize = 240.;\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-127., -127., -127.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(254., 254., 254.);\n#else\n  auto size = itk::MakeSize(128, 128, 128);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(508., 508., 508.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * ArcSize / NumberOfProjectionImages);\n\n  // Shepp Logan projections filter\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projectionsSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(slp->Update());\n\n  // Short scan image filter\n#ifdef USE_CUDA\n  using PSSFType = rtk::CudaParkerShortScanImageFilter;\n#else\n  using PSSFType = rtk::ParkerShortScanImageFilter<OutputImageType>;\n#endif\n  auto pssf = PSSFType::New();\n  pssf->SetInput(slp->GetOutput());\n  pssf->SetGeometry(geometry);\n  pssf->InPlaceOff();\n  pssf->Update();\n\n  // Create a reference object (in this case a 3D phantom reference).\n  auto dsl = rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n  dsl->SetPhantomScale(116);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update())\n\n  // FDK reconstruction filtering\n  auto feldkamp = rtk::FDKConeBeamReconstructionFilter<OutputImageType>::New();\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, pssf->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(feldkamp->Update());\n\n  CheckImageQuality<OutputImageType>(feldkamp->GetOutput(), dsl->GetOutput(), 0.09, 22, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkspectralonesteptest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkMechlemOneStepSpectralReconstructionFilter.h\"\n#include \"rtkSpectralForwardModelImageFilter.h\"\n\n#ifdef USE_CUDA\n#  include \"itkCudaImage.h\"\n#endif\n\n#include <itkImageFileReader.h>\n#include <itkComposeImageFilter.h>\n#include <itkImportImageFilter.h>\n#include <itkVectorIndexSelectionCastImageFilter.h>\n\n/**\n * \\file rtkspectralonesteptest.cxx\n *\n * \\brief Functional test for Mechlem one-step spectral reconstruction\n *\n * This test generates the projections of a multi-material phantom and reconstructs\n * from them using the MechlemOneStep algorithm with different backprojectors (Voxel-Based,\n * Joseph).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 4)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"  incident_spectrum  detector_response  material_attenuations\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  constexpr unsigned int Dimension = 3;\n  constexpr unsigned int nBins = 5;\n  constexpr unsigned int nMaterials = 3;\n  constexpr unsigned int nEnergies = 150;\n  using DataType = float;\n  using MaterialPixelType = itk::Vector<DataType, nMaterials>;\n  using MeasuredProjectionsPixelType = itk::Vector<DataType, nBins>;\n\n  using VectorImageType = typename itk::VectorImage<DataType, Dimension>;\n\n#ifdef RTK_USE_CUDA\n  using MaterialVolumeType = itk::CudaImage<MaterialPixelType, Dimension>;\n  using MeasuredProjectionsType = itk::CudaImage<MeasuredProjectionsPixelType, Dimension>;\n  using IncidentSpectrumImageType = itk::CudaImage<DataType, Dimension>;\n  using DetectorResponseImageType = itk::CudaImage<DataType, Dimension - 1>;\n  using MaterialAttenuationsImageType = itk::CudaImage<DataType, Dimension - 1>;\n  using SingleComponentImageType = itk::CudaImage<DataType, Dimension>;\n#else\n  using MaterialVolumeType = itk::Image<MaterialPixelType, Dimension>;\n  using MeasuredProjectionsType = itk::Image<MeasuredProjectionsPixelType, Dimension>;\n  using IncidentSpectrumImageType = itk::Image<DataType, Dimension>;\n  using DetectorResponseImageType = itk::Image<DataType, Dimension - 1>;\n  using MaterialAttenuationsImageType = itk::Image<DataType, Dimension - 1>;\n  using SingleComponentImageType = itk::Image<DataType, Dimension>;\n#endif\n\n\n  // Cast filters to convert between vector image types\n  using CastMeasuredProjectionsFilterType = itk::CastImageFilter<VectorImageType, MeasuredProjectionsType>;\n\n  // Read all inputs\n  auto incidentSpectrumReader = itk::ImageFileReader<IncidentSpectrumImageType>::New();\n  incidentSpectrumReader->SetFileName(argv[1]);\n  incidentSpectrumReader->Update();\n\n  auto detectorResponseReader = itk::ImageFileReader<DetectorResponseImageType>::New();\n  detectorResponseReader->SetFileName(argv[3]);\n  detectorResponseReader->Update();\n\n  auto materialAttenuationsReader = itk::ImageFileReader<MaterialAttenuationsImageType>::New();\n  materialAttenuationsReader->SetFileName(argv[4]);\n  materialAttenuationsReader->Update();\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 4;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 64;\n#endif\n\n  // Define the material concentrations\n  MaterialPixelType concentrations;\n  concentrations[0] = 0.002; // Iodine\n  concentrations[1] = 0.001; // Gadolinium\n  concentrations[2] = 1;     // Water\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<SingleComponentImageType>;\n\n  // Generate a blank volume\n  auto tomographySource = ConstantImageSourceType::New();\n#if FAST_TESTS_NO_CHECKS\n  auto origin = itk::MakePoint(-64., -64., -64.);\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(128., 128., 128.);\n#else\n  auto origin = itk::MakePoint(-124., -124., -124.);\n  auto size = itk::MakeSize(32, 32, 32);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n  tomographySource->Update();\n\n  // Generate a blank set of material volumes\n  auto materialVolumeSource = rtk::ConstantImageSource<MaterialVolumeType>::New();\n  materialVolumeSource->SetInformationFromImage(tomographySource->GetOutput());\n  materialVolumeSource->SetConstant(itk::NumericTraits<MaterialPixelType>::ZeroValue());\n\n  // Generate a blank set of projections\n  auto projectionsSource = ConstantImageSourceType::New();\n#if FAST_TESTS_NO_CHECKS\n  origin = itk::MakePoint(-128., -128., 0.);\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(256., 256., 256.);\n#else\n  origin = itk::MakePoint(-240., -240., 0.);\n  size = itk::MakeSize(32, 64, NumberOfProjectionImages);\n  spacing = itk::MakeVector(16., 16., 16.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n  projectionsSource->Update();\n\n  // Create a vectorImage of blank photon counts\n  using vMeasuredProjectionsType = itk::VectorImage<DataType, Dimension>;\n  auto vMeasuredProjections = vMeasuredProjectionsType::New();\n  vMeasuredProjections->CopyInformation(projectionsSource->GetOutput());\n  vMeasuredProjections->SetVectorLength(nBins);\n  vMeasuredProjections->SetRegions(vMeasuredProjections->GetLargestPossibleRegion());\n  vMeasuredProjections->Allocate();\n  itk::VariableLengthVector<DataType> vZeros;\n  vZeros.SetSize(nBins);\n  vZeros.Fill(0);\n  vMeasuredProjections->FillBuffer(vZeros);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages);\n\n  // Create ellipsoid PROJECTIONS\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<SingleComponentImageType, SingleComponentImageType>;\n  REIType::Pointer rei;\n\n  rei = REIType::New();\n  rei->SetAngle(0.);\n  rei->SetCenter(itk::MakeVector(0., 0., 0.));\n  rei->SetAxis(itk::MakeVector(90., 90., 90.));\n  rei->SetInput(projectionsSource->GetOutput());\n  rei->SetGeometry(geometry);\n\n  // Create reference volume (3D ellipsoid).\n  auto dsl = rtk::DrawEllipsoidImageFilter<SingleComponentImageType, SingleComponentImageType>::New();\n  dsl->SetInput(tomographySource->GetOutput());\n\n  // Generate one set of projections and one reference volume per material, and assemble them\n  SingleComponentImageType::Pointer projs[nMaterials];\n  SingleComponentImageType::Pointer vols[nMaterials];\n  auto                              composeProjs = itk::ComposeImageFilter<SingleComponentImageType>::New();\n  auto composeVols = itk::ComposeImageFilter<SingleComponentImageType, MaterialVolumeType>::New();\n  for (unsigned int mat = 0; mat < nMaterials; mat++)\n  {\n    rei->SetDensity(concentrations[mat]);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(rei->Update());\n    projs[mat] = rei->GetOutput();\n    projs[mat]->DisconnectPipeline();\n    composeProjs->SetInput(mat, projs[mat]);\n\n    dsl->SetDensity(concentrations[mat]);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(dsl->Update());\n    vols[mat] = dsl->GetOutput();\n    vols[mat]->DisconnectPipeline();\n    composeVols->SetInput(mat, vols[mat]);\n  }\n  composeProjs->Update();\n  composeVols->Update();\n\n  // Apply spectral forward model to turn material projections into photon counts\n  auto forward = rtk::SpectralForwardModelImageFilter<itk::VectorImage<DataType, Dimension>,\n                                                      vMeasuredProjectionsType,\n                                                      IncidentSpectrumImageType>::New();\n  forward->SetInputDecomposedProjections(composeProjs->GetOutput());\n  forward->SetInputMeasuredProjections(vMeasuredProjections);\n  forward->SetInputIncidentSpectrum(incidentSpectrumReader->GetOutput());\n  forward->SetDetectorResponse(detectorResponseReader->GetOutput());\n  forward->SetMaterialAttenuations(materialAttenuationsReader->GetOutput());\n  itk::VariableLengthVector<double> thresholds;\n  thresholds.SetSize(nBins + 1);\n  thresholds[0] = 25;\n  thresholds[1] = 40;\n  thresholds[2] = 55;\n  thresholds[3] = 70;\n  thresholds[4] = 85;\n  thresholds[5] = detectorResponseReader->GetOutput()->GetLargestPossibleRegion().GetSize()[1];\n  forward->SetThresholds(thresholds);\n  forward->SetIsSpectralCT(true);\n  forward->Update();\n\n  // Convert the itk::VectorImage<> returned by \"forward\" into\n  // an itk::Image<itk::Vector<>>\n  auto castMeasuredProjections = CastMeasuredProjectionsFilterType::New();\n  castMeasuredProjections->SetInput(forward->GetOutput());\n\n  // Read the material attenuations image as a matrix\n  MaterialAttenuationsImageType::IndexType indexMat;\n  vnl_matrix<DataType>                     materialAttenuationsMatrix(nEnergies, nMaterials);\n  for (unsigned int energy = 0; energy < nEnergies; energy++)\n  {\n    indexMat[1] = energy;\n    for (unsigned int material = 0; material < nMaterials; material++)\n    {\n      indexMat[0] = material;\n      materialAttenuationsMatrix[energy][material] = materialAttenuationsReader->GetOutput()->GetPixel(indexMat);\n    }\n  }\n\n  // Read the detector response image as a matrix, and bin it\n  vnl_matrix<DataType> drm =\n    rtk::SpectralBinDetectorResponse<DataType>(detectorResponseReader->GetOutput(), thresholds, nEnergies);\n\n  // Reconstruct using Mechlem\n  using MechlemType = rtk::\n    MechlemOneStepSpectralReconstructionFilter<MaterialVolumeType, MeasuredProjectionsType, IncidentSpectrumImageType>;\n  auto mechlemOneStep = MechlemType::New();\n  mechlemOneStep->SetForwardProjectionFilter(MechlemType::FP_JOSEPH); // Joseph\n  mechlemOneStep->SetInputMaterialVolumes(materialVolumeSource->GetOutput());\n  mechlemOneStep->SetInputMeasuredProjections(castMeasuredProjections->GetOutput());\n  mechlemOneStep->SetInputIncidentSpectrum(incidentSpectrumReader->GetOutput());\n  mechlemOneStep->SetBinnedDetectorResponse(drm);\n  mechlemOneStep->SetMaterialAttenuations(materialAttenuationsMatrix);\n  mechlemOneStep->SetGeometry(geometry);\n  mechlemOneStep->SetNumberOfIterations(20);\n\n  std::cout << \"\\n\\n****** Case 1: Joseph Backprojector ******\" << std::endl;\n\n  mechlemOneStep->SetBackProjectionFilter(MechlemType::BP_JOSEPH);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mechlemOneStep->Update());\n\n  CheckVectorImageQuality<MaterialVolumeType>(mechlemOneStep->GetOutput(), composeVols->GetOutput(), 0.08, 22, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: Voxel-based Backprojector ******\" << std::endl;\n\n  mechlemOneStep->SetBackProjectionFilter(MechlemType::BP_VOXELBASED);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mechlemOneStep->Update());\n\n  CheckVectorImageQuality<MaterialVolumeType>(mechlemOneStep->GetOutput(), composeVols->GetOutput(), 0.08, 22, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 3: Voxel-based Backprojector, 4 subsets, with regularization  ******\" << std::endl;\n\n  mechlemOneStep->SetBackProjectionFilter(MechlemType::BP_VOXELBASED);\n  mechlemOneStep->SetNumberOfSubsets(4);\n  mechlemOneStep->SetNumberOfIterations(5);\n  MaterialVolumeType::RegionType::SizeType radius;\n  radius.Fill(1);\n  MaterialVolumeType::PixelType weights;\n  weights.Fill(1);\n  mechlemOneStep->SetRegularizationRadius(radius);\n  mechlemOneStep->SetRegularizationWeights(weights);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mechlemOneStep->Update());\n\n  CheckVectorImageQuality<MaterialVolumeType>(mechlemOneStep->GetOutput(), composeVols->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n#ifdef RTK_USE_CUDA\n  std::cout << \"\\n\\n****** Case 4: CUDA voxel-based Backprojector, 4 subsets, with regularization ******\" << std::endl;\n\n  mechlemOneStep->SetForwardProjectionFilter(MechlemType::FP_CUDARAYCAST);\n  mechlemOneStep->SetBackProjectionFilter(MechlemType::BP_CUDAVOXELBASED);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mechlemOneStep->Update());\n\n  CheckVectorImageQuality<MaterialVolumeType>(mechlemOneStep->GetOutput(), composeVols->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n#ifdef RTK_USE_CUDA\n  std::cout\n    << \"\\n\\n****** Case 5: CUDA voxel-based Backprojector, 4 subsets, with regularization, itkVectorImage inputs ******\"\n    << std::endl;\n#else\n  std::cout\n    << \"\\n\\n****** Case 4: Voxel-based Backprojector, 4 subsets, with regularization, itkVectorImage inputs ******\"\n    << std::endl;\n#endif\n  // Add a cast to itkVectorImage, to test the overloaded SetInputMaterialVolumes method\n  auto castMaterials = itk::CastImageFilter<MaterialVolumeType, VectorImageType>::New();\n  castMaterials->SetInput(materialVolumeSource->GetOutput());\n  mechlemOneStep->SetInputMaterialVolumes(castMaterials->GetOutput());\n\n  // Remove the cast from itkVectorImage, to test the overloaded SetInputMeasuredProjections method\n  mechlemOneStep->SetInputMeasuredProjections(forward->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(mechlemOneStep->Update());\n\n  CheckVectorImageQuality<MaterialVolumeType>(mechlemOneStep->GetOutput(), composeVols->GetOutput(), 0.08, 23, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtktestexamples.py",
    "content": "import sys\nimport os\nimport itk\nimport pytest\nimport urllib.request\nimport runpy\nfrom pathlib import Path\n\n# Base examples directory\nEXAMPLES = Path(__file__).resolve().parent.parent / \"examples\"\n\ndef run_example(tmp_path, rel_script, *args):\n    script = EXAMPLES / rel_script\n    os.chdir(tmp_path)\n    sys.argv = [str(script), *map(str, args)]\n    runpy.run_path(str(script), run_name=\"__main__\")\n\n\n@pytest.fixture\ndef thorax_file(tmp_path):\n    url = \"https://raw.githubusercontent.com/RTKConsortium/Forbild/refs/heads/main/Thorax\"\n    thorax_path = tmp_path / \"Thorax\"\n    with urllib.request.urlopen(url) as response, open(thorax_path, \"wb\") as out_file:\n        out_file.write(response.read())\n    return thorax_path\n\n# This file wraps the example scripts as pytest tests executed in-process via runpy.\n# All outputs are written to a temporary directory using the tmp_path fixture.\nif hasattr(itk, \"CudaImage\"):\n    def test_FirstCudaReconstructionExample(tmp_path):\n        out_img = tmp_path / \"FirstCudaReconstruction.mha\"\n        out_geom = tmp_path / \"FirstCudaReconstruction.xml\"\n        run_example(tmp_path, \"FirstReconstruction/FirstCudaReconstruction.py\", out_img, out_geom)\n\ndef test_InlineReconstructionExample(tmp_path):\n    run_example(tmp_path, \"InlineReconstruction/InlineReconstruction.py\")\n\ndef test_AddNoiseExample(tmp_path):\n    run_example(tmp_path, \"AddNoise/AddNoise.py\")\n\ndef test_GeometricPhantomExample(tmp_path, thorax_file):\n    run_example(tmp_path, \"GeometricPhantom/GeometricPhantom.py\", thorax_file)\n\ndef test_FirstReconstructionExample(tmp_path):\n    out_img = tmp_path / \"FirstReconstruction.mha\"\n    out_geom = tmp_path / \"FirstReconstruction.xml\"\n    run_example(tmp_path, \"FirstReconstruction/FirstReconstruction.py\", out_img, out_geom)\n\ndef test_ConjugateGradient(tmp_path, thorax_file):\n    out_img = tmp_path / \"ConjugateGradient.mha\"\n    run_example(tmp_path, \"ConjugateGradient/ConjugateGradient.py\", thorax_file, out_img)"
  },
  {
    "path": "test/rtktotalvariationtest.cxx",
    "content": "#include \"itkRandomImageSource.h\"\n#include \"math.h\"\n\n#include \"rtkTotalVariationImageFilter.h\"\n#include \"rtkTotalVariationDenoisingBPDQImageFilter.h\"\n#include \"rtkMacro.h\"\n\ntemplate <class TImage>\nvoid\nCheckTotalVariation(typename TImage::Pointer before, typename TImage::Pointer after)\n{\n  auto tv = rtk::TotalVariationImageFilter<TImage>::New();\n\n  double totalVariationBefore = NAN;\n  double totalVariationAfter = NAN;\n\n  tv->SetInput(before);\n  tv->Update();\n  totalVariationBefore = tv->GetTotalVariation();\n  std::cout << \"Total variation before denoising is \" << totalVariationBefore << std::endl;\n\n  tv->SetInput(after);\n  tv->Update();\n  totalVariationAfter = tv->GetTotalVariation();\n  std::cout << \"Total variation after denoising is \" << totalVariationAfter << std::endl;\n\n  // Checking results\n  if (totalVariationBefore / 2 < totalVariationAfter)\n  {\n    std::cerr << \"Test Failed: total variation was not reduced enough\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n\n/**\n * \\file rtktotalvariationtest.cxx\n *\n * \\brief Tests whether the Total Variation denoising BPDQ filter indeed\n * reduces the total variation of a random image\n *\n * This test generates a random volume and performs TV denoising on this\n * volume. It measures its total variation before and after denoising and\n * compares. Note that the TV denoising filter does not minimize TV alone,\n * but TV + a data attachment term (it computes the proximal operator of TV).\n * Nevertheless, in most cases, it is expected that the output has\n * a lower TV than the input.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n  constexpr unsigned int Dimension = 3;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n  using GradientOutputImageType = itk::CudaImage<itk::CovariantVector<OutputPixelType, Dimension>, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n  using GradientOutputImageType = itk::Image<itk::CovariantVector<OutputPixelType, Dimension>, Dimension>;\n#endif\n\n  // Random image sources\n  auto randomVolumeSource = itk::RandomImageSource<OutputImageType>::New();\n\n  // Volume metadata\n  auto origin = itk::MakePoint(0., 0., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(64, 64, 1);\n  auto spacing = itk::MakeVector(1., 1., 1.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  randomVolumeSource->SetOrigin(origin);\n  randomVolumeSource->SetSpacing(spacing);\n  randomVolumeSource->SetSize(size);\n  randomVolumeSource->SetMin(0.);\n  randomVolumeSource->SetMax(1.);\n  randomVolumeSource->SetNumberOfWorkUnits(2); // With 1, it's deterministic\n\n  // Update the source\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource->Update());\n\n  // Create and set the TV denoising filter\n  auto TVdenoising = rtk::TotalVariationDenoisingBPDQImageFilter<OutputImageType, GradientOutputImageType>::New();\n  TVdenoising->SetInput(randomVolumeSource->GetOutput());\n  TVdenoising->SetNumberOfIterations(100);\n  TVdenoising->SetGamma(0.3);\n\n  bool dimsProcessed[Dimension];\n  for (bool & dimProcessed : dimsProcessed)\n  {\n    dimProcessed = true;\n  }\n  TVdenoising->SetDimensionsProcessed(dimsProcessed);\n\n  // Update the TV denoising filter\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(TVdenoising->Update());\n\n  CheckTotalVariation<OutputImageType>(randomVolumeSource->GetOutput(), TVdenoising->GetOutput());\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkvariancereconstructiontest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkAddImageFilter.h>\n#include <itkSquareImageFilter.h>\n#include <itkMultiplyImageFilter.h>\n\n#include \"rtkTestConfiguration.h\"\n#include \"rtkSheppLoganPhantomFilter.h\"\n#include \"rtkDrawSheppLoganFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"itkShotNoiseImageFilter.h\"\n#include \"rtkTest.h\"\n#include \"rtkFDKConeBeamReconstructionFilter.h\"\n#include \"rtkFDKVarianceReconstructionFilter.h\"\n\n/**\n * \\file rtkvariancereconstructiontest.cxx\n *\n * \\brief Functional test for the filter that reconstruct the variance map with FDK.\n *\n * This test generates a set of noisy projections of a Shepp-Logan phantom and\n * reconstruct them using FDK algorithm. Then, the variance of the reconstructed\n * images is computed and compared to the variance map obtain with the tested filter.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n  constexpr double hann = 1.0;\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n  constexpr unsigned int NumberOfSamples = 2;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 50;\n  constexpr unsigned int NumberOfSamples = 100;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-7.5, 0., -7.5);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(254., 254., 254.);\n#else\n  auto size = itk::MakeSize(16, 1, 16);\n  auto spacing = itk::MakeVector(1., 1., 1.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-7.5, -1., 0.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(2, 2, NumberOfProjectionImages);\n  spacing = itk::MakeVector(508., 508., 508.);\n#else\n  size = itk::MakeSize(16, 3, NumberOfProjectionImages);\n  spacing = itk::MakeVector(1., 1., 1.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  // Geometry object\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    geometry->AddProjection(600., 0., noProj * 360. / NumberOfProjectionImages);\n\n  // Shepp Logan projections filter\n  auto slp = rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType>::New();\n  slp->SetInput(projectionsSource->GetOutput());\n  slp->SetGeometry(geometry);\n  slp->SetPhantomScale(8.);\n  slp->InPlaceOff();\n\n  std::cout << \"\\n\\n****** Test : Create a set of noisy projections ******\" << std::endl;\n\n  // Add noise\n  auto noisy = itk::ShotNoiseImageFilter<OutputImageType>::New();\n  noisy->SetInput(slp->GetOutput());\n\n  using AddType = itk::AddImageFilter<OutputImageType, OutputImageType>;\n  auto add = AddType::New();\n  add->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(tomographySource->Update());\n  OutputImageType::Pointer currentSum = tomographySource->GetOutput();\n  currentSum->DisconnectPipeline();\n\n  auto square = itk::SquareImageFilter<OutputImageType, OutputImageType>::New();\n  auto addSquare = AddType::New();\n  addSquare->SetInput(1, square->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(tomographySource->Update());\n  OutputImageType::Pointer currentSumOfSquares = tomographySource->GetOutput();\n  currentSumOfSquares->DisconnectPipeline();\n\n  // FDK reconstruction\n  auto feldkamp = rtk::FDKConeBeamReconstructionFilter<OutputImageType>::New();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(tomographySource->Update());\n  feldkamp->SetInput(0, tomographySource->GetOutput());\n  feldkamp->SetInput(1, noisy->GetOutput());\n  feldkamp->SetGeometry(geometry);\n  feldkamp->GetRampFilter()->SetHannCutFrequency(hann);\n  add->SetInput(1, feldkamp->GetOutput());\n  square->SetInput(0, feldkamp->GetOutput());\n\n  for (unsigned int i = 0; i < NumberOfSamples; ++i)\n  {\n    // New realization\n    noisy->SetSeed(i);\n\n    // Update sum\n    add->SetInput(0, currentSum);\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(add->Update());\n    currentSum = add->GetOutput();\n    currentSum->DisconnectPipeline();\n\n    // Update sum of squared values\n    addSquare->SetInput(0, currentSumOfSquares);\n    addSquare->SetInput(1, square->GetOutput());\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(addSquare->Update());\n    currentSumOfSquares = addSquare->GetOutput();\n    currentSumOfSquares->DisconnectPipeline();\n  }\n\n  auto multiply = itk::MultiplyImageFilter<OutputImageType, OutputImageType>::New();\n  multiply->SetInput(0, currentSumOfSquares);\n  multiply->SetConstant((float)(1. / NumberOfSamples));\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(multiply->Update());\n  currentSumOfSquares = multiply->GetOutput();\n  currentSumOfSquares->DisconnectPipeline();\n  addSquare->SetInput(0, currentSumOfSquares);\n\n  currentSum->DisconnectPipeline();\n  square->SetInput(currentSum);\n  multiply->SetInput(0, square->GetOutput());\n  multiply->SetConstant((float)(-1. / (NumberOfSamples * NumberOfSamples)));\n  addSquare->SetInput(1, multiply->GetOutput());\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(addSquare->Update());\n\n  auto variance = rtk::FDKVarianceReconstructionFilter<OutputImageType, OutputImageType>::New();\n  variance->SetGeometry(geometry);\n  variance->SetInput(0, tomographySource->GetOutput());\n  variance->SetInput(1, slp->GetOutput());\n  variance->GetVarianceRampFilter()->SetHannCutFrequency(hann);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(variance->Update());\n\n  CheckImageQuality<OutputImageType>(addSquare->GetOutput(), variance->GetOutput(), 0.72, 22.4, 2.);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkvariantest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkMacro.h\"\n#include \"rtkVarianObiGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkVarianProBeamGeometryReader.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\n/**\n * \\file rtkvariantest.cxx\n *\n * \\brief Functional tests for classes managing Varian data\n *\n * This test reads a projection and the geometry of an acquisition from a\n * Varian acquisition and compares it to the expected results, which are\n * read from a baseline image in the MetaIO file format and a geometry file in\n * the RTK format, respectively.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 12)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"  projection.hnd acqui.xml\"\n              << \" ximFile.xim varianGeometry.xml\"\n              << \" projection.hnc\"\n              << \" reference.xml refGeometry.mha\"\n              << \" referenceXim.xml refGeometryXim.mha\"\n              << \" referenceHnc.xml refGeometryHnc.mha\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  std::vector<std::string> fileNames;\n  fileNames.emplace_back(argv[1]);\n\n  // Varian geometry\n  rtk::VarianObiGeometryReader::Pointer geoTargReader;\n  geoTargReader = rtk::VarianObiGeometryReader::New();\n  geoTargReader->SetXMLFileName(argv[2]);\n  geoTargReader->SetProjectionsFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader->UpdateOutputData());\n\n  // Reference geometry\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer geoRefReader;\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[6]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // 1. Check geometries\n  CheckGeometries(geoTargReader->GetGeometry(), geoRefReader->GetOutputObject());\n\n  // ******* COMPARING projections *******\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::Image<float, Dimension>;\n\n  // Varian projections reader\n  using ReaderType = rtk::ProjectionsReader<ImageType>;\n  auto reader = ReaderType::New();\n  reader->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update());\n\n  // Reference projections reader\n  auto readerRef = ReaderType::New();\n  fileNames.clear();\n  fileNames.emplace_back(argv[7]);\n  readerRef->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 1e-8, 100, 2.0);\n\n  ///////////////////// Xim file format\n  fileNames.clear();\n  fileNames.emplace_back(argv[3]);\n\n  // Varian geometry\n  rtk::VarianProBeamGeometryReader::Pointer geoProBeamReader;\n  geoProBeamReader = rtk::VarianProBeamGeometryReader::New();\n  geoProBeamReader->SetXMLFileName(argv[4]);\n  geoProBeamReader->SetProjectionsFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoProBeamReader->UpdateOutputData());\n\n  // Reference geometry\n  geoRefReader->SetFilename(argv[8]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // 1. Check geometries\n  CheckGeometries(geoProBeamReader->GetGeometry(), geoRefReader->GetOutputObject());\n\n  // ******* COMPARING projections *******\n  // Varian projections reader\n  reader->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update());\n\n  // Reference projections reader\n  fileNames.clear();\n  fileNames.emplace_back(argv[9]);\n  readerRef->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 1e-8, 100, 2.0);\n\n  ///////////////////// Hnc file format\n  fileNames.clear();\n  fileNames.emplace_back(argv[5]);\n\n  // Varian geometry\n  geoTargReader->SetProjectionsFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader->UpdateOutputData());\n\n  // Reference geometry\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[10]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // 1. Check geometries\n  CheckGeometries(geoTargReader->GetGeometry(), geoRefReader->GetOutputObject());\n\n  // ******* COMPARING projections *******\n\n  // Varian projections reader\n  reader->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->UpdateLargestPossibleRegion());\n\n  // Reference projections reader\n  fileNames.clear();\n  fileNames.emplace_back(argv[11]);\n  readerRef->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->UpdateLargestPossibleRegion());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 1e-8, 100, 2.0);\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkvectorimageconverterstest.cxx",
    "content": "#include <itksys/SystemTools.hxx>\n\n#include \"rtkTest.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkImageToVectorImageFilter.h\"\n#include \"rtkVectorImageToImageFilter.h\"\n\n#include <itkImageRegionIterator.h>\n\n/**\n * \\file rtkvectorimageconverterstest.cxx\n *\n * \\brief Test for the rtkImageToVectorImageFilter and the rtkVectorImageToImageFilter\n *\n * This code tests both behaviors of the ImageToVectorImage and VectorImageToImage filters:\n * - generates a 3D image and converts it to a 2D vector image,\n * then back to a 3D image\n * - generates a 2D image and converts it to a 2D vector image,\n * then back to a 2D image\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using PixelType = float;\n  using HigherDimensionImageType = itk::Image<PixelType, 3>;\n  using ImageType = itk::Image<PixelType, 2>;\n  using VectorImageType = itk::VectorImage<PixelType, 2>;\n\n  std::cout << \"\\n\\n****** Case 1: 3D image to 2D vector image, and back ******\" << std::endl;\n\n  // Initialize the first input image\n  auto                                 higherDimensionInput = HigherDimensionImageType::New();\n  HigherDimensionImageType::RegionType hregion;\n\n  auto hspacing = itk::MakeVector(1., 1., 1.);\n  auto hsize = itk::MakeSize(8, 8, 8);\n  hregion.SetSize(hsize);\n  higherDimensionInput->SetSpacing(hspacing);\n  higherDimensionInput->SetRegions(hregion);\n  higherDimensionInput->Allocate();\n\n  // Set each pixel's value to its position on the third dimension\n  HigherDimensionImageType::RegionType slice;\n  slice.SetSize(hsize);\n  slice.SetSize(2, 1);\n  for (unsigned int s = 0; s < hsize[2]; s++)\n  {\n    slice.SetIndex(2, s);\n    itk::ImageRegionIterator<HigherDimensionImageType> sliceIt(higherDimensionInput, slice);\n    while (!sliceIt.IsAtEnd())\n    {\n      sliceIt.Set(s);\n      ++sliceIt;\n    }\n  }\n\n  // Create the filter to convert it to a vector image\n  auto higherDimensionToVector = rtk::ImageToVectorImageFilter<HigherDimensionImageType, VectorImageType>::New();\n  higherDimensionToVector->SetInput(higherDimensionInput);\n\n  // Perform conversion\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(higherDimensionToVector->Update());\n\n  // Create a reference vector image, equal to the expected output of higherDimensionToVector, and perform the\n  // comparison\n  auto refVectorImage = VectorImageType::New();\n\n  VectorImageType::SizeType    refVectorSize;\n  VectorImageType::IndexType   refVectorIndex;\n  VectorImageType::SpacingType refVectorSpacing;\n  VectorImageType::RegionType  refVectorRegion;\n\n  refVectorIndex.Fill(0);\n  refVectorSpacing.Fill(1);\n  refVectorSize[0] = hsize[0];\n  refVectorSize[1] = hsize[1];\n  refVectorRegion.SetSize(refVectorSize);\n  refVectorRegion.SetIndex(refVectorIndex);\n  refVectorImage->SetSpacing(refVectorSpacing);\n  refVectorImage->SetRegions(refVectorRegion);\n  refVectorImage->SetVectorLength(hsize[2]);\n  refVectorImage->Allocate();\n\n  // Construct a vector to fill refVectorImage\n  itk::VariableLengthVector<PixelType> vector;\n  vector.SetSize(hsize[2]);\n  for (unsigned int i = 0; i < hsize[2]; i++)\n    vector[i] = i;\n  itk::ImageRegionIterator<VectorImageType> vecIt(refVectorImage, refVectorRegion);\n  while (!vecIt.IsAtEnd())\n  {\n    vecIt.Set(vector);\n    ++vecIt;\n  }\n\n  // Perform comparison\n  CheckVariableLengthVectorImageQuality<VectorImageType>(\n    higherDimensionToVector->GetOutput(), refVectorImage, 1e-7, 100, 2.0);\n\n  // Create the filter to convert the result back to an image\n  auto vectorToHigherDimension = rtk::VectorImageToImageFilter<VectorImageType, HigherDimensionImageType>::New();\n  vectorToHigherDimension->SetInput(higherDimensionToVector->GetOutput());\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(vectorToHigherDimension->Update());\n\n  // Compare with the initial image\n  CheckImageQuality<HigherDimensionImageType>(\n    vectorToHigherDimension->GetOutput(), higherDimensionInput, 1e-7, 100, 2.0);\n\n  std::cout << \"\\n\\n****** Case 2: 2D image to 2D vector image, and back ******\" << std::endl;\n\n  // Initialize the first input image\n  auto                  input = ImageType::New();\n  ImageType::RegionType region;\n\n  auto spacing = itk::MakeVector(1., 1.);\n  auto size = itk::MakeSize(8, 64);\n  region.SetSize(size);\n  input->SetSpacing(spacing);\n  input->SetRegions(region);\n  input->Allocate();\n\n  // Set each pixel's value to its position on the third dimension\n  ImageType::RegionType block;\n  block.SetSize(size);\n  block.SetSize(1, 8);\n  for (unsigned int b = 0; b < 8; b++)\n  {\n    block.SetIndex(1, 8 * b);\n    itk::ImageRegionIterator<ImageType> blockIt(input, block);\n    while (!blockIt.IsAtEnd())\n    {\n      blockIt.Set(b);\n      ++blockIt;\n    }\n  }\n\n  // Create the filter to convert it to a vector image\n  auto imageToVector = rtk::ImageToVectorImageFilter<ImageType, VectorImageType>::New();\n  imageToVector->SetInput(input);\n  imageToVector->SetNumberOfChannels(8);\n\n  // Perform conversion\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(imageToVector->Update());\n\n  // Perform comparison\n  CheckVariableLengthVectorImageQuality<VectorImageType>(imageToVector->GetOutput(), refVectorImage, 1e-7, 100, 2.0);\n\n  // Create the filter to convert the result back to an image\n  auto vectorToImage = rtk::VectorImageToImageFilter<VectorImageType, ImageType>::New();\n  vectorToImage->SetInput(imageToVector->GetOutput());\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(vectorToImage->Update());\n\n  // Compare with the initial image\n  CheckImageQuality<ImageType>(vectorToImage->GetOutput(), input, 1e-7, 100, 2.0);\n\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkwarpfourdtoprojectionstacktest.cxx",
    "content": "#include <itkPasteImageFilter.h>\n#include <itksys/SystemTools.hxx>\n#include <itkJoinSeriesImageFilter.h>\n\n#include \"rtkTest.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n#include \"rtkWarpFourDToProjectionStackImageFilter.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n#include \"rtkGeneralPurposeFunctions.h\"\n\n/**\n * \\file rtkwarpfourdtoprojectionstacktest.cxx\n *\n * \\brief Functional test for classes performing motion-compensated\n * forward projection combining warping and forward projection\n *\n * This test generates the projections of a phantom, which consists of two\n * ellipsoids (one of them moving). The resulting moving phantom is\n * forward projected, each ray following a trajectory that matches the motion\n * The result is compared to the expected results (analytical computation).\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n\n  using DVFVectorType = itk::CovariantVector<OutputPixelType, 3>;\n\n#ifdef USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n  using VolumeType = itk::CudaImage<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n  using VolumeType = itk::Image<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 5;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 64;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<VolumeType>;\n\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-63.0, -31.0, -63.0);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(8, 8, 8);\n  auto spacing = itk::MakeVector(16., 8., 16.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(2., 1., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto fourdSource = rtk::ConstantImageSource<VolumeSeriesType>::New();\n  auto fourDOrigin = itk::MakePoint(-63.0, -31.5, -63.0, 0.0);\n#if FAST_TESTS_NO_CHECKS\n  auto fourDSize = itk::MakeSize(8, 8, 8, 2);\n  auto fourDSpacing = itk::MakeVector(16., 8., 16., 1.);\n#else\n  auto fourDSize = itk::MakeSize(64, 64, 64, 8);\n  auto fourDSpacing = itk::MakeVector(2., 1., 2., 1.);\n#endif\n  fourdSource->SetOrigin(fourDOrigin);\n  fourdSource->SetSpacing(fourDSpacing);\n  fourdSource->SetSize(fourDSize);\n  fourdSource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(32, 32, NumberOfProjectionImages);\n  spacing = itk::MakeVector(32., 32., 32.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 1.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  auto oneProjectionSource = ConstantImageSourceType::New();\n  size[2] = 1;\n  oneProjectionSource->SetOrigin(origin);\n  oneProjectionSource->SetSpacing(spacing);\n  oneProjectionSource->SetSize(size);\n  oneProjectionSource->SetConstant(0.);\n\n  // Geometry object\n  using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n  auto geometry = GeometryType::New();\n\n  // Projections\n  using REIType = rtk::RayEllipsoidIntersectionImageFilter<VolumeType, ProjectionStackType>;\n  using PasteImageFilterType = itk::PasteImageFilter<ProjectionStackType, ProjectionStackType, ProjectionStackType>;\n  ProjectionStackType::IndexType destinationIndex;\n  destinationIndex[0] = 0;\n  destinationIndex[1] = 0;\n  destinationIndex[2] = 0;\n\n  auto pasteFilter = PasteImageFilterType::New();\n  pasteFilter->SetDestinationImage(projectionsSource->GetOutput());\n\n  auto pasteFilterStaticProjections = PasteImageFilterType::New();\n  pasteFilterStaticProjections->SetDestinationImage(projectionsSource->GetOutput());\n\n#ifdef USE_CUDA\n  std::string signalFileName = \"signal_bw_cuda.txt\";\n#else\n  std::string signalFileName = \"signal_bw.txt\";\n#endif\n\n  std::ofstream signalFile(signalFileName.c_str());\n  for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n  {\n    geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Geometry object\n    auto oneProjGeometry = GeometryType::New();\n    oneProjGeometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n    // Ellipse 1\n    auto e1 = REIType::New();\n    auto semiprincipalaxis = itk::MakeVector(60., 30., 60.);\n    auto center = itk::MakeVector(0., 0., 0.);\n    e1->SetInput(oneProjectionSource->GetOutput());\n    e1->SetGeometry(oneProjGeometry);\n    e1->SetDensity(1.);\n    e1->SetAxis(semiprincipalaxis);\n    e1->SetCenter(center);\n    e1->SetAngle(0.);\n    e1->InPlaceOff();\n    e1->Update();\n\n    // Ellipse 2\n    auto e2 = REIType::New();\n    semiprincipalaxis.Fill(8.);\n    center[0] = 4 * (itk::Math::abs((4 + noProj) % 8 - 4.) - 2.);\n    e2->SetInput(e1->GetOutput());\n    e2->SetGeometry(oneProjGeometry);\n    e2->SetDensity(-1.);\n    e2->SetAxis(semiprincipalaxis);\n    e2->SetCenter(center);\n    e2->SetAngle(0.);\n    e2->Update();\n\n    // Ellipse 2 without motion\n    auto e2static = REIType::New();\n    center[0] = 0;\n    e2static->SetInput(e1->GetOutput());\n    e2static->SetGeometry(oneProjGeometry);\n    e2static->SetDensity(-1.);\n    e2static->SetAxis(semiprincipalaxis);\n    e2static->SetCenter(center);\n    e2static->SetAngle(0.);\n    e2static->Update();\n\n    // Adding each projection to the projection stacks\n    if (noProj > 0) // After the first projection, we use the output as input\n    {\n      ProjectionStackType::Pointer wholeImage = pasteFilter->GetOutput();\n      wholeImage->DisconnectPipeline();\n      pasteFilter->SetDestinationImage(wholeImage);\n\n      ProjectionStackType::Pointer wholeImageStatic = pasteFilterStaticProjections->GetOutput();\n      wholeImageStatic->DisconnectPipeline();\n      pasteFilterStaticProjections->SetDestinationImage(wholeImageStatic);\n    }\n    pasteFilter->SetSourceImage(e2->GetOutput());\n    pasteFilter->SetSourceRegion(e2->GetOutput()->GetLargestPossibleRegion());\n    pasteFilter->SetDestinationIndex(destinationIndex);\n    pasteFilter->UpdateLargestPossibleRegion();\n\n    pasteFilterStaticProjections->SetSourceImage(e2static->GetOutput());\n    pasteFilterStaticProjections->SetSourceRegion(e2static->GetOutput()->GetLargestPossibleRegion());\n    pasteFilterStaticProjections->SetDestinationIndex(destinationIndex);\n    pasteFilterStaticProjections->UpdateLargestPossibleRegion();\n\n    destinationIndex[2]++;\n\n    // Signal\n    signalFile << (noProj % 8) / 8. << std::endl;\n  }\n  signalFile.close();\n\n  // Create a vector field and its (very rough) inverse\n  using IteratorType = itk::ImageRegionIteratorWithIndex<DVFSequenceImageType>;\n\n  auto deformationField = DVFSequenceImageType::New();\n  auto inverseDeformationField = DVFSequenceImageType::New();\n\n  auto sizeMotion = itk::MakeSize(fourDSize[0], fourDSize[1], fourDSize[2], 2);\n  auto originMotion = itk::MakePoint(-63., -31., -63., 0.);\n  auto spacingMotion = itk::MakeVector(fourDSpacing[0], fourDSpacing[1], fourDSpacing[2], fourDSpacing[3]);\n  DVFSequenceImageType::RegionType regionMotion;\n  regionMotion.SetSize(sizeMotion);\n\n  deformationField->SetRegions(regionMotion);\n  deformationField->SetOrigin(originMotion);\n  deformationField->SetSpacing(spacingMotion);\n  deformationField->Allocate();\n\n  inverseDeformationField->SetRegions(regionMotion);\n  inverseDeformationField->SetOrigin(originMotion);\n  inverseDeformationField->SetSpacing(spacingMotion);\n  inverseDeformationField->Allocate();\n\n  // Vector Field initilization\n  DVFVectorType vec;\n  IteratorType  dvfIt(deformationField, deformationField->GetLargestPossibleRegion());\n  IteratorType  idvfIt(inverseDeformationField, inverseDeformationField->GetLargestPossibleRegion());\n\n  DVFSequenceImageType::OffsetType DVFCenter;\n  DVFSequenceImageType::IndexType  toCenter;\n  DVFCenter.Fill(0);\n  DVFCenter[0] = sizeMotion[0] / 2;\n  DVFCenter[1] = sizeMotion[1] / 2;\n  DVFCenter[2] = sizeMotion[2] / 2;\n  while (!dvfIt.IsAtEnd())\n  {\n    vec.Fill(0.);\n    toCenter = dvfIt.GetIndex() - DVFCenter;\n\n    if (0.3 * toCenter[0] * toCenter[0] + 0.5 * toCenter[1] * toCenter[1] + 0.5 * toCenter[2] * toCenter[2] < 40)\n    {\n      if (dvfIt.GetIndex()[3] == 0)\n        vec[0] = -8.;\n      else\n        vec[0] = 8.;\n    }\n    dvfIt.Set(vec);\n    idvfIt.Set(-vec);\n\n    ++dvfIt;\n    ++idvfIt;\n  }\n\n  // Input 4D volume sequence\n  auto * Volumes = new VolumeType::Pointer[fourDSize[3]];\n  auto   join = itk::JoinSeriesImageFilter<VolumeType, VolumeSeriesType>::New();\n\n  for (itk::SizeValueType n = 0; n < fourDSize[3]; n++)\n  {\n    // Ellipse 1\n    using DEType = rtk::DrawEllipsoidImageFilter<VolumeType, VolumeType>;\n    auto de1 = DEType::New();\n    de1->SetInput(tomographySource->GetOutput());\n    de1->SetDensity(1.);\n    DEType::VectorType axis;\n    axis.Fill(60.);\n    axis[1] = 30;\n    de1->SetAxis(axis);\n    DEType::VectorType center;\n    center.Fill(0.);\n    de1->SetCenter(center);\n    de1->SetAngle(0.);\n    de1->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(de1->Update())\n\n    // Ellipse 2\n    auto de2 = DEType::New();\n    de2->SetInput(de1->GetOutput());\n    de2->SetDensity(-1.);\n    DEType::VectorType axis2;\n    axis2.Fill(8.);\n    de2->SetAxis(axis2);\n    DEType::VectorType center2;\n    center2[0] = 4 * (itk::Math::abs((4 + n) % 8 - 4.) - 2.);\n    center2[1] = 0.;\n    center2[2] = 0.;\n    de2->SetCenter(center2);\n    de2->SetAngle(0.);\n    de2->InPlaceOff();\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(de2->Update());\n\n    Volumes[n] = de2->GetOutput();\n    Volumes[n]->DisconnectPipeline();\n    join->SetInput(n, Volumes[n]);\n  }\n  join->Update();\n\n  // Read the phases file\n  auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n  phaseReader->SetFileName(signalFileName);\n  phaseReader->SetNumberOfReconstructedFrames(fourDSize[3]);\n  phaseReader->Update();\n\n  // Create and set the warped forward projection filter\n  auto warpforwardproject = rtk::WarpFourDToProjectionStackImageFilter<VolumeSeriesType, VolumeType>::New();\n  warpforwardproject->SetInputVolumeSeries(join->GetOutput());\n  warpforwardproject->SetInputProjectionStack(pasteFilter->GetOutput());\n  warpforwardproject->SetGeometry(geometry);\n  warpforwardproject->SetDisplacementField(deformationField);\n  warpforwardproject->SetWeights(phaseReader->GetOutput());\n  warpforwardproject->SetSignal(rtk::ReadSignalFile(signalFileName));\n\n#ifndef USE_CUDA\n  std::cout\n    << \"\\n\\n****** Case 1: Non-warped joseph forward projection (warped forward projection exists only in CUDA) ******\"\n    << std::endl;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(warpforwardproject->Update());\n\n  // The warpforwardproject filter doesn't really need the data in pasteFilter->GetOutput().\n  // During the update, its requested region is set to empty, and its buffered region follows.\n  // To perform the CheckImageQuality, we need to recompute the data\n  pasteFilter->UpdateLargestPossibleRegion();\n\n  CheckImageQuality<ProjectionStackType>(warpforwardproject->GetOutput(), pasteFilter->GetOutput(), 0.25, 14, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n#ifdef USE_CUDA\n  std::cout << \"\\n\\n****** Case 2: CUDA warped forward projection ******\" << std::endl;\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(warpforwardproject->Update());\n  CheckImageQuality<ProjectionStackType>(\n    warpforwardproject->GetOutput(), pasteFilterStaticProjections->GetOutput(), 0.25, 14, 2.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n  itksys::SystemTools::RemoveFile(signalFileName.c_str());\n  delete[] Volumes;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkwarpprojectionstacktofourdtest.cxx",
    "content": "#include <itkPasteImageFilter.h>\n#include <itksys/SystemTools.hxx>\n#include <itkJoinSeriesImageFilter.h>\n#include <itkDivideImageFilter.h>\n\n#include \"rtkTest.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkFieldOfViewImageFilter.h\"\n#include \"rtkWarpProjectionStackToFourDImageFilter.h\"\n#include \"rtkPhasesToInterpolationWeights.h\"\n#include \"rtkBackProjectionImageFilter.h\"\n\n/**\n * \\file rtkwarpprojectionstacktofourdtest.cxx\n *\n * \\brief Functional test for classes performing motion-compensated\n * back projection combining warping and back projection\n *\n * This test generates the projections of a phantom, which consists of two\n * ellipsoids (one of them moving). The resulting moving phantom is\n * back projected, each ray following a trajectory that matches the motion\n * The result is compared to the CPU voxel based back projection of the static object.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  using OutputPixelType = float;\n\n  using DVFVectorType = itk::CovariantVector<OutputPixelType, 3>;\n\n#ifdef USE_CUDA\n  using VolumeSeriesType = itk::CudaImage<OutputPixelType, 4>;\n  using ProjectionStackType = itk::CudaImage<OutputPixelType, 3>;\n  using VolumeType = itk::CudaImage<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::CudaImage<DVFVectorType, VolumeSeriesType::ImageDimension>;\n#else\n  using VolumeSeriesType = itk::Image<OutputPixelType, 4>;\n  using ProjectionStackType = itk::Image<OutputPixelType, 3>;\n  using VolumeType = itk::Image<OutputPixelType, 3>;\n  using DVFSequenceImageType = itk::Image<DVFVectorType, VolumeSeriesType::ImageDimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 5;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 64;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<VolumeType>;\n\n  auto tomographySource = ConstantImageSourceType::New();\n  auto origin = itk::MakePoint(-63., -31., -63.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(8, 8, 8);\n  auto spacing = itk::MakeVector(16., 8., 16.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(2., 1., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto fourdSource = rtk::ConstantImageSource<VolumeSeriesType>::New();\n  auto fourDOrigin = itk::MakePoint(-63., -31.5, -63., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto fourDSize = itk::MakeSize(8, 8, 8, 2);\n  auto fourDSpacing = itk::MakeVector(16., 8., 16., 1.);\n#else\n  auto fourDSize = itk::MakeSize(64, 64, 64, 8);\n  auto fourDSpacing = itk::MakeVector(2., 1., 2., 1.);\n#endif\n  fourdSource->SetOrigin(fourDOrigin);\n  fourdSource->SetSpacing(fourDSpacing);\n  fourdSource->SetSize(fourDSize);\n  fourdSource->SetConstant(0.);\n\n  auto projectionsSource = ConstantImageSourceType::New();\n  origin = itk::MakePoint(-254., -254., -254.);\n#if FAST_TESTS_NO_CHECKS\n  size = itk::MakeSize(32, 32, NumberOfProjectionImages);\n  spacing = itk::MakeVector(32., 32., 32.);\n#else\n  size = itk::MakeSize(128, 128, NumberOfProjectionImages);\n  spacing = itk::MakeVector(4., 4., 1.);\n#endif\n  projectionsSource->SetOrigin(origin);\n  projectionsSource->SetSpacing(spacing);\n  projectionsSource->SetSize(size);\n  projectionsSource->SetConstant(0.);\n\n  auto oneProjectionSource = ConstantImageSourceType::New();\n  size[2] = 1;\n  oneProjectionSource->SetOrigin(origin);\n  oneProjectionSource->SetSpacing(spacing);\n  oneProjectionSource->SetSize(size);\n  oneProjectionSource->SetConstant(0.);\n\n  for (double radius = 0; radius < 2; radius++)\n  {\n    // Geometry object\n    using GeometryType = rtk::ThreeDCircularProjectionGeometry;\n    auto geometry = GeometryType::New();\n\n    // Projections\n    using REIType = rtk::RayEllipsoidIntersectionImageFilter<VolumeType, ProjectionStackType>;\n    using PasteImageFilterType = itk::PasteImageFilter<ProjectionStackType, ProjectionStackType, ProjectionStackType>;\n    auto destinationIndex = itk::MakeIndex(0, 0, 0);\n\n    auto pasteFilter = PasteImageFilterType::New();\n    pasteFilter->SetDestinationImage(projectionsSource->GetOutput());\n\n    auto pasteFilterStaticProjections = PasteImageFilterType::New();\n    pasteFilterStaticProjections->SetDestinationImage(projectionsSource->GetOutput());\n\n#ifdef USE_CUDA\n    std::string signalFileName = \"signal_fw_cuda.txt\";\n#else\n    std::string signalFileName = \"signal_fw.txt\";\n#endif\n\n    std::ofstream signalFile(signalFileName.c_str());\n\n    for (unsigned int noProj = 0; noProj < NumberOfProjectionImages; noProj++)\n    {\n      geometry->SetRadiusCylindricalDetector(radius * 1200.);\n      geometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n      // Geometry object\n      auto oneProjGeometry = GeometryType::New();\n      oneProjGeometry->AddProjection(600., 1200., noProj * 360. / NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);\n\n      // Ellipse 1\n      auto e1 = REIType::New();\n      auto semiprincipalaxis = itk::MakeVector(60., 30., 60.);\n      auto center = itk::MakeVector(0., 0., 0.);\n      e1->SetInput(oneProjectionSource->GetOutput());\n      e1->SetGeometry(oneProjGeometry);\n      e1->SetDensity(1.);\n      e1->SetAxis(semiprincipalaxis);\n      e1->SetCenter(center);\n      e1->SetAngle(0.);\n      e1->InPlaceOff();\n      e1->Update();\n\n      // Ellipse 2\n      auto e2 = REIType::New();\n      semiprincipalaxis.Fill(8.);\n      center[0] = 4 * (itk::Math::abs((4 + noProj) % 8 - 4.) - 2.);\n      e2->SetInput(e1->GetOutput());\n      e2->SetGeometry(oneProjGeometry);\n      e2->SetDensity(-1.);\n      e2->SetAxis(semiprincipalaxis);\n      e2->SetCenter(center);\n      e2->SetAngle(0.);\n      e2->Update();\n\n      // Ellipse 2 without motion\n      auto e2static = REIType::New();\n      center[0] = 0;\n      e2static->SetInput(e1->GetOutput());\n      e2static->SetGeometry(oneProjGeometry);\n      e2static->SetDensity(-1.);\n      e2static->SetAxis(semiprincipalaxis);\n      e2static->SetCenter(center);\n      e2static->SetAngle(0.);\n      e2static->Update();\n\n      // Adding each projection to the projection stacks\n      if (noProj > 0) // After the first projection, we use the output as input\n      {\n        ProjectionStackType::Pointer wholeImage = pasteFilter->GetOutput();\n        wholeImage->DisconnectPipeline();\n        pasteFilter->SetDestinationImage(wholeImage);\n\n        ProjectionStackType::Pointer wholeImageStatic = pasteFilterStaticProjections->GetOutput();\n        wholeImageStatic->DisconnectPipeline();\n        pasteFilterStaticProjections->SetDestinationImage(wholeImageStatic);\n      }\n      pasteFilter->SetSourceImage(e2->GetOutput());\n      pasteFilter->SetSourceRegion(e2->GetOutput()->GetLargestPossibleRegion());\n      pasteFilter->SetDestinationIndex(destinationIndex);\n      pasteFilter->UpdateLargestPossibleRegion();\n\n      pasteFilterStaticProjections->SetSourceImage(e2static->GetOutput());\n      pasteFilterStaticProjections->SetSourceRegion(e2static->GetOutput()->GetLargestPossibleRegion());\n      pasteFilterStaticProjections->SetDestinationIndex(destinationIndex);\n      pasteFilterStaticProjections->UpdateLargestPossibleRegion();\n\n      destinationIndex[2]++;\n\n      // Signal\n      signalFile << (noProj % 8) / 8. << std::endl;\n    }\n    signalFile.close();\n\n    // Create a vector field and its (very rough) inverse\n    using IteratorType = itk::ImageRegionIteratorWithIndex<DVFSequenceImageType>;\n\n    auto deformationField = DVFSequenceImageType::New();\n    auto inverseDeformationField = DVFSequenceImageType::New();\n\n    auto sizeMotion = itk::MakeSize(fourDSize[0], fourDSize[1], fourDSize[2], 2);\n    auto originMotion = itk::MakePoint(-63., -31., -63., 0.);\n    auto spacingMotion = itk::MakeVector(fourDSpacing[0], fourDSpacing[1], fourDSpacing[2], fourDSpacing[3]);\n    DVFSequenceImageType::RegionType regionMotion;\n    regionMotion.SetSize(sizeMotion);\n\n    deformationField->SetRegions(regionMotion);\n    deformationField->SetOrigin(originMotion);\n    deformationField->SetSpacing(spacingMotion);\n    deformationField->Allocate();\n\n    inverseDeformationField->SetRegions(regionMotion);\n    inverseDeformationField->SetOrigin(originMotion);\n    inverseDeformationField->SetSpacing(spacingMotion);\n    inverseDeformationField->Allocate();\n\n    // Vector Field initilization\n    DVFVectorType vec;\n    IteratorType  dvfIt(deformationField, deformationField->GetLargestPossibleRegion());\n    IteratorType  idvfIt(inverseDeformationField, inverseDeformationField->GetLargestPossibleRegion());\n\n    DVFSequenceImageType::OffsetType DVFCenter;\n    DVFSequenceImageType::IndexType  toCenter;\n    DVFCenter.Fill(0);\n    DVFCenter[0] = sizeMotion[0] / 2;\n    DVFCenter[1] = sizeMotion[1] / 2;\n    DVFCenter[2] = sizeMotion[2] / 2;\n    while (!dvfIt.IsAtEnd())\n    {\n      vec.Fill(0.);\n      toCenter = dvfIt.GetIndex() - DVFCenter;\n\n      if (0.3 * toCenter[0] * toCenter[0] + 0.5 * toCenter[1] * toCenter[1] + 0.5 * toCenter[2] * toCenter[2] < 40)\n      {\n        if (dvfIt.GetIndex()[3] == 0)\n          vec[0] = -8.;\n        else\n          vec[0] = 8.;\n      }\n      dvfIt.Set(vec);\n      idvfIt.Set(-vec);\n\n      ++dvfIt;\n      ++idvfIt;\n    }\n\n    // Input 4D volume sequence\n    auto join = itk::JoinSeriesImageFilter<VolumeType, VolumeSeriesType>::New();\n\n    // Read the phases file\n    auto phaseReader = rtk::PhasesToInterpolationWeights::New();\n    phaseReader->SetFileName(signalFileName);\n    phaseReader->SetNumberOfReconstructedFrames(fourDSize[3]);\n    phaseReader->Update();\n\n    // The CPU voxel-based static 3D back projection used as a reference for comparison\n    auto backprojection = rtk::BackProjectionImageFilter<VolumeType, VolumeType>::New();\n    backprojection->SetInput(0, tomographySource->GetOutput());\n    backprojection->SetInput(1, pasteFilterStaticProjections->GetOutput());\n    backprojection->SetGeometry(geometry.GetPointer());\n    backprojection->Update();\n\n    // Divide the result by the number of volumes in the 4D sequence,\n    // for the attenuation results to approximately match\n    auto divide = itk::DivideImageFilter<VolumeType, VolumeType, VolumeType>::New();\n    divide->SetInput1(backprojection->GetOutput());\n    divide->SetConstant2(fourDSize[3]);\n    divide->Update();\n\n    // Concatenate n times the 3D reconstruction with itself to compare the result with\n    // the 4D output of warpbackproject\n    for (itk::SizeValueType n = 0; n < fourDSize[3]; n++)\n      join->SetInput(n, divide->GetOutput());\n    join->Update();\n\n    // Create and set the warped forward projection filter\n    auto warpbackproject = rtk::WarpProjectionStackToFourDImageFilter<VolumeSeriesType, VolumeType>::New();\n    warpbackproject->SetInputVolumeSeries(fourdSource->GetOutput());\n    warpbackproject->SetInputProjectionStack(pasteFilter->GetOutput());\n    warpbackproject->SetGeometry(geometry);\n    warpbackproject->SetDisplacementField(deformationField);\n    warpbackproject->SetWeights(phaseReader->GetOutput());\n    warpbackproject->SetSignal(rtk::ReadSignalFile(signalFileName));\n\n#ifndef USE_CUDA\n    std::cout << \"\\n\\n****** Case \" << 1 + 2 * radius\n              << \": Non-warped voxel based back projection (warped back projection exists only in CUDA) ******\"\n              << std::endl;\n    if (radius)\n      std::cout << \"\\n\\n****** Cylindrical detector ******\" << std::endl;\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(warpbackproject->Update());\n    CheckImageQuality<VolumeSeriesType>(warpbackproject->GetOutput(), join->GetOutput(), 15, 33, 800.0);\n    std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n#ifdef USE_CUDA\n    std::cout << \"\\n\\n****** Case \" << 2 + 2 * radius << \": CUDA warped back projection ******\" << std::endl;\n    if (radius)\n      std::cout << \"\\n\\n****** Cylindrical detector ******\" << std::endl;\n    TRY_AND_EXIT_ON_ITK_EXCEPTION(warpbackproject->Update());\n    CheckImageQuality<VolumeSeriesType>(warpbackproject->GetOutput(), join->GetOutput(), 15, 33, 800.0);\n    std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n#endif\n\n    itksys::SystemTools::RemoveFile(signalFileName.c_str());\n  }\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkwarptest.cxx",
    "content": "#include <itkPasteImageFilter.h>\n#include <itksys/SystemTools.hxx>\n\n#include \"rtkTest.h\"\n#include \"rtkRayEllipsoidIntersectionImageFilter.h\"\n#include \"rtkDrawEllipsoidImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkCyclicDeformationImageFilter.h\"\n#include \"rtkForwardWarpImageFilter.h\"\n\n#include <itkWarpImageFilter.h>\n\n/**\n * \\file rtkwarptest.cxx\n *\n * \\brief Test for the itkWarpImageFilter and the rtkForwardWarpImageFilter\n *\n * This test generates a phantom, which consists of two\n * ellipsoids, and a Displacement Vector Field (DVF). It warps the phantom\n * backward (using the itkWarpImageFilter and trilinear interpolation) and then\n * forward (using the rtkForwardWarpImageFilter and trilinear splat), and\n * compares the result to the original phantom\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Constant image sources\n  auto tomographySource = rtk::ConstantImageSource<OutputImageType>::New();\n  auto origin = itk::MakePoint(-63., -31., -63.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(32, 32, 32);\n  auto spacing = itk::MakeVector(8., 8., 8.);\n#else\n  auto size = itk::MakeSize(64, 32, 64);\n  auto spacing = itk::MakeVector(2., 2., 2.);\n#endif\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  // Create vector field\n  using DVFPixelType = itk::Vector<float, 3>;\n  using DVFImageType = itk::Image<DVFPixelType, 3>;\n\n  auto deformationField = DVFImageType::New();\n\n  auto                    sizeMotion = itk::MakeSize(64, 64, 64);\n  DVFImageType::PointType originMotion;\n  originMotion[0] = (sizeMotion[0] - 1) * (-0.5); // size along X\n  originMotion[1] = (sizeMotion[1] - 1) * (-0.5); // size along Y\n  originMotion[2] = (sizeMotion[2] - 1) * (-0.5); // size along Z\n  DVFImageType::RegionType regionMotion;\n  regionMotion.SetSize(sizeMotion);\n  deformationField->SetRegions(regionMotion);\n  deformationField->SetOrigin(originMotion);\n  deformationField->Allocate();\n\n  // Vector Field initilization\n  DVFPixelType vec;\n  vec.Fill(0.);\n  itk::ImageRegionIteratorWithIndex<DVFImageType> defIt(deformationField, deformationField->GetLargestPossibleRegion());\n  for (defIt.GoToBegin(); !defIt.IsAtEnd(); ++defIt)\n  {\n    vec.Fill(0.);\n    vec[0] = 8.;\n    defIt.Set(vec);\n  }\n\n  // Create a reference object (in this case a 3D phantom reference).\n  // Ellipse 1\n  using DEType = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>;\n  auto e1 = DEType::New();\n  e1->SetInput(tomographySource->GetOutput());\n  e1->SetDensity(2.);\n  DEType::VectorType axis;\n  axis.Fill(60.);\n  e1->SetAxis(axis);\n  DEType::VectorType center;\n  center.Fill(0.);\n  e1->SetCenter(center);\n  e1->SetAngle(0.);\n  e1->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(e1->Update())\n\n  // Ellipse 2\n  auto e2 = DEType::New();\n  e2->SetInput(e1->GetOutput());\n  e2->SetDensity(-1.);\n  DEType::VectorType axis2;\n  axis2.Fill(8.);\n  e2->SetAxis(axis2);\n  DEType::VectorType center2;\n  center2.Fill(0.);\n  e2->SetCenter(center2);\n  e2->SetAngle(0.);\n  e2->InPlaceOff();\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(e2->Update())\n\n  auto warp = itk::WarpImageFilter<OutputImageType, OutputImageType, DVFImageType>::New();\n  warp->SetInput(e2->GetOutput());\n  warp->SetDisplacementField(deformationField);\n  warp->SetOutputParametersFromImage(e2->GetOutput());\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(warp->Update());\n\n  auto forwardWarp = rtk::ForwardWarpImageFilter<OutputImageType, OutputImageType, DVFImageType>::New();\n  forwardWarp->SetInput(warp->GetOutput());\n  forwardWarp->SetDisplacementField(deformationField);\n  forwardWarp->SetOutputParametersFromImage(warp->GetOutput());\n\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(forwardWarp->Update());\n\n  CheckImageQuality<OutputImageType>(forwardWarp->GetOutput(), e2->GetOutput(), 0.1, 12, 2.0);\n\n  std::cout << \"Test PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkwaterprecorrectiontest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkConstantImageSource.h\"\n\n#include \"rtkWaterPrecorrectionImageFilter.h\"\n\n/**\n * \\file rtkwaterprecorrectiontest.cxx\n *\n * \\brief Functional test for the water precorrection class\n *\n * \\author S. Brousmiche\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 2;\n  using OutputImageType = itk::Image<float, Dimension>;\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n\n  // Create constant image of value 2 and reference image.\n  auto imgIn = ConstantImageSourceType::New();\n  auto imgRef = ConstantImageSourceType::New();\n\n  auto origin = itk::MakePoint(-126., -126.);\n  auto size = itk::MakeSize(16, 16);\n  auto spacing = itk::MakeVector(16., 16.);\n\n  imgIn->SetOrigin(origin);\n  imgIn->SetSpacing(spacing);\n  imgIn->SetSize(size);\n  imgIn->SetConstant(1.5);\n  // imgIn->UpdateOutputInformation();\n\n  imgRef->SetOrigin(origin);\n  imgRef->SetSpacing(spacing);\n  imgRef->SetSize(size);\n  imgRef->SetConstant(5.0);\n  imgRef->Update();\n\n  OutputImageType::Pointer output = imgIn->GetOutput();\n\n  std::cout << \"\\n\\n****** Case 1: order 2 ******\" << std::endl;\n\n  using WPCType = rtk::WaterPrecorrectionImageFilter<OutputImageType, OutputImageType>;\n  auto model2 = WPCType::New();\n\n  // Update median filter\n  WPCType::VectorType c1;\n  c1.push_back(2.0);\n  c1.push_back(2.0);\n  model2->SetInput(output);\n  model2->SetCoefficients(c1);\n  model2->Update();\n\n  CheckImageQuality<OutputImageType>(model2->GetOutput(), imgRef->GetOutput(), 1.8, 51, 1011.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 2: order 3 ******\" << std::endl;\n\n  auto                model3 = WPCType::New();\n  WPCType::VectorType c2;\n  c2.push_back(0.05);\n  c2.push_back(0.3);\n  c2.push_back(2.0);\n  model3->SetInput(imgIn->GetOutput());\n  model3->SetCoefficients(c2);\n  model3->Update();\n\n  CheckImageQuality<OutputImageType>(model3->GetOutput(), imgRef->GetOutput(), 1.8, 51, 1011.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  std::cout << \"\\n\\n****** Case 3: order 5 ******\" << std::endl;\n\n  auto model5 = WPCType::New();\n\n  WPCType::VectorType c3;\n  c3.push_back(0.0687);\n  c3.push_back(2.5);\n  c3.push_back(0.6);\n  c3.push_back(-0.2);\n  c3.push_back(0.1);\n  model5->SetInput(imgIn->GetOutput());\n  model5->SetCoefficients(c3);\n  model5->Update();\n\n  CheckImageQuality<OutputImageType>(model5->GetOutput(), imgRef->GetOutput(), 1.8, 51, 1011.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkwaveletstest.cxx",
    "content": "#include <itkImageRegionConstIterator.h>\n#include <itkRandomImageSource.h>\n\n#include \"rtkTestConfiguration.h\"\n#include \"rtkDeconstructSoftThresholdReconstructImageFilter.h\"\n#include \"rtkMacro.h\"\n\ntemplate <class TImage>\n#if FAST_TESTS_NO_CHECKS\nvoid\nCheckImageQuality(typename TImage::Pointer itkNotUsed(recon), typename TImage::Pointer itkNotUsed(ref))\n{}\n#else\nvoid\nCheckImageQuality(typename TImage::Pointer recon, typename TImage::Pointer ref)\n{\n  using ImageIteratorType = itk::ImageRegionConstIterator<TImage>;\n  ImageIteratorType itTest(recon, recon->GetBufferedRegion());\n  ImageIteratorType itRef(ref, ref->GetBufferedRegion());\n\n  using ErrorType = double;\n  ErrorType TestError = 0.;\n  ErrorType EnerError = 0.;\n\n  itTest.GoToBegin();\n  itRef.GoToBegin();\n\n  while (!itRef.IsAtEnd())\n  {\n    typename TImage::PixelType TestVal = itTest.Get();\n    typename TImage::PixelType RefVal = itRef.Get();\n    TestError += itk::Math::abs(RefVal - TestVal);\n    EnerError += std::pow(ErrorType(RefVal - TestVal), 2.);\n    ++itTest;\n    ++itRef;\n  }\n  // Error per Pixel\n  ErrorType ErrorPerPixel = TestError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"\\nError per Pixel = \" << ErrorPerPixel << std::endl;\n  // MSE\n  ErrorType MSE = EnerError / ref->GetBufferedRegion().GetNumberOfPixels();\n  std::cout << \"MSE = \" << MSE << std::endl;\n  // PSNR\n  ErrorType PSNR = 20 * log10(2.0) - 10 * log10(MSE);\n  std::cout << \"PSNR = \" << PSNR << \"dB\" << std::endl;\n  // QI\n  ErrorType QI = (2.0 - ErrorPerPixel) / 2.0;\n  std::cout << \"QI = \" << QI << std::endl;\n\n  // Checking results\n  if (ErrorPerPixel > 0.032)\n  {\n    std::cerr << \"Test Failed, Error per pixel not valid! \" << ErrorPerPixel << \" instead of 0.08\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n  if (PSNR < 28)\n  {\n    std::cerr << \"Test Failed, PSNR not valid! \" << PSNR << \" instead of 23\" << std::endl;\n    exit(EXIT_FAILURE);\n  }\n}\n#endif\n\n/**\n * \\file rtkwaveletstest.cxx\n *\n * \\brief Functional test for wavelets deconstruction / reconstruction\n *\n * This test generates a random image, computes its wavelets deconstruction,\n * reconstructs from it, and compares the results to the original image.\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n\n  using OutputImageType = itk::Image<float, Dimension>;\n  // Random image sources\n  auto randomVolumeSource = itk::RandomImageSource<OutputImageType>::New();\n\n  // Volume metadata\n  auto origin = itk::MakePoint(0., 0., 0.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(8, 8, 8);\n  auto spacing = itk::MakeVector(32., 32., 32.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n  origin.Fill(0.);\n  randomVolumeSource->SetOrigin(origin);\n  randomVolumeSource->SetSpacing(spacing);\n  randomVolumeSource->SetSize(size);\n  randomVolumeSource->SetMin(0.);\n  randomVolumeSource->SetMax(1.);\n  randomVolumeSource->SetNumberOfWorkUnits(2); // With 1, it's deterministic\n\n  // Update the source\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(randomVolumeSource->Update());\n\n  // Wavelets deconstruction and reconstruction\n  auto wavelets = rtk::DeconstructSoftThresholdReconstructImageFilter<OutputImageType>::New();\n  wavelets->SetInput(randomVolumeSource->GetOutput());\n  wavelets->SetNumberOfLevels(3);\n  wavelets->SetOrder(3);\n  wavelets->SetThreshold(0);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(wavelets->Update());\n\n  CheckImageQuality<OutputImageType>(wavelets->GetOutput(), randomVolumeSource->GetOutput());\n\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkweidingerforwardmodeltest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkMacro.h\"\n#include <itkImageFileReader.h>\n#include \"rtkWeidingerForwardModelImageFilter.h\"\n#include <itkCSVArray2DFileReader.h>\n\n/**\n * \\file rtkweidingerforwardmodeltest.cxx\n *\n * \\brief Test for the filter rtkWeidingerForwardModelImageFilter\n *\n * This test reads decomposed projections, measured projections, incident spectrum, material\n * attenuations, detector response, and projections of a volume of ones,\n * runs the filter rtkWeidingerForwardModelImageFilter, and compare its outputs\n * to the expected ones (computed with Matlab)\n *\n * \\author Cyril Mory\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 9)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr\n      << argv[0]\n      << \" decomposedProjections.mha measuredProjections.mha incidentSpectrum.mha projections.mha DetectorResponse.csv \"\n         \"materialAttenuations.csv out1.mha out2.mha\"\n      << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Define types\n  constexpr unsigned int nBins = 5;\n  constexpr unsigned int nMaterials = 3;\n  constexpr unsigned int nEnergies = 150;\n  using dataType = double;\n  using TDecomposedProjections = itk::Image<itk::Vector<dataType, nMaterials>, 3>;\n  using TMeasuredProjections = itk::Image<itk::Vector<dataType, nBins>, 3>;\n  using TIncidentSpectrum = itk::Image<dataType, 3>;\n  using TProjections = itk::Image<dataType, 3>;\n  using TOutput1 = itk::Image<itk::Vector<dataType, nMaterials>, 3>;\n  using TOutput2 = itk::Image<itk::Vector<dataType, nMaterials * nMaterials>, 3>;\n\n  vnl_matrix<dataType> detectorResponse(nBins, nEnergies);\n  vnl_matrix<dataType> materialAttenuations(nEnergies, nMaterials);\n\n  // Define, instantiate, set and update readers\n  auto decomposedProjectionsReader = itk::ImageFileReader<TDecomposedProjections>::New();\n  decomposedProjectionsReader->SetFileName(argv[1]);\n  decomposedProjectionsReader->Update();\n\n  auto measuredProjectionsReader = itk::ImageFileReader<TMeasuredProjections>::New();\n  measuredProjectionsReader->SetFileName(argv[2]);\n  measuredProjectionsReader->Update();\n\n  auto incidentSpectrumReader = itk::ImageFileReader<TIncidentSpectrum>::New();\n  incidentSpectrumReader->SetFileName(argv[3]);\n  incidentSpectrumReader->Update();\n\n  auto projectionsReader = itk::ImageFileReader<TProjections>::New();\n  projectionsReader->SetFileName(argv[4]);\n  projectionsReader->Update();\n\n  auto output1Reader = itk::ImageFileReader<TOutput1>::New();\n  output1Reader->SetFileName(argv[7]);\n  output1Reader->Update();\n\n  auto output2Reader = itk::ImageFileReader<TOutput2>::New();\n  output2Reader->SetFileName(argv[8]);\n  output2Reader->Update();\n\n  // Read binned detector response\n  auto csvReader = itk::CSVArray2DFileReader<dataType>::New();\n  csvReader->SetFieldDelimiterCharacter(',');\n  csvReader->HasColumnHeadersOff();\n  csvReader->HasRowHeadersOff();\n\n  std::string filename = argv[5];\n  csvReader->SetFileName(filename);\n  csvReader->Parse();\n  for (unsigned int r = 0; r < nBins; r++)\n    for (unsigned int c = 0; c < nEnergies; c++)\n      detectorResponse[r][c] = csvReader->GetOutput()->GetData(r, c);\n\n  // Read material attenuations\n  filename = argv[6];\n  csvReader->SetFileName(filename);\n  csvReader->Parse();\n  for (unsigned int r = 0; r < nEnergies; r++)\n    for (unsigned int c = 0; c < nMaterials; c++)\n      materialAttenuations[r][c] = csvReader->GetOutput()->GetData(r, c);\n\n  // Create the filter\n  auto weidingerForward = rtk::WeidingerForwardModelImageFilter<TDecomposedProjections,\n                                                                TMeasuredProjections,\n                                                                TIncidentSpectrum,\n                                                                TProjections>::New();\n\n  // Set its inputs\n  weidingerForward->SetInputDecomposedProjections(decomposedProjectionsReader->GetOutput());\n  weidingerForward->SetInputMeasuredProjections(measuredProjectionsReader->GetOutput());\n  weidingerForward->SetInputIncidentSpectrum(incidentSpectrumReader->GetOutput());\n  weidingerForward->SetInputProjectionsOfOnes(projectionsReader->GetOutput());\n  weidingerForward->SetBinnedDetectorResponse(detectorResponse);\n  weidingerForward->SetMaterialAttenuations(materialAttenuations);\n\n  // Update the filter\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(weidingerForward->Update());\n\n  // 2. Compare read projections\n  CheckVectorImageQuality<TOutput1>(weidingerForward->GetOutput1(), output1Reader->GetOutput(), 1.e-9, 200, 2000.0);\n  CheckVectorImageQuality<TOutput2>(weidingerForward->GetOutput2(), output2Reader->GetOutput(), 1.e-7, 200, 2000.0);\n\n  // If all succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkxradtest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkProjectionsReader.h\"\n#include \"rtkMacro.h\"\n#include \"rtkXRadGeometryReader.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n\n#include <itkRegularExpressionSeriesFileNames.h>\n\n/**\n * \\file rtkxradtest.cxx\n *\n * \\brief Functional tests for classes managing X-Rad data\n *\n * This test reads a projection and the geometry of an acquisition from a\n * X-Rad acquisition and compares it to the expected results, which are\n * read from a baseline image in the MetaIO file format and a geometry file in\n * the RTK format, respectively.\n *\n * \\author Simon Rit\n */\n\nint\nmain(int argc, char * argv[])\n{\n  if (argc < 5)\n  {\n    std::cerr << \"Usage: \" << std::endl;\n    std::cerr << argv[0] << \"  xradGeometry.header xradProj.header refGeometry.xml reference.mha\" << std::endl;\n    return EXIT_FAILURE;\n  }\n\n  // Elekta geometry\n  rtk::XRadGeometryReader::Pointer geoTargReader;\n  geoTargReader = rtk::XRadGeometryReader::New();\n  geoTargReader->SetImageFileName(argv[1]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoTargReader->UpdateOutputData());\n\n  // Reference geometry\n  rtk::ThreeDCircularProjectionGeometryXMLFileReader::Pointer geoRefReader;\n  geoRefReader = rtk::ThreeDCircularProjectionGeometryXMLFileReader::New();\n  geoRefReader->SetFilename(argv[3]);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(geoRefReader->GenerateOutputInformation())\n\n  // 1. Check geometries\n  CheckGeometries(geoTargReader->GetGeometry(), geoRefReader->GetOutputObject());\n\n  // ******* COMPARING projections *******\n  constexpr unsigned int Dimension = 3;\n  using ImageType = itk::Image<float, Dimension>;\n\n  // Elekta projections reader\n  using ReaderType = rtk::ProjectionsReader<ImageType>;\n  auto                     reader = ReaderType::New();\n  std::vector<std::string> fileNames;\n  fileNames.emplace_back(argv[2]);\n  reader->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(reader->Update());\n\n  // Reference projections reader\n  auto readerRef = ReaderType::New();\n  fileNames.clear();\n  fileNames.emplace_back(argv[4]);\n  readerRef->SetFileNames(fileNames);\n  TRY_AND_EXIT_ON_ITK_EXCEPTION(readerRef->Update());\n\n  // 2. Compare read projections\n  CheckImageQuality<ImageType>(reader->GetOutput(), readerRef->GetOutput(), 1.6e-7, 100, 2.0);\n\n  // If both succeed\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "test/rtkzengforwardprojectiontest.cxx",
    "content": "#include \"rtkTest.h\"\n#include \"rtkThreeDCircularProjectionGeometryXMLFile.h\"\n#include \"rtkJosephForwardAttenuatedProjectionImageFilter.h\"\n#include \"rtkConstantImageSource.h\"\n#include \"rtkZengForwardProjectionImageFilter.h\"\n#include <itkImageRegionSplitterDirection.h>\n#include <itkImageRegionIterator.h>\n#include <cmath>\n#include \"rtkDrawEllipsoidImageFilter.h\"\n\n/**\n * \\file rtkzengforwardprojectiontest.cxx\n *\n * \\brief Functional test for forward projection\n *\n * The test projects a volume filled with ones. The forward projector should\n * then return the intersection of the ray with the box and it is compared\n * with the analytical intersection of a box with a ray.\n *\n * \\author Antoine Robert\n */\n\nint\nmain(int, char **)\n{\n  constexpr unsigned int Dimension = 3;\n  using OutputPixelType = float;\n\n#ifdef USE_CUDA\n  using OutputImageType = itk::CudaImage<OutputPixelType, Dimension>;\n#else\n  using OutputImageType = itk::Image<OutputPixelType, Dimension>;\n#endif\n\n#if FAST_TESTS_NO_CHECKS\n  constexpr unsigned int NumberOfProjectionImages = 3;\n#else\n  constexpr unsigned int NumberOfProjectionImages = 40;\n#endif\n\n  // Constant image sources\n  using ConstantImageSourceType = rtk::ConstantImageSource<OutputImageType>;\n  constexpr double att = 0.0154;\n  // Create Joseph Forward Projector volume input.\n  auto origin = itk::MakePoint(-126., -126., -126.);\n#if FAST_TESTS_NO_CHECKS\n  auto size = itk::MakeSize(2, 2, 2);\n  auto spacing = itk::MakeVector(252., 252., 252.);\n#else\n  auto size = itk::MakeSize(64, 64, 64);\n  auto spacing = itk::MakeVector(4., 4., 4.);\n#endif\n\n  auto tomographySource = ConstantImageSourceType::New();\n  tomographySource->SetOrigin(origin);\n  tomographySource->SetSpacing(spacing);\n  tomographySource->SetSize(size);\n  tomographySource->SetConstant(0.);\n\n  auto attenuationInput = ConstantImageSourceType::New();\n  attenuationInput->SetOrigin(origin);\n  attenuationInput->SetSpacing(spacing);\n  attenuationInput->SetSize(size);\n  attenuationInput->SetConstant(att);\n\n\n  // Initialization Volume, it is used in the Zeng Forward Projector and in the Joseph Attenuated Projector\n  auto projInput = ConstantImageSourceType::New();\n  size[2] = NumberOfProjectionImages;\n  projInput->SetOrigin(origin);\n  projInput->SetSpacing(spacing);\n  projInput->SetSize(size);\n  projInput->SetConstant(0.);\n  projInput->Update();\n\n\n  auto volInput = rtk::DrawEllipsoidImageFilter<OutputImageType, OutputImageType>::New();\n  auto axis_vol = itk::MakeVector(32., 32., 32.);\n  auto center_vol = itk::MakeVector(0., 0., 0.);\n  volInput->SetInput(tomographySource->GetOutput());\n  volInput->SetCenter(center_vol);\n  volInput->SetAxis(axis_vol);\n  volInput->SetDensity(1);\n  volInput->Update();\n\n  // Zeng Forward Projection filter\n\n  auto jfp = rtk::ZengForwardProjectionImageFilter<OutputImageType, OutputImageType>::New();\n  jfp->InPlaceOff();\n  jfp->SetInput(projInput->GetOutput());\n  jfp->SetInput(1, volInput->GetOutput());\n  jfp->SetInput(2, attenuationInput->GetOutput());\n\n  // Joseph Forward Attenuated Projection filter\n  auto attjfp = rtk::JosephForwardAttenuatedProjectionImageFilter<OutputImageType, OutputImageType>::New();\n  attjfp->InPlaceOff();\n  attjfp->SetInput(projInput->GetOutput());\n  attjfp->SetInput(1, volInput->GetOutput());\n  attjfp->SetInput(2, attenuationInput->GetOutput());\n\n  auto geometry = rtk::ThreeDCircularProjectionGeometry::New();\n  for (unsigned int i = 0; i < NumberOfProjectionImages; i++)\n  {\n    geometry->AddProjection(500, 0, i * 360. / NumberOfProjectionImages, 16., 12.);\n  }\n\n  attjfp->SetGeometry(geometry);\n  attjfp->Update();\n\n  jfp->SetGeometry(geometry);\n  jfp->SetAlpha(0.);\n  jfp->SetSigmaZero(0.);\n  jfp->Update();\n\n  CheckImageQuality<OutputImageType>(jfp->GetOutput(), attjfp->GetOutput(), 0.1, 44.0, 255.0);\n  std::cout << \"\\n\\nTest PASSED! \" << std::endl;\n\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "utilities/SetupForDevelopment.sh",
    "content": "#!/usr/bin/env bash\n#==========================================================================\n#\n#   Copyright NumFOCUS\n#\n#   Licensed under the Apache License, Version 2.0 (the \"License\");\n#   you may not use this file except in compliance with the License.\n#   You may obtain a copy of the License at\n#\n#          https://www.apache.org/licenses/LICENSE-2.0.txt\n#\n#   Unless required by applicable law or agreed to in writing, software\n#   distributed under the License is distributed on an \"AS IS\" BASIS,\n#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n#   See the License for the specific language governing permissions and\n#   limitations under the License.\n#\n#==========================================================================*/\n\n\n# Run this script to set up the git hooks for committing changes to RTK.\n# For more information, see:\n#   https://www.itk.org/Wiki/ITK/Git#Hooks\n#   https://www.itk.org/Wiki/Git/Hooks\n\n#!/usr/bin/env bash\n#=============================================================================\n# Copyright 2010-2012 Kitware, Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#=============================================================================\n\n# Run this script to set up local Git hooks for this project.\n\n# Project configuration instructions:\n#\n# - Publish a \"hooks\" branch in the project repository such that\n#   clones will have \"refs/remotes/origin/hooks\".\n#\n# - Populate adjacent \"config\" file with:\n#    hooks.url    = Repository URL publishing \"hooks\" branch\n#    hooks.branch = Repository branch instead of \"hooks\"\n\negrep-q() {\n\tegrep \"$@\" >/dev/null 2>/dev/null\n}\n\ndie() {\n\techo 1>&2 \"$@\" ; exit 1\n}\n\n# Make sure we are inside the repository.\ncd \"${BASH_SOURCE%/*}\" &&\n\n# Select a hooks branch.\nif url=$(git config --get hooks.url); then\n\t# Fetch hooks from locally configured repository.\n\tbranch=$(git config hooks.branch || echo hooks)\nelif git for-each-ref refs/remotes/origin/hooks 2>/dev/null |\n     egrep-q 'refs/remotes/origin/hooks$'; then\n\t# Use hooks cloned from origin.\n\turl=.. && branch=remotes/origin/hooks\nelif url=$(git config -f config --get hooks.url); then\n\t# Fetch hooks from project-configured repository.\n\tbranch=$(git config -f config hooks.branch || echo hooks)\nelse\n\tdie 'This project is not configured to install local hooks.'\nfi &&\n\n# Populate \".git/hooks\".\necho 'Setting up git hooks...' &&\ngit_dir=$(git rev-parse --git-dir) &&\nmkdir -p \"$git_dir/hooks\" &&\ncd \"$git_dir/hooks\" &&\nif ! test -e .git; then\n\tgit init -q || die 'Could not run git init for hooks.'\nfi &&\ngit fetch -q \"$url\" \"$branch\" &&\ngit reset -q --hard FETCH_HEAD || die 'Failed to install hooks'\n\ncd ../..\n\n# Set up KWStyle hook.\necho \"Setting up the KWStyle hook...\"\ngit config hooks.KWStyle.conf \"cmake/KWStyle/RTK.kws.xml\"\ngit config hooks.KWStyle.overwriteRulesConf \"cmake/KWStyle/RTKOverwrite.txt\"\n\necho \"Done.\"\n"
  },
  {
    "path": "utilities/UploadTestData.py",
    "content": "#!/usr/bin/env python\n\nimport argparse\nimport girder_client\nfrom girder_client import GirderClient\nimport os\nimport fnmatch\nfrom distutils.version import StrictVersion\n\nif StrictVersion(girder_client.__version__) < StrictVersion(\"2.0.0\"):\n    raise Exception(\"Girder 2.0.0 or newer is required\")\n\n\nclass GirderExternalDataCli(GirderClient):\n    \"\"\"\n    A command line Python client for interacting with a Girder instance's\n    RESTful api, specifically for performing uploads into a Girder instance.\n    \"\"\"\n\n    def __init__(self, apiKey):\n        \"\"\"initialization function to create a GirderCli instance, will attempt\n        to authenticate with the designated Girder instance.\n        \"\"\"\n        GirderClient.__init__(self, apiUrl=\"https://data.kitware.com/api/v1\")\n\n        self.authenticate(apiKey=apiKey)\n\n    def _uploadContentLinkItem(\n        self,\n        content_link,\n        test_folder,\n        parent_id,\n        reuseExisting=True,\n        dryRun=False,\n    ):\n        \"\"\"Upload objects corresponding to CMake ExternalData content links.\n\n        This will upload the file for the content link *content_link*\n        located in the *test_folder* folder, to the corresponding Girder folder.\n\n        :param parentType: one of (collection,folder,user), default of folder.\n        :param reuseExisting: bool whether to accept an existing item of\n            the same name in the same location, or create a new one instead.\n        :param dryRun: Do not actually upload any content.\n        \"\"\"\n        test_folder = os.path.normpath(test_folder)\n        name = os.path.splitext(content_link)[0]  # remove .sha512 extension\n\n        if dryRun:\n            # create a dryRun placeholder\n            folder = {\"_id\": \"dryRun\"}\n            print(\n                '\\n Trying to upload \"'\n                + name\n                + \" (\"\n                + content_link\n                + ')\" into folder \"'\n                + self.getFolder(parent_id)[\"name\"]\n                + test_folder\n                + '\"'\n            )\n        else:\n            parent_folder = parent_id\n            for dirnames in test_folder.split(\"/\"):\n                if dirnames:\n                    folder = self.loadOrCreateFolder(dirnames, parent_folder, \"folder\")\n                    parent_folder = folder[\"_id\"]\n\n        scriptDir = os.path.dirname(os.path.realpath(__file__))\n        workDir = os.path.normpath(scriptDir + \"/../test/\" + test_folder)\n\n        content_link = os.path.join(workDir, content_link)\n\n        if os.path.isfile(content_link) and fnmatch.fnmatch(content_link, \"*.sha512\"):\n            with open(content_link, \"r\") as fp:\n                hash_value = fp.readline().strip()\n\n            content_file = os.path.join(workDir, \".ExternalData_SHA512_\" + hash_value)\n            if os.path.isfile(content_file):\n                print(\"\\n Found content file: \" + content_file)\n\n                self._uploadAsItem(\n                    name,\n                    folder[\"_id\"],\n                    content_file,\n                    reuseExisting=reuseExisting,\n                    dryRun=dryRun,\n                )\n\n                print(\"\\n Upload Successful !\")\n                return\n\n        print(\" File not found. Upload failed for \" + content_link)\n\n\ndef main():\n    parser = rtk.RTKArgumentParser(\n        description=\"Upload CMake ExternalData content links to Girder\"\n    )\n    parser.add_argument(\n        \"--dry-run\",\n        action=\"store_true\",\n        help=\"will not write anything to Girder, only report on what would \" \"happen\",\n    )\n    parser.add_argument(\"--api-key\", required=True, default=None)\n    # Default is RTK/RTKTestingData\n    parser.add_argument(\n        \"--parent-id\",\n        required=False,\n        default=\"5b178a918d777f15ebe1fff8\",\n        help=\"id of Girder parent target (default: RTK/RTKTestingData)\",\n    )\n    parser.add_argument(\n        \"--content-link\",\n        required=True,\n        help=\"name of the content-link .sha512 file. (eg: Test.png.sha512)\",\n    )\n    parser.add_argument(\n        \"--test-folder\",\n        required=True,\n        help=\"path to the content link file. (eg: Baseline/path/To/File/)\",\n    )\n    args = parser.parse_args()\n\n    gc = GirderExternalDataCli(args.api_key)\n    gc._uploadContentLinkItem(\n        args.content_link,\n        args.test_folder,\n        args.parent_id,\n        reuseExisting=False,\n        dryRun=args.dry_run,\n    )\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "utilities/clang-format.bash",
    "content": "set -e\nset -x\nRTK_DIR=$(dirname $0)/..\n\nITK_SOURCE_DIR=$(grep ITK_SOURCE_DIR ${ITK_DIR}/CMakeCache.txt | sed \"s/.*=//g\")\nif ! test -e ${RTK_DIR}/../../../CMake/itkVersion.cmake\nthen\n    echo \"$(basename $0) must be run from the ITK source directory\"\nfi\nfor i in \\\n  ${RTK_DIR}/cmake/*.cxx \\\n  ${RTK_DIR}/include/*.h* \\\n  ${RTK_DIR}/src/*.c{xx,u} \\\n  ${RTK_DIR}/applications/*/*.{h,cxx,hxx} \\\n  ${RTK_DIR}/examples/FirstReconstruction/*.cxx \\\n  ${RTK_DIR}/utilities/ITKCudaCommon/include/*.h* \\\n  ${RTK_DIR}/utilities/ITKCudaCommon/src/*.cxx \\\n  ${RTK_DIR}/test/*{h,cxx}\ndo\n\tclang-format -style=file -i $i\ndone\n\n"
  },
  {
    "path": "utilities/gengetopt/CMakeLists.txt",
    "content": "# Gengetopt: https://www.gnu.org/software/gengetopt/\n\nADD_DEFINITIONS(-DPACKAGE=\\\"gengetopt\\\")\nADD_DEFINITIONS(-DVERSION=\\\"2.22.4\\\")\nADD_DEFINITIONS(-DHAVE_SSTREAM)\nADD_DEFINITIONS(-DHAVE_NAMESPACES)\n\nrtk_module_warnings_disable(C CXX)\n\ninclude(CheckCXXCompilerFlag)\nCHECK_CXX_COMPILER_FLAG(-fno-var-tracking-assignments HAS_NO_VAR_TRACKING_ASSIGNMENTS)\nif (HAS_NO_VAR_TRACKING_ASSIGNMENTS)\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -fno-var-tracking-assignments\")\nendif()\n\n# MSVC specific issues\nADD_DEFINITIONS(-DHAVE_STRING_H)\nIF(MSVC)\n  ADD_DEFINITIONS(-DYY_NO_UNISTD_H)\n  ADD_DEFINITIONS(-Disatty=!)\nENDIF(MSVC)\n\nADD_EXECUTABLE(gengetopt\n  ./cmdline.c\n  ./ggos.cpp\n  ./scanner.cc\n  ./skels/required_option.cc\n  ./skels/handle_version.cc\n  ./skels/generic_option.cc\n  ./skels/clear_arg.cc\n  ./skels/update_given.cc\n  ./skels/dependant_option.cc\n  ./skels/custom_getopt_gen.cc\n  ./skels/handle_help.cc\n  ./skels/given_field.cc\n  ./skels/init_args_info.cc\n  ./skels/multiple_opt_list.cc\n  ./skels/free_list.cc\n  ./skels/exit_failure.cc\n  ./skels/clear_given.cc\n  ./skels/free_multiple.cc\n  ./skels/enum_decl.cc\n  ./skels/reset_group.cc\n  ./skels/c_source.cc\n  ./skels/group_option.cc\n  ./skels/file_save.cc\n  ./skels/check_modes.cc\n  ./skels/copyright.cc\n  ./skels/option_arg.cc\n  ./skels/group_counter.cc\n  ./skels/free_string.cc\n  ./skels/header.cc\n  ./skels/print_help_string.cc\n  ./skels/multiple_fill_array.cc\n  ./skels/file_save_multiple.cc\n  ./fileutils.cpp\n  ./getopt.c\n  ./gm.cc\n  ./globals.cpp\n  ./yywrap.c\n  ./getopt1.c\n  ./argsdef.c\n  ./gm_utils.cpp\n  ./acceptedvalues.cpp\n  ./gengetopt.cc\n  ./yyerror.cc\n  ./parser.cc)\n\nINCLUDE_DIRECTORIES(.)\nINCLUDE_DIRECTORIES(skels)\n#INCLUDE_DIRECTORIES(includes)\n"
  },
  {
    "path": "utilities/gengetopt/Makefile.am",
    "content": "# Copyright (C) 1999-2009  Free Software Foundation, Inc.\n#\n# This file is part of GNU gengetopt\n#\n# GNU gengetopt is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 3, or (at your option)\n# any later version.\n#\n# GNU gengetopt is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n# Public License for more details.\n#\n# You should have received a copy of the GNU General Public License along\n# with gengetopt; see the file COPYING. If not, write to the Free Software\n# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\nSUBDIRS = includes skels tests\n\n#INCLUDES = -I@top_srcdir@/src/skels\n\nSUFFIXES = .text .c .ggo\n\n.text.o:\n\t$(TXTC) $<\n\nbin_PROGRAMS = gengetopt\n\nnoinst_LTLIBRARIES = libgengetopt.la\n\nlibgengetopt_la_SOURCES = parser.cc scanner.cc \\\nglobals.cpp \\\nargsdef.c cmdline.ggo gm.cc \\\nyyerror.cc gm_utils.cpp fileutils.cpp acceptedvalues.cpp ggos.cpp\n\ngengetopt_SOURCES = gengetopt.cc\n\nscanner.cc: $(srcdir)/scanner.ll\n\t$(LEX) $(LFLAGS) -o $(srcdir)/scanner.cc $(srcdir)/scanner.ll\n\nparser.cc: $(srcdir)/parser.yy\n\t$(YACC) -o $(srcdir)/parser.cc $(srcdir)/parser.yy --defines=$(srcdir)/parser.h\n\n#gengetopt_LDADD = @LIBOBJS@ @LEXLIB@ skels/libgen.a\n\n# these are for gnulib\nAM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_builddir)/gl\n\nlibgengetopt_la_LIBADD = $(top_builddir)/gl/libgnu.la \\\n\t@LTLIBOBJS@ \\\n\tskels/libgen.la\n\nLDADD = $(top_builddir)/src/libgengetopt.la\n\nEXTRA_DIST = parser.h argsdef.h gengetopt.h ggos.h gm.h gnugetopt.h \\\ncmdline.c cmdline.h my_sstream.h my_string.h my_map.h \\\nglobal_opts.h \\\nggo_options.h \\\ngroups.h \\\nparser.yy scanner.ll \\\nglobals.h \\\n$(pkgdata_DATA)\n\n# version of gengetopt linked to the ElectricFence library\n# don't use it anymore: use valgrind\n#EXTRA_PROGRAMS = gengetopt-efence\n#gengetopt_efence_SOURCES = $(gengetopt_SOURCES)\n#gengetopt_efence_LDADD = -lefence $(gengetopt_LDADD)\n\nPROGNAME = $(top_builddir)/src/gengetopt$(EXEEXT)\n\n# to have flex generate a case insensitive scanner\nAM_LFLAGS = -i\n\n# it may happen, usually if the sources have been downloaded from CVS\n# repository, that cmdline.ggo is more recent than cmdline.c, but\n# cmdline.c cannot be re-generated, even because gengetopt has\n# to be built first. For instance if you only change spaces in cmdline.ggo\n# cmdline.c will not be different, and thus it is not updated in the CVS\n# repository; then when you make a checkout on another place, make\n# would try to build cmdline.c, but to do this it would need gengetopt\n# which is not built yet; so we simply touch cmdline.c (and this is safe)\n\n.ggo.c:\n\tif test -f $(PROGNAME); then \\\n\t$(PROGNAME) --input=$< --output-dir=$(srcdir) ; \\\n\telse touch $(srcdir)/$@ ; fi\n\ncmdline.h: cmdline.c\n\nBUILT_SOURCES = cmdline.h cmdline.c parser.cc scanner.cc\n\n# automatically generate gengetopt_strdup() from the replacement function\n# strdup().\n# gengetopt_strdup.text: strdup.c\n#\techo \"/* gengetopt_strdup(): automatically generated from strdup.c. */\" > $@\n#\tcat strdup.c | sed -e 's/^strdup (/gengetopt_&/' \\\n#               -e 's/^char \\* *$$/&/' \\\n#               -e '/^#include.*$$/D' -e '/^$$/D' >> $@\n\n# we distribute these files because who uses gengetopt might need them\n# these are installed in $(prefix)/share/gengetopt\npkgdata_DATA = gnugetopt.h getopt.c getopt1.c\n\n# yywrap.c is added only if it is not found on lex (flex) lib, and will be\n# added automatically by automake\n\n# automake (maybe due to a bug) doesn't added these files well,\n# so we explicitely declare them\nMAINTAINERCLEANFILES = scanner.cc parser.h parser.cc\n\nnoinst_HEADERS = acceptedvalues.h errorcodes.h fileutils.h \\\n\tgm_utils.h yyerror.h\n\n"
  },
  {
    "path": "utilities/gengetopt/acceptedvalues.cpp",
    "content": "//\n// C++ Implementation: acceptedvalues\n//\n// Description:\n//\n//\n// Author: Lorenzo Bettini <https://www.lorenzobettini.it>, (C) 2004\n//\n// Copyright: See COPYING file that comes with this distribution\n//\n//\n\n#include \"acceptedvalues.h\"\n#include \"my_sstream.h\"\n\nusing namespace std;\n\nvoid\nAcceptedValues::insert(const string &s)\n{\n  push_back(s);\n  values.insert(s);\n}\n\nbool\nAcceptedValues::contains(const string &s) const\n{\n  return (values.count(s) > 0);\n}\n\nconst string\nAcceptedValues::toString(bool escape) const\n{\n  ostringstream buf;\n\n  for (const_iterator it = begin(); it != end(); ) {\n    buf << (escape ? \"\\\\\\\"\" : \"\\\"\") << *it\n        << (escape ? \"\\\\\\\"\" : \"\\\"\");\n    if (++it != end())\n      buf << \", \";\n  }\n\n  return buf.str();\n}\n"
  },
  {
    "path": "utilities/gengetopt/acceptedvalues.h",
    "content": "//\n// C++ Interface: acceptedvalues\n//\n// Description:\n//\n//\n// Author: Lorenzo Bettini <https://www.lorenzobettini.it>, (C) 2004\n//\n// Copyright: See COPYING file that comes with this distribution\n//\n//\n#ifndef ACCEPTEDVALUES_H\n#define ACCEPTEDVALUES_H\n\n#include <list>\n#include <set>\n#include <string>\n\n/**\nthe values that can be passed to an option\n\n@author Lorenzo Bettini\n*/\nclass AcceptedValues : protected std::list<std::string>\n{\n  private:\n    typedef std::set<std::string> value_set;\n    value_set values;\n\n  public:\n    using std::list<std::string>::const_iterator;\n    using std::list<std::string>::begin;\n    using std::list<std::string>::end;\n\n    void insert(const std::string &s);\n    const std::string toString(bool escape = true) const;\n    bool contains(const std::string &s) const;\n};\n\n#endif\n"
  },
  {
    "path": "utilities/gengetopt/argsdef.c",
    "content": "/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#include \"argsdef.h\"\n\nconst char * arg_names [] = { (const char*)0, (const char*)0, \"STRING\", \"INT\",\n        \"SHORT\", \"LONG\", \"FLOAT\", \"DOUBLE\", \"LONGDOUBLE\", \"LONGLONG\", \"ENUM\" };\n\nconst char * arg_type_constants [] = { \"ARG_NO\", \"ARG_FLAG\", \"ARG_STRING\",\n        \"ARG_INT\", \"ARG_SHORT\", \"ARG_LONG\", \"ARG_FLOAT\", \"ARG_DOUBLE\",\n        \"ARG_LONGDOUBLE\", \"ARG_LONGLONG\", \"ARG_ENUM\" };\n\nconst char * arg_types [] = { (const char*)0, \"int\", \"char *\", \"int\", \"short\",\n        \"long\", \"float\", \"double\", \"long double\", \"long long int\", \"enum\" };\n\nconst char * arg_types_names [] = { (const char*)0, \"int\", \"string\", \"int\",\n        \"short\", \"long\", \"float\", \"double\", \"longdouble\", \"longlong\", \"int\" };\n\n"
  },
  {
    "path": "utilities/gengetopt/argsdef.h",
    "content": "/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#ifndef GENGETOPT_ARGSDEF_H\n#define GENGETOPT_ARGSDEF_H\n\n#define ARG_NO\t\t0\n#define ARG_FLAG\t1\n#define ARG_STRING\t2\n#define ARG_INT\t\t3\n#define ARG_SHORT\t4\n#define ARG_LONG\t5\n#define ARG_FLOAT\t6\n#define ARG_DOUBLE\t7\n#define ARG_LONGDOUBLE\t8\n#define ARG_LONGLONG\t9\n#define ARG_ENUM    10\n\n/** corresponding strings for above defines */\nextern const char * arg_type_constants [];\n/** symbolic names for argument types */\nextern const char * arg_names [];\n/** corresponding C types */\nextern const char * arg_types [];\n/** string representation of types */\nextern const char * arg_types_names [];\n\n#define ARGS_STRUCT \"args_info\"\n\n#endif /* GENGETOPT_ARGSDEF_H */\n\n"
  },
  {
    "path": "utilities/gengetopt/cmdline.c",
    "content": "/*\n  File autogenerated by gengetopt version 2.22.4\n  generated with the following command:\n  ../src/gengetopt --input=../../src/cmdline.ggo --output-dir=../../src --no-handle-version --no-handle-help --no-handle-error --string-parser\n\n  The developers of gengetopt consider the fixed text that goes in all\n  gengetopt output files to be in the public domain:\n  we make no copyright claims on it.\n*/\n\n/* If we use autoconf.  */\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifndef FIX_UNUSED\n#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */\n#endif\n\n#include <getopt.h>\n\n#include \"cmdline.h\"\n\nconst char *gengetopt_args_info_purpose = \"This program generates a C function that uses getopt_long function\\nto parse the command line options, validate them and fill a struct.\";\n\nconst char *gengetopt_args_info_usage = \"Usage: \" CMDLINE_PARSER_PACKAGE \" [OPTIONS]...\";\n\nconst char *gengetopt_args_info_description = \"\";\n\nconst char *gengetopt_args_info_detailed_help[] = {\n  \"  -h, --help                    Print help and exit\",\n  \"      --detailed-help           Print help, including all details and hidden \\n                                  options, and exit\",\n  \"  -V, --version                 Print version and exit\",\n  \"\\nMain options:\",\n  \"\",\n  \"  -i, --input=filename          input file (default std input)\",\n  \"  -f, --func-name=name          name of generated function  \\n                                  (default=`cmdline_parser')\",\n  \"  -a, --arg-struct-name=name    name of generated args info struct  \\n                                  (default=`gengetopt_args_info')\",\n  \"  -F, --file-name=name          name of generated file  (default=`cmdline')\",\n  \"      --output-dir=path         output directory\",\n  \"  \\n  if this option is not specified, the files are generated in the current \\n  directory.\\n\",\n  \"      --header-output-dir=path  header output directory\",\n  \"      --src-output-dir=path     source output directory\",\n  \"  -c, --c-extension=ext         extension of c file  (default=`c')\",\n  \"  -H, --header-extension=ext    extension of header file  (default=`h')\",\n  \"  -l, --long-help               long usage line in help\",\n  \"  \\n  The usage line will print all the options, e.g.,\\n\\n  sample1 -iINT|--int-opt=INT [-h|--help]\\n\",\n  \"      --default-optional        by default, an option is considered optional if \\n                                  not specified otherwise\",\n  \"  -u, --unamed-opts[=STRING]    accept options without names (e.g., file names) \\n                                   (default=`FILES')\",\n  \"\\nThe parser generated is thought to be used to parse the command line arguments. \\nHowever, you can also generate parsers for configuration files, or strings that \\ncontain the arguments to parse, by using the following two options.\\n\",\n  \"  -C, --conf-parser             generate a config file parser\",\n  \"  -S, --string-parser           generate a string parser (the string contains \\n                                  the command line)\",\n  \"\",\n  \"\\nAdditional options:\",\n  \"  -G, --include-getopt          adds the code for getopt_long in the generated \\n                                  C file\",\n  \"  -n, --no-handle-help          do not handle --help|-h automatically\",\n  \"  \\n  If --no-handle-help is specified, the command line option --help|-h will not \\n  be handled automatically, so the programmer will be able to print some other \\n  information; then the function for printing the standard help output can be \\n  used; this function is called <parser-name>_print_help.\\n\\n  Notice that, although the programmer can handle --help|-h manually, the \\n  parser will return after finding such option: the other command line options, \\n  if any, will be ignored.  In case you want to have full control on --help|-h, \\n  you should use --ho-help.\\n\",\n  \"      --no-help                 do not add --help|-h automatically\",\n  \"  \\n  With this option you can disable the automatic addition of options --help|-h. \\n  The programmer will then be able to add this option in the input file and \\n  handle it as he sees fit.  Notice that --no-help will also disable the \\n  automatic options --detailed-help and --full-help.\\n\\n  The programmer can still define options with short character h as he wants, \\n  but he cannot define options help, unless he specifies --no-help (otherwise \\n  an error will be printed).\\n\",\n  \"  -N, --no-handle-version       do not handle --version|-V automatically\",\n  \"      --no-version              do not add --version|-V automatically\",\n  \"  \\n  See above the details about --no-handle-help and --no-help, respectively.\\n\",\n  \"  -e, --no-handle-error         do not exit on errors\",\n  \"  \\n  With this option, if the generated parser encounters an error (e.g., an \\n  unknown option) it does not make the main program exit; instead, the parser \\n  function returns a value different 0, and the main program can print a help \\n  message.\\n\",\n  \"      --show-required[=STRING]  in the output of help will specify which \\n                                  options are mandatory, by using the optional \\n                                  passed string  (default=`(mandatory)')\",\n  \"  -g, --gen-version             put gengetopt version in the generated file  \\n                                  (default=on)\",\n  \"      --set-package=STRING      set the package name (override package defined \\n                                  in the .ggo file)\",\n  \"      --set-version=STRING      set the version number (override version \\n                                  defined in the .ggo file)\",\n  \"      --show-help               show the output of --help instead of generating \\n                                  code\",\n  \"      --show-full-help          show the output of --full-help (i.e., including \\n                                  hidden options) instead of generating code\",\n  \"      --show-detailed-help      show the output of --detailed-help (i.e., \\n                                  including details and hidden options) instead \\n                                  of generating code\",\n  \"      --show-version            show the output of --version instead of \\n                                  generating code\",\n  \"\\nPlease refer to the info manual for further explanations.\",\n    0\n};\n\nstatic void\ninit_help_array(void)\n{\n  gengetopt_args_info_help[0] = gengetopt_args_info_detailed_help[0];\n  gengetopt_args_info_help[1] = gengetopt_args_info_detailed_help[1];\n  gengetopt_args_info_help[2] = gengetopt_args_info_detailed_help[2];\n  gengetopt_args_info_help[3] = gengetopt_args_info_detailed_help[3];\n  gengetopt_args_info_help[4] = gengetopt_args_info_detailed_help[4];\n  gengetopt_args_info_help[5] = gengetopt_args_info_detailed_help[5];\n  gengetopt_args_info_help[6] = gengetopt_args_info_detailed_help[6];\n  gengetopt_args_info_help[7] = gengetopt_args_info_detailed_help[7];\n  gengetopt_args_info_help[8] = gengetopt_args_info_detailed_help[8];\n  gengetopt_args_info_help[9] = gengetopt_args_info_detailed_help[9];\n  gengetopt_args_info_help[10] = gengetopt_args_info_detailed_help[11];\n  gengetopt_args_info_help[11] = gengetopt_args_info_detailed_help[12];\n  gengetopt_args_info_help[12] = gengetopt_args_info_detailed_help[13];\n  gengetopt_args_info_help[13] = gengetopt_args_info_detailed_help[14];\n  gengetopt_args_info_help[14] = gengetopt_args_info_detailed_help[15];\n  gengetopt_args_info_help[15] = gengetopt_args_info_detailed_help[17];\n  gengetopt_args_info_help[16] = gengetopt_args_info_detailed_help[18];\n  gengetopt_args_info_help[17] = gengetopt_args_info_detailed_help[19];\n  gengetopt_args_info_help[18] = gengetopt_args_info_detailed_help[20];\n  gengetopt_args_info_help[19] = gengetopt_args_info_detailed_help[21];\n  gengetopt_args_info_help[20] = gengetopt_args_info_detailed_help[22];\n  gengetopt_args_info_help[21] = gengetopt_args_info_detailed_help[23];\n  gengetopt_args_info_help[22] = gengetopt_args_info_detailed_help[24];\n  gengetopt_args_info_help[23] = gengetopt_args_info_detailed_help[25];\n  gengetopt_args_info_help[24] = gengetopt_args_info_detailed_help[27];\n  gengetopt_args_info_help[25] = gengetopt_args_info_detailed_help[29];\n  gengetopt_args_info_help[26] = gengetopt_args_info_detailed_help[30];\n  gengetopt_args_info_help[27] = gengetopt_args_info_detailed_help[32];\n  gengetopt_args_info_help[28] = gengetopt_args_info_detailed_help[34];\n  gengetopt_args_info_help[29] = gengetopt_args_info_detailed_help[35];\n  gengetopt_args_info_help[30] = gengetopt_args_info_detailed_help[36];\n  gengetopt_args_info_help[31] = gengetopt_args_info_detailed_help[37];\n  gengetopt_args_info_help[32] = gengetopt_args_info_detailed_help[38];\n  gengetopt_args_info_help[33] = gengetopt_args_info_detailed_help[39];\n  gengetopt_args_info_help[34] = gengetopt_args_info_detailed_help[40];\n  gengetopt_args_info_help[35] = gengetopt_args_info_detailed_help[41];\n  gengetopt_args_info_help[36] = gengetopt_args_info_detailed_help[42];\n  gengetopt_args_info_help[37] = 0;\n\n}\n\nconst char *gengetopt_args_info_help[38];\n\ntypedef enum {ARG_NO\n  , ARG_FLAG\n  , ARG_STRING\n} cmdline_parser_arg_type;\n\nstatic\nvoid clear_given (struct gengetopt_args_info *args_info);\nstatic\nvoid clear_args (struct gengetopt_args_info *args_info);\n\nstatic int\ncmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,\n                        struct cmdline_parser_params *params, const char *additional_error);\n\nstruct line_list\n{\n  char * string_arg;\n  struct line_list * next;\n};\n\nstatic struct line_list *cmd_line_list = 0;\nstatic struct line_list *cmd_line_list_tmp = 0;\n\nstatic void\nfree_cmd_list(void)\n{\n  /* free the list of a previous call */\n  if (cmd_line_list)\n    {\n      while (cmd_line_list) {\n        cmd_line_list_tmp = cmd_line_list;\n        cmd_line_list = cmd_line_list->next;\n        free (cmd_line_list_tmp->string_arg);\n        free (cmd_line_list_tmp);\n      }\n    }\n}\n\n\nstatic char *\ngengetopt_strdup (const char *s);\n\nstatic\nvoid clear_given (struct gengetopt_args_info *args_info)\n{\n  args_info->help_given = 0 ;\n  args_info->detailed_help_given = 0 ;\n  args_info->version_given = 0 ;\n  args_info->input_given = 0 ;\n  args_info->func_name_given = 0 ;\n  args_info->arg_struct_name_given = 0 ;\n  args_info->file_name_given = 0 ;\n  args_info->output_dir_given = 0 ;\n  args_info->header_output_dir_given = 0 ;\n  args_info->src_output_dir_given = 0 ;\n  args_info->c_extension_given = 0 ;\n  args_info->header_extension_given = 0 ;\n  args_info->long_help_given = 0 ;\n  args_info->default_optional_given = 0 ;\n  args_info->unamed_opts_given = 0 ;\n  args_info->conf_parser_given = 0 ;\n  args_info->string_parser_given = 0 ;\n  args_info->include_getopt_given = 0 ;\n  args_info->no_handle_help_given = 0 ;\n  args_info->no_help_given = 0 ;\n  args_info->no_handle_version_given = 0 ;\n  args_info->no_version_given = 0 ;\n  args_info->no_handle_error_given = 0 ;\n  args_info->show_required_given = 0 ;\n  args_info->gen_version_given = 0 ;\n  args_info->set_package_given = 0 ;\n  args_info->set_version_given = 0 ;\n  args_info->show_help_given = 0 ;\n  args_info->show_full_help_given = 0 ;\n  args_info->show_detailed_help_given = 0 ;\n  args_info->show_version_given = 0 ;\n}\n\nstatic\nvoid clear_args (struct gengetopt_args_info *args_info)\n{\n  FIX_UNUSED (args_info);\n  args_info->input_arg = NULL;\n  args_info->input_orig = NULL;\n  args_info->func_name_arg = gengetopt_strdup (\"cmdline_parser\");\n  args_info->func_name_orig = NULL;\n  args_info->arg_struct_name_arg = gengetopt_strdup (\"gengetopt_args_info\");\n  args_info->arg_struct_name_orig = NULL;\n  args_info->file_name_arg = gengetopt_strdup (\"cmdline\");\n  args_info->file_name_orig = NULL;\n  args_info->output_dir_arg = NULL;\n  args_info->output_dir_orig = NULL;\n  args_info->header_output_dir_arg = NULL;\n  args_info->header_output_dir_orig = NULL;\n  args_info->src_output_dir_arg = NULL;\n  args_info->src_output_dir_orig = NULL;\n  args_info->c_extension_arg = gengetopt_strdup (\"c\");\n  args_info->c_extension_orig = NULL;\n  args_info->header_extension_arg = gengetopt_strdup (\"h\");\n  args_info->header_extension_orig = NULL;\n  args_info->unamed_opts_arg = gengetopt_strdup (\"FILES\");\n  args_info->unamed_opts_orig = NULL;\n  args_info->show_required_arg = gengetopt_strdup (\"(mandatory)\");\n  args_info->show_required_orig = NULL;\n  args_info->gen_version_flag = 1;\n  args_info->set_package_arg = NULL;\n  args_info->set_package_orig = NULL;\n  args_info->set_version_arg = NULL;\n  args_info->set_version_orig = NULL;\n\n}\n\nstatic\nvoid init_args_info(struct gengetopt_args_info *args_info)\n{\n\n  init_help_array();\n  args_info->help_help = gengetopt_args_info_detailed_help[0] ;\n  args_info->detailed_help_help = gengetopt_args_info_detailed_help[1] ;\n  args_info->version_help = gengetopt_args_info_detailed_help[2] ;\n  args_info->input_help = gengetopt_args_info_detailed_help[5] ;\n  args_info->func_name_help = gengetopt_args_info_detailed_help[6] ;\n  args_info->arg_struct_name_help = gengetopt_args_info_detailed_help[7] ;\n  args_info->file_name_help = gengetopt_args_info_detailed_help[8] ;\n  args_info->output_dir_help = gengetopt_args_info_detailed_help[9] ;\n  args_info->header_output_dir_help = gengetopt_args_info_detailed_help[11] ;\n  args_info->src_output_dir_help = gengetopt_args_info_detailed_help[12] ;\n  args_info->c_extension_help = gengetopt_args_info_detailed_help[13] ;\n  args_info->header_extension_help = gengetopt_args_info_detailed_help[14] ;\n  args_info->long_help_help = gengetopt_args_info_detailed_help[15] ;\n  args_info->default_optional_help = gengetopt_args_info_detailed_help[17] ;\n  args_info->unamed_opts_help = gengetopt_args_info_detailed_help[18] ;\n  args_info->conf_parser_help = gengetopt_args_info_detailed_help[20] ;\n  args_info->string_parser_help = gengetopt_args_info_detailed_help[21] ;\n  args_info->include_getopt_help = gengetopt_args_info_detailed_help[24] ;\n  args_info->no_handle_help_help = gengetopt_args_info_detailed_help[25] ;\n  args_info->no_help_help = gengetopt_args_info_detailed_help[27] ;\n  args_info->no_handle_version_help = gengetopt_args_info_detailed_help[29] ;\n  args_info->no_version_help = gengetopt_args_info_detailed_help[30] ;\n  args_info->no_handle_error_help = gengetopt_args_info_detailed_help[32] ;\n  args_info->show_required_help = gengetopt_args_info_detailed_help[34] ;\n  args_info->gen_version_help = gengetopt_args_info_detailed_help[35] ;\n  args_info->set_package_help = gengetopt_args_info_detailed_help[36] ;\n  args_info->set_version_help = gengetopt_args_info_detailed_help[37] ;\n  args_info->show_help_help = gengetopt_args_info_detailed_help[38] ;\n  args_info->show_full_help_help = gengetopt_args_info_detailed_help[39] ;\n  args_info->show_detailed_help_help = gengetopt_args_info_detailed_help[40] ;\n  args_info->show_version_help = gengetopt_args_info_detailed_help[41] ;\n\n}\n\nvoid\ncmdline_parser_print_version (void)\n{\n  printf (\"%s %s\\n\",\n     (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),\n     CMDLINE_PARSER_VERSION);\n}\n\nstatic void print_help_common(void) {\n  cmdline_parser_print_version ();\n\n  if (strlen(gengetopt_args_info_purpose) > 0)\n    printf(\"\\n%s\\n\", gengetopt_args_info_purpose);\n\n  if (strlen(gengetopt_args_info_usage) > 0)\n    printf(\"\\n%s\\n\", gengetopt_args_info_usage);\n\n  printf(\"\\n\");\n\n  if (strlen(gengetopt_args_info_description) > 0)\n    printf(\"%s\\n\\n\", gengetopt_args_info_description);\n}\n\nvoid\ncmdline_parser_print_help (void)\n{\n  int i = 0;\n  print_help_common();\n  while (gengetopt_args_info_help[i])\n    printf(\"%s\\n\", gengetopt_args_info_help[i++]);\n}\n\nvoid\ncmdline_parser_print_detailed_help (void)\n{\n  int i = 0;\n  print_help_common();\n  while (gengetopt_args_info_detailed_help[i])\n    printf(\"%s\\n\", gengetopt_args_info_detailed_help[i++]);\n}\n\nvoid\ncmdline_parser_init (struct gengetopt_args_info *args_info)\n{\n  clear_given (args_info);\n  clear_args (args_info);\n  init_args_info (args_info);\n}\n\nvoid\ncmdline_parser_params_init(struct cmdline_parser_params *params)\n{\n  if (params)\n    {\n      params->override = 0;\n      params->initialize = 1;\n      params->check_required = 1;\n      params->check_ambiguity = 0;\n      params->print_errors = 1;\n    }\n}\n\nstruct cmdline_parser_params *\ncmdline_parser_params_create(void)\n{\n  struct cmdline_parser_params *params =\n    (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));\n  cmdline_parser_params_init(params);\n  return params;\n}\n\nstatic void\nfree_string_field (char **s)\n{\n  if (*s)\n    {\n      free (*s);\n      *s = 0;\n    }\n}\n\n\nstatic void\ncmdline_parser_release (struct gengetopt_args_info *args_info)\n{\n\n  free_string_field (&(args_info->input_arg));\n  free_string_field (&(args_info->input_orig));\n  free_string_field (&(args_info->func_name_arg));\n  free_string_field (&(args_info->func_name_orig));\n  free_string_field (&(args_info->arg_struct_name_arg));\n  free_string_field (&(args_info->arg_struct_name_orig));\n  free_string_field (&(args_info->file_name_arg));\n  free_string_field (&(args_info->file_name_orig));\n  free_string_field (&(args_info->output_dir_arg));\n  free_string_field (&(args_info->output_dir_orig));\n  free_string_field (&(args_info->header_output_dir_arg));\n  free_string_field (&(args_info->header_output_dir_orig));\n  free_string_field (&(args_info->src_output_dir_arg));\n  free_string_field (&(args_info->src_output_dir_orig));\n  free_string_field (&(args_info->c_extension_arg));\n  free_string_field (&(args_info->c_extension_orig));\n  free_string_field (&(args_info->header_extension_arg));\n  free_string_field (&(args_info->header_extension_orig));\n  free_string_field (&(args_info->unamed_opts_arg));\n  free_string_field (&(args_info->unamed_opts_orig));\n  free_string_field (&(args_info->show_required_arg));\n  free_string_field (&(args_info->show_required_orig));\n  free_string_field (&(args_info->set_package_arg));\n  free_string_field (&(args_info->set_package_orig));\n  free_string_field (&(args_info->set_version_arg));\n  free_string_field (&(args_info->set_version_orig));\n\n\n\n  clear_given (args_info);\n}\n\n\nstatic void\nwrite_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])\n{\n  FIX_UNUSED (values);\n  if (arg) {\n    fprintf(outfile, \"%s=\\\"%s\\\"\\n\", opt, arg);\n  } else {\n    fprintf(outfile, \"%s\\n\", opt);\n  }\n}\n\n\nint\ncmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)\n{\n  int i = 0;\n\n  if (!outfile)\n    {\n      fprintf (stderr, \"%s: cannot dump options to stream\\n\", CMDLINE_PARSER_PACKAGE);\n      return EXIT_FAILURE;\n    }\n\n  if (args_info->help_given)\n    write_into_file(outfile, \"help\", 0, 0 );\n  if (args_info->detailed_help_given)\n    write_into_file(outfile, \"detailed-help\", 0, 0 );\n  if (args_info->version_given)\n    write_into_file(outfile, \"version\", 0, 0 );\n  if (args_info->input_given)\n    write_into_file(outfile, \"input\", args_info->input_orig, 0);\n  if (args_info->func_name_given)\n    write_into_file(outfile, \"func-name\", args_info->func_name_orig, 0);\n  if (args_info->arg_struct_name_given)\n    write_into_file(outfile, \"arg-struct-name\", args_info->arg_struct_name_orig, 0);\n  if (args_info->file_name_given)\n    write_into_file(outfile, \"file-name\", args_info->file_name_orig, 0);\n  if (args_info->output_dir_given)\n    write_into_file(outfile, \"output-dir\", args_info->output_dir_orig, 0);\n  if (args_info->header_output_dir_given)\n    write_into_file(outfile, \"header-output-dir\", args_info->header_output_dir_orig, 0);\n  if (args_info->src_output_dir_given)\n    write_into_file(outfile, \"src-output-dir\", args_info->src_output_dir_orig, 0);\n  if (args_info->c_extension_given)\n    write_into_file(outfile, \"c-extension\", args_info->c_extension_orig, 0);\n  if (args_info->header_extension_given)\n    write_into_file(outfile, \"header-extension\", args_info->header_extension_orig, 0);\n  if (args_info->long_help_given)\n    write_into_file(outfile, \"long-help\", 0, 0 );\n  if (args_info->default_optional_given)\n    write_into_file(outfile, \"default-optional\", 0, 0 );\n  if (args_info->unamed_opts_given)\n    write_into_file(outfile, \"unamed-opts\", args_info->unamed_opts_orig, 0);\n  if (args_info->conf_parser_given)\n    write_into_file(outfile, \"conf-parser\", 0, 0 );\n  if (args_info->string_parser_given)\n    write_into_file(outfile, \"string-parser\", 0, 0 );\n  if (args_info->include_getopt_given)\n    write_into_file(outfile, \"include-getopt\", 0, 0 );\n  if (args_info->no_handle_help_given)\n    write_into_file(outfile, \"no-handle-help\", 0, 0 );\n  if (args_info->no_help_given)\n    write_into_file(outfile, \"no-help\", 0, 0 );\n  if (args_info->no_handle_version_given)\n    write_into_file(outfile, \"no-handle-version\", 0, 0 );\n  if (args_info->no_version_given)\n    write_into_file(outfile, \"no-version\", 0, 0 );\n  if (args_info->no_handle_error_given)\n    write_into_file(outfile, \"no-handle-error\", 0, 0 );\n  if (args_info->show_required_given)\n    write_into_file(outfile, \"show-required\", args_info->show_required_orig, 0);\n  if (args_info->gen_version_given)\n    write_into_file(outfile, \"gen-version\", 0, 0 );\n  if (args_info->set_package_given)\n    write_into_file(outfile, \"set-package\", args_info->set_package_orig, 0);\n  if (args_info->set_version_given)\n    write_into_file(outfile, \"set-version\", args_info->set_version_orig, 0);\n  if (args_info->show_help_given)\n    write_into_file(outfile, \"show-help\", 0, 0 );\n  if (args_info->show_full_help_given)\n    write_into_file(outfile, \"show-full-help\", 0, 0 );\n  if (args_info->show_detailed_help_given)\n    write_into_file(outfile, \"show-detailed-help\", 0, 0 );\n  if (args_info->show_version_given)\n    write_into_file(outfile, \"show-version\", 0, 0 );\n\n\n  i = EXIT_SUCCESS;\n  return i;\n}\n\nint\ncmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)\n{\n  FILE *outfile;\n  int i = 0;\n\n  outfile = fopen(filename, \"w\");\n\n  if (!outfile)\n    {\n      fprintf (stderr, \"%s: cannot open file for writing: %s\\n\", CMDLINE_PARSER_PACKAGE, filename);\n      return EXIT_FAILURE;\n    }\n\n  i = cmdline_parser_dump(outfile, args_info);\n  fclose (outfile);\n\n  return i;\n}\n\nvoid\ncmdline_parser_free (struct gengetopt_args_info *args_info)\n{\n  cmdline_parser_release (args_info);\n}\n\n/** @brief replacement of strdup, which is not standard */\nchar *\ngengetopt_strdup (const char *s)\n{\n  char *result = 0;\n  if (!s)\n    return result;\n\n  result = (char*)malloc(strlen(s) + 1);\n  if (result == (char*)0)\n    return (char*)0;\n  strcpy(result, s);\n  return result;\n}\n\nint\ncmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)\n{\n  return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);\n}\n\nint\ncmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,\n                   struct cmdline_parser_params *params)\n{\n  int result;\n  result = cmdline_parser_internal (argc, argv, args_info, params, 0);\n\n  return result;\n}\n\nint\ncmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)\n{\n  int result;\n  struct cmdline_parser_params params;\n\n  params.override = override;\n  params.initialize = initialize;\n  params.check_required = check_required;\n  params.check_ambiguity = 0;\n  params.print_errors = 1;\n\n  result = cmdline_parser_internal (argc, argv, args_info, &params, 0);\n\n  return result;\n}\n\nint\ncmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)\n{\n  FIX_UNUSED (args_info);\n  FIX_UNUSED (prog_name);\n  return EXIT_SUCCESS;\n}\n\n\nstatic char *package_name = 0;\n\n/**\n * @brief updates an option\n * @param field the generic pointer to the field to update\n * @param orig_field the pointer to the orig field\n * @param field_given the pointer to the number of occurrence of this option\n * @param prev_given the pointer to the number of occurrence already seen\n * @param value the argument for this option (if null no arg was specified)\n * @param possible_values the possible values for this option (if specified)\n * @param default_value the default value (in case the option only accepts fixed values)\n * @param arg_type the type of this option\n * @param check_ambiguity @see cmdline_parser_params.check_ambiguity\n * @param override @see cmdline_parser_params.override\n * @param no_free whether to free a possible previous value\n * @param multiple_option whether this is a multiple option\n * @param long_opt the corresponding long option\n * @param short_opt the corresponding short option (or '-' if none)\n * @param additional_error possible further error specification\n */\nstatic\nint update_arg(void *field, char **orig_field,\n               unsigned int *field_given, unsigned int *prev_given,\n               char *value, const char *possible_values[],\n               const char *default_value,\n               cmdline_parser_arg_type arg_type,\n               int check_ambiguity, int override,\n               int no_free, int multiple_option,\n               const char *long_opt, char short_opt,\n               const char *additional_error)\n{\n  char *stop_char = 0;\n  const char *val = value;\n  int found;\n  char **string_field;\n  FIX_UNUSED (field);\n\n  stop_char = 0;\n  found = 0;\n\n  if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))\n    {\n      if (short_opt != '-')\n        fprintf (stderr, \"%s: `--%s' (`-%c') option given more than once%s\\n\",\n               package_name, long_opt, short_opt,\n               (additional_error ? additional_error : \"\"));\n      else\n        fprintf (stderr, \"%s: `--%s' option given more than once%s\\n\",\n               package_name, long_opt,\n               (additional_error ? additional_error : \"\"));\n      return 1; /* failure */\n    }\n\n  FIX_UNUSED (default_value);\n\n  if (field_given && *field_given && ! override)\n    return 0;\n  if (prev_given)\n    (*prev_given)++;\n  if (field_given)\n    (*field_given)++;\n  if (possible_values)\n    val = possible_values[found];\n\n  switch(arg_type) {\n  case ARG_FLAG:\n    *((int *)field) = !*((int *)field);\n    break;\n  case ARG_STRING:\n    if (val) {\n      string_field = (char **)field;\n      if (!no_free && *string_field)\n        free (*string_field); /* free previous string */\n      *string_field = gengetopt_strdup (val);\n    }\n    break;\n  default:\n    break;\n  };\n\n\n  /* store the original value */\n  switch(arg_type) {\n  case ARG_NO:\n  case ARG_FLAG:\n    break;\n  default:\n    if (value && orig_field) {\n      if (no_free) {\n        *orig_field = value;\n      } else {\n        if (*orig_field)\n          free (*orig_field); /* free previous string */\n        *orig_field = gengetopt_strdup (value);\n      }\n    }\n  };\n\n  return 0; /* OK */\n}\n\n\nint\ncmdline_parser_internal (\n  int argc, char **argv, struct gengetopt_args_info *args_info,\n                        struct cmdline_parser_params *params, const char *additional_error)\n{\n  int c;\t/* Character of the parsed option.  */\n\n  int error = 0;\n  struct gengetopt_args_info local_args_info;\n\n  int override;\n  int initialize;\n  int check_required;\n  int check_ambiguity;\n\n  package_name = argv[0];\n\n  override = params->override;\n  initialize = params->initialize;\n  check_required = params->check_required;\n  check_ambiguity = params->check_ambiguity;\n\n  if (initialize)\n    cmdline_parser_init (args_info);\n\n  cmdline_parser_init (&local_args_info);\n\n  optarg = 0;\n  optind = 0;\n  opterr = params->print_errors;\n  optopt = '?';\n\n  while (1)\n    {\n      int option_index = 0;\n\n      static struct option long_options[] = {\n        { \"help\",\t0, NULL, 'h' },\n        { \"detailed-help\",\t0, NULL, 0 },\n        { \"version\",\t0, NULL, 'V' },\n        { \"input\",\t1, NULL, 'i' },\n        { \"func-name\",\t1, NULL, 'f' },\n        { \"arg-struct-name\",\t1, NULL, 'a' },\n        { \"file-name\",\t1, NULL, 'F' },\n        { \"output-dir\",\t1, NULL, 0 },\n        { \"header-output-dir\",\t1, NULL, 0 },\n        { \"src-output-dir\",\t1, NULL, 0 },\n        { \"c-extension\",\t1, NULL, 'c' },\n        { \"header-extension\",\t1, NULL, 'H' },\n        { \"long-help\",\t0, NULL, 'l' },\n        { \"default-optional\",\t0, NULL, 0 },\n        { \"unamed-opts\",\t2, NULL, 'u' },\n        { \"conf-parser\",\t0, NULL, 'C' },\n        { \"string-parser\",\t0, NULL, 'S' },\n        { \"include-getopt\",\t0, NULL, 'G' },\n        { \"no-handle-help\",\t0, NULL, 'n' },\n        { \"no-help\",\t0, NULL, 0 },\n        { \"no-handle-version\",\t0, NULL, 'N' },\n        { \"no-version\",\t0, NULL, 0 },\n        { \"no-handle-error\",\t0, NULL, 'e' },\n        { \"show-required\",\t2, NULL, 0 },\n        { \"gen-version\",\t0, NULL, 'g' },\n        { \"set-package\",\t1, NULL, 0 },\n        { \"set-version\",\t1, NULL, 0 },\n        { \"show-help\",\t0, NULL, 0 },\n        { \"show-full-help\",\t0, NULL, 0 },\n        { \"show-detailed-help\",\t0, NULL, 0 },\n        { \"show-version\",\t0, NULL, 0 },\n        { 0,  0, 0, 0 }\n      };\n\n      c = getopt_long (argc, argv, \"hVi:f:a:F:c:H:lu::CSGnNeg\", long_options, &option_index);\n\n      if (c == -1) break;\t/* Exit from `while (1)' loop.  */\n\n      switch (c)\n        {\n        case 'h':\t/* Print help and exit.  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->help_given),\n              &(local_args_info.help_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"help\", 'h',\n              additional_error))\n            goto failure;\n          cmdline_parser_free (&local_args_info);\n          return 0;\n\n          break;\n        case 'V':\t/* Print version and exit.  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->version_given),\n              &(local_args_info.version_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"version\", 'V',\n              additional_error))\n            goto failure;\n          cmdline_parser_free (&local_args_info);\n          return 0;\n\n          break;\n        case 'i':\t/* input file (default std input).  */\n\n\n          if (update_arg( (void *)&(args_info->input_arg),\n               &(args_info->input_orig), &(args_info->input_given),\n              &(local_args_info.input_given), optarg, 0, 0, ARG_STRING,\n              check_ambiguity, override, 0, 0,\n              \"input\", 'i',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'f':\t/* name of generated function.  */\n\n\n          if (update_arg( (void *)&(args_info->func_name_arg),\n               &(args_info->func_name_orig), &(args_info->func_name_given),\n              &(local_args_info.func_name_given), optarg, 0, \"cmdline_parser\", ARG_STRING,\n              check_ambiguity, override, 0, 0,\n              \"func-name\", 'f',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'a':\t/* name of generated args info struct.  */\n\n\n          if (update_arg( (void *)&(args_info->arg_struct_name_arg),\n               &(args_info->arg_struct_name_orig), &(args_info->arg_struct_name_given),\n              &(local_args_info.arg_struct_name_given), optarg, 0, \"gengetopt_args_info\", ARG_STRING,\n              check_ambiguity, override, 0, 0,\n              \"arg-struct-name\", 'a',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'F':\t/* name of generated file.  */\n\n\n          if (update_arg( (void *)&(args_info->file_name_arg),\n               &(args_info->file_name_orig), &(args_info->file_name_given),\n              &(local_args_info.file_name_given), optarg, 0, \"cmdline\", ARG_STRING,\n              check_ambiguity, override, 0, 0,\n              \"file-name\", 'F',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'c':\t/* extension of c file.  */\n\n\n          if (update_arg( (void *)&(args_info->c_extension_arg),\n               &(args_info->c_extension_orig), &(args_info->c_extension_given),\n              &(local_args_info.c_extension_given), optarg, 0, \"c\", ARG_STRING,\n              check_ambiguity, override, 0, 0,\n              \"c-extension\", 'c',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'H':\t/* extension of header file.  */\n\n\n          if (update_arg( (void *)&(args_info->header_extension_arg),\n               &(args_info->header_extension_orig), &(args_info->header_extension_given),\n              &(local_args_info.header_extension_given), optarg, 0, \"h\", ARG_STRING,\n              check_ambiguity, override, 0, 0,\n              \"header-extension\", 'H',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'l':\t/* long usage line in help.  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->long_help_given),\n              &(local_args_info.long_help_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"long-help\", 'l',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'u':\t/* accept options without names (e.g., file names).  */\n\n\n          if (update_arg( (void *)&(args_info->unamed_opts_arg),\n               &(args_info->unamed_opts_orig), &(args_info->unamed_opts_given),\n              &(local_args_info.unamed_opts_given), optarg, 0, \"FILES\", ARG_STRING,\n              check_ambiguity, override, 0, 0,\n              \"unamed-opts\", 'u',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'C':\t/* generate a config file parser.  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->conf_parser_given),\n              &(local_args_info.conf_parser_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"conf-parser\", 'C',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'S':\t/* generate a string parser (the string contains the command line).  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->string_parser_given),\n              &(local_args_info.string_parser_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"string-parser\", 'S',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'G':\t/* adds the code for getopt_long in the generated C file.  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->include_getopt_given),\n              &(local_args_info.include_getopt_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"include-getopt\", 'G',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'n':\t/* do not handle --help|-h automatically.  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->no_handle_help_given),\n              &(local_args_info.no_handle_help_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"no-handle-help\", 'n',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'N':\t/* do not handle --version|-V automatically.  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->no_handle_version_given),\n              &(local_args_info.no_handle_version_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"no-handle-version\", 'N',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'e':\t/* do not exit on errors.  */\n\n\n          if (update_arg( 0 ,\n               0 , &(args_info->no_handle_error_given),\n              &(local_args_info.no_handle_error_given), optarg, 0, 0, ARG_NO,\n              check_ambiguity, override, 0, 0,\n              \"no-handle-error\", 'e',\n              additional_error))\n            goto failure;\n\n          break;\n        case 'g':\t/* put gengetopt version in the generated file.  */\n\n\n          if (update_arg((void *)&(args_info->gen_version_flag), 0, &(args_info->gen_version_given),\n              &(local_args_info.gen_version_given), optarg, 0, 0, ARG_FLAG,\n              check_ambiguity, override, 1, 0, \"gen-version\", 'g',\n              additional_error))\n            goto failure;\n\n          break;\n\n        case 0:\t/* Long option with no short option */\n          /* Print help, including all details and hidden options, and exit.  */\n          if (strcmp (long_options[option_index].name, \"detailed-help\") == 0)\n          {\n\n\n            if (update_arg( 0 ,\n                 0 , &(args_info->detailed_help_given),\n                &(local_args_info.detailed_help_given), optarg, 0, 0, ARG_NO,\n                check_ambiguity, override, 0, 0,\n                \"detailed-help\", '-',\n                additional_error))\n              goto failure;\n            cmdline_parser_free (&local_args_info);\n            return 0;\n\n          }\n          /* output directory.  */\n          else if (strcmp (long_options[option_index].name, \"output-dir\") == 0)\n          {\n\n\n            if (update_arg( (void *)&(args_info->output_dir_arg),\n                 &(args_info->output_dir_orig), &(args_info->output_dir_given),\n                &(local_args_info.output_dir_given), optarg, 0, 0, ARG_STRING,\n                check_ambiguity, override, 0, 0,\n                \"output-dir\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* header output directory.  */\n          else if (strcmp (long_options[option_index].name, \"header-output-dir\") == 0)\n          {\n\n\n            if (update_arg( (void *)&(args_info->header_output_dir_arg),\n                 &(args_info->header_output_dir_orig), &(args_info->header_output_dir_given),\n                &(local_args_info.header_output_dir_given), optarg, 0, 0, ARG_STRING,\n                check_ambiguity, override, 0, 0,\n                \"header-output-dir\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* source output directory.  */\n          else if (strcmp (long_options[option_index].name, \"src-output-dir\") == 0)\n          {\n\n\n            if (update_arg( (void *)&(args_info->src_output_dir_arg),\n                 &(args_info->src_output_dir_orig), &(args_info->src_output_dir_given),\n                &(local_args_info.src_output_dir_given), optarg, 0, 0, ARG_STRING,\n                check_ambiguity, override, 0, 0,\n                \"src-output-dir\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* by default, an option is considered optional if not specified otherwise.  */\n          else if (strcmp (long_options[option_index].name, \"default-optional\") == 0)\n          {\n\n\n            if (update_arg( 0 ,\n                 0 , &(args_info->default_optional_given),\n                &(local_args_info.default_optional_given), optarg, 0, 0, ARG_NO,\n                check_ambiguity, override, 0, 0,\n                \"default-optional\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* do not add --help|-h automatically.  */\n          else if (strcmp (long_options[option_index].name, \"no-help\") == 0)\n          {\n\n\n            if (update_arg( 0 ,\n                 0 , &(args_info->no_help_given),\n                &(local_args_info.no_help_given), optarg, 0, 0, ARG_NO,\n                check_ambiguity, override, 0, 0,\n                \"no-help\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* do not add --version|-V automatically.  */\n          else if (strcmp (long_options[option_index].name, \"no-version\") == 0)\n          {\n\n\n            if (update_arg( 0 ,\n                 0 , &(args_info->no_version_given),\n                &(local_args_info.no_version_given), optarg, 0, 0, ARG_NO,\n                check_ambiguity, override, 0, 0,\n                \"no-version\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* in the output of help will specify which options are mandatory, by using the optional passed string.  */\n          else if (strcmp (long_options[option_index].name, \"show-required\") == 0)\n          {\n\n\n            if (update_arg( (void *)&(args_info->show_required_arg),\n                 &(args_info->show_required_orig), &(args_info->show_required_given),\n                &(local_args_info.show_required_given), optarg, 0, \"(mandatory)\", ARG_STRING,\n                check_ambiguity, override, 0, 0,\n                \"show-required\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* set the package name (override package defined in the .ggo file).  */\n          else if (strcmp (long_options[option_index].name, \"set-package\") == 0)\n          {\n\n\n            if (update_arg( (void *)&(args_info->set_package_arg),\n                 &(args_info->set_package_orig), &(args_info->set_package_given),\n                &(local_args_info.set_package_given), optarg, 0, 0, ARG_STRING,\n                check_ambiguity, override, 0, 0,\n                \"set-package\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* set the version number (override version defined in the .ggo file).  */\n          else if (strcmp (long_options[option_index].name, \"set-version\") == 0)\n          {\n\n\n            if (update_arg( (void *)&(args_info->set_version_arg),\n                 &(args_info->set_version_orig), &(args_info->set_version_given),\n                &(local_args_info.set_version_given), optarg, 0, 0, ARG_STRING,\n                check_ambiguity, override, 0, 0,\n                \"set-version\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* show the output of --help instead of generating code.  */\n          else if (strcmp (long_options[option_index].name, \"show-help\") == 0)\n          {\n\n\n            if (update_arg( 0 ,\n                 0 , &(args_info->show_help_given),\n                &(local_args_info.show_help_given), optarg, 0, 0, ARG_NO,\n                check_ambiguity, override, 0, 0,\n                \"show-help\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* show the output of --full-help (i.e., including hidden options) instead of generating code.  */\n          else if (strcmp (long_options[option_index].name, \"show-full-help\") == 0)\n          {\n\n\n            if (update_arg( 0 ,\n                 0 , &(args_info->show_full_help_given),\n                &(local_args_info.show_full_help_given), optarg, 0, 0, ARG_NO,\n                check_ambiguity, override, 0, 0,\n                \"show-full-help\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* show the output of --detailed-help (i.e., including details and hidden options) instead of generating code.  */\n          else if (strcmp (long_options[option_index].name, \"show-detailed-help\") == 0)\n          {\n\n\n            if (update_arg( 0 ,\n                 0 , &(args_info->show_detailed_help_given),\n                &(local_args_info.show_detailed_help_given), optarg, 0, 0, ARG_NO,\n                check_ambiguity, override, 0, 0,\n                \"show-detailed-help\", '-',\n                additional_error))\n              goto failure;\n\n          }\n          /* show the output of --version instead of generating code.  */\n          else if (strcmp (long_options[option_index].name, \"show-version\") == 0)\n          {\n\n\n            if (update_arg( 0 ,\n                 0 , &(args_info->show_version_given),\n                &(local_args_info.show_version_given), optarg, 0, 0, ARG_NO,\n                check_ambiguity, override, 0, 0,\n                \"show-version\", '-',\n                additional_error))\n              goto failure;\n\n          }\n\n          break;\n        case '?':\t/* Invalid option.  */\n          /* `getopt_long' already printed an error message.  */\n          goto failure;\n\n        default:\t/* bug: option not considered.  */\n          fprintf (stderr, \"%s: option unknown: %c%s\\n\", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : \"\"));\n          abort ();\n        } /* switch */\n    } /* while */\n\n\n\n\n  cmdline_parser_release (&local_args_info);\n\n  if ( error )\n    return (EXIT_FAILURE);\n\n  return 0;\n\nfailure:\n\n  cmdline_parser_release (&local_args_info);\n  return (EXIT_FAILURE);\n}\n\nstatic unsigned int\ncmdline_parser_create_argv(const char *cmdline_, char ***argv_ptr, const char *prog_name)\n{\n  char *cmdline, *p;\n  size_t n = 0, j;\n  int i;\n\n  if (prog_name) {\n    cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));\n    cmd_line_list_tmp->next = cmd_line_list;\n    cmd_line_list = cmd_line_list_tmp;\n    cmd_line_list->string_arg = gengetopt_strdup (prog_name);\n\n    ++n;\n  }\n\n  cmdline = gengetopt_strdup(cmdline_);\n  p = cmdline;\n\n  while (p && strlen(p))\n    {\n      j = strcspn(p, \" \\t\");\n      ++n;\n      if (j && j < strlen(p))\n        {\n          p[j] = '\\0';\n\n          cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));\n          cmd_line_list_tmp->next = cmd_line_list;\n          cmd_line_list = cmd_line_list_tmp;\n          cmd_line_list->string_arg = gengetopt_strdup (p);\n\n          p += (j+1);\n          p += strspn(p, \" \\t\");\n        }\n      else\n        {\n          cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));\n          cmd_line_list_tmp->next = cmd_line_list;\n          cmd_line_list = cmd_line_list_tmp;\n          cmd_line_list->string_arg = gengetopt_strdup (p);\n\n          break;\n        }\n    }\n\n  *argv_ptr = (char **) malloc((n + 1) * sizeof(char *));\n  cmd_line_list_tmp = cmd_line_list;\n  for (i = (n-1); i >= 0; --i)\n    {\n      (*argv_ptr)[i] = cmd_line_list_tmp->string_arg;\n      cmd_line_list_tmp = cmd_line_list_tmp->next;\n    }\n\n  (*argv_ptr)[n] = 0;\n\n  free(cmdline);\n  return n;\n}\n\nint\ncmdline_parser_string(const char *cmdline, struct gengetopt_args_info *args_info, const char *prog_name)\n{\n  return cmdline_parser_string2(cmdline, args_info, prog_name, 0, 1, 1);\n}\n\nint\ncmdline_parser_string2(const char *cmdline, struct gengetopt_args_info *args_info, const char *prog_name,\n    int override, int initialize, int check_required)\n{\n  struct cmdline_parser_params params;\n\n  params.override = override;\n  params.initialize = initialize;\n  params.check_required = check_required;\n  params.check_ambiguity = 0;\n  params.print_errors = 1;\n\n  return cmdline_parser_string_ext(cmdline, args_info, prog_name, &params);\n}\n\nint\ncmdline_parser_string_ext(const char *cmdline, struct gengetopt_args_info *args_info, const char *prog_name,\n    struct cmdline_parser_params *params)\n{\n  char **argv_ptr = 0;\n  int result;\n  unsigned int argc;\n\n  argc = cmdline_parser_create_argv(cmdline, &argv_ptr, prog_name);\n\n  result =\n    cmdline_parser_internal (argc, argv_ptr, args_info, params, 0);\n\n  if (argv_ptr)\n    {\n      free (argv_ptr);\n    }\n\n  free_cmd_list();\n\n  return result;\n}\n\n"
  },
  {
    "path": "utilities/gengetopt/cmdline.ggo",
    "content": "# Copyright (C) 1999-2010  Free Software Foundation, Inc.\n#\n# This file is part of GNU gengetopt\n#\n# GNU gengetopt is free software; you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation; either version 2, or (at your option)\n# any later version.\n#\n# GNU gengetopt is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n# Public License for more details.\n#\n# You should have received a copy of the GNU General Public License along\n# with gengetopt; see the file COPYING. If not, write to the Free Software\n# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n\n\n# Specification file format:\n#\n# This file consist in lines of sentences with the following format:\n#\n#         package <packname>\n#         version <version>\n#         purpose <string>\n#         option <long> <short> <desc> <argtype> <required>\n#         option <long> <short> <desc> flag      <onoff>\n#         option <long> <short> <desc> <required>\n#         ... # ...\n#\n# Where:\n#\n# <packname> = Double quoted string.\n# <version>  = Double quoted string.\n# <purpose>  = What the program does\n#              Double quoted string (even on more than one line)\n# <long>     = Double quoted string with upper and lower case chars, digits,\n#              '-' and '.'.  No spaces allowed.\n# <short>    = A single upper or lower case char, or a digit.\n# <desc>     = String with upper and lower case chars, digits, '-', '.' and\n#              spaces.\n# <argtype>  = string, int, short, long, float, double, longdouble or longlong.\n# <required> = required or optional.\n# <onoff>    = on or off.\n# Comments begins with '#' in any place of the line and ends in the\n# end of line.\n# The third form of option is used if the option does not take an argument;\n# it must not be required.\n\n\n# Name of our program\n#package \"gengetopt\"       # we don't use it: we're using automake\n# Version of our program\n#version \"1.0.1\"           # we don't use it: we're using automake\n\npurpose \"This program generates a C function that uses getopt_long function\nto parse the command line options, validate them and fill a struct.\"\n\n# options that will be added to command line options of gengetopt\nargs \"--no-handle-version --no-handle-help --no-handle-error --string-parser\"\n\n# Options\n\nsection \"Main options\"\n\ntext \"\"\n\noption  \"input\"         i \"input file (default std input)\"  string typestr=\"filename\"     optional\noption  \"func-name\"     f \"name of generated function\" string typestr=\"name\"  default=\"cmdline_parser\"   optional\noption  \"arg-struct-name\" a \"name of generated args info struct\" string typestr=\"name\"  default=\"gengetopt_args_info\"   optional\noption  \"file-name\"     F \"name of generated file\"  string typestr=\"name\"  default=\"cmdline\"     optional\noption  \"output-dir\"     - \"output directory\"  string typestr=\"path\"  optional\n\tdetails=\"\\nif this option is not specified, the \\\nfiles are generated in the current directory.\\n\"\noption  \"header-output-dir\"     - \"header output directory\"  string typestr=\"path\" optional\noption  \"src-output-dir\"     - \"source output directory\"  string typestr=\"path\" optional\noption  \"c-extension\"   c \"extension of c file\" string typestr=\"ext\" default=\"c\" optional\noption  \"header-extension\"   H \"extension of header file\" string typestr=\"ext\" default=\"h\" optional\noption  \"long-help\"     l \"long usage line in help\" optional\n\tdetails=\"\\nThe usage line will print all the options, e.g.,\n\nsample1 -iINT|--int-opt=INT [-h|--help]\\n\"\noption  \"default-optional\"     - \"by default, an option is considered optional if not specified otherwise\" optional\noption  \"unamed-opts\"   u \"accept options without names (e.g., file names)\" string default=\"FILES\" optional argoptional\n\ntext \"\\nThe parser generated is thought to be used to parse the command line arguments. \"\ntext \"However, you can also generate parsers for configuration files, or strings \"\ntext \"that contain the arguments to parse, by using the following two options.\\n\"\n\noption  \"conf-parser\" C \"generate a config file parser\" optional\noption  \"string-parser\" S \"generate a string parser (the string contains the command line)\" optional\n\ntext \"\"\n\nsection \"Additional options\"\n\noption  \"include-getopt\" G \"adds the code for getopt_long in the generated C file\" optional\n\noption  \"no-handle-help\"   n \"do not handle --help|-h automatically\" optional\n\tdetails=\"\\nIf --no-handle-help is specified, the command line option \\\n--help|-h will not be handled automatically, so the programmer will be able \\\nto print some \\\nother information; then the function for printing the standard help \\\noutput can be used; this function is called \\\n<parser-name>_print_help.\\n\\nNotice \\\nthat, although the programmer can handle --help|-h manually, the \\\nparser will return after finding such option: the other command \\\nline options, if any, will be ignored.  In case you want to have full \\\ncontrol on --help|-h, you should use --ho-help.\\n\"\n\t\noption  \"no-help\"   - \"do not add --help|-h automatically\" optional\n\tdetails=\"\\nWith this option you can disable the \\\nautomatic addition of options --help|-h. The programmer \\\nwill then be able to add this option in \\\nthe input file and handle it as he sees fit.  Notice that \\\n--no-help will also disable the automatic options \\\n--detailed-help and --full-help.\n\nThe programmer can still \\\ndefine options with short character h as he wants, \\\nbut he cannot define options help, unless he \\\nspecifies --no-help \\\n(otherwise an error will be printed).\\n\"\n\noption  \"no-handle-version\"  N  \"do not handle --version|-V automatically\" optional\noption  \"no-version\"  -  \"do not add --version|-V automatically\" optional\n\tdetails=\"\\nSee above the details about \\\n--no-handle-help and --no-help, respectively.\\n\"\n\noption  \"no-handle-error\" e \"do not exit on errors\" optional\n\tdetails=\"\\nWith this option, if the generated parser encounters an error \\\n(e.g., an unknown option) it does not make the main program exit; instead, the parser \\\nfunction returns a value different 0, and the main program can print a help message.\\n\"\n\noption  \"show-required\"   - \"in the output of help will specify which options are mandatory, \\\nby using the optional passed string\" string default=\"(mandatory)\" optional argoptional\n\noption  \"gen-version\" g \"put gengetopt version in the generated file\" flag on\noption  \"set-package\" - \"set the package name (override package defined in the .ggo file)\" string optional\noption  \"set-version\" - \"set the version number (override version defined in the .ggo file)\" string optional\noption  \"show-help\" - \"show the output of --help instead of generating code\" optional\noption  \"show-full-help\" - \"show the output of --full-help (i.e., including hidden options) instead of generating code\" optional\noption  \"show-detailed-help\" - \"show the output of --detailed-help (i.e., including details and hidden options) instead of generating code\" optional\noption  \"show-version\" - \"show the output of --version instead of generating code\" optional\n\ntext \"\\nPlease refer to the info manual for further explanations.\"\n"
  },
  {
    "path": "utilities/gengetopt/cmdline.h",
    "content": "/** @file cmdline.h\n *  @brief The header file for the command line option parser\n *  generated by GNU Gengetopt version 2.22.4\n *  https://www.gnu.org/software/gengetopt.\n *  DO NOT modify this file, since it can be overwritten\n *  @author GNU Gengetopt by Lorenzo Bettini */\n\n#ifndef CMDLINE_H\n#define CMDLINE_H\n\n/* If we use autoconf.  */\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdio.h> /* for FILE */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif /* __cplusplus */\n\n#ifndef CMDLINE_PARSER_PACKAGE\n/** @brief the program name (used for printing errors) */\n#define CMDLINE_PARSER_PACKAGE PACKAGE\n#endif\n\n#ifndef CMDLINE_PARSER_PACKAGE_NAME\n/** @brief the complete program name (used for help and version) */\n#ifdef PACKAGE_NAME\n#define CMDLINE_PARSER_PACKAGE_NAME PACKAGE_NAME\n#else\n#define CMDLINE_PARSER_PACKAGE_NAME PACKAGE\n#endif\n#endif\n\n#ifndef CMDLINE_PARSER_VERSION\n/** @brief the program version */\n#define CMDLINE_PARSER_VERSION VERSION\n#endif\n\n/** @brief Where the command line options are stored */\nstruct gengetopt_args_info\n{\n  const char *help_help; /**< @brief Print help and exit help description.  */\n  const char *detailed_help_help; /**< @brief Print help, including all details and hidden options, and exit help description.  */\n  const char *version_help; /**< @brief Print version and exit help description.  */\n  char * input_arg;\t/**< @brief input file (default std input).  */\n  char * input_orig;\t/**< @brief input file (default std input) original value given at command line.  */\n  const char *input_help; /**< @brief input file (default std input) help description.  */\n  char * func_name_arg;\t/**< @brief name of generated function (default='cmdline_parser').  */\n  char * func_name_orig;\t/**< @brief name of generated function original value given at command line.  */\n  const char *func_name_help; /**< @brief name of generated function help description.  */\n  char * arg_struct_name_arg;\t/**< @brief name of generated args info struct (default='gengetopt_args_info').  */\n  char * arg_struct_name_orig;\t/**< @brief name of generated args info struct original value given at command line.  */\n  const char *arg_struct_name_help; /**< @brief name of generated args info struct help description.  */\n  char * file_name_arg;\t/**< @brief name of generated file (default='cmdline').  */\n  char * file_name_orig;\t/**< @brief name of generated file original value given at command line.  */\n  const char *file_name_help; /**< @brief name of generated file help description.  */\n  char * output_dir_arg;\t/**< @brief output directory.  */\n  char * output_dir_orig;\t/**< @brief output directory original value given at command line.  */\n  const char *output_dir_help; /**< @brief output directory help description.  */\n  char * header_output_dir_arg;\t/**< @brief header output directory.  */\n  char * header_output_dir_orig;\t/**< @brief header output directory original value given at command line.  */\n  const char *header_output_dir_help; /**< @brief header output directory help description.  */\n  char * src_output_dir_arg;\t/**< @brief source output directory.  */\n  char * src_output_dir_orig;\t/**< @brief source output directory original value given at command line.  */\n  const char *src_output_dir_help; /**< @brief source output directory help description.  */\n  char * c_extension_arg;\t/**< @brief extension of c file (default='c').  */\n  char * c_extension_orig;\t/**< @brief extension of c file original value given at command line.  */\n  const char *c_extension_help; /**< @brief extension of c file help description.  */\n  char * header_extension_arg;\t/**< @brief extension of header file (default='h').  */\n  char * header_extension_orig;\t/**< @brief extension of header file original value given at command line.  */\n  const char *header_extension_help; /**< @brief extension of header file help description.  */\n  const char *long_help_help; /**< @brief long usage line in help help description.  */\n  const char *default_optional_help; /**< @brief by default, an option is considered optional if not specified otherwise help description.  */\n  char * unamed_opts_arg;\t/**< @brief accept options without names (e.g., file names) (default='FILES').  */\n  char * unamed_opts_orig;\t/**< @brief accept options without names (e.g., file names) original value given at command line.  */\n  const char *unamed_opts_help; /**< @brief accept options without names (e.g., file names) help description.  */\n  const char *conf_parser_help; /**< @brief generate a config file parser help description.  */\n  const char *string_parser_help; /**< @brief generate a string parser (the string contains the command line) help description.  */\n  const char *include_getopt_help; /**< @brief adds the code for getopt_long in the generated C file help description.  */\n  const char *no_handle_help_help; /**< @brief do not handle --help|-h automatically help description.  */\n  const char *no_help_help; /**< @brief do not add --help|-h automatically help description.  */\n  const char *no_handle_version_help; /**< @brief do not handle --version|-V automatically help description.  */\n  const char *no_version_help; /**< @brief do not add --version|-V automatically help description.  */\n  const char *no_handle_error_help; /**< @brief do not exit on errors help description.  */\n  char * show_required_arg;\t/**< @brief in the output of help will specify which options are mandatory, by using the optional passed string (default='(mandatory)').  */\n  char * show_required_orig;\t/**< @brief in the output of help will specify which options are mandatory, by using the optional passed string original value given at command line.  */\n  const char *show_required_help; /**< @brief in the output of help will specify which options are mandatory, by using the optional passed string help description.  */\n  int gen_version_flag;\t/**< @brief put gengetopt version in the generated file (default=on).  */\n  const char *gen_version_help; /**< @brief put gengetopt version in the generated file help description.  */\n  char * set_package_arg;\t/**< @brief set the package name (override package defined in the .ggo file).  */\n  char * set_package_orig;\t/**< @brief set the package name (override package defined in the .ggo file) original value given at command line.  */\n  const char *set_package_help; /**< @brief set the package name (override package defined in the .ggo file) help description.  */\n  char * set_version_arg;\t/**< @brief set the version number (override version defined in the .ggo file).  */\n  char * set_version_orig;\t/**< @brief set the version number (override version defined in the .ggo file) original value given at command line.  */\n  const char *set_version_help; /**< @brief set the version number (override version defined in the .ggo file) help description.  */\n  const char *show_help_help; /**< @brief show the output of --help instead of generating code help description.  */\n  const char *show_full_help_help; /**< @brief show the output of --full-help (i.e., including hidden options) instead of generating code help description.  */\n  const char *show_detailed_help_help; /**< @brief show the output of --detailed-help (i.e., including details and hidden options) instead of generating code help description.  */\n  const char *show_version_help; /**< @brief show the output of --version instead of generating code help description.  */\n\n  unsigned int help_given ;\t/**< @brief Whether help was given.  */\n  unsigned int detailed_help_given ;\t/**< @brief Whether detailed-help was given.  */\n  unsigned int version_given ;\t/**< @brief Whether version was given.  */\n  unsigned int input_given ;\t/**< @brief Whether input was given.  */\n  unsigned int func_name_given ;\t/**< @brief Whether func-name was given.  */\n  unsigned int arg_struct_name_given ;\t/**< @brief Whether arg-struct-name was given.  */\n  unsigned int file_name_given ;\t/**< @brief Whether file-name was given.  */\n  unsigned int output_dir_given ;\t/**< @brief Whether output-dir was given.  */\n  unsigned int header_output_dir_given ;\t/**< @brief Whether header-output-dir was given.  */\n  unsigned int src_output_dir_given ;\t/**< @brief Whether src-output-dir was given.  */\n  unsigned int c_extension_given ;\t/**< @brief Whether c-extension was given.  */\n  unsigned int header_extension_given ;\t/**< @brief Whether header-extension was given.  */\n  unsigned int long_help_given ;\t/**< @brief Whether long-help was given.  */\n  unsigned int default_optional_given ;\t/**< @brief Whether default-optional was given.  */\n  unsigned int unamed_opts_given ;\t/**< @brief Whether unamed-opts was given.  */\n  unsigned int conf_parser_given ;\t/**< @brief Whether conf-parser was given.  */\n  unsigned int string_parser_given ;\t/**< @brief Whether string-parser was given.  */\n  unsigned int include_getopt_given ;\t/**< @brief Whether include-getopt was given.  */\n  unsigned int no_handle_help_given ;\t/**< @brief Whether no-handle-help was given.  */\n  unsigned int no_help_given ;\t/**< @brief Whether no-help was given.  */\n  unsigned int no_handle_version_given ;\t/**< @brief Whether no-handle-version was given.  */\n  unsigned int no_version_given ;\t/**< @brief Whether no-version was given.  */\n  unsigned int no_handle_error_given ;\t/**< @brief Whether no-handle-error was given.  */\n  unsigned int show_required_given ;\t/**< @brief Whether show-required was given.  */\n  unsigned int gen_version_given ;\t/**< @brief Whether gen-version was given.  */\n  unsigned int set_package_given ;\t/**< @brief Whether set-package was given.  */\n  unsigned int set_version_given ;\t/**< @brief Whether set-version was given.  */\n  unsigned int show_help_given ;\t/**< @brief Whether show-help was given.  */\n  unsigned int show_full_help_given ;\t/**< @brief Whether show-full-help was given.  */\n  unsigned int show_detailed_help_given ;\t/**< @brief Whether show-detailed-help was given.  */\n  unsigned int show_version_given ;\t/**< @brief Whether show-version was given.  */\n\n} ;\n\n/** @brief The additional parameters to pass to parser functions */\nstruct cmdline_parser_params\n{\n  int override; /**< @brief whether to override possibly already present options (default 0) */\n  int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */\n  int check_required; /**< @brief whether to check that all required options were provided (default 1) */\n  int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */\n  int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */\n} ;\n\n/** @brief the purpose string of the program */\nextern const char *gengetopt_args_info_purpose;\n/** @brief the usage string of the program */\nextern const char *gengetopt_args_info_usage;\n/** @brief all the lines making the help output */\nextern const char *gengetopt_args_info_help[];\n/** @brief all the lines making the detailed help output (including hidden options and details) */\nextern const char *gengetopt_args_info_detailed_help[];\n\n/**\n * The command line parser\n * @param argc the number of command line options\n * @param argv the command line options\n * @param args_info the structure where option information will be stored\n * @return 0 if everything went fine, NON 0 if an error took place\n */\nint cmdline_parser (int argc, char **argv,\n  struct gengetopt_args_info *args_info);\n\n/**\n * The command line parser (version with additional parameters - deprecated)\n * @param argc the number of command line options\n * @param argv the command line options\n * @param args_info the structure where option information will be stored\n * @param override whether to override possibly already present options\n * @param initialize whether to initialize the option structure my_args_info\n * @param check_required whether to check that all required options were provided\n * @return 0 if everything went fine, NON 0 if an error took place\n * @deprecated use cmdline_parser_ext() instead\n */\nint cmdline_parser2 (int argc, char **argv,\n  struct gengetopt_args_info *args_info,\n  int override, int initialize, int check_required);\n\n/**\n * The command line parser (version with additional parameters)\n * @param argc the number of command line options\n * @param argv the command line options\n * @param args_info the structure where option information will be stored\n * @param params additional parameters for the parser\n * @return 0 if everything went fine, NON 0 if an error took place\n */\nint cmdline_parser_ext (int argc, char **argv,\n  struct gengetopt_args_info *args_info,\n  struct cmdline_parser_params *params);\n\n/**\n * Save the contents of the option struct into an already open FILE stream.\n * @param outfile the stream where to dump options\n * @param args_info the option struct to dump\n * @return 0 if everything went fine, NON 0 if an error took place\n */\nint cmdline_parser_dump(FILE *outfile,\n  struct gengetopt_args_info *args_info);\n\n/**\n * Save the contents of the option struct into a (text) file.\n * This file can be read by the config file parser (if generated by gengetopt)\n * @param filename the file where to save\n * @param args_info the option struct to save\n * @return 0 if everything went fine, NON 0 if an error took place\n */\nint cmdline_parser_file_save(const char *filename,\n  struct gengetopt_args_info *args_info);\n\n/**\n * Print the help\n */\nvoid cmdline_parser_print_help(void);\n/**\n * Print the detailed help (including hidden options and details)\n */\nvoid cmdline_parser_print_detailed_help(void);\n/**\n * Print the version\n */\nvoid cmdline_parser_print_version(void);\n\n/**\n * Initializes all the fields a cmdline_parser_params structure\n * to their default values\n * @param params the structure to initialize\n */\nvoid cmdline_parser_params_init(struct cmdline_parser_params *params);\n\n/**\n * Allocates dynamically a cmdline_parser_params structure and initializes\n * all its fields to their default values\n * @return the created and initialized cmdline_parser_params structure\n */\nstruct cmdline_parser_params *cmdline_parser_params_create(void);\n\n/**\n * Initializes the passed gengetopt_args_info structure's fields\n * (also set default values for options that have a default)\n * @param args_info the structure to initialize\n */\nvoid cmdline_parser_init (struct gengetopt_args_info *args_info);\n/**\n * Deallocates the string fields of the gengetopt_args_info structure\n * (but does not deallocate the structure itself)\n * @param args_info the structure to deallocate\n */\nvoid cmdline_parser_free (struct gengetopt_args_info *args_info);\n\n/**\n * The string parser (interprets the passed string as a command line)\n * @param cmdline the command line stirng\n * @param args_info the structure where option information will be stored\n * @param prog_name the name of the program that will be used to print\n *   possible errors\n * @return 0 if everything went fine, NON 0 if an error took place\n */\nint cmdline_parser_string (const char *cmdline, struct gengetopt_args_info *args_info,\n  const char *prog_name);\n/**\n * The string parser (version with additional parameters - deprecated)\n * @param cmdline the command line stirng\n * @param args_info the structure where option information will be stored\n * @param prog_name the name of the program that will be used to print\n *   possible errors\n * @param override whether to override possibly already present options\n * @param initialize whether to initialize the option structure my_args_info\n * @param check_required whether to check that all required options were provided\n * @return 0 if everything went fine, NON 0 if an error took place\n * @deprecated use cmdline_parser_string_ext() instead\n */\nint cmdline_parser_string2 (const char *cmdline, struct gengetopt_args_info *args_info,\n  const char *prog_name,\n  int override, int initialize, int check_required);\n/**\n * The string parser (version with additional parameters)\n * @param cmdline the command line stirng\n * @param args_info the structure where option information will be stored\n * @param prog_name the name of the program that will be used to print\n *   possible errors\n * @param params additional parameters for the parser\n * @return 0 if everything went fine, NON 0 if an error took place\n */\nint cmdline_parser_string_ext (const char *cmdline, struct gengetopt_args_info *args_info,\n  const char *prog_name,\n  struct cmdline_parser_params *params);\n\n/**\n * Checks that all the required options were specified\n * @param args_info the structure to check\n * @param prog_name the name of the program that will be used to print\n *   possible errors\n * @return\n */\nint cmdline_parser_required (struct gengetopt_args_info *args_info,\n  const char *prog_name);\n\n\n#ifdef __cplusplus\n}\n#endif /* __cplusplus */\n#endif /* CMDLINE_H */\n"
  },
  {
    "path": "utilities/gengetopt/errorcodes.h",
    "content": "//\n// C++ Interface: errorcodes\n//\n// Description:\n//\n//\n// Author: Lorenzo Bettini <https://www.lorenzobettini.it>, (C) 2004\n//\n// Copyright: See COPYING file that comes with this distribution\n//\n//\n\n#ifndef ERRORCODES_H\n#define ERRORCODES_H\n\n#define NOT_ENOUGH_MEMORY 1\n#define REQ_LONG_OPTION 2\n#define REQ_SHORT_OPTION 3\n#define FOUND_BUG 4\n#define GROUP_UNDEFINED 5\n#define INVALID_DEFAULT_VALUE 6\n#define NOT_REQUESTED_TYPE 7\n#define NOT_VALID_SPECIFICATION 8\n#define SPECIFY_FLAG_STAT 9\n#define NOT_GROUP_OPTION 10\n#define SPECIFY_GROUP 11\n#define INVALID_NUMERIC_VALUE 12\n#define INVALID_ENUM_TYPE_USE 13\n#define MODE_UNDEFINED 14\n#define NOT_MODE_OPTION 15\n#define SPECIFY_MODE 16\n#define HELP_REDEFINED 17\n#define VERSION_REDEFINED 18\n\n#endif\n"
  },
  {
    "path": "utilities/gengetopt/fileutils.cpp",
    "content": "//\n// C++ Implementation: fileutils\n//\n// Description:\n//\n//\n// Author: Lorenzo Bettini <https://www.lorenzobettini.it>, (C) 2004\n//\n// Copyright: See COPYING file that comes with this distribution\n//\n//\n\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n\n#include \"fileutils.h\"\n\nusing namespace std;\n\nchar *\ncreate_filename (char *name, char *ext)\n{\n  char *filename ;\n\n  filename = (char *) malloc (strlen (name) + strlen (ext) + 2);\n  /* 2 = 1 for the . and one for the '\\0' */\n  if (! filename)\n    {\n      fprintf (stderr, \"Error in memory allocation! %s %d\\n\",\n               __FILE__, __LINE__);\n      abort ();\n    }\n\n  sprintf (filename, \"%s.%s\", name, ext);\n\n  return filename ;\n}\n\nofstream *\nopen_fstream (const char *filename)\n{\n  ofstream *fstream = new ofstream (filename);\n\n  if ( ! (*fstream) )\n    {\n      fprintf( stderr, \"Error creating %s\\n\", filename ) ;\n      abort() ;\n    }\n\n  return fstream;\n}\n"
  },
  {
    "path": "utilities/gengetopt/fileutils.h",
    "content": "//\n// C++ Interface: fileutils\n//\n// Description:\n//\n//\n// Author: Lorenzo Bettini <https://www.lorenzobettini.it>, (C) 2004\n//\n// Copyright: See COPYING file that comes with this distribution\n//\n//\n\n#ifndef FILEUTILS_H\n#define FILEUTILS_H\n\n#include <fstream>\n\nusing std::ofstream;\n\nchar *create_filename (char *name, char *ext);\nofstream *open_fstream (const char *filename);\n\n#endif\n"
  },
  {
    "path": "utilities/gengetopt/gengetopt.cc",
    "content": "/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <iostream>\n\nvoid gengetopt_free (void);\n\n/* The following one is generated by gengetopt itself */\n#include \"cmdline.h\"\n\nextern int yyparse () ;\n\n#include \"gengetopt.h\"\n#include \"errorcodes.h\"\n\n#include \"argsdef.h\"\n#include \"global_opts.h\"\n\n#include \"my_sstream.h\"\n#include \"my_string.h\"\n\n#include \"gm.h\"\n#include \"groups.h\"\n#include \"gm_utils.h\"\n\n#include \"skels/copyright.h\"\n\n#include \"yyerror.h\"\n#include \"globals.h\"\n\nchar * gengetopt_package = NULL;\nchar * gengetopt_version = NULL;\nchar * gengetopt_purpose = NULL;\nchar * gengetopt_description = NULL;\nchar * gengetopt_usage = NULL;\n\nmodes_collection_t gengetopt_modes;\n\nint gengetopt_count_line = 1;\nchar * gengetopt_input_filename = 0;\nchar *current_section = 0;\nchar *current_section_desc = 0;\nchar *current_text = 0;\nchar *current_args = 0;\n\n/// whether, if not specified, an option is considered optional\nbool default_to_optional = false;\n\nint canonize_vars (void);\nstatic void set_default_required_properties(void);\n\nstatic void print_copyright();\nstatic void print_reportbugs();\n\nstatic void output_formatted_string(const string &);\n\nstatic bool check_dependencies();\n\nstatic int gengetopt_create_option (gengetopt_option *&opt, const char * long_opt, char short_opt,\n                          const char * desc,\n                          int type, int flagstat, int required,\n                          const char *default_value,\n                          const char * group_value,\n                          const char * mode_value,\n                          const char * type_str,\n                          const AcceptedValues *acceptedvalues,\n                          int multiple = 0,\n                          int argoptional = 0);\n\n\n#include <algorithm>\n#include <iterator>\n\nusing namespace std;\n\n/// the structure for command line arguments\nstruct gengetopt_args_info args_info ;\n\nint\nmain (int argc, char **argv)\n{\n  char *cmdline_parser_name ; /* name of the generated function */\n  char *cmdline_filename ; /* name of generated file */\n  char *c_ext ; /* extenstion of c file */\n  char *header_ext  ; /* extenstion of header file */\n  string output_dir, header_output_dir, src_output_dir; /* output directory (default empty -> current dir)*/\n\n  int i, has_help, has_version;\n  FILE *input_file ;\n\n  if (cmdline_parser (argc, argv, &args_info) != 0) {\n      fprintf (stderr, \"Run gengetopt --help to see the list of options.\\n\");\n      exit(1) ;\n  }\n\n  if (args_info.help_given)\n  {\n    cmdline_parser_print_help ();\n    print_reportbugs ();\n    exit (0);\n  }\n\n  if (args_info.detailed_help_given)\n    {\n      cmdline_parser_print_detailed_help ();\n      print_reportbugs ();\n      exit (0);\n    }\n\n  if (args_info.version_given)\n  {\n    cmdline_parser_print_version ();\n    print_copyright ();\n    exit (0);\n  }\n\n  if ( args_info.input_arg )\n    {\n      gengetopt_input_filename = strdup (args_info.input_arg);\n      input_file = freopen (args_info.input_arg, \"r\", stdin) ;\n      if (!input_file)\n        {\n          fprintf (stderr, \"Error opening input file: %s\\n\",\n                   args_info.input_arg);\n          exit (1);\n        }\n    } /* else standard input is used */\n\n  if (yyparse () != 0) {\n        gengetopt_free ();\n        return 1;\n  }\n\n  // check whether some options were given in the input file\n  bool no_options = (gengetopt_options.size() == 0);\n\n  if (current_args) {\n    // parse the arguments passed in the \"args\" part of the input file\n    // by possibily overriding those given at command line\n    if (cmdline_parser_string2 (current_args, &args_info, \"gengetopt\", 1, 0, 0) != 0) {\n      fprintf (stderr, \"Error in the args specification of the input_file.\\n\");\n      exit(1) ;\n    }\n  }\n\n  cmdline_parser_name = args_info.func_name_arg ;\n  cmdline_filename = args_info.file_name_arg ;\n  c_ext = args_info.c_extension_arg;\n  header_ext = args_info.header_extension_arg;\n\n  default_to_optional = args_info.default_optional_given;\n\n  // now set the default \"required\" property for options\n  set_default_required_properties();\n\n  if (! check_dependencies()) {\n    gengetopt_free();\n    return 1;\n  }\n\n  // insert options for help and version if not already present\n  gengetopt_option *opt;\n\n  if (current_section)\n    free(current_section);\n  current_section = 0;\n\n  has_version = gengetopt_has_option (VERSION_LONG_OPT, VERSION_SHORT_OPT);\n\n  if (has_version != REQ_LONG_OPTION && !args_info.no_version_given) {\n    gengetopt_create_option (opt, VERSION_LONG_OPT, has_version ? '-' : VERSION_SHORT_OPT,\n                                 VERSION_OPT_DESCR, ARG_NO, 0, 0, 0, 0, 0, 0, 0);\n    gengetopt_options.push_front(opt);\n  }\n\n  if (!args_info.no_help_given && has_hidden_options() && gengetopt_has_option(FULL_HELP_LONG_OPT, 0) == 0) {\n      gengetopt_create_option (opt, FULL_HELP_LONG_OPT, '-',\n                               FULL_HELP_OPT_DESCR, ARG_NO, 0, 0, 0, 0, 0, 0, 0);\n      gengetopt_options.push_front(opt);\n  }\n\n  if (!args_info.no_help_given && has_options_with_details() && gengetopt_has_option(DETAILED_HELP_LONG_OPT, 0) == 0) {\n      gengetopt_create_option (opt, DETAILED_HELP_LONG_OPT, '-',\n              DETAILED_HELP_OPT_DESCR, ARG_NO, 0, 0, 0, 0, 0, 0, 0);\n      gengetopt_options.push_front(opt);\n  }\n\n  has_help = gengetopt_has_option(HELP_LONG_OPT, HELP_SHORT_OPT);\n\n  if (has_help != REQ_LONG_OPTION && !args_info.no_help_given) {\n    gengetopt_create_option (opt, HELP_LONG_OPT, has_help ? '-' : HELP_SHORT_OPT,\n                                 HELP_OPT_DESCR, ARG_NO, 0, 0, 0, 0, 0, 0, 0);\n    gengetopt_options.push_front(opt);\n  }\n\n  // check whether there's pending text after all options and\n  // in case, set it to the last option\n  if (current_text && gengetopt_options.size()) {\n    gengetopt_options.back()->text_after = current_text;\n    gengetopt_set_text(0);\n  }\n\n  if (canonize_vars ()) {\n        gengetopt_free ();\n        return 1;\n  }\n\n  if (args_info.set_package_given) {\n    if (gengetopt_package)\n      free (gengetopt_package);\n    gengetopt_package = args_info.set_package_arg;\n  }\n\n  if (args_info.set_version_given) {\n    if (gengetopt_version)\n      free (gengetopt_version);\n    gengetopt_version = args_info.set_version_arg;\n  }\n\n  ostringstream command_line;\n  for ( i = 0; i < argc ; ++i )\n      command_line << argv[i] << \" \";\n\n  // add also possible args specification in the input file\n  if (current_args)\n    command_line << current_args;\n\n  if (args_info.output_dir_given)\n      output_dir = args_info.output_dir_arg;\n  if (args_info.header_output_dir_given)\n      header_output_dir = args_info.header_output_dir_arg;\n  if (args_info.src_output_dir_given)\n      src_output_dir = args_info.src_output_dir_arg;\n\n  CmdlineParserCreator cmdline_parser_creator\n    (cmdline_parser_name,\n     args_info.arg_struct_name_arg,\n     (args_info.unamed_opts_given ? args_info.unamed_opts_arg : 0),\n     cmdline_filename,\n     header_ext,\n     c_ext,\n     args_info.long_help_given,\n     args_info.no_handle_help_given,\n     args_info.no_help_given,\n     args_info.no_handle_version_given,\n     args_info.no_version_given,\n     args_info.no_handle_error_given,\n     args_info.conf_parser_given,\n     args_info.string_parser_given,\n     args_info.gen_version_flag,\n     args_info.include_getopt_given,\n     no_options,\n     command_line.str (),\n     output_dir,\n     header_output_dir,\n     src_output_dir,\n     (args_info.show_required_given ? args_info.show_required_arg : \"\"));\n\n  if (! gengetopt_package && (args_info.show_version_given || args_info.show_help_given))\n    {\n      cerr << \"package not defined; please specify it with --set-package\" << endl;\n      return 1;\n    }\n  else if (! gengetopt_version && (args_info.show_version_given || args_info.show_help_given))\n    {\n      cerr << \"version not defined; please specify it with --set-version\" << endl;\n      return 1;\n    }\n  else if (args_info.show_version_given)\n    {\n      cout << gengetopt_package << \" \" << gengetopt_version << endl;\n    }\n  else if (args_info.show_help_given ||\n          args_info.show_full_help_given || args_info.show_detailed_help_given)\n    {\n      cout << gengetopt_package << \" \" << gengetopt_version << \"\\n\" << endl;\n\n      if (gengetopt_purpose) {\n        output_formatted_string(cmdline_parser_creator.generate_purpose());\n        cout << endl;\n      }\n\n      output_formatted_string(\"Usage: \" +\n        cmdline_parser_creator.generate_usage_string(false) + \"\\n\");\n\n      if (gengetopt_description) {\n        output_formatted_string(cmdline_parser_creator.generate_description());\n        cout << endl;\n      }\n\n      // if --show-full-help is specified we have to generate also hidden options\n      OptionHelpList *option_list =\n          cmdline_parser_creator.generate_help_option_list(args_info.show_full_help_given, args_info.show_detailed_help_given);\n\n      std::for_each(option_list->begin(), option_list->end(),\n              output_formatted_string);\n\n      delete option_list;\n    }\n  else if (cmdline_parser_creator.generate ())\n    {\n        gengetopt_free ();\n        return 1;\n    }\n\n  gengetopt_free ();\n\n  return 0;\n}\n\nvoid\noutput_formatted_string(const string &s)\n{\n  for (string::const_iterator it = s.begin(); it != s.end(); ++it)\n    {\n      if (*it == '\\\\' && ((it+1) != s.end()) && *(it+1) == 'n') {\n        cout << \"\\n\";\n        ++it;\n      } else if (*it == '\\\\' && ((it+1) != s.end()) && *(it+1) == '\"') {\n        cout << \"\\\"\";\n        ++it;\n      } else\n        cout << *it;\n    }\n\n  cout << endl;\n}\n\n/* ************* */\n\nint\ngengetopt_define_package (char * s)\n{\n        gengetopt_package = strdup (s);\n        if (gengetopt_package == NULL)\n                return 1;\n        return 0;\n}\n\nint\ngengetopt_define_version (char * s)\n{\n        gengetopt_version = strdup (s);\n        if (gengetopt_version == NULL)\n                return 1;\n        return 0;\n}\n\nint\ngengetopt_define_purpose (char * s)\n{\n  gengetopt_purpose = strdup (s);\n  if (gengetopt_purpose == NULL)\n    return 1;\n  return 0;\n}\n\nint\ngengetopt_define_description (char * s)\n{\n  gengetopt_description = strdup (s);\n  if (gengetopt_description == NULL)\n    return 1;\n  return 0;\n}\n\nint gengetopt_define_usage (char * s)\n{\n  gengetopt_usage = strdup (s);\n  if (gengetopt_usage == NULL)\n    return 1;\n  return 0;\n}\n\nint\ngengetopt_add_group (const char *s, const char *desc, int required)\n{\n  string group_desc;\n  if (desc)\n    group_desc = desc;\n  if ( !gengetopt_groups.insert\n       (make_pair(string(s),Group (group_desc, required != 0))).second )\n    return 1;\n  else\n    return 0;\n}\n\nint\ngengetopt_add_mode (const char *s, const char *desc)\n{\n  string mode_desc;\n  if (desc)\n    mode_desc = desc;\n  if ( !gengetopt_modes.insert\n       (make_pair(string(s),Mode (mode_desc))).second )\n    return 1;\n  else\n    return 0;\n}\n\nvoid\ngengetopt_set_section (const char * s, const char *desc)\n{\n  if (current_section)\n    free (current_section);\n  if (current_section_desc)\n    free (current_section_desc);\n  current_section = strdup (s);\n  if (desc)\n    current_section_desc = strdup (desc);\n  else\n    current_section_desc = 0;\n}\n\nvoid\ngengetopt_set_text (const char * desc)\n{\n  /*\n  no need to free it, since it will be then owned by the\n  option only\n\n  if (current_text)\n    free (current_text);\n  */\n\n  // the current text is reset\n  if (!desc) {\n    current_text = 0;\n    return;\n  }\n\n  if (current_text) {\n    // a previous text was collected, so we append the new text\n    // to the current one.\n    string buffer = current_text;\n    buffer += desc;\n    current_text = strdup(buffer.c_str());\n    return;\n  }\n\n  // otherwise simply copy the passed text\n  current_text = strdup (desc);\n}\n\nvoid gengetopt_set_args(const char *a)\n{\n  if (current_args)\n    free(current_args);\n\n  if (a)\n    current_args = strdup(a);\n  else\n    current_args = 0;\n}\n\nint\ngengetopt_has_option (const char * long_opt, char short_opt)\n{\n  gengetopt_option * n;\n\n  for (gengetopt_option_list::const_iterator it = gengetopt_options.begin();\n       it != gengetopt_options.end(); ++it)\n    {\n      n = *it;\n      if (!strcmp (n->long_opt, long_opt)) return REQ_LONG_OPTION;\n      if (short_opt && n->short_opt == short_opt)\n        return REQ_SHORT_OPTION;\n    }\n\n  return 0;\n}\n\nbool check_numeric_validity(const char *val, int opt_type)\n{\n    char *end_of_string, *expected_eos;\n\n    expected_eos = (char *) (val + strlen(val));\n\n    switch ( opt_type )\n      {\n      case ARG_INT :\n      case ARG_SHORT :\n      case ARG_LONG :\n      case ARG_LONGLONG :\n        (void) strtol(val, &end_of_string, 0);\n        break;\n\n      case ARG_FLOAT:\n      case ARG_DOUBLE:\n      case ARG_LONGDOUBLE:\n        (void) strtod(val, &end_of_string);\n        break;\n\n      default :\n        // This will allow us to factorise as a single line the\n        // test for correctness of the default value\n        end_of_string = expected_eos;\n        break;\n      }\n    return ( end_of_string == expected_eos );\n}\n\nbool\ncheck_values(const AcceptedValues *acceptedvalues, int opt_type)\n{\n    for (AcceptedValues::const_iterator it = acceptedvalues->begin();\n        it != acceptedvalues->end(); ++it) {\n        if (!check_numeric_validity((*it).c_str(), opt_type))\n            return false;\n    }\n\n    return true;\n}\n\nint\ngengetopt_create_option (gengetopt_option *&n, const char * long_opt, char short_opt,\n                      const char * desc,\n                      int type, int flagstat, int required,\n                      const char * default_value,\n                      const char * group_value,\n                      const char * mode_value,\n                      const char * type_str,\n                      const AcceptedValues *acceptedvalues,\n                      int multiple,\n                      int argoptional)\n{\n  if ((long_opt == NULL) ||\n      (long_opt[0] == 0) ||\n      (desc == NULL))\n    return FOUND_BUG;\n\n  n = new gengetopt_option;\n  if (n == NULL)\n    return NOT_ENOUGH_MEMORY;\n\n  // here we will set required anyway\n  n->required_set = true;\n\n  n->long_opt = strdup (long_opt);\n  if (n->long_opt == NULL)\n    {\n      free (n);\n      return NOT_ENOUGH_MEMORY;\n    }\n\n  n->desc = strdup (desc);\n  if (n->desc == NULL)\n    {\n      free (n->long_opt);\n      free (n);\n      return NOT_ENOUGH_MEMORY;\n    }\n\n  n->short_opt = ((short_opt == '-') ? 0 : short_opt);\n  n->type = type;\n  n->flagstat = flagstat;\n  n->required = required;\n  n->multiple = (multiple != 0);\n  n->arg_is_optional = (argoptional != 0);\n\n  if (type_str != 0)\n    n->type_str = strdup(type_str);\n  else\n    n->type_str = NULL;\n\n  n->section = 0;\n  n->section_desc = 0;\n  if (current_section)\n    n->section = strdup (current_section);\n  if (current_section_desc)\n    n->section_desc = strdup (current_section_desc);\n\n  if (group_value != 0)\n    {\n      n->group_value = strdup(group_value);\n      n->required = 0;\n      groups_collection_t::const_iterator it =\n        gengetopt_groups.find(string(n->group_value));\n      if (it == gengetopt_groups.end())\n        return GROUP_UNDEFINED;\n      n->group_desc = strdup (it->second.desc.c_str ());\n    }\n  else\n    {\n      n->group_value = 0;\n    }\n\n  if (mode_value != 0) {\n      n->mode_value = strdup(mode_value);\n      modes_collection_t::const_iterator it =\n          gengetopt_modes.find(string(n->mode_value));\n      if (it == gengetopt_modes.end())\n          return MODE_UNDEFINED;\n      n->mode_desc = strdup (it->second.desc.c_str ());\n  } else {\n      n->mode_value = 0;\n  }\n\n  if (n->group_value && n->mode_value)\n      return FOUND_BUG;\n\n\n  n->acceptedvalues = acceptedvalues;\n\n  // if (acceptedvalues && type != ARG_NO)\n  // return NOT_REQUESTED_TYPE;\n\n  if (acceptedvalues && ! (n->type))\n    n->type = ARG_STRING;\n\n  n->default_string = 0;\n  n->default_given = (default_value != 0);\n  if (n->default_given)\n    {\n      n->default_string = strdup (default_value);\n      if ( ! check_numeric_validity(default_value, n->type) )\n        {\n          free (n);\n          return INVALID_DEFAULT_VALUE;\n        }\n\n      if (acceptedvalues)\n        {\n          if (! acceptedvalues->contains(n->default_string))\n            return INVALID_DEFAULT_VALUE;\n        }\n    }\n\n  if (acceptedvalues) {\n      if (!check_values(acceptedvalues, n->type))\n          return INVALID_NUMERIC_VALUE;\n  }\n\n  n->var_arg = NULL;\n\n  return 0;\n}\n\nint\ngengetopt_check_option (gengetopt_option *n, bool groupoption, bool modeoption)\n{\n  if ((n->long_opt == NULL) ||\n      (n->long_opt[0] == 0) ||\n      (n->desc == NULL))\n    return FOUND_BUG;\n\n  if (strcmp(n->long_opt, HELP_LONG_OPT) == 0 && !args_info.no_help_given)\n      return HELP_REDEFINED;\n\n  if (strcmp(n->long_opt, VERSION_LONG_OPT) == 0 && !args_info.no_version_given)\n      return VERSION_REDEFINED;\n\n  n->section = 0;\n  n->section_desc = 0;\n  if (current_section)\n    n->section = strdup (current_section);\n  if (current_section_desc)\n    n->section_desc = strdup (current_section_desc);\n\n  n->text_before = current_text;\n  // reset the description\n  gengetopt_set_text(0);\n\n  if (n->group_value != 0)\n  {\n      if (! groupoption)\n          return NOT_GROUP_OPTION;\n\n      n->required = 0;\n      n->required_set = true;\n\n      groups_collection_t::const_iterator it =\n          gengetopt_groups.find(string(n->group_value));\n      if (it == gengetopt_groups.end())\n          return GROUP_UNDEFINED;\n      n->group_desc = strdup (it->second.desc.c_str ());\n  }\n  else\n  {\n      if (groupoption)\n          return SPECIFY_GROUP;\n  }\n\n  if (n->mode_value != 0)\n  {\n      if (! modeoption)\n          return NOT_MODE_OPTION;\n\n      modes_collection_t::const_iterator it =\n          gengetopt_modes.find(string(n->mode_value));\n      if (it == gengetopt_modes.end())\n          return MODE_UNDEFINED;\n      n->mode_desc = strdup (it->second.desc.c_str ());\n  }\n  else\n  {\n      if (modeoption)\n          return SPECIFY_MODE;\n  }\n\n  if (n->group_value && n->mode_value)\n      return FOUND_BUG;\n\n  // now we have to check for flag options\n  if (n->type == ARG_FLAG)\n  {\n    if (n->flagstat < 0)\n      return SPECIFY_FLAG_STAT;\n\n    if (n->default_string || n->multiple || n->arg_is_optional\n        || n->type_str || n->acceptedvalues || n->required_set)\n      return NOT_VALID_SPECIFICATION;\n\n    n->required = 0;\n    n->required_set = true;\n  }\n  else\n  {\n    if (n->flagstat >= 0)\n      return NOT_VALID_SPECIFICATION;\n  }\n\n  // enum type can only be specified with options with values\n  if (n->type == ARG_ENUM && !(n->acceptedvalues)) {\n      return INVALID_ENUM_TYPE_USE;\n  }\n\n  // if (acceptedvalues && type != ARG_NO)\n  // return NOT_REQUESTED_TYPE;\n\n  if (n->acceptedvalues && ! (n->type))\n    n->type = ARG_STRING;\n\n  n->default_given = (n->default_string != 0);\n  if (n->default_given)\n    {\n      if ( !check_numeric_validity(n->default_string, n->type) )\n        {\n          return INVALID_DEFAULT_VALUE;\n        }\n\n      if (n->acceptedvalues)\n        {\n          if (! n->acceptedvalues->contains(n->default_string))\n            return INVALID_DEFAULT_VALUE;\n        }\n    }\n\n  if (n->acceptedvalues) {\n      if (!check_values(n->acceptedvalues, n->type))\n          return INVALID_NUMERIC_VALUE;\n  }\n\n  n->var_arg = NULL;\n\n  return 0;\n}\n\nint\ngengetopt_add_option (const char * long_opt, char short_opt,\n                      const char * desc,\n                      int type, int flagstat, int required,\n                      const char * default_value,\n                      const char * group_value,\n                      const char * mode_value,\n                      const char * type_str,\n                      const AcceptedValues *acceptedvalues,\n                      int multiple,\n                      int argoptional)\n{\n  gengetopt_option * n;\n\n  /* search for collisions */\n  int res = gengetopt_has_option(long_opt, short_opt);\n  if (res != 0)\n    return res;\n\n  res = gengetopt_create_option(n, long_opt, short_opt,\n    desc, type, flagstat, required, default_value, group_value, mode_value,\n    type_str, acceptedvalues, multiple, argoptional);\n  if (res != 0)\n    return res;\n\n  gengetopt_options.push_back(n);\n\n  return 0;\n}\n\nint\ngengetopt_add_option (gengetopt_option * n)\n{\n  /* search for collisions */\n  int res = gengetopt_has_option(n);\n  if (res != 0)\n    return res;\n\n  gengetopt_options.push_back(n);\n\n  return 0;\n}\n\nint\ngengetopt_has_option (gengetopt_option * opt)\n{\n  gengetopt_option * n;\n\n  for (gengetopt_option_list::const_iterator it = gengetopt_options.begin();\n       it != gengetopt_options.end(); ++it)\n    {\n      n = *it;\n      if (!strcmp (n->long_opt, opt->long_opt))\n        return REQ_LONG_OPTION;\n      if (opt->short_opt && n->short_opt == opt->short_opt)\n        return REQ_SHORT_OPTION;\n    }\n\n  return 0;\n}\n\nbool\ncheck_dependencies()\n{\n  gengetopt_option * n;\n  bool result = true;\n\n  for (gengetopt_option_list::const_iterator it = gengetopt_options.begin();\n       it != gengetopt_options.end(); ++it)\n  {\n    n = *it;\n    if (n->dependon) {\n        if (strcmp(n->dependon, n->long_opt) == 0) {\n            yyerror(n, \"option depends on itself\");\n            result = false;\n            continue;\n        }\n\n        bool found = false;\n        for (gengetopt_option_list::const_iterator it2 = gengetopt_options.begin();\n            it2 != gengetopt_options.end(); ++it2)\n        {\n            if (strcmp(n->dependon, (*it2)->long_opt) == 0) {\n                found = true;\n                break;\n            }\n        }\n\n        if (! found) {\n            yyerror (n, \"option depends on undefined option\");\n            result = false;\n        }\n    }\n  }\n\n  return result;\n}\n\nvoid\ngengetopt_free (void)\n{\n  gengetopt_option *p;\n\n  if (gengetopt_package != NULL)\n    free (gengetopt_package);\n\n  for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it != gengetopt_options.end(); ++it)\n  {\n        p = *it;\n        if (p->long_opt != NULL) free (p->long_opt);\n        if (p->desc != NULL) free (p->desc);\n        if (p->var_arg != NULL) free (p->var_arg);\n        if (p->acceptedvalues) delete p->acceptedvalues;\n        delete p;\n  }\n}\n\nstatic void\ncanonize_var (gengetopt_option *p)\n{\n  char *pvar;\n\n  p->var_arg = strdup (p->long_opt);\n  if (p->var_arg == NULL) {\n      printf (\"gengetopt: not enough memory to canonize vars\\n\");\n      abort();\n  }\n\n  for (pvar = p->var_arg; *pvar; pvar++)\n    if (*pvar == '.' || *pvar == '-') *pvar = '_';\n}\n\nint\ncanonize_vars (void)\n{\n  for_each(gengetopt_options.begin(), gengetopt_options.end(), canonize_var);\n\n  return 0;\n}\n\nstatic void\nset_default_required_prop (gengetopt_option *p)\n{\n    if (!p->required_set)\n        p->required = (default_to_optional ? 0 : 1);\n}\n\nstatic void set_default_required_properties(void)\n{\n  for_each(gengetopt_options.begin(), gengetopt_options.end(), set_default_required_prop);\n}\n\nvoid\nprint_copyright()\n{\n  copyright_gen_class copyright_g;\n\n  copyright_g.set_year (\"1999-2009\");\n  copyright_g.generate_copyright (cout);\n}\n\nvoid\nprint_reportbugs()\n{\n  cout << endl;\n  cout << \"Maintained by Lorenzo Bettini <https://www.lorenzobettini.it>\" << endl;\n  cout << \"Report bugs to <bug-gengetopt at gnu.org>\" << endl;\n}\n"
  },
  {
    "path": "utilities/gengetopt/gengetopt.h",
    "content": "/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#ifndef _GENGETOPT_H\n#define _GENGETOPT_H\n\n#include \"acceptedvalues.h\"\n#include \"ggos.h\"\n\nint gengetopt_define_package (char * s) ;\nint gengetopt_define_version (char * s) ;\nint gengetopt_define_purpose (char * s) ;\nint gengetopt_define_description (char * s) ;\nint gengetopt_define_usage (char * s) ;\n\n/**\n * Sets the \"global\" section specification that will be then set\n * in the following options\n * @param s The section\n * @param sd The section description\n */\nvoid gengetopt_set_section (const char * s, const char *sd) ;\n\n/**\n * Sets the \"global\" text string that will be inserted in\n * a specific field of the next option\n * @param desc The text string\n */\nvoid gengetopt_set_text (const char * desc) ;\n\n/**\n * Sets the \"global\" text string containing the arguments\n * that complement the command line arguments of gengetopt.\n * @param args\n */\nvoid gengetopt_set_args (const char *args);\n\nint gengetopt_add_group (const char * s, const char *desc, int required) ;\nint gengetopt_add_mode (const char * s, const char *desc) ;\n\nint gengetopt_has_option (const char * long_opt, char short_opt);\nint gengetopt_add_option (const char * long_opt, char short_opt,\n                          const char * desc,\n                          int type, int flagstat, int required,\n                          const char *default_value,\n                          const char * group_value,\n                          const char * mode_value,\n                          const char * type_str,\n                          const AcceptedValues *acceptedvalues,\n                          int multiple = 0,\n                          int argoptional = 0);\n\nint gengetopt_has_option (gengetopt_option *opt);\nint gengetopt_check_option (gengetopt_option *opt,\n    bool groupoption = false, bool modeoption = false);\nint gengetopt_add_option (gengetopt_option *opt);\n\n#endif /* _GENGETOPT_H */\n"
  },
  {
    "path": "utilities/gengetopt/getopt.c",
    "content": "/* Getopt for GNU.\n   NOTE: getopt is now part of the C library, so if you don't know what\n   \"Keep this file name-space clean\" means, talk to drepper@gnu.org\n   before changing it!\n   Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001\n   \tFree Software Foundation, Inc.\n   This file is part of the GNU C Library.\n\n   The GNU C Library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   The GNU C Library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with the GNU C Library; if not, write to the Free\n   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\n   02111-1307 USA.  */\n\f\n/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.\n   Ditto for AIX 3.2 and <stdlib.h>.  */\n#ifndef _NO_PROTO\n# define _NO_PROTO\n#endif\n\n#ifdef HAVE_CONFIG_H\n# include <config.h>\n#endif\n\n#if !defined __STDC__ || !__STDC__\n/* This is a separate conditional since some stdc systems\n   reject `defined (const)'.  */\n# ifndef const\n#  define const\n# endif\n#endif\n\n#include <stdio.h>\n\n/* Comment out all this code if we are using the GNU C Library, and are not\n   actually compiling the library itself.  This code is part of the GNU C\n   Library, but also included in many other GNU distributions.  Compiling\n   and linking in this code is a waste when using the GNU C library\n   (especially if it is a shared library).  Rather than having every GNU\n   program understand `configure --with-gnu-libc' and omit the object files,\n   it is simpler to just do this in the source for each such file.  */\n\n#define GETOPT_INTERFACE_VERSION 2\n#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2\n# include <gnu-versions.h>\n# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION\n#  define ELIDE_CODE\n# endif\n#endif\n\n#ifndef ELIDE_CODE\n\n\n/* This needs to come after some library #include\n   to get __GNU_LIBRARY__ defined.  */\n#ifdef\t__GNU_LIBRARY__\n/* Don't include stdlib.h for non-GNU C libraries because some of them\n   contain conflicting prototypes for getopt.  */\n# include <stdlib.h>\n# include <unistd.h>\n#endif\t/* GNU C library.  */\n\n#ifdef VMS\n# include <unixlib.h>\n# if HAVE_STRING_H - 0\n#  include <string.h>\n# endif\n#endif\n\n#ifndef _\n/* This is for other GNU distributions with internationalized messages.  */\n# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC\n#  include <libintl.h>\n#  ifndef _\n#   define _(msgid)\tgettext (msgid)\n#  endif\n# else\n#  define _(msgid)\t(msgid)\n# endif\n#endif\n\n/* This version of `getopt' appears to the caller like standard Unix `getopt'\n   but it behaves differently for the user, since it allows the user\n   to intersperse the options with the other arguments.\n\n   As `getopt' works, it permutes the elements of ARGV so that,\n   when it is done, all the options precede everything else.  Thus\n   all application programs are extended to handle flexible argument order.\n\n   Setting the environment variable POSIXLY_CORRECT disables permutation.\n   Then the behavior is completely standard.\n\n   GNU application programs can use a third alternative mode in which\n   they can distinguish the relative order of options and other arguments.  */\n\n#include \"getopt.h\"\n\n/* For communication from `getopt' to the caller.\n   When `getopt' finds an option that takes an argument,\n   the argument value is returned here.\n   Also, when `ordering' is RETURN_IN_ORDER,\n   each non-option ARGV-element is returned here.  */\n\nchar *optarg;\n\n/* Index in ARGV of the next element to be scanned.\n   This is used for communication to and from the caller\n   and for communication between successive calls to `getopt'.\n\n   On entry to `getopt', zero means this is the first call; initialize.\n\n   When `getopt' returns -1, this is the index of the first of the\n   non-option elements that the caller should itself scan.\n\n   Otherwise, `optind' communicates from one call to the next\n   how much of ARGV has been scanned so far.  */\n\n/* 1003.2 says this must be 1 before any call.  */\nint optind = 1;\n\n/* Formerly, initialization of getopt depended on optind==0, which\n   causes problems with re-calling getopt as programs generally don't\n   know that. */\n\nint __getopt_initialized;\n\n/* The next char to be scanned in the option-element\n   in which the last option character we returned was found.\n   This allows us to pick up the scan where we left off.\n\n   If this is zero, or a null string, it means resume the scan\n   by advancing to the next ARGV-element.  */\n\nstatic char *nextchar;\n\n/* Callers store zero here to inhibit the error message\n   for unrecognized options.  */\n\nint opterr = 1;\n\n/* Set to an option character which was unrecognized.\n   This must be initialized on some systems to avoid linking in the\n   system's own getopt implementation.  */\n\nint optopt = '?';\n\n/* Describe how to deal with options that follow non-option ARGV-elements.\n\n   If the caller did not specify anything,\n   the default is REQUIRE_ORDER if the environment variable\n   POSIXLY_CORRECT is defined, PERMUTE otherwise.\n\n   REQUIRE_ORDER means don't recognize them as options;\n   stop option processing when the first non-option is seen.\n   This is what Unix does.\n   This mode of operation is selected by either setting the environment\n   variable POSIXLY_CORRECT, or using `+' as the first character\n   of the list of option characters.\n\n   PERMUTE is the default.  We permute the contents of ARGV as we scan,\n   so that eventually all the non-options are at the end.  This allows options\n   to be given in any order, even with programs that were not written to\n   expect this.\n\n   RETURN_IN_ORDER is an option available to programs that were written\n   to expect options and other ARGV-elements in any order and that care about\n   the ordering of the two.  We describe each non-option ARGV-element\n   as if it were the argument of an option with character code 1.\n   Using `-' as the first character of the list of option characters\n   selects this mode of operation.\n\n   The special argument `--' forces an end of option-scanning regardless\n   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only\n   `--' can cause `getopt' to return -1 with `optind' != ARGC.  */\n\nstatic enum\n{\n  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER\n} ordering;\n\n/* Value of POSIXLY_CORRECT environment variable.  */\nstatic char *posixly_correct;\n\f\n#ifdef\t__GNU_LIBRARY__\n/* We want to avoid inclusion of string.h with non-GNU libraries\n   because there are many ways it can cause trouble.\n   On some systems, it contains special magic macros that don't work\n   in GCC.  */\n# include <string.h>\n# define my_index\tstrchr\n#else\n\n# if HAVE_STRING_H\n#  include <string.h>\n# else\n#  include <strings.h>\n# endif\n\n/* Avoid depending on library functions or files\n   whose names are inconsistent.  */\n\n#ifndef getenv\nextern char *getenv ();\n#endif\n\nstatic char *\nmy_index (str, chr)\n     const char *str;\n     int chr;\n{\n  while (*str)\n    {\n      if (*str == chr)\n\treturn (char *) str;\n      str++;\n    }\n  return 0;\n}\n\n/* If using GCC, we can safely declare strlen this way.\n   If not using GCC, it is ok not to declare it.  */\n#ifdef __GNUC__\n/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.\n   That was relevant to code that was here before.  */\n# if (!defined __STDC__ || !__STDC__) && !defined strlen\n/* gcc with -traditional declares the built-in strlen to return int,\n   and has done so at least since version 2.4.5. -- rms.  */\nextern int strlen (const char *);\n# endif /* not __STDC__ */\n#endif /* __GNUC__ */\n\n#endif /* not __GNU_LIBRARY__ */\n\f\n/* Handle permutation of arguments.  */\n\n/* Describe the part of ARGV that contains non-options that have\n   been skipped.  `first_nonopt' is the index in ARGV of the first of them;\n   `last_nonopt' is the index after the last of them.  */\n\nstatic int first_nonopt;\nstatic int last_nonopt;\n\n#ifdef _LIBC\n/* Stored original parameters.\n   XXX This is no good solution.  We should rather copy the args so\n   that we can compare them later.  But we must not use malloc(3).  */\nextern int __libc_argc;\nextern char **__libc_argv;\n\n/* Bash 2.0 gives us an environment variable containing flags\n   indicating ARGV elements that should not be considered arguments.  */\n\n# ifdef USE_NONOPTION_FLAGS\n/* Defined in getopt_init.c  */\nextern char *__getopt_nonoption_flags;\n\nstatic int nonoption_flags_max_len;\nstatic int nonoption_flags_len;\n# endif\n\n# ifdef USE_NONOPTION_FLAGS\n#  define SWAP_FLAGS(ch1, ch2) \\\n  if (nonoption_flags_len > 0)\t\t\t\t\t\t      \\\n    {\t\t\t\t\t\t\t\t\t      \\\n      char __tmp = __getopt_nonoption_flags[ch1];\t\t\t      \\\n      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];\t      \\\n      __getopt_nonoption_flags[ch2] = __tmp;\t\t\t\t      \\\n    }\n# else\n#  define SWAP_FLAGS(ch1, ch2)\n# endif\n#else\t/* !_LIBC */\n# define SWAP_FLAGS(ch1, ch2)\n#endif\t/* _LIBC */\n\n/* Exchange two adjacent subsequences of ARGV.\n   One subsequence is elements [first_nonopt,last_nonopt)\n   which contains all the non-options that have been skipped so far.\n   The other is elements [last_nonopt,optind), which contains all\n   the options processed since those non-options were skipped.\n\n   `first_nonopt' and `last_nonopt' are relocated so that they describe\n   the new indices of the non-options in ARGV after they are moved.  */\n\n#if defined __STDC__ && __STDC__\nstatic void exchange (char **);\n#endif\n\nstatic void\nexchange (argv)\n     char **argv;\n{\n  int bottom = first_nonopt;\n  int middle = last_nonopt;\n  int top = optind;\n  char *tem;\n\n  /* Exchange the shorter segment with the far end of the longer segment.\n     That puts the shorter segment into the right place.\n     It leaves the longer segment in the right place overall,\n     but it consists of two parts that need to be swapped next.  */\n\n#if defined _LIBC && defined USE_NONOPTION_FLAGS\n  /* First make sure the handling of the `__getopt_nonoption_flags'\n     string can work normally.  Our top argument must be in the range\n     of the string.  */\n  if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)\n    {\n      /* We must extend the array.  The user plays games with us and\n\t presents new arguments.  */\n      char *new_str = malloc (top + 1);\n      if (new_str == NULL)\n\tnonoption_flags_len = nonoption_flags_max_len = 0;\n      else\n\t{\n\t  memset (__mempcpy (new_str, __getopt_nonoption_flags,\n\t\t\t     nonoption_flags_max_len),\n\t\t  '\\0', top + 1 - nonoption_flags_max_len);\n\t  nonoption_flags_max_len = top + 1;\n\t  __getopt_nonoption_flags = new_str;\n\t}\n    }\n#endif\n\n  while (top > middle && middle > bottom)\n    {\n      if (top - middle > middle - bottom)\n\t{\n\t  /* Bottom segment is the short one.  */\n\t  int len = middle - bottom;\n\t  int i;\n\n\t  /* Swap it with the top part of the top segment.  */\n\t  for (i = 0; i < len; i++)\n\t    {\n\t      tem = argv[bottom + i];\n\t      argv[bottom + i] = argv[top - (middle - bottom) + i];\n\t      argv[top - (middle - bottom) + i] = tem;\n\t      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);\n\t    }\n\t  /* Exclude the moved bottom segment from further swapping.  */\n\t  top -= len;\n\t}\n      else\n\t{\n\t  /* Top segment is the short one.  */\n\t  int len = top - middle;\n\t  int i;\n\n\t  /* Swap it with the bottom part of the bottom segment.  */\n\t  for (i = 0; i < len; i++)\n\t    {\n\t      tem = argv[bottom + i];\n\t      argv[bottom + i] = argv[middle + i];\n\t      argv[middle + i] = tem;\n\t      SWAP_FLAGS (bottom + i, middle + i);\n\t    }\n\t  /* Exclude the moved top segment from further swapping.  */\n\t  bottom += len;\n\t}\n    }\n\n  /* Update records for the slots the non-options now occupy.  */\n\n  first_nonopt += (optind - last_nonopt);\n  last_nonopt = optind;\n}\n\n/* Initialize the internal data when the first call is made.  */\n\n#if defined __STDC__ && __STDC__\nstatic const char *_getopt_initialize (int, char *const *, const char *);\n#endif\nstatic const char *\n_getopt_initialize (argc, argv, optstring)\n     int argc;\n     char *const *argv;\n     const char *optstring;\n{\n  /* Start processing options with ARGV-element 1 (since ARGV-element 0\n     is the program name); the sequence of previously skipped\n     non-option ARGV-elements is empty.  */\n\n  first_nonopt = last_nonopt = optind;\n\n  nextchar = NULL;\n\n  posixly_correct = getenv (\"POSIXLY_CORRECT\");\n\n  /* Determine how to handle the ordering of options and nonoptions.  */\n\n  if (optstring[0] == '-')\n    {\n      ordering = RETURN_IN_ORDER;\n      ++optstring;\n    }\n  else if (optstring[0] == '+')\n    {\n      ordering = REQUIRE_ORDER;\n      ++optstring;\n    }\n  else if (posixly_correct != NULL)\n    ordering = REQUIRE_ORDER;\n  else\n    ordering = PERMUTE;\n\n#if defined _LIBC && defined USE_NONOPTION_FLAGS\n  if (posixly_correct == NULL\n      && argc == __libc_argc && argv == __libc_argv)\n    {\n      if (nonoption_flags_max_len == 0)\n\t{\n\t  if (__getopt_nonoption_flags == NULL\n\t      || __getopt_nonoption_flags[0] == '\\0')\n\t    nonoption_flags_max_len = -1;\n\t  else\n\t    {\n\t      const char *orig_str = __getopt_nonoption_flags;\n\t      int len = nonoption_flags_max_len = strlen (orig_str);\n\t      if (nonoption_flags_max_len < argc)\n\t\tnonoption_flags_max_len = argc;\n\t      __getopt_nonoption_flags =\n\t\t(char *) malloc (nonoption_flags_max_len);\n\t      if (__getopt_nonoption_flags == NULL)\n\t\tnonoption_flags_max_len = -1;\n\t      else\n\t\tmemset (__mempcpy (__getopt_nonoption_flags, orig_str, len),\n\t\t\t'\\0', nonoption_flags_max_len - len);\n\t    }\n\t}\n      nonoption_flags_len = nonoption_flags_max_len;\n    }\n  else\n    nonoption_flags_len = 0;\n#endif\n\n  return optstring;\n}\n\f\n/* Scan elements of ARGV (whose length is ARGC) for option characters\n   given in OPTSTRING.\n\n   If an element of ARGV starts with '-', and is not exactly \"-\" or \"--\",\n   then it is an option element.  The characters of this element\n   (aside from the initial '-') are option characters.  If `getopt'\n   is called repeatedly, it returns successively each of the option characters\n   from each of the option elements.\n\n   If `getopt' finds another option character, it returns that character,\n   updating `optind' and `nextchar' so that the next call to `getopt' can\n   resume the scan with the following option character or ARGV-element.\n\n   If there are no more option characters, `getopt' returns -1.\n   Then `optind' is the index in ARGV of the first ARGV-element\n   that is not an option.  (The ARGV-elements have been permuted\n   so that those that are not options now come last.)\n\n   OPTSTRING is a string containing the legitimate option characters.\n   If an option character is seen that is not listed in OPTSTRING,\n   return '?' after printing an error message.  If you set `opterr' to\n   zero, the error message is suppressed but we still return '?'.\n\n   If a char in OPTSTRING is followed by a colon, that means it wants an arg,\n   so the following text in the same ARGV-element, or the text of the following\n   ARGV-element, is returned in `optarg'.  Two colons mean an option that\n   wants an optional arg; if there is text in the current ARGV-element,\n   it is returned in `optarg', otherwise `optarg' is set to zero.\n\n   If OPTSTRING starts with `-' or `+', it requests different methods of\n   handling the non-option ARGV-elements.\n   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.\n\n   Long-named options begin with `--' instead of `-'.\n   Their names may be abbreviated as long as the abbreviation is unique\n   or is an exact match for some defined option.  If they have an\n   argument, it follows the option name in the same ARGV-element, separated\n   from the option name by a `=', or else the in next ARGV-element.\n   When `getopt' finds a long-named option, it returns 0 if that option's\n   `flag' field is nonzero, the value of the option's `val' field\n   if the `flag' field is zero.\n\n   The elements of ARGV aren't really const, because we permute them.\n   But we pretend they're const in the prototype to be compatible\n   with other systems.\n\n   LONGOPTS is a vector of `struct option' terminated by an\n   element containing a name which is zero.\n\n   LONGIND returns the index in LONGOPT of the long-named option found.\n   It is only valid when a long-named option has been found by the most\n   recent call.\n\n   If LONG_ONLY is nonzero, '-' as well as '--' can introduce\n   long-named options.  */\n\nint\n_getopt_internal (argc, argv, optstring, longopts, longind, long_only)\n     int argc;\n     char *const *argv;\n     const char *optstring;\n     const struct option *longopts;\n     int *longind;\n     int long_only;\n{\n  int print_errors = opterr;\n  if (optstring[0] == ':')\n    print_errors = 0;\n\n  if (argc < 1)\n    return -1;\n\n  optarg = NULL;\n\n  if (optind == 0 || !__getopt_initialized)\n    {\n      if (optind == 0)\n\toptind = 1;\t/* Don't scan ARGV[0], the program name.  */\n      optstring = _getopt_initialize (argc, argv, optstring);\n      __getopt_initialized = 1;\n    }\n\n  /* Test whether ARGV[optind] points to a non-option argument.\n     Either it does not have option syntax, or there is an environment flag\n     from the shell indicating it is not an option.  The later information\n     is only used when the used in the GNU libc.  */\n#if defined _LIBC && defined USE_NONOPTION_FLAGS\n# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\\0'\t      \\\n\t\t      || (optind < nonoption_flags_len\t\t\t      \\\n\t\t\t  && __getopt_nonoption_flags[optind] == '1'))\n#else\n# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\\0')\n#endif\n\n  if (nextchar == NULL || *nextchar == '\\0')\n    {\n      /* Advance to the next ARGV-element.  */\n\n      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been\n\t moved back by the user (who may also have changed the arguments).  */\n      if (last_nonopt > optind)\n\tlast_nonopt = optind;\n      if (first_nonopt > optind)\n\tfirst_nonopt = optind;\n\n      if (ordering == PERMUTE)\n\t{\n\t  /* If we have just processed some options following some non-options,\n\t     exchange them so that the options come first.  */\n\n\t  if (first_nonopt != last_nonopt && last_nonopt != optind)\n\t    exchange ((char **) argv);\n\t  else if (last_nonopt != optind)\n\t    first_nonopt = optind;\n\n\t  /* Skip any additional non-options\n\t     and extend the range of non-options previously skipped.  */\n\n\t  while (optind < argc && NONOPTION_P)\n\t    optind++;\n\t  last_nonopt = optind;\n\t}\n\n      /* The special ARGV-element `--' means premature end of options.\n\t Skip it like a null option,\n\t then exchange with previous non-options as if it were an option,\n\t then skip everything else like a non-option.  */\n\n      if (optind != argc && !strcmp (argv[optind], \"--\"))\n\t{\n\t  optind++;\n\n\t  if (first_nonopt != last_nonopt && last_nonopt != optind)\n\t    exchange ((char **) argv);\n\t  else if (first_nonopt == last_nonopt)\n\t    first_nonopt = optind;\n\t  last_nonopt = argc;\n\n\t  optind = argc;\n\t}\n\n      /* If we have done all the ARGV-elements, stop the scan\n\t and back over any non-options that we skipped and permuted.  */\n\n      if (optind == argc)\n\t{\n\t  /* Set the next-arg-index to point at the non-options\n\t     that we previously skipped, so the caller will digest them.  */\n\t  if (first_nonopt != last_nonopt)\n\t    optind = first_nonopt;\n\t  return -1;\n\t}\n\n      /* If we have come to a non-option and did not permute it,\n\t either stop the scan or describe it to the caller and pass it by.  */\n\n      if (NONOPTION_P)\n\t{\n\t  if (ordering == REQUIRE_ORDER)\n\t    return -1;\n\t  optarg = argv[optind++];\n\t  return 1;\n\t}\n\n      /* We have found another option-ARGV-element.\n\t Skip the initial punctuation.  */\n\n      nextchar = (argv[optind] + 1\n\t\t  + (longopts != NULL && argv[optind][1] == '-'));\n    }\n\n  /* Decode the current option-ARGV-element.  */\n\n  /* Check whether the ARGV-element is a long option.\n\n     If long_only and the ARGV-element has the form \"-f\", where f is\n     a valid short option, don't consider it an abbreviated form of\n     a long option that starts with f.  Otherwise there would be no\n     way to give the -f short option.\n\n     On the other hand, if there's a long option \"fubar\" and\n     the ARGV-element is \"-fu\", do consider that an abbreviation of\n     the long option, just like \"--fu\", and not \"-f\" with arg \"u\".\n\n     This distinction seems to be the most useful approach.  */\n\n  if (longopts != NULL\n      && (argv[optind][1] == '-'\n\t  || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))\n    {\n      char *nameend;\n      const struct option *p;\n      const struct option *pfound = NULL;\n      int exact = 0;\n      int ambig = 0;\n      int indfound = -1;\n      int option_index;\n\n      for (nameend = nextchar; *nameend && *nameend != '='; nameend++)\n\t/* Do nothing.  */ ;\n\n      /* Test all long options for either exact match\n\t or abbreviated matches.  */\n      for (p = longopts, option_index = 0; p->name; p++, option_index++)\n\tif (!strncmp (p->name, nextchar, nameend - nextchar))\n\t  {\n\t    if ((unsigned int) (nameend - nextchar)\n\t\t== (unsigned int) strlen (p->name))\n\t      {\n\t\t/* Exact match found.  */\n\t\tpfound = p;\n\t\tindfound = option_index;\n\t\texact = 1;\n\t\tbreak;\n\t      }\n\t    else if (pfound == NULL)\n\t      {\n\t\t/* First nonexact match found.  */\n\t\tpfound = p;\n\t\tindfound = option_index;\n\t      }\n\t    else if (long_only\n\t\t     || pfound->has_arg != p->has_arg\n\t\t     || pfound->flag != p->flag\n\t\t     || pfound->val != p->val)\n\t      /* Second or later nonexact match found.  */\n\t      ambig = 1;\n\t  }\n\n      if (ambig && !exact)\n\t{\n\t  if (print_errors)\n\t    fprintf (stderr, _(\"%s: option `%s' is ambiguous\\n\"),\n\t\t     argv[0], argv[optind]);\n\t  nextchar += strlen (nextchar);\n\t  optind++;\n\t  optopt = 0;\n\t  return '?';\n\t}\n\n      if (pfound != NULL)\n\t{\n\t  option_index = indfound;\n\t  optind++;\n\t  if (*nameend)\n\t    {\n\t      /* Don't test has_arg with >, because some C compilers don't\n\t\t allow it to be used on enums.  */\n\t      if (pfound->has_arg)\n\t\toptarg = nameend + 1;\n\t      else\n\t\t{\n\t\t  if (print_errors)\n\t\t    {\n\t\t      if (argv[optind - 1][1] == '-')\n\t\t\t/* --option */\n\t\t\tfprintf (stderr,\n\t\t\t\t _(\"%s: option `--%s' doesn't allow an argument\\n\"),\n\t\t\t\t argv[0], pfound->name);\n\t\t      else\n\t\t\t/* +option or -option */\n\t\t\tfprintf (stderr,\n\t\t\t\t _(\"%s: option `%c%s' doesn't allow an argument\\n\"),\n\t\t\t\t argv[0], argv[optind - 1][0], pfound->name);\n\t\t    }\n\n\t\t  nextchar += strlen (nextchar);\n\n\t\t  optopt = pfound->val;\n\t\t  return '?';\n\t\t}\n\t    }\n\t  else if (pfound->has_arg == 1)\n\t    {\n\t      if (optind < argc)\n\t\toptarg = argv[optind++];\n\t      else\n\t\t{\n\t\t  if (print_errors)\n\t\t    fprintf (stderr,\n\t\t\t   _(\"%s: option `%s' requires an argument\\n\"),\n\t\t\t   argv[0], argv[optind - 1]);\n\t\t  nextchar += strlen (nextchar);\n\t\t  optopt = pfound->val;\n\t\t  return optstring[0] == ':' ? ':' : '?';\n\t\t}\n\t    }\n\t  nextchar += strlen (nextchar);\n\t  if (longind != NULL)\n\t    *longind = option_index;\n\t  if (pfound->flag)\n\t    {\n\t      *(pfound->flag) = pfound->val;\n\t      return 0;\n\t    }\n\t  return pfound->val;\n\t}\n\n      /* Can't find it as a long option.  If this is not getopt_long_only,\n\t or the option starts with '--' or is not a valid short\n\t option, then it's an error.\n\t Otherwise interpret it as a short option.  */\n      if (!long_only || argv[optind][1] == '-'\n\t  || my_index (optstring, *nextchar) == NULL)\n\t{\n\t  if (print_errors)\n\t    {\n\t      if (argv[optind][1] == '-')\n\t\t/* --option */\n\t\tfprintf (stderr, _(\"%s: unrecognized option `--%s'\\n\"),\n\t\t\t argv[0], nextchar);\n\t      else\n\t\t/* +option or -option */\n\t\tfprintf (stderr, _(\"%s: unrecognized option `%c%s'\\n\"),\n\t\t\t argv[0], argv[optind][0], nextchar);\n\t    }\n\t  nextchar = (char *) \"\";\n\t  optind++;\n\t  optopt = 0;\n\t  return '?';\n\t}\n    }\n\n  /* Look at and handle the next short option-character.  */\n\n  {\n    char c = *nextchar++;\n    char *temp = my_index (optstring, c);\n\n    /* Increment `optind' when we start to process its last character.  */\n    if (*nextchar == '\\0')\n      ++optind;\n\n    if (temp == NULL || c == ':')\n      {\n\tif (print_errors)\n\t  {\n\t    if (posixly_correct)\n\t      /* 1003.2 specifies the format of this message.  */\n\t      fprintf (stderr, _(\"%s: illegal option -- %c\\n\"),\n\t\t       argv[0], c);\n\t    else\n\t      fprintf (stderr, _(\"%s: invalid option -- %c\\n\"),\n\t\t       argv[0], c);\n\t  }\n\toptopt = c;\n\treturn '?';\n      }\n    /* Convenience. Treat POSIX -W foo same as long option --foo */\n    if (temp[0] == 'W' && temp[1] == ';')\n      {\n\tchar *nameend;\n\tconst struct option *p;\n\tconst struct option *pfound = NULL;\n\tint exact = 0;\n\tint ambig = 0;\n\tint indfound = 0;\n\tint option_index;\n\n\t/* This is an option that requires an argument.  */\n\tif (*nextchar != '\\0')\n\t  {\n\t    optarg = nextchar;\n\t    /* If we end this ARGV-element by taking the rest as an arg,\n\t       we must advance to the next element now.  */\n\t    optind++;\n\t  }\n\telse if (optind == argc)\n\t  {\n\t    if (print_errors)\n\t      {\n\t\t/* 1003.2 specifies the format of this message.  */\n\t\tfprintf (stderr, _(\"%s: option requires an argument -- %c\\n\"),\n\t\t\t argv[0], c);\n\t      }\n\t    optopt = c;\n\t    if (optstring[0] == ':')\n\t      c = ':';\n\t    else\n\t      c = '?';\n\t    return c;\n\t  }\n\telse\n\t  /* We already incremented `optind' once;\n\t     increment it again when taking next ARGV-elt as argument.  */\n\t  optarg = argv[optind++];\n\n\t/* optarg is now the argument, see if it's in the\n\t   table of longopts.  */\n\n\tfor (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)\n\t  /* Do nothing.  */ ;\n\n\t/* Test all long options for either exact match\n\t   or abbreviated matches.  */\n\tfor (p = longopts, option_index = 0; p->name; p++, option_index++)\n\t  if (!strncmp (p->name, nextchar, nameend - nextchar))\n\t    {\n\t      if ((unsigned int) (nameend - nextchar) == strlen (p->name))\n\t\t{\n\t\t  /* Exact match found.  */\n\t\t  pfound = p;\n\t\t  indfound = option_index;\n\t\t  exact = 1;\n\t\t  break;\n\t\t}\n\t      else if (pfound == NULL)\n\t\t{\n\t\t  /* First nonexact match found.  */\n\t\t  pfound = p;\n\t\t  indfound = option_index;\n\t\t}\n\t      else\n\t\t/* Second or later nonexact match found.  */\n\t\tambig = 1;\n\t    }\n\tif (ambig && !exact)\n\t  {\n\t    if (print_errors)\n\t      fprintf (stderr, _(\"%s: option `-W %s' is ambiguous\\n\"),\n\t\t       argv[0], argv[optind]);\n\t    nextchar += strlen (nextchar);\n\t    optind++;\n\t    return '?';\n\t  }\n\tif (pfound != NULL)\n\t  {\n\t    option_index = indfound;\n\t    if (*nameend)\n\t      {\n\t\t/* Don't test has_arg with >, because some C compilers don't\n\t\t   allow it to be used on enums.  */\n\t\tif (pfound->has_arg)\n\t\t  optarg = nameend + 1;\n\t\telse\n\t\t  {\n\t\t    if (print_errors)\n\t\t      fprintf (stderr, _(\"\\\n%s: option `-W %s' doesn't allow an argument\\n\"),\n\t\t\t       argv[0], pfound->name);\n\n\t\t    nextchar += strlen (nextchar);\n\t\t    return '?';\n\t\t  }\n\t      }\n\t    else if (pfound->has_arg == 1)\n\t      {\n\t\tif (optind < argc)\n\t\t  optarg = argv[optind++];\n\t\telse\n\t\t  {\n\t\t    if (print_errors)\n\t\t      fprintf (stderr,\n\t\t\t       _(\"%s: option `%s' requires an argument\\n\"),\n\t\t\t       argv[0], argv[optind - 1]);\n\t\t    nextchar += strlen (nextchar);\n\t\t    return optstring[0] == ':' ? ':' : '?';\n\t\t  }\n\t      }\n\t    nextchar += strlen (nextchar);\n\t    if (longind != NULL)\n\t      *longind = option_index;\n\t    if (pfound->flag)\n\t      {\n\t\t*(pfound->flag) = pfound->val;\n\t\treturn 0;\n\t      }\n\t    return pfound->val;\n\t  }\n\t  nextchar = NULL;\n\t  return 'W';\t/* Let the application handle it.   */\n      }\n    if (temp[1] == ':')\n      {\n\tif (temp[2] == ':')\n\t  {\n\t    /* This is an option that accepts an argument optionally.  */\n\t    if (*nextchar != '\\0')\n\t      {\n\t\toptarg = nextchar;\n\t\toptind++;\n\t      }\n\t    else\n\t      optarg = NULL;\n\t    nextchar = NULL;\n\t  }\n\telse\n\t  {\n\t    /* This is an option that requires an argument.  */\n\t    if (*nextchar != '\\0')\n\t      {\n\t\toptarg = nextchar;\n\t\t/* If we end this ARGV-element by taking the rest as an arg,\n\t\t   we must advance to the next element now.  */\n\t\toptind++;\n\t      }\n\t    else if (optind == argc)\n\t      {\n\t\tif (print_errors)\n\t\t  {\n\t\t    /* 1003.2 specifies the format of this message.  */\n\t\t    fprintf (stderr,\n\t\t\t     _(\"%s: option requires an argument -- %c\\n\"),\n\t\t\t     argv[0], c);\n\t\t  }\n\t\toptopt = c;\n\t\tif (optstring[0] == ':')\n\t\t  c = ':';\n\t\telse\n\t\t  c = '?';\n\t      }\n\t    else\n\t      /* We already incremented `optind' once;\n\t\t increment it again when taking next ARGV-elt as argument.  */\n\t      optarg = argv[optind++];\n\t    nextchar = NULL;\n\t  }\n      }\n    return c;\n  }\n}\n\nint\ngetopt (argc, argv, optstring)\n     int argc;\n     char *const *argv;\n     const char *optstring;\n{\n  return _getopt_internal (argc, argv, optstring,\n\t\t\t   (const struct option *) 0,\n\t\t\t   (int *) 0,\n\t\t\t   0);\n}\n\n#endif\t/* Not ELIDE_CODE.  */\n\f\n#ifdef TEST\n\n/* Compile with -DTEST to make an executable for use in testing\n   the above definition of `getopt'.  */\n\nint\nmain (argc, argv)\n     int argc;\n     char **argv;\n{\n  int c;\n  int digit_optind = 0;\n\n  while (1)\n    {\n      int this_option_optind = optind ? optind : 1;\n\n      c = getopt (argc, argv, \"abc:d:0123456789\");\n      if (c == -1)\n\tbreak;\n\n      switch (c)\n\t{\n\tcase '0':\n\tcase '1':\n\tcase '2':\n\tcase '3':\n\tcase '4':\n\tcase '5':\n\tcase '6':\n\tcase '7':\n\tcase '8':\n\tcase '9':\n\t  if (digit_optind != 0 && digit_optind != this_option_optind)\n\t    printf (\"digits occur in two different argv-elements.\\n\");\n\t  digit_optind = this_option_optind;\n\t  printf (\"option %c\\n\", c);\n\t  break;\n\n\tcase 'a':\n\t  printf (\"option a\\n\");\n\t  break;\n\n\tcase 'b':\n\t  printf (\"option b\\n\");\n\t  break;\n\n\tcase 'c':\n\t  printf (\"option c with value `%s'\\n\", optarg);\n\t  break;\n\n\tcase '?':\n\t  break;\n\n\tdefault:\n\t  printf (\"?? getopt returned character code 0%o ??\\n\", c);\n\t}\n    }\n\n  if (optind < argc)\n    {\n      printf (\"non-option ARGV-elements: \");\n      while (optind < argc)\n\tprintf (\"%s \", argv[optind++]);\n      printf (\"\\n\");\n    }\n\n  exit (0);\n}\n\n#endif /* TEST */\n"
  },
  {
    "path": "utilities/gengetopt/getopt.h",
    "content": "/* Declarations for getopt.\n   Copyright (C) 1989-1994, 1996-1999, 2001 Free Software Foundation, Inc.\n   This file is part of the GNU C Library.\n\n   The GNU C Library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   The GNU C Library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with the GNU C Library; if not, write to the Free\n   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\n   02111-1307 USA.  */\n\n#ifndef _GETOPT_H\n\n#ifndef __need_getopt\n# define _GETOPT_H 1\n#endif\n\n/* If __GNU_LIBRARY__ is not already defined, either we are being used\n   standalone, or this is the first header included in the source file.\n   If we are being used with glibc, we need to include <features.h>, but\n   that does not exist if we are standalone.  So: if __GNU_LIBRARY__ is\n   not defined, include <ctype.h>, which will pull in <features.h> for us\n   if it's from glibc.  (Why ctype.h?  It's guaranteed to exist and it\n   doesn't flood the namespace with stuff the way some other headers do.)  */\n#if !defined __GNU_LIBRARY__\n# include <ctype.h>\n#endif\n\n#ifdef\t__cplusplus\nextern \"C\" {\n#endif\n\n/* For communication from `getopt' to the caller.\n   When `getopt' finds an option that takes an argument,\n   the argument value is returned here.\n   Also, when `ordering' is RETURN_IN_ORDER,\n   each non-option ARGV-element is returned here.  */\n\nextern char *optarg;\n\n/* Index in ARGV of the next element to be scanned.\n   This is used for communication to and from the caller\n   and for communication between successive calls to `getopt'.\n\n   On entry to `getopt', zero means this is the first call; initialize.\n\n   When `getopt' returns -1, this is the index of the first of the\n   non-option elements that the caller should itself scan.\n\n   Otherwise, `optind' communicates from one call to the next\n   how much of ARGV has been scanned so far.  */\n\nextern int optind;\n\n/* Callers store zero here to inhibit the error message `getopt' prints\n   for unrecognized options.  */\n\nextern int opterr;\n\n/* Set to an option character which was unrecognized.  */\n\nextern int optopt;\n\n#ifndef __need_getopt\n/* Describe the long-named options requested by the application.\n   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector\n   of `struct option' terminated by an element containing a name which is\n   zero.\n\n   The field `has_arg' is:\n   no_argument\t\t(or 0) if the option does not take an argument,\n   required_argument\t(or 1) if the option requires an argument,\n   optional_argument \t(or 2) if the option takes an optional argument.\n\n   If the field `flag' is not NULL, it points to a variable that is set\n   to the value given in the field `val' when the option is found, but\n   left unchanged if the option is not found.\n\n   To have a long-named option do something other than set an `int' to\n   a compiled-in constant, such as set a value from `optarg', set the\n   option's `flag' field to zero and its `val' field to a nonzero\n   value (the equivalent single-letter option character, if there is\n   one).  For long options that have a zero `flag' field, `getopt'\n   returns the contents of the `val' field.  */\n\nstruct option\n{\n# if (defined __STDC__ && __STDC__) || defined __cplusplus\n  const char *name;\n# else\n  char *name;\n# endif\n  /* has_arg can't be an enum because some compilers complain about\n     type mismatches in all the code that assumes it is an int.  */\n  int has_arg;\n  int *flag;\n  int val;\n};\n\n/* Names for the values of the `has_arg' field of `struct option'.  */\n\n# define no_argument\t\t0\n# define required_argument\t1\n# define optional_argument\t2\n#endif\t/* need getopt */\n\n\n/* Get definitions and prototypes for functions to process the\n   arguments in ARGV (ARGC of them, minus the program name) for\n   options given in OPTS.\n\n   Return the option character from OPTS just read.  Return -1 when\n   there are no more options.  For unrecognized options, or options\n   missing arguments, `optopt' is set to the option letter, and '?' is\n   returned.\n\n   The OPTS string is a list of characters which are recognized option\n   letters, optionally followed by colons, specifying that that letter\n   takes an argument, to be placed in `optarg'.\n\n   If a letter in OPTS is followed by two colons, its argument is\n   optional.  This behavior is specific to the GNU `getopt'.\n\n   The argument `--' causes premature termination of argument\n   scanning, explicitly telling `getopt' that there are no more\n   options.\n\n   If OPTS begins with `--', then non-option arguments are treated as\n   arguments to the option '\\0'.  This behavior is specific to the GNU\n   `getopt'.  */\n\n#if (defined __STDC__ && __STDC__) || defined __cplusplus\n# ifdef __GNU_LIBRARY__\n/* Many other libraries have conflicting prototypes for getopt, with\n   differences in the consts, in stdlib.h.  To avoid compilation\n   errors, only prototype getopt for the GNU C library.  */\nextern int getopt (int __argc, char *const *__argv, const char *__shortopts);\n# else /* not __GNU_LIBRARY__ */\nextern int getopt ();\n# endif /* __GNU_LIBRARY__ */\n\n# ifndef __need_getopt\nextern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,\n\t\t        const struct option *__longopts, int *__longind);\nextern int getopt_long_only (int __argc, char *const *__argv,\n\t\t\t     const char *__shortopts,\n\t\t             const struct option *__longopts, int *__longind);\n\n/* Internal only.  Users should not call this directly.  */\nextern int _getopt_internal (int __argc, char *const *__argv,\n\t\t\t     const char *__shortopts,\n\t\t             const struct option *__longopts, int *__longind,\n\t\t\t     int __long_only);\n# endif\n#else /* not __STDC__ */\nextern int getopt ();\n# ifndef __need_getopt\nextern int getopt_long ();\nextern int getopt_long_only ();\n\nextern int _getopt_internal ();\n# endif\n#endif /* __STDC__ */\n\n#ifdef\t__cplusplus\n}\n#endif\n\n/* Make sure we later can get all the definitions and declarations.  */\n#undef __need_getopt\n\n#endif /* getopt.h */\n"
  },
  {
    "path": "utilities/gengetopt/getopt1.c",
    "content": "/* getopt_long and getopt_long_only entry points for GNU getopt.\n   Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98\n     Free Software Foundation, Inc.\n   This file is part of the GNU C Library.\n\n   The GNU C Library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   The GNU C Library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with the GNU C Library; if not, write to the Free\n   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA\n   02111-1307 USA.  */\n\f\n#ifdef HAVE_CONFIG_H\n#include <config.h>\n#endif\n\n#include \"getopt.h\"\n\n#if !defined __STDC__ || !__STDC__\n/* This is a separate conditional since some stdc systems\n   reject `defined (const)'.  */\n#ifndef const\n#define const\n#endif\n#endif\n\n#include <stdio.h>\n\n/* Comment out all this code if we are using the GNU C Library, and are not\n   actually compiling the library itself.  This code is part of the GNU C\n   Library, but also included in many other GNU distributions.  Compiling\n   and linking in this code is a waste when using the GNU C library\n   (especially if it is a shared library).  Rather than having every GNU\n   program understand `configure --with-gnu-libc' and omit the object files,\n   it is simpler to just do this in the source for each such file.  */\n\n#define GETOPT_INTERFACE_VERSION 2\n#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2\n#include <gnu-versions.h>\n#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION\n#define ELIDE_CODE\n#endif\n#endif\n\n#ifndef ELIDE_CODE\n\n\n/* This needs to come after some library #include\n   to get __GNU_LIBRARY__ defined.  */\n#ifdef __GNU_LIBRARY__\n#include <stdlib.h>\n#endif\n\n#ifndef\tNULL\n#define NULL 0\n#endif\n\nint\ngetopt_long (argc, argv, options, long_options, opt_index)\n     int argc;\n     char *const *argv;\n     const char *options;\n     const struct option *long_options;\n     int *opt_index;\n{\n  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);\n}\n\n/* Like getopt_long, but '-' as well as '--' can indicate a long option.\n   If an option that starts with '-' (not '--') doesn't match a long option,\n   but does match a short option, it is parsed as a short option\n   instead.  */\n\nint\ngetopt_long_only (argc, argv, options, long_options, opt_index)\n     int argc;\n     char *const *argv;\n     const char *options;\n     const struct option *long_options;\n     int *opt_index;\n{\n  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);\n}\n\n\n#endif\t/* Not ELIDE_CODE.  */\n\f\n#ifdef TEST\n\n#include <stdio.h>\n\nint\nmain (argc, argv)\n     int argc;\n     char **argv;\n{\n  int c;\n  int digit_optind = 0;\n\n  while (1)\n    {\n      int this_option_optind = optind ? optind : 1;\n      int option_index = 0;\n      static struct option long_options[] =\n      {\n\t{\"add\", 1, 0, 0},\n\t{\"append\", 0, 0, 0},\n\t{\"delete\", 1, 0, 0},\n\t{\"verbose\", 0, 0, 0},\n\t{\"create\", 0, 0, 0},\n\t{\"file\", 1, 0, 0},\n\t{0, 0, 0, 0}\n      };\n\n      c = getopt_long (argc, argv, \"abc:d:0123456789\",\n\t\t       long_options, &option_index);\n      if (c == -1)\n\tbreak;\n\n      switch (c)\n\t{\n\tcase 0:\n\t  printf (\"option %s\", long_options[option_index].name);\n\t  if (optarg)\n\t    printf (\" with arg %s\", optarg);\n\t  printf (\"\\n\");\n\t  break;\n\n\tcase '0':\n\tcase '1':\n\tcase '2':\n\tcase '3':\n\tcase '4':\n\tcase '5':\n\tcase '6':\n\tcase '7':\n\tcase '8':\n\tcase '9':\n\t  if (digit_optind != 0 && digit_optind != this_option_optind)\n\t    printf (\"digits occur in two different argv-elements.\\n\");\n\t  digit_optind = this_option_optind;\n\t  printf (\"option %c\\n\", c);\n\t  break;\n\n\tcase 'a':\n\t  printf (\"option a\\n\");\n\t  break;\n\n\tcase 'b':\n\t  printf (\"option b\\n\");\n\t  break;\n\n\tcase 'c':\n\t  printf (\"option c with value `%s'\\n\", optarg);\n\t  break;\n\n\tcase 'd':\n\t  printf (\"option d with value `%s'\\n\", optarg);\n\t  break;\n\n\tcase '?':\n\t  break;\n\n\tdefault:\n\t  printf (\"?? getopt returned character code 0%o ??\\n\", c);\n\t}\n    }\n\n  if (optind < argc)\n    {\n      printf (\"non-option ARGV-elements: \");\n      while (optind < argc)\n\tprintf (\"%s \", argv[optind++]);\n      printf (\"\\n\");\n    }\n\n  exit (0);\n}\n\n#endif /* TEST */\n"
  },
  {
    "path": "utilities/gengetopt/ggo_options.h",
    "content": "#ifndef GGO_OPTIONS_H\n#define GGO_OPTIONS_H\n\n#include \"ggos.h\"\n\nextern gengetopt_option_list gengetopt_options;\n\n#define foropt for (gengetopt_option_list::iterator it = gengetopt_options.begin();             \\\n                    it != gengetopt_options.end() && (opt = *it); \\\n                    ++it)\n\n#endif /* GGO_OPTIONS_H */\n"
  },
  {
    "path": "utilities/gengetopt/ggos.cpp",
    "content": "//\n// C++ Implementation: ggos\n//\n// Description:\n//\n//\n// Author: Lorenzo Bettini <https://www.lorenzobettini.it>, (C) 2005-2007\n//\n// Copyright: See COPYING file that comes with this distribution\n//\n//\n\n#include \"ggos.h\"\n\nusing namespace std;\n\ngengetopt_option::gengetopt_option() :\n    short_opt(0), long_opt(0), desc(0), type(ARG_NO), flagstat(-1),\n            required(1), required_set(false), var_arg(0), default_string(0),\n            group_value(0), group_desc(0),\n            mode_value(0), mode_desc(0),\n            multiple(false),\n            arg_is_optional(false), hidden(false), type_str(0),\n            acceptedvalues(0), section(0), section_desc(0), dependon(0),\n            text_before(0), text_after(0), details(0), filename(0), linenum(0) {\n}\n\nostream & operator <<(std::ostream &s, gengetopt_option &opt) {\n    s << \"long: \" << opt.long_opt << \", short: \" << opt.short_opt << \"\\n\"\n            << \"desc: \" << opt.desc;\n\n    s << endl;\n\n    return s;\n}\n"
  },
  {
    "path": "utilities/gengetopt/ggos.h",
    "content": "/*\nThis file is licensed to you under the license specified in the included file\n`LICENSE'. Look there for further details.\n*/\n\n\n#ifndef _GENGETOPT_GGOS_H\n#define _GENGETOPT_GGOS_H\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <list>\n#include <iostream>\n\n#include \"acceptedvalues.h\"\n#include \"argsdef.h\"\n\n/**\n * The structure for storing an option specified in the .ggo file\n */\nstruct gengetopt_option\n{\n  char short_opt; /**< the short option specification (one char) */\n  char * long_opt; /**< the short option specification */\n  char * desc; /**< the option description */\n  int type; /**< the type of the option (possible values in `argsdef.h') */\n  int flagstat ; /**< if the option is of type flag, this indicates its state (on/off) */\n  int required; /**< whether the option required */\n  bool required_set; /**< whether the required property was set */\n  char * var_arg; /**< canonized long_opt + \"_arg\" = argument var */\n  int default_given ; /**< if a default is given */\n  char * default_string ; /**< default value for this option, if string */\n  char * group_value; /**< group name, if it's part of an option group */\n  char * group_desc; /**< group description, if it's part of an option group */\n  char * mode_value; /**< mode name, if it's part of an option mode */\n  char * mode_desc; /**< mode description, if it's part of an option mode */\n  bool multiple; /**< whether this option can be given more than once */\n  char * multiple_min; /**< minimum occurrences of a multiple option (-1: not specified) */\n  char * multiple_max; /**< maximum occurrences of a multiple option (-1: not specified) */\n  bool arg_is_optional; /**< whether the argument is optional */\n  bool hidden; /**< whether this option will be hidden from the help output */\n  char *type_str; /**< Alternative name for type,\n                     e.g. \"URL\" or \"SECONDS\" */\n  const AcceptedValues *acceptedvalues; /**< values that can be passed to this option */\n  char *section; /**< the section of this option */\n  char *section_desc; /**< the description associated with the possible section */\n  char *dependon; /**< the name of the option this one depends on */\n\n  char *text_before; /**< a possible text specified before this option */\n  char *text_after; /**< a possible text specified after this option */\n\n  char *details; /**< possible further details for this option that will be\n  printed only if --detailed-help is specified */\n\n  /**< parser information */\n  char *filename; /**< source file */\n  int linenum; /**< line number */\n\n  gengetopt_option();\n};\n\n/** the list storing gengetopt options */\ntypedef std::list<gengetopt_option *> gengetopt_option_list;\n\nstd::ostream & operator <<(std::ostream &s, gengetopt_option &opt);\n\n#endif /* _GENGETOPT_GGOS_H */\n"
  },
  {
    "path": "utilities/gengetopt/global_opts.h",
    "content": "/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#ifndef GLOBAL_OPTS_H\n#define GLOBAL_OPTS_H\n\n#define HELP_LONG_OPT \"help\"\n#define HELP_SHORT_OPT 'h'\n#define HELP_SHORT_OPT_STR \"h\"\n#define HELP_OPT_DESCR \"Print help and exit\"\n\n#define FULL_HELP_LONG_OPT \"full-help\"\n#define FULL_HELP_LONG_OPT_FIELD \"full_help\"\n#define FULL_HELP_OPT_DESCR \"Print help, including hidden options, and exit\"\n\n#define DETAILED_HELP_LONG_OPT \"detailed-help\"\n#define DETAILED_HELP_LONG_OPT_FIELD \"detailed_help\"\n#define DETAILED_HELP_OPT_DESCR \"Print help, including all details and hidden options, and exit\"\n\n#define VERSION_LONG_OPT \"version\"\n#define VERSION_SHORT_OPT 'V'\n#define VERSION_SHORT_OPT_STR \"V\"\n#define VERSION_OPT_DESCR \"Print version and exit\"\n\n#endif /* GLOBAL_OPTS_H */\n"
  },
  {
    "path": "utilities/gengetopt/globals.cpp",
    "content": "/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#include \"globals.h\"\n\ngengetopt_option_list gengetopt_options;\n\ngroups_collection_t gengetopt_groups;\n"
  },
  {
    "path": "utilities/gengetopt/globals.h",
    "content": "/**\n * Copyright (C) 1999-2010  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#ifndef GLOBALS_H_\n#define GLOBALS_H_\n\n#include \"ggos.h\"\n#include \"groups.h\"\n\nextern gengetopt_option_list gengetopt_options;\n\nextern groups_collection_t gengetopt_groups;\n\n#endif /* GLOBALS_H_ */\n"
  },
  {
    "path": "utilities/gengetopt/gm.cc",
    "content": "/**\n * Copyright (C) 1999-2010  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <string>\n#include <set>\n#include <algorithm> // for pair\n\n#include <fstream>\n\nextern \"C\"\n{\n#include \"argsdef.h\"\n#include \"global_opts.h\"\n};\n\n#include \"ggo_options.h\"\n\n#include \"gm.h\"\n#include \"my_sstream.h\"\n\n#include \"groups.h\"\n#include \"skels/option_arg.h\"\n#include \"skels/required_option.h\"\n#include \"skels/dependant_option.h\"\n#include \"skels/generic_option.h\"\n#include \"skels/group_option.h\"\n#include \"skels/group_counter.h\"\n#include \"skels/handle_help.h\"\n#include \"skels/handle_version.h\"\n#include \"skels/print_help_string.h\"\n#include \"skels/multiple_opt_list.h\"\n#include \"skels/multiple_fill_array.h\"\n#include \"skels/free_string.h\"\n#include \"skels/free_multiple.h\"\n#include \"skels/reset_group.h\"\n#include \"skels/exit_failure.h\"\n#include \"skels/update_given.h\"\n#include \"skels/given_field.h\"\n#include \"skels/clear_given.h\"\n#include \"skels/clear_arg.h\"\n#include \"skels/free_list.h\"\n#include \"skels/file_save.h\"\n#include \"skels/file_save_multiple.h\"\n#include \"skels/init_args_info.h\"\n#include \"skels/custom_getopt_gen.h\"\n#include \"skels/check_modes.h\"\n#include \"skels/enum_decl.h\"\n#include \"gm_utils.h\"\n#include \"fileutils.h\"\n\n#ifndef FIX_UNUSED\n#define FIX_UNUSED(X) (void) (X)\n#endif // FIX_UNUSED\n\n#define MAX_STARTING_COLUMN 32\n\n#define EXE_NAME \"argv[0]\"\n\n#define PARSER_NAME_PREFIX (c_source_gen_class::parser_name + \"_\")\n#define OPTION_VALUES_NAME(n) (PARSER_NAME_PREFIX + n + \"_values\")\n\nusing std::endl;\nusing std::set;\n\nextern char * gengetopt_package;\nextern char * gengetopt_version;\nextern char * gengetopt_purpose;\nextern char * gengetopt_description;\nextern char * gengetopt_usage;\nextern char * gengetopt_input_filename;\n\nextern groups_collection_t gengetopt_groups;\nextern modes_collection_t gengetopt_modes;\n\n// a map where for each mode we store the corresponding given field names\n// and the options\ntypedef std::pair<string, string> OptionValueElem;\ntypedef std::list<OptionValueElem> ModeOptions;\ntypedef std::map<string, ModeOptions> ModeOptionMap;\n\nstatic ModeOptionMap modeOptionMap;\n\nstatic const ModeOptionMap &getModeOptionMap() {\n    if (modeOptionMap.size() == 0) {\n        // it's the first time, so we build it\n        struct gengetopt_option * opt;\n        foropt {\n            if (opt->mode_value) {\n                modeOptionMap[opt->mode_value].push_back\n                (std::make_pair(\"args_info->\" + string(opt->var_arg) + \"_given\",\n                        string(\"\\\"--\") + opt->long_opt + \"\\\"\"));\n            }\n        }\n    }\n\n    return modeOptionMap;\n}\n\n// a map associating to a mode the list of gengetopt_options\ntypedef std::map<string, gengetopt_option_list> ModeOptMap;\n\nstatic ModeOptMap modeOptMap;\n\nstatic const ModeOptMap &getModeOptMap() {\n    if (modeOptMap.size() == 0) {\n        // it's the first time, so we build it\n        struct gengetopt_option * opt;\n        foropt {\n            if (opt->mode_value) {\n                modeOptMap[opt->mode_value].push_back(opt);\n            }\n        }\n    }\n\n    return modeOptMap;\n}\n\nstatic void _generate_option_arg(ostream &stream,\n                                 unsigned int indent,\n                                 struct gengetopt_option * opt);\n\nstatic void\ngenerate_help_desc_print(ostream &stream,\n                         unsigned int desc_column,\n                         const char *descript, const char *defval,\n                         const string &values,\n                         const string &show_required_string);\n\nCmdlineParserCreator::CmdlineParserCreator (char *function_name,\n                                            char *struct_name,\n                                            char *unamed_options_,\n                                            char *filename_,\n                                            char *header_ext, char *c_ext,\n                                            bool long_help_,\n                                            bool no_handle_help_,\n                                            bool no_help_,\n                                            bool no_handle_version_,\n                                            bool no_version_,\n                                            bool no_handle_error_,\n                                            bool conf_parser_,\n                                            bool string_parser_,\n                                            bool gen_version,\n                                            bool gen_getopt,\n                                            bool no_options_,\n                                            const string &comment_,\n                                            const string &outdir,\n                                            const string &header_outdir,\n                                            const string &src_outdir,\n                                            const string &show_required) :\n  filename (filename_),\n  args_info_name (struct_name),\n  output_dir (outdir),\n  header_output_dir (header_outdir),\n  src_output_dir (src_outdir),\n  comment (comment_),\n  unamed_options (unamed_options_),\n  show_required_string (show_required),\n  long_help (long_help_), no_handle_help (no_handle_help_),\n  no_help (no_help_),\n  no_handle_version (no_handle_version_),\n  no_version (no_version_),\n  no_handle_error (no_handle_error_),\n  conf_parser (conf_parser_), string_parser (string_parser_),\n  gen_gengetopt_version (gen_version),\n  tab_indentation (0)\n{\n  parser_function_name = canonize_names (function_name);\n  c_filename = create_filename (filename, c_ext);\n  header_filename = create_filename (filename, header_ext);\n\n  // header_gen_class\n  const string stripped_header_file_name = strip_path (filename);\n  set_header_file_name (stripped_header_file_name);\n  header_gen_class::set_header_file_ext (header_ext);\n  c_source_gen_class::set_header_file_ext (header_ext);\n  if (gen_gengetopt_version)\n    header_gen_class::set_generator_version\n      (\"version \" VERSION);\n  const string my_ifndefname =\n    to_upper (strip_path (stripped_header_file_name));\n  set_ifndefname (canonize_names (my_ifndefname.c_str ()));\n  header_gen_class::set_parser_name (parser_function_name);\n  const string my_package_var_name =\n    to_upper (parser_function_name) + \"_PACKAGE\";\n  const string my_version_var_name =\n    to_upper (parser_function_name) + \"_VERSION\";\n  header_gen_class::set_package_var_name (my_package_var_name);\n  c_source_gen_class::set_package_var_name (my_package_var_name);\n  header_gen_class::set_version_var_name (my_version_var_name);\n  c_source_gen_class::set_version_var_name (my_version_var_name);\n  header_gen_class::set_args_info (args_info_name);\n  c_source_gen_class::set_args_info (args_info_name);\n  const string uppersand = \"\\\"\";\n\n  // if no_options then we don't need to generate update_arg,\n  // but if we need to handle help or version we still need to generate it\n  set_no_options (no_options_ && !no_handle_help && !no_handle_version);\n\n  if (gengetopt_package)\n    set_package_var_val\n      (uppersand + gengetopt_package + uppersand);\n  else\n    set_package_var_val (\"PACKAGE\");\n\n  if (gengetopt_version)\n    set_version_var_val\n      (uppersand + gengetopt_version + uppersand);\n  else\n    set_version_var_val (\"VERSION\");\n\n  header_gen_class::set_generate_config_parser (conf_parser);\n\n  header_gen_class::set_generate_string_parser (string_parser);\n  c_source_gen_class::set_generate_string_parser (string_parser);\n\n  // c_source_gen_class\n  set_command_line (comment);\n  if (gen_gengetopt_version)\n    c_source_gen_class::set_generator_version\n      (\"version \" VERSION);\n  c_source_gen_class::set_parser_name (parser_function_name);\n  set_source_name (filename);\n\n  ostringstream exit_failure_str;\n  exit_failure_gen_class exit_gen;\n  exit_gen.set_parser_name (c_source_gen_class::parser_name);\n  exit_gen.set_handle_error (! no_handle_error);\n  exit_gen.generate_exit_failure (exit_failure_str);\n  set_final_exit (exit_failure_str.str ());\n\n  set_conf_parser (conf_parser);\n  set_cmd_list (conf_parser || string_parser);\n  set_include_getopt (gen_getopt);\n\n  struct gengetopt_option * opt;\n  gen_strdup = (unamed_options != 0 || conf_parser || string_parser);\n\n  if (! gen_strdup)\n    {\n      foropt\n        if (opt->type != ARG_FLAG || opt->type != ARG_NO) {\n          gen_strdup = true;\n          break;\n        }\n    }\n\n  set_do_generate_strdup(gen_strdup);\n  set_check_possible_values(has_values());\n  set_multiple_token_functions(has_multiple_options_with_type());\n  set_multiple_options_with_default(has_multiple_options_with_default());\n  set_multiple_options(has_multiple_options());\n  set_multiple_options_string(has_multiple_options_string());\n  set_multiple_options_all_string(has_multiple_options_all_string());\n  set_has_typed_options(has_options_with_type());\n  set_has_modes(has_options_with_mode());\n  set_handle_unamed(unamed_options);\n  set_check_required_options(has_required() || has_dependencies() || has_multiple_options());\n  set_purpose(generate_purpose());\n  set_description(generate_description());\n  set_no_package((gengetopt_package == 0));\n  c_source_gen_class::set_has_hidden(has_hidden_options());\n  header_gen_class::set_has_hidden(c_source_gen_class::has_hidden);\n  c_source_gen_class::set_has_details(has_options_with_details());\n  header_gen_class::set_has_details(c_source_gen_class::has_details);\n\n  set_has_arg_types();\n}\n\nvoid CmdlineParserCreator::set_has_arg_types() {\n    struct gengetopt_option * opt;\n\n    set_has_arg_flag(false);\n    set_has_arg_string(false);\n    set_has_arg_int(false);\n    set_has_arg_short(false);\n    set_has_arg_long(false);\n    set_has_arg_float(false);\n    set_has_arg_double(false);\n    set_has_arg_longdouble(false);\n    set_has_arg_longlong(false);\n\n    foropt\n    {\n        switch (opt->type) {\n        case ARG_NO:\n            break;\n        case ARG_FLAG:\n            set_has_arg_flag(true);\n            break;\n        case ARG_STRING:\n            set_has_arg_string(true);\n            break;\n        case ARG_INT:\n            set_has_arg_int(true);\n            break;\n        case ARG_SHORT:\n            set_has_arg_short(true);\n            break;\n        case ARG_LONG:\n            set_has_arg_long(true);\n            break;\n        case ARG_FLOAT:\n            set_has_arg_float(true);\n            break;\n        case ARG_DOUBLE:\n            set_has_arg_double(true);\n            break;\n        case ARG_LONGDOUBLE:\n            set_has_arg_longdouble(true);\n            break;\n        case ARG_LONGLONG:\n            set_has_arg_longlong(true);\n            break;\n        case ARG_ENUM:\n            set_has_arg_enum(true);\n            break;\n        default:\n            fprintf (stderr, \"gengetopt: bug found in %s:%d!!\\n\",\n                    __FILE__, __LINE__);\n            abort ();\n        }\n    }\n\n}\n\nvoid\nCmdlineParserCreator::generateBreak(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n\n  stream << endl;\n  stream << indent_str;\n  stream << \"break;\";\n}\n\nint\nCmdlineParserCreator::generate ()\n{\n  int head_result;\n\n  head_result = generate_header_file ();\n  if (head_result)\n    return head_result;\n\n  return generate_source ();\n}\n\nint\nCmdlineParserCreator::generate_header_file ()\n{\n  if (! gengetopt_options.size())\n    {\n      fprintf (stderr, \"gengetopt: none option given\\n\");\n      return 1;\n    }\n\n  /* ****************************************************** */\n  /* HEADER FILE******************************************* */\n  /* ****************************************************** */\n\n    string header_file = header_filename;\n    if (header_output_dir.size())\n        header_file = header_output_dir + \"/\" + header_file;\n    else if (output_dir.size())\n        header_file = output_dir + \"/\" + header_file;\n\n    ofstream *output_file = open_fstream\n            (header_file.c_str());\n    generate_header (*output_file);\n    output_file->close ();\n    delete output_file;\n\n    return 0;\n}\n\n/**\n * generate the enum value from a given option\n * @param name the (canonized) name of the option\n * @param val the value of the option\n * @return the enum value string\n */\nstatic const string from_value_to_enum(const string &name, const string &val) {\n    return name + \"_arg_\" + canonize_enum(val);\n}\n\nvoid\nCmdlineParserCreator::generate_enum_types(ostream &stream,\n                                          unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  FIX_UNUSED (indent);\n\n  if (has_arg_enum)\n      stream << endl;\n\n  foropt {\n    // if type is enum then it should also have values (checked during parsing)\n    // but it's better to check it\n    if (opt->type == ARG_ENUM) {\n        if (! (opt->acceptedvalues)) {\n            fprintf (stderr, \"gengetopt: bug found in %s:%d!!\\n\",\n                            __FILE__, __LINE__);\n            abort ();\n        }\n        ostringstream enum_values;\n        enum_decl_gen_class enum_gen;\n        enum_gen.set_var_arg(opt->var_arg);\n        for (AcceptedValues::const_iterator it = opt->acceptedvalues->begin();\n            it != opt->acceptedvalues->end(); ++it) {\n            enum_values << \", \";\n            // the first enum element is set to 0\n            enum_values << from_value_to_enum(opt->var_arg, *it);\n            if (it == opt->acceptedvalues->begin())\n                enum_values << \" = 0\";\n\n        }\n        enum_gen.set_enum_values(enum_values.str());\n        enum_gen.generate_enum_decl(stream);\n    }\n  }\n}\n\nvoid\nCmdlineParserCreator::generate_option_arg(ostream &stream,\n                                          unsigned int indent)\n{\n  struct gengetopt_option * opt;\n\n  foropt {\n    _generate_option_arg (stream, indent, opt);\n  }\n}\n\nvoid\n_generate_option_arg(ostream &stream,\n                     unsigned int indent,\n                     struct gengetopt_option *opt)\n{\n  option_arg_gen_class option_arg_gen;\n\n  string type = \"\";\n  if (opt->type)\n      type = arg_types[opt->type];\n  string origtype = \"char *\";\n\n  if (opt->multiple) {\n    type += \"*\";\n    origtype += \"*\";\n    option_arg_gen.set_multiple(true);\n  } else {\n    option_arg_gen.set_multiple(false);\n  }\n\n  option_arg_gen.set_type(type);\n  option_arg_gen.set_origtype(origtype);\n  option_arg_gen.set_flag_arg((opt->type == ARG_FLAG));\n  option_arg_gen.set_desc(opt->desc);\n  option_arg_gen.set_name(opt->var_arg);\n  option_arg_gen.set_has_arg(opt->type != ARG_NO);\n  option_arg_gen.set_has_enum(opt->type == ARG_ENUM);\n\n  if (opt->default_given)\n    {\n      option_arg_gen.set_has_default(true);\n      option_arg_gen.set_default_value(opt->default_string);\n    }\n\n  if (opt->type == ARG_FLAG)\n    {\n      option_arg_gen.set_default_on(opt->flagstat);\n    }\n\n  if (opt->type == ARG_LONGLONG)\n    {\n      // the fallback type in case longlong is not supported by the compiler\n      string longtype = arg_types[ARG_LONG];\n      if (opt->multiple)\n          longtype += \"*\";\n\n      option_arg_gen.set_long_long_arg(true);\n      option_arg_gen.set_longtype(longtype);\n    }\n\n  option_arg_gen.generate_option_arg(stream, indent);\n}\n\nvoid\nCmdlineParserCreator::generate_option_given(ostream &stream,\n                                            unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  string indent_str (indent, ' ');\n  bool first = true;\n  given_field_gen_class given_gen;\n\n  foropt\n    {\n      switch (opt->type) {\n      case ARG_NO:\n      case ARG_FLAG:\n      case ARG_STRING:\n      case ARG_INT:\n      case ARG_SHORT:\n      case ARG_LONG:\n      case ARG_FLOAT:\n      case ARG_DOUBLE:\n      case ARG_LONGDOUBLE:\n      case ARG_LONGLONG:\n      case ARG_ENUM:\n          break;\n      default:\n        fprintf (stderr, \"gengetopt: bug found in %s:%d!!\\n\",\n                 __FILE__, __LINE__);\n        abort ();\n      }\n      if (! first)\n        stream << indent_str;\n      else\n        first = false;\n\n      given_gen.set_arg_name (opt->var_arg);\n      given_gen.set_long_opt (opt->long_opt);\n      given_gen.set_group (opt->multiple && opt->group_value);\n      given_gen.generate_given_field (stream);\n    }\n\n  if (unamed_options)\n    {\n      stream << endl;\n      stream << indent_str;\n      stream << \"char **inputs ; /**< @brief unamed options (options without names) */\\n\" ;\n      stream << indent_str;\n      stream << \"unsigned inputs_num ; /**< @brief unamed options number */\" ;\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_option_values_decl(ostream &stream,\n                                                  unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  bool first = true;\n  FIX_UNUSED (indent);\n\n  foropt\n    {\n      if (opt->acceptedvalues) {\n        if (first) {\n          first = false;\n        }\n\n        stream << \"extern const char *\" << OPTION_VALUES_NAME(opt->var_arg) <<\n          \"[];  /**< @brief Possible values for \" << opt->long_opt << \". */\\n\";\n      }\n    }\n\n  if (! first)\n    stream << \"\\n\";\n}\n\nvoid\nCmdlineParserCreator::generate_option_values(ostream &stream,\n                                             unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  bool first = true;\n  FIX_UNUSED (indent);\n\n  foropt\n    {\n      if (opt->acceptedvalues) {\n        if (first) {\n          first = false;\n        }\n\n        stream << \"const char *\" << OPTION_VALUES_NAME(opt->var_arg) <<\n          \"[] = {\" << opt->acceptedvalues->toString(false) <<\n          \", 0}; /*< Possible values for \" << opt->long_opt << \". */\\n\";\n      }\n    }\n\n  if (! first)\n    stream << \"\\n\";\n}\n\nstatic void generate_option_usage_string(gengetopt_option * opt, ostream &usage) {\n    const char   *type_str;\n\n    usage << \" \";\n\n    if (!opt->required)\n        usage << \"[\";\n\n    switch (opt->type) {\n    case ARG_NO:\n    case ARG_FLAG:\n        if (opt->short_opt)\n            usage << \"-\" << opt->short_opt << \"|\";\n        usage << \"--\" << opt->long_opt;\n        break;\n    case ARG_INT:\n    case ARG_SHORT:\n    case ARG_LONG:\n    case ARG_FLOAT:\n    case ARG_DOUBLE:\n    case ARG_LONGDOUBLE:\n    case ARG_LONGLONG:\n    case ARG_STRING:\n    case ARG_ENUM:\n        if (opt->type_str)\n            type_str = opt->type_str;\n        else\n            type_str = arg_names[opt->type];\n\n        if (opt->short_opt)\n            usage << \"-\" << opt->short_opt << type_str << \"|\";\n        usage << \"--\" << opt->long_opt << \"=\" << type_str;\n\n        break;\n    default: fprintf (stderr, \"gengetopt: bug found in %s:%d!!\\n\",\n            __FILE__, __LINE__);\n    abort ();\n    }\n\n    if (!opt->required)\n        usage << \"]\";\n}\n\nconst string\nCmdlineParserCreator::generate_usage_string(bool use_config_package)\n{\n  FIX_UNUSED (use_config_package);\n  // if specified by the programmer, the usage string has the precedence\n  if (gengetopt_usage) {\n    return gengetopt_usage;\n  }\n\n  struct gengetopt_option * opt;\n  ostringstream usage;\n\n  // otherwise the config.h package constant will be used\n  if (gengetopt_package)\n    usage << gengetopt_package;\n\n  if ( long_help ) {\n      // we first generate usage strings of required options\n      // handle mode options separately\n      foropt\n          if (opt->required && !opt->hidden && !opt->mode_value) {\n              generate_option_usage_string(opt, usage);\n          }\n\n      foropt\n          if (!opt->required && !opt->hidden && !opt->mode_value) {\n              generate_option_usage_string(opt, usage);\n          }\n  } else { /* if not long help we generate it as GNU standards */\n      usage << \" [OPTIONS]...\";\n  }\n\n  string wrapped;\n\n  if ( unamed_options )\n      usage << \" [\" << unamed_options << \"]...\";\n\n  wrap_cstr ( wrapped, strlen(\"Usage: \"), 2, usage.str() );\n\n  // now deal with modes\n  if (has_modes && long_help) {\n      const ModeOptMap &modeOptMap = getModeOptMap();\n\n      for (ModeOptMap::const_iterator map_it = modeOptMap.begin(); map_it != modeOptMap.end(); ++map_it) {\n          string mode_line; // a mode alternative in the usage string\n          gengetopt_option_list::const_iterator opt_it;\n          usage.str(\"\"); // reset the usage string buffer\n\n          for (opt_it = map_it->second.begin(); opt_it != map_it->second.end(); ++opt_it) {\n              if (((*opt_it)->required) && !((*opt_it)->hidden)) {\n                  generate_option_usage_string(*opt_it, usage);\n              }\n          }\n\n          for (opt_it = map_it->second.begin(); opt_it != map_it->second.end(); ++opt_it) {\n              if (!((*opt_it)->required) && !((*opt_it)->hidden)) {\n                  generate_option_usage_string(*opt_it, usage);\n              }\n          }\n\n          wrap_cstr ( mode_line, strlen(\"  or : \"), 2, gengetopt_package + usage.str() );\n          wrapped += \"\\\\n  or : \";\n          wrapped += mode_line;\n      }\n  }\n\n  return wrapped;\n}\n\nstatic void\ngenerate_help_desc_print(ostream &stream,\n                         unsigned int desc_column,\n                         const char *descript, const char *defval,\n                         const string &values,\n                         const string &show_required_string)\n{\n  string desc;\n  string desc_with_default = descript;\n\n  if (defval || values.size()) {\n      desc_with_default += \"  (\";\n\n      if (values.size()) {\n        desc_with_default += \"possible values=\";\n        desc_with_default += values;\n        if (defval)\n          desc_with_default += \" \";\n      }\n\n      if (defval) {\n        desc_with_default += \"default=\";\n        desc_with_default += defval;\n      }\n\n      desc_with_default += \")\";\n  }\n\n  if (show_required_string != \"\")\n    desc_with_default += \" \" + show_required_string;\n\n  wrap_cstr ( desc, desc_column, 2, desc_with_default );\n\n  stream << desc;\n}\n\n\nvoid\nCmdlineParserCreator::generate_help_option_print_from_lists(ostream &stream,\n        unsigned int indent, OptionHelpList *full_option_list,\n        OptionHelpList *option_list, const std::string &target_array,\n        const std::string &source_array) {\n    print_help_string_gen_class print_gen;\n\n    // the index into the help arrays\n    int i = 0, full_i = 0;\n    // num of help strings\n    int help_num = 0;\n\n    print_gen.set_target(target_array);\n    print_gen.set_from(source_array);\n    print_gen.set_shared(true);\n    print_gen.set_last(false);\n\n    OptionHelpList::const_iterator it = option_list->begin();\n    OptionHelpList::const_iterator it2 = full_option_list->begin();\n    // the second list is surely longer so we scan that one\n    for (; it != option_list->end() && it2 != full_option_list->end(); ++it2)\n    {\n        if (*it == *it2) {\n            // when the two strings are the same it means that's a non-hidden\n            // option, so we share it with the full help array\n            ostringstream converted_int;\n            converted_int << i;\n\n            // the index into the help array\n            print_gen.set_index(converted_int.str());\n\n            converted_int.str(\"\");\n            converted_int << full_i;\n\n            // the index into the full help array\n            print_gen.set_full_index(converted_int.str());\n            print_gen.generate_print_help_string(stream, indent);\n\n            ++help_num;\n            ++i;\n            ++it;\n        }\n        ++full_i;\n    }\n\n    ostringstream converted_int;\n    converted_int << help_num;\n\n    // the final 0\n    print_gen.set_last(true);\n    print_gen.set_index(converted_int.str());\n    print_gen.generate_print_help_string(stream, indent);\n\n    // we increment it to store the final 0\n    converted_int.str(\"\");\n    converted_int << ++help_num;\n\n    set_help_string_num(converted_int.str());\n\n}\n\nvoid\nCmdlineParserCreator::generate_help_option_print(ostream &stream,\n                                                 unsigned int indent)\n{\n    OptionHelpList *option_list = generate_help_option_list();\n\n    if (!c_source_gen_class::has_hidden && !c_source_gen_class::has_details) {\n        print_help_string_gen_class print_gen;\n        print_gen.set_shared(false);\n\n        // simple help generation\n        for (OptionHelpList::const_iterator it = option_list->begin();\n        it != option_list->end(); ++it)\n        {\n            print_gen.set_helpstring(*it);\n            print_gen.generate_print_help_string(stream, indent);\n        }\n    } else {\n        // in order to avoid generating the same help string twice, and thus\n        // to save memory, in case of hidden options (or details), we try to share most\n        // of the strings with the full help array\n        OptionHelpList *full_option_list = generate_help_option_list(true, true);\n\n        generate_help_option_print_from_lists\n        (stream, indent, full_option_list, option_list,\n                c_source_gen_class::args_info + \"_help\",\n                (c_source_gen_class::has_details ?\n                        c_source_gen_class::args_info + \"_detailed_help\" :\n                            c_source_gen_class::args_info + \"_full_help\"));\n\n        delete full_option_list;\n    }\n\n    delete option_list;\n}\n\nvoid\nCmdlineParserCreator::generate_full_help_option_print(ostream &stream,\n        unsigned int indent)\n{\n    // generate also hidden options\n    OptionHelpList *option_list = generate_help_option_list(true);\n\n    if (!c_source_gen_class::has_details) {\n        print_help_string_gen_class print_gen;\n        print_gen.set_shared(false);\n\n        for (OptionHelpList::const_iterator it = option_list->begin();\n        it != option_list->end(); ++it)\n        {\n            print_gen.set_helpstring(*it);\n            print_gen.generate_print_help_string(stream, indent);\n        }\n    } else {\n        // in order to avoid generating the same help string twice, and thus\n        // to save memory, in case of options with details, we try to share most\n        // of the strings with the full help array\n        OptionHelpList *full_option_list = generate_help_option_list(true, true);\n\n        generate_help_option_print_from_lists\n        (stream, indent, full_option_list, option_list,\n                c_source_gen_class::args_info + \"_full_help\",\n                c_source_gen_class::args_info + \"_detailed_help\");\n\n        delete full_option_list;\n    }\n\n    delete option_list;\n}\n\nvoid\nCmdlineParserCreator::generate_detailed_help_option_print(ostream &stream,\n        unsigned int indent)\n{\n    // generate also hidden options and details\n    OptionHelpList *option_list = generate_help_option_list(true, true);\n\n    print_help_string_gen_class print_gen;\n    print_gen.set_shared(false);\n\n    for (OptionHelpList::const_iterator it = option_list->begin();\n         it != option_list->end(); ++it)\n    {\n        print_gen.set_helpstring(*it);\n        print_gen.generate_print_help_string(stream, indent);\n    }\n\n    delete option_list;\n}\n\nvoid\nCmdlineParserCreator::generate_init_args_info(ostream &stream, unsigned int indent)\n{\n    struct gengetopt_option * opt;\n    init_args_info_gen_class init_args_info_gen;\n    int i = 0;\n    ostringstream index;\n\n    string help_string = c_source_gen_class::args_info;\n\n    if (c_source_gen_class::has_details) {\n        help_string += \"_detailed_help\";\n    } else if (c_source_gen_class::has_hidden) {\n        help_string += \"_full_help\";\n    } else {\n        help_string += \"_help\";\n    }\n    init_args_info_gen.set_help_strings(help_string);\n\n    const char *current_section = 0, *current_group = 0, *current_mode = 0;\n\n    // we have to skip section description references (that appear in the help vector)\n    foropt {\n        index.str(\"\");\n\n        if (opt->section) {\n          if (!current_section || (strcmp(current_section, opt->section) != 0)) {\n            // a different section reference, skip it\n            current_section = opt->section;\n            ++i;\n\n            if (opt->section_desc) {\n              // section description takes another line, thus we have to skip this too\n              ++i;\n            }\n          }\n        }\n\n        // skip group desc\n        if (opt->group_value) {\n            if (!current_group || strcmp(current_group, opt->group_value) != 0) {\n                current_group = opt->group_value;\n                ++i;\n            }\n        }\n\n        // skip mode desc\n        if (opt->mode_value) {\n            if (!current_mode || strcmp(current_mode, opt->mode_value) != 0) {\n                current_mode = opt->mode_value;\n                ++i;\n            }\n        }\n\n        // also skip the text before\n        if (opt->text_before)\n            ++i;\n\n        index << i++;\n\n        init_args_info_gen.set_var_arg(opt->var_arg);\n        init_args_info_gen.set_num(index.str());\n\n        if (opt->multiple) {\n            init_args_info_gen.set_multiple(true);\n            init_args_info_gen.set_min(opt->multiple_min);\n            init_args_info_gen.set_max(opt->multiple_max);\n        } else {\n            init_args_info_gen.set_multiple(false);\n        }\n\n        init_args_info_gen.generate_init_args_info(stream, indent);\n\n        // skip the details\n        if (opt->details)\n            ++i;\n\n        // skip the text after\n        if (opt->text_after)\n            ++i;\n\n    }\n}\n\nvoid CmdlineParserCreator::generate_custom_getopt(ostream &stream, unsigned int indent)\n{\n    custom_getopt_gen_gen_class custom_getopt;\n\n    custom_getopt.generate_custom_getopt_gen (stream, indent);\n}\n\nconst string\nCmdlineParserCreator::generate_purpose()\n{\n  string wrapped_purpose;\n\n  if (gengetopt_purpose != NULL)\n    {\n      wrap_cstr(wrapped_purpose, 0, 0, gengetopt_purpose);\n    }\n\n  return wrapped_purpose;\n}\n\nconst string\nCmdlineParserCreator::generate_description()\n{\n  string wrapped_description;\n\n  if (gengetopt_description != NULL)\n    {\n      wrap_cstr(wrapped_description, 0, 0, gengetopt_description);\n    }\n\n  return wrapped_description;\n}\n\n\nOptionHelpList *\nCmdlineParserCreator::generate_help_option_list(bool generate_hidden, bool generate_details)\n{\n  OptionHelpList *option_list = new OptionHelpList;\n\n  unsigned long desc_col;\n  struct gengetopt_option * opt;\n\n  int           type_len;\n  const char   *type_str;\n  ostringstream stream;\n\n  // if we want to generate details then we will also generate hidden options\n  if (generate_details)\n      generate_hidden = true;\n\n  /* calculate columns */\n  desc_col = 0;\n  foropt {\n    // if (opt->hidden && !generate_hidden)\n    //    continue;\n    // when computing columns, we also consider hidden_options, so that\n    // the --help and --full-help will be aligned just the same\n    // IMPORTANT: this is also crucial due to how the help string array\n    // is built starting from the full-help string array:\n    // we iterate over the two lists of options and check whether the\n    // corresponding strings are the same; thus, the help strings must\n    // have the same space alignments, otherwise they're not equal\n\n    unsigned int width = 2 + 4 + 2;  // ws + \"-a, \" + ws\n\n    width += strlen (opt->long_opt) + 2;  // \"--\"\n\n    if ((opt->type != ARG_FLAG) &&\n        (opt->type != ARG_NO))\n      {\n        if (opt->type_str)\n          type_str = opt->type_str;\n        else\n          type_str = arg_names[opt->type];\n        type_len = strlen(type_str);\n\n        width += type_len + 1;        // \"=\"\n\n        if (opt->arg_is_optional)\n          width += 2; // \"[\" and \"]\"\n      }\n\n    if (width > desc_col)\n      desc_col = width;\n  }\n\n  if (desc_col > MAX_STARTING_COLUMN)\n    desc_col = MAX_STARTING_COLUMN;\n\n  /* print justified options */\n  char *prev_group = 0;\n  char *prev_mode = 0;\n  char *curr_section = 0;\n  bool first_option = true;\n\n  foropt\n    {\n      // if the option is hidden, avoid to print a section containing only\n      // hidden options\n      if (opt->section &&\n              (!curr_section || strcmp (curr_section, opt->section)) &&\n              (!opt->hidden || generate_hidden))\n      {\n          curr_section = opt->section;\n\n          ostringstream sec_string;\n\n          if (! first_option)\n              sec_string << \"\\\\n\";\n\n          sec_string << opt->section << \":\" ;\n\n          string wrapped_def;\n          wrap_cstr(wrapped_def, 0, 0, sec_string.str());\n          option_list->push_back(wrapped_def);\n\n          if (opt->section_desc)\n          {\n              string wrapped_desc ( 2, ' ');\n              wrap_cstr ( wrapped_desc, 2, 0, opt->section_desc );\n\n              option_list->push_back(wrapped_desc);\n          }\n      }\n\n      if (opt->group_value &&\n              (! prev_group || strcmp (opt->group_value, prev_group) != 0))\n      {\n          string group_string = \"\\\\n Group: \";\n          string wrapped_desc;\n\n          if (opt->group_desc && strlen (opt->group_desc))\n          {\n              wrapped_desc = \"\\\\n  \";\n              wrap_cstr (wrapped_desc, 2, 0, opt->group_desc);\n          }\n\n          group_string += opt->group_value + wrapped_desc;\n\n          option_list->push_back (group_string);\n\n          prev_group = opt->group_value;\n      }\n\n      if (opt->mode_value &&\n              (! prev_mode || strcmp (opt->mode_value, prev_mode) != 0))\n      {\n          string mode_string = \"\\\\n Mode: \";\n          string wrapped_desc;\n\n          if (opt->mode_desc && strlen (opt->mode_desc))\n          {\n              wrapped_desc = \"\\\\n  \";\n              wrap_cstr (wrapped_desc, 2, 0, opt->mode_desc);\n          }\n\n          mode_string += opt->mode_value + wrapped_desc;\n\n          option_list->push_back (mode_string);\n\n          prev_mode = opt->mode_value;\n      }\n\n      // a possible description to be printed before this option\n      if (opt->text_before)\n      {\n          string wrapped_desc;\n          wrap_cstr ( wrapped_desc, 0, 0, opt->text_before);\n\n          option_list->push_back(wrapped_desc);\n      }\n\n      if (!opt->hidden || generate_hidden) {\n          first_option = false;\n          const char * def_val = NULL;\n          string def_str = \"`\";\n\n          ostringstream option_stream;\n\n          if (opt->type == ARG_FLAG || opt->type == ARG_NO)\n          {\n              def_val = NULL;\n\n              if (opt->short_opt)\n                  option_stream << \"  -\" << opt->short_opt << \", \";\n              else\n                  option_stream << \"      \";\n\n              option_stream << \"--\" << opt->long_opt;\n\n              if (opt->type == ARG_FLAG)\n                  def_val = opt->flagstat ? \"on\" : \"off\";\n          }\n          else\n          {\n              def_val = NULL;\n\n              if (opt->type_str)\n                  type_str = opt->type_str;\n              else\n                  type_str = arg_names[opt->type];\n\n              type_len = strlen(type_str);\n\n              if (opt->short_opt)\n              {\n                  option_stream << \"  -\" << opt->short_opt << \", \";\n              }\n              else\n              {\n                  option_stream << \"      \";\n              }\n\n              bool arg_optional = opt->arg_is_optional;\n              option_stream << \"--\" << opt->long_opt\n              << (arg_optional ? \"[\" : \"\")\n              << \"=\" << type_str\n              << (arg_optional ? \"]\" : \"\");\n\n              if (opt->default_string)\n              {\n                  def_str += opt->default_string;\n                  def_str += \"'\";\n                  def_val = def_str.c_str();\n              }\n          }\n\n          const string &option_string = option_stream.str();\n          stream << option_string;\n          const char *opt_desc = opt->desc;\n\n          if ((option_string.size() >= MAX_STARTING_COLUMN) ||\n                  (desc_col <= option_string.size()))\n          {\n              string indent (MAX_STARTING_COLUMN, ' ');\n              stream << \"\\\\n\" << indent;\n          }\n          else\n          {\n              string indent (desc_col - option_string.size(), ' ');\n              stream << indent;\n          }\n\n          generate_help_desc_print(stream, desc_col, opt_desc, def_val,\n                  (opt->acceptedvalues ? opt->acceptedvalues->toString() : \"\"),\n                  (opt->required && show_required_string != \"\" ? show_required_string : \"\"));\n\n          option_list->push_back(stream.str());\n          stream.str(\"\");\n      }\n\n      // before the text after we generate details if we need to\n      if (opt->details && generate_details) {\n          string wrapped_desc ( 2, ' ');\n          // details are indented\n          wrap_cstr ( wrapped_desc, 2, 0, opt->details);\n\n          option_list->push_back(wrapped_desc);\n      }\n\n      // a possible description to be printed after this option\n      if (opt->text_after)\n      {\n          string wrapped_desc;\n          wrap_cstr ( wrapped_desc, 0, 0, opt->text_after);\n\n          option_list->push_back(wrapped_desc);\n      }\n    }\n\n  return option_list;\n}\n\ntemplate <typename Collection>\nvoid generate_counter_init(const Collection &collection, const string &name, ostream &stream, unsigned int indent)\n{\n    string indent_str (indent, ' ');\n    typename Collection::const_iterator end = collection.end();\n\n    for ( typename Collection::const_iterator idx = collection.begin(); idx != end; ++idx)\n    {\n        stream << indent_str;\n        stream << ARGS_STRUCT << \"->\" << canonize_name (idx->first) << \"_\" <<\n            name << \"_counter = 0 ;\";\n        stream << endl;\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_given_init(ostream &stream,\n                                          unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  string indent_str (indent, ' ');\n  clear_given_gen_class clear_given;\n  clear_given.set_arg_struct(ARGS_STRUCT);\n\n  /* now we initialize \"given\" fields */\n  foropt\n    {\n      stream << indent_str;\n      clear_given.set_var_arg(opt->var_arg);\n      clear_given.set_group(opt->multiple && opt->group_value);\n      clear_given.generate_clear_given(stream);\n    }\n\n  // for group counter initialization\n  generate_counter_init(gengetopt_groups, \"group\", stream, indent);\n\n  // for mode counter initialization\n  generate_counter_init(gengetopt_modes, \"mode\", stream, indent);\n}\n\nvoid\nCmdlineParserCreator::generate_reset_groups(ostream &stream, unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  string indent_str (indent, ' ');\n  ostringstream body;\n  reset_group_gen_class reset_group;\n  clear_given_gen_class clear_given;\n  clear_given.set_arg_struct(ARGS_STRUCT);\n\n  reset_group.set_args_info (c_source_gen_class::args_info);\n\n  groups_collection_t::const_iterator end = gengetopt_groups.end();\n  for ( groups_collection_t::const_iterator idx = gengetopt_groups.begin();\n        idx != end; ++idx)\n    {\n      body.str (\"\");\n      bool found_option = false;\n      bool multiple_arg = false;\n\n      foropt\n      {\n        if (opt->group_value && strcmp(opt->group_value, idx->first.c_str()) == 0)\n          {\n            /* now we reset \"given\" fields */\n            stream << indent_str;\n            clear_given.set_var_arg(opt->var_arg);\n            if (opt->multiple && opt->group_value)\n              multiple_arg = true;\n            clear_given.set_group(opt->multiple && opt->group_value);\n            clear_given.generate_clear_given(body);\n\n            free_option (opt, body, indent);\n            found_option = true;\n          }\n      }\n\n      if (found_option)\n        {\n          reset_group.set_name (canonize_name (idx->first));\n          reset_group.set_body (body.str ());\n          reset_group.generate_reset_group (stream);\n        }\n    }\n}\n\nvoid\nCmdlineParserCreator::free_option(struct gengetopt_option *opt,\n                                  ostream &stream, unsigned int indent)\n{\n  if (opt->type == ARG_NO)\n    return;\n\n  if (opt->type != ARG_FLAG)\n    {\n      if (opt->multiple)\n        {\n          free_multiple_gen_class free_multiple;\n          free_multiple.set_has_string_type(opt->type == ARG_STRING);\n          free_multiple.set_structure (ARGS_STRUCT);\n\n          free_multiple.set_opt_var (opt->var_arg);\n          free_multiple.generate_free_multiple\n            (stream, indent);\n        }\n      else\n        {\n          free_string_gen_class free_string;\n          free_string.set_has_string_type(opt->type == ARG_STRING);\n          free_string.set_structure (ARGS_STRUCT);\n\n          free_string.set_opt_var (opt->var_arg);\n          free_string.generate_free_string (stream, indent);\n        }\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_list_def(ostream &stream, unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  string indent_str (indent, ' ');\n  multiple_opt_list_gen_class multiple_opt_list;\n\n  /* define linked-list structs for multiple options */\n  foropt\n    {\n      if (opt->multiple)\n        {\n          if (opt->type)\n            {\n              stream << indent_str;\n              multiple_opt_list.set_arg_name (opt->var_arg);\n              multiple_opt_list.generate_multiple_opt_list (stream, indent);\n              stream << endl;\n            }\n        }\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_multiple_fill_array(ostream &stream, unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  string indent_str (indent, ' ');\n  multiple_fill_array_gen_class filler;\n\n  /* copy linked list into the array */\n  foropt\n    {\n      if (opt->multiple && opt->type)\n        {\n          stream << indent_str;\n          filler.set_option_var_name (opt->var_arg);\n          filler.set_arg_type(arg_type_constants[opt->type]);\n          filler.set_type (arg_types_names[opt->type]);\n          string default_string = \"0\";\n          if (opt->default_string) {\n              if (opt->type == ARG_STRING)\n                  default_string = string(\"\\\"\") + opt->default_string + \"\\\"\";\n              else if (opt->type == ARG_ENUM)\n                  default_string = from_value_to_enum(opt->var_arg, opt->default_string);\n              else\n                  default_string = opt->default_string;\n          }\n          filler.set_default_value (default_string);\n\n          filler.generate_multiple_fill_array (stream, indent);\n\n          stream << endl;\n        }\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_update_multiple_given(ostream &stream, unsigned int indent)\n{\n  if (! has_multiple_options())\n    return;\n\n  string indent_str (indent, ' ');\n\n  stream << endl;\n  stream << indent_str;\n\n  update_given_gen_class update_given_gen;\n  struct gengetopt_option * opt;\n\n  foropt\n    {\n      if (opt->multiple)\n        {\n          update_given_gen.set_option_var_name (opt->var_arg);\n          update_given_gen.generate_update_given (stream, indent);\n        }\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_check_modes(ostream &stream, unsigned int indent)\n{\n    // no need to check for conflict if there's only one mode\n    if (gengetopt_modes.size() < 2)\n        return;\n\n    string indent_str (indent, ' ');\n\n    stream << endl;\n    stream << indent_str;\n\n    const ModeOptionMap &modeOptionMap = getModeOptionMap();\n\n    check_modes_gen_class check_modes_gen;\n\n    // now we check each mode options against every other mode options:\n    // the first one with the other n-1, the second one with the other n-2, etc.\n    ModeOptionMap::const_iterator map_it1, map_it2;\n    for (ModeOptionMap::const_iterator map_it = modeOptionMap.begin(); map_it != modeOptionMap.end(); ++map_it) {\n        map_it1 = map_it;\n        ++map_it;\n        if (map_it == modeOptionMap.end())\n            break;\n        for (map_it2 = map_it; map_it2 != modeOptionMap.end(); ++map_it2) {\n            const string mode1 = canonize_name(map_it1->first);\n            const string mode2 = canonize_name(map_it2->first);\n\n            check_modes_gen.set_mode1_name(mode1);\n            check_modes_gen.set_mode2_name(mode2);\n\n            ostringstream mode1_given, mode2_given, mode1_options, mode2_options;\n\n            std::for_each(map_it1->second.begin(), map_it1->second.end(), pair_print_f<OptionValueElem>(mode1_given, mode1_options));\n            std::for_each(map_it2->second.begin(), map_it2->second.end(), pair_print_f<OptionValueElem>(mode2_given, mode2_options));\n\n            check_modes_gen.set_mode1_given_fields(mode1_given.str());\n            check_modes_gen.set_mode1_options(mode1_options.str());\n            check_modes_gen.set_mode2_given_fields(mode2_given.str());\n            check_modes_gen.set_mode2_options(mode2_options.str());\n\n            check_modes_gen.generate_check_modes(stream, indent);\n        }\n        map_it = map_it1;\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_clear_arg(ostream &stream, unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  clear_arg_gen_class clear_arg;\n\n  /* now we initialize value fields */\n  foropt\n    {\n      if (opt->type == ARG_NO)\n        continue;\n\n      clear_arg.set_name(opt->var_arg);\n      clear_arg.set_suffix(\"arg\");\n      clear_arg.set_value(\"NULL\");\n      clear_arg.set_has_orig(opt->type != ARG_FLAG);\n      clear_arg.set_has_arg(false);\n\n      if (opt->multiple && opt->type)\n        {\n          clear_arg.set_has_arg(true);\n        }\n      else if (opt->type == ARG_STRING)\n        {\n          clear_arg.set_has_arg(true);\n          if (opt->default_given)\n            clear_arg.set_value\n                (\"gengetopt_strdup (\\\"\" + string(opt->default_string) +\n                \"\\\")\");\n        }\n      else if (opt->type == ARG_FLAG)\n        {\n          clear_arg.set_has_arg(true);\n          clear_arg.set_suffix(\"flag\");\n          clear_arg.set_value(opt->flagstat ? \"1\" : \"0\");\n        }\n      else if (opt->type == ARG_ENUM)\n      {\n        // initialize enum arguments to -1 (unless they have a default)\n        clear_arg.set_has_arg(true);\n        if (opt->default_given)\n            clear_arg.set_value(from_value_to_enum(opt->var_arg, opt->default_string));\n        else\n            clear_arg.set_value(string(opt->var_arg) + \"__NULL\");\n      }\n      else if (opt->default_given)\n        {\n          clear_arg.set_has_arg(true);\n          clear_arg.set_value(opt->default_string);\n        }\n\n      clear_arg.generate_clear_arg(stream, indent);\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_long_option_struct(ostream &stream,\n                                                  unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  struct gengetopt_option * opt;\n\n  foropt\n    {\n      stream << indent_str;\n\n      stream << \"{ \\\"\" << opt->long_opt << \"\\\",\\t\"\n             << (opt->type == ARG_NO || opt->type == ARG_FLAG ? 0 :\n                 (opt->arg_is_optional ? 2 : 1))\n             << \", NULL, \";\n\n      if (opt->short_opt)\n        stream << \"\\'\" << opt->short_opt << \"\\'\";\n      else\n        stream << \"0\";\n\n      stream << \" },\" << endl;\n    }\n}\n\nstring\nCmdlineParserCreator::generate_getopt_string()\n{\n  struct gengetopt_option * opt;\n  ostringstream built_getopt_string;\n\n  foropt\n    if (opt->short_opt)\n      {\n        built_getopt_string << opt->short_opt <<\n          (opt->type == ARG_NO || opt->type == ARG_FLAG ? \"\" : \":\");\n        built_getopt_string <<\n          (opt->arg_is_optional ? \":\" : \"\");\n      }\n\n  return built_getopt_string.str ();\n}\n\nvoid\nCmdlineParserCreator::generate_handle_no_short_option(ostream &stream,\n                                                      unsigned int indent)\n{\n  handle_options(stream, indent, false);\n}\n\nvoid\nCmdlineParserCreator::generate_handle_option(ostream &stream,\n                                             unsigned int indent)\n{\n  handle_options(stream, indent, true);\n}\n\nvoid\nCmdlineParserCreator::handle_options(ostream &stream, unsigned int indent, bool has_short)\n{\n  struct gengetopt_option * opt;\n  generic_option_gen_class option_gen;\n  string indent_str (indent, ' ');\n  bool first = true;\n\n  option_gen.set_has_short_option (has_short);\n\n  // by default we handle '?' case in the switch\n  // unless the user defined a short option as ?\n  set_handle_question_mark(true);\n\n  foropt\n    {\n      if (opt->short_opt == '?')\n          set_handle_question_mark(false);\n\n      if ((has_short && opt->short_opt) || (!has_short && !opt->short_opt))\n        {\n          if (has_short || first)\n            stream << indent_str;\n\n          option_gen.set_option_comment (opt->desc);\n          option_gen.set_long_option (opt->long_opt);\n          option_gen.set_short_option(opt->short_opt ? string (1, opt->short_opt) : \"-\");\n          option_gen.set_option_var_name (opt->var_arg);\n          option_gen.set_final_instructions(\"\");\n\n          if (!no_help && ((opt->short_opt == HELP_SHORT_OPT &&\n                  strcmp(opt->long_opt, HELP_LONG_OPT) == 0)\n                  || strcmp(opt->long_opt, HELP_LONG_OPT) == 0\n                  || strcmp(opt->long_opt, FULL_HELP_LONG_OPT) == 0\n                  || strcmp(opt->long_opt, DETAILED_HELP_LONG_OPT) == 0)) {\n              bool full_help = (strcmp(opt->long_opt, FULL_HELP_LONG_OPT) == 0);\n              bool detailed_help = (strcmp(opt->long_opt, DETAILED_HELP_LONG_OPT) == 0);\n              if (no_handle_help) {\n                    // we use the final_instructions parameter to call the free function\n                    // and to return 0\n                    const string final_instructions =\n                    parser_function_name +\n                    string(\"_free (&local_args_info);\\nreturn 0;\");\n\n                    option_gen.set_final_instructions(final_instructions);\n\n                    if (full_help) {\n                        option_gen.set_long_option (FULL_HELP_LONG_OPT);\n                        option_gen.set_option_comment (FULL_HELP_OPT_DESCR);\n                    } else if (detailed_help) {\n                        option_gen.set_long_option (DETAILED_HELP_LONG_OPT);\n                        option_gen.set_option_comment (DETAILED_HELP_OPT_DESCR);\n                    } else {\n                        option_gen.set_long_option (HELP_LONG_OPT);\n                        option_gen.set_short_option (HELP_SHORT_OPT_STR);\n                        option_gen.set_option_comment (HELP_OPT_DESCR);\n                    }\n                    //option_gen.set_has_short_option (!full_help);\n              } else {\n                  handle_help_gen_class help_gen;\n                  help_gen.set_parser_name (parser_function_name);\n                  help_gen.set_full_help(full_help);\n                  help_gen.set_detailed_help(detailed_help);\n                  help_gen.set_short_opt(opt->short_opt == HELP_SHORT_OPT);\n                  help_gen.generate_handle_help (stream, indent);\n                  stream << endl;\n                  stream << endl;\n                  continue;\n              }\n          }\n\n          if (!no_version && ((opt->short_opt == VERSION_SHORT_OPT && strcmp(opt->long_opt, VERSION_LONG_OPT) == 0)\n                  || strcmp(opt->long_opt, VERSION_LONG_OPT) == 0)) {\n              if (no_handle_version) {\n                  option_gen.set_long_option (VERSION_LONG_OPT);\n                  option_gen.set_short_option (VERSION_SHORT_OPT_STR);\n                  option_gen.set_option_comment (VERSION_OPT_DESCR);\n                  //option_gen.set_has_short_option (true);\n\n                  // we use the final_instrauctions parameter to call the free function\n                  // and to return 0\n                  const string final_instructions =\n                      parser_function_name +\n                      string(\"_free (&local_args_info);\\nreturn 0;\");\n\n                  option_gen.set_final_instructions(final_instructions);\n              } else {\n                  handle_version_gen_class version_gen;\n                  version_gen.set_parser_name (parser_function_name);\n                  version_gen.set_short_opt (opt->short_opt == VERSION_SHORT_OPT);\n                  version_gen.generate_handle_version (stream, indent);\n                  stream << endl;\n                  stream << endl;\n                  continue;\n              }\n          }\n\n          if (opt->acceptedvalues != 0)\n              option_gen.set_possible_values (OPTION_VALUES_NAME(opt->var_arg));\n          else\n              option_gen.set_possible_values (\"0\");\n\n          string default_string = \"0\";\n          if (opt->default_string)\n              default_string = string(\"\\\"\") + opt->default_string + \"\\\"\";\n          option_gen.set_default_value (default_string);\n\n          option_gen.set_arg_type(arg_type_constants[opt->type]);\n\n          if (opt->group_value) {\n              option_gen.set_group_var_name (canonize_name (opt->group_value));\n              option_gen.set_option_has_group(true);\n          } else\n              option_gen.set_option_has_group(false);\n\n          if (opt->mode_value) {\n              // we reuse the variable group_var_name also for modes\n              option_gen.set_group_var_name (canonize_name (opt->mode_value));\n              option_gen.set_option_has_mode(true);\n          } else\n              option_gen.set_option_has_mode(false);\n\n          option_gen.set_option_has_type(opt->type != 0);\n\n          if (opt->multiple) {\n              option_gen.set_multiple(true);\n              option_gen.set_structure (string (opt->var_arg) + \"_list\");\n          } else {\n              option_gen.set_multiple(false);\n              option_gen.set_structure (ARGS_STRUCT);\n          }\n\n          option_gen.generate_generic_option (stream, indent);\n\n          if (has_short)\n            {\n              stream << endl;\n            }\n\n          if (first && !has_short)\n            {\n              first = false;\n              option_gen.set_gen_else (\"else \");\n            }\n        }\n    }\n\n  if (! first && !has_short) // something has been generated\n    {\n      generateBreak(stream, indent);\n      stream << endl;\n    }\n}\n\n#define GROUP_REQUIRED_COMPARISON \"!=\"\n#define GROUP_NOT_REQUIRED_COMPARISON \">\"\n#define GROUP_REQUIRED_MESSAGE \"One\"\n#define GROUP_NOT_REQUIRED_MESSAGE \"At most one\"\n\nvoid\nCmdlineParserCreator::generate_handle_group(ostream &stream,\n                                            unsigned int indent)\n{\n  group_option_gen_class opt_gen;\n  string indent_str (indent, ' ');\n  opt_gen.set_package_var_name (EXE_NAME);\n\n  opt_gen.set_Comparison_rule(GROUP_NOT_REQUIRED_COMPARISON \" 1\");\n\n  groups_collection_t::const_iterator end = gengetopt_groups.end();\n  for ( groups_collection_t::const_iterator idx = gengetopt_groups.begin();\n        idx != end; ++idx)\n    {\n      stream << indent_str;\n      opt_gen.set_group_name (idx->first);\n      opt_gen.set_group_var_name (canonize_name (idx->first));\n      if (idx->second.required)\n        {\n          opt_gen.set_number_required(GROUP_REQUIRED_MESSAGE);\n        }\n      else\n        {\n          opt_gen.set_number_required(GROUP_NOT_REQUIRED_MESSAGE);\n        }\n\n      opt_gen.generate_group_option (stream, indent);\n      stream << endl;\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_handle_required(ostream &stream,\n                                               unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  required_option_gen_class opt_gen;\n  opt_gen.set_package_var_name (\"prog_name\");\n\n  /* write test for required options or for multiple options\n     (occurrence number check) */\n  foropt\n    if ( opt->required || opt->multiple )\n      {\n        if (opt->mode_value) {\n            opt_gen.set_mode_condition(\"args_info->\" +\n                    canonize_name(opt->mode_value) + \"_mode_counter && \");\n        } else {\n            opt_gen.set_mode_condition(\"\");\n        }\n\n        // build the option command line representation\n        ostringstream req_opt;\n        req_opt << \"'--\" << opt->long_opt << \"'\";\n        if (opt->short_opt)\n          req_opt << \" ('-\" << opt->short_opt << \"')\";\n\n        opt_gen.set_option_var_name (opt->var_arg);\n        opt_gen.set_option_descr (req_opt.str ());\n\n        // if the option is required this is the standard check\n        if (opt->required) {\n          opt_gen.set_checkrange(false);\n\n          opt_gen.generate_required_option (stream, indent);\n        }\n\n        // if the option is multiple we generate also the\n        // occurrence range check\n        if (opt->multiple) {\n          opt_gen.set_checkrange(true);\n\n          opt_gen.generate_required_option (stream, indent);\n        }\n\n        // notice that the above ifs are not mutual exclusive:\n        // a multiple option can have a range check without being\n        // required.\n      }\n\n  // now generate the checks for required group options\n  group_option_gen_class group_opt_gen;\n  group_opt_gen.set_package_var_name (\"prog_name\");\n\n  group_opt_gen.set_Comparison_rule(\"== 0\");\n  group_opt_gen.set_number_required(GROUP_REQUIRED_MESSAGE);\n\n  groups_collection_t::const_iterator end = gengetopt_groups.end();\n  for ( groups_collection_t::const_iterator idx = gengetopt_groups.begin();\n        idx != end; ++idx)\n  {\n    if (idx->second.required)\n    {\n      group_opt_gen.set_group_name (idx->first);\n      group_opt_gen.set_group_var_name (canonize_name (idx->first));\n\n      group_opt_gen.generate_group_option (stream, indent);\n      stream << endl;\n    }\n  }\n}\n\nvoid\nCmdlineParserCreator::generate_handle_dependencies(ostream &stream,\n                                               unsigned int indent)\n{\n  struct gengetopt_option * opt;\n  dependant_option_gen_class opt_gen;\n  opt_gen.set_package_var_name (\"prog_name\");\n  string indent_str (indent, ' ');\n\n  /* write test for required options */\n  foropt\n    if ( opt->dependon )\n      {\n        stream << indent_str;\n\n        ostringstream req_opt;\n        req_opt << \"'--\" << opt->long_opt << \"'\";\n        if (opt->short_opt)\n          req_opt << \" ('-\" << opt->short_opt << \"')\";\n\n        opt_gen.set_option_var_name (opt->var_arg);\n        opt_gen.set_dep_option (canonize_name(opt->dependon));\n        opt_gen.set_option_descr (req_opt.str ());\n        opt_gen.set_dep_option_descr (opt->dependon);\n\n        opt_gen.generate_dependant_option (stream, indent);\n\n        stream << endl;\n      }\n}\n\ntemplate <typename Collection>\nvoid generate_counters(const Collection &collection, const string &name, ostream &stream, unsigned int indent)\n{\n    group_counter_gen_class counter_gen;\n    string indent_str (indent, ' ');\n\n    counter_gen.set_name(name);\n\n    typename Collection::const_iterator end = collection.end();\n    for ( typename Collection::const_iterator idx = collection.begin(); idx != end; ++idx) {\n        stream << indent_str;\n        counter_gen.set_group_name (canonize_name (idx->first));\n        counter_gen.generate_group_counter (stream, indent);\n        stream << endl;\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_group_counters(ostream &stream,\n                                              unsigned int indent)\n{\n    generate_counters(gengetopt_groups, \"group\", stream, indent);\n}\n\nvoid\nCmdlineParserCreator::generate_mode_counters(ostream &stream,\n                                              unsigned int indent)\n{\n    // we can reuse group counter gen class also for modes\n    generate_counters(gengetopt_modes, \"mode\", stream, indent);\n}\n\nint\nCmdlineParserCreator::generate_source ()\n{\n  /* ****************************************************** */\n  /* ********************************************** C FILE  */\n  /* ****************************************************** */\n\n  set_usage_string (generate_usage_string ());\n  set_getopt_string (generate_getopt_string ());\n\n  string output_source = c_filename;\n\n  if (src_output_dir.size())\n      output_source = src_output_dir + \"/\" + output_source;\n  else if (output_dir.size())\n      output_source = output_dir + \"/\" + output_source;\n\n  ofstream *output_file = open_fstream (output_source.c_str());\n  generate_c_source (*output_file);\n  output_file->close ();\n  delete output_file;\n\n  return 0;\n}\n\nvoid\nCmdlineParserCreator::generate_free(ostream &stream,\n                                    unsigned int indent)\n{\n  struct gengetopt_option * opt;\n\n  foropt\n    {\n      free_option (opt, stream, indent);\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_list_free(ostream &stream,\n                                         unsigned int indent)\n{\n  struct gengetopt_option * opt;\n\n  if (! has_multiple_options())\n    return;\n\n  free_list_gen_class free_list;\n\n  foropt\n    {\n      if (opt->multiple && opt->type) {\n        free_list.set_list_name(opt->var_arg);\n        free_list.set_string_list(opt->type == ARG_STRING);\n        free_list.generate_free_list(stream, indent);\n      }\n    }\n}\n\nvoid\nCmdlineParserCreator::generate_file_save_loop(ostream &stream, unsigned int indent)\n{\n  struct gengetopt_option * opt;\n\n  file_save_multiple_gen_class file_save_multiple;\n  file_save_gen_class file_save;\n\n  const string suffix = \"_orig\";\n  const string suffix_given = \"_given\";\n\n  foropt {\n    if (opt->multiple) {\n      file_save_multiple.set_has_arg(opt->type != ARG_NO);\n      file_save_multiple.set_opt_var(opt->var_arg);\n      file_save_multiple.set_opt_name(opt->long_opt);\n      file_save_multiple.set_values\n          ((opt->acceptedvalues ? OPTION_VALUES_NAME(opt->var_arg) : \"0\"));\n\n      file_save_multiple.generate_file_save_multiple(stream, indent);\n    } else {\n      file_save.set_opt_name(opt->long_opt);\n      file_save.set_given(opt->var_arg + suffix_given);\n      file_save.set_values\n          ((opt->acceptedvalues ? OPTION_VALUES_NAME(opt->var_arg) : \"0\"));\n\n      if (opt->type != ARG_NO && opt->type != ARG_FLAG) {\n        file_save.set_arg(opt->var_arg + suffix + (opt->multiple ? \" [i]\" : \"\"));\n      } else {\n        file_save.set_arg(\"\");\n      }\n      file_save.generate_file_save(stream, indent);\n    }\n  }\n}\n\n\n"
  },
  {
    "path": "utilities/gengetopt/gm.h",
    "content": "/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#ifndef _GM_H\n#define _GM_H\n\n#include \"skels/header.h\"\n#include \"skels/c_source.h\"\n\n#include <list>\n#include <string>\n\n#define TAB_LEN 2\n\nstruct gengetopt_option;\n\ntypedef std::list<std::string> OptionHelpList;\n\nclass CmdlineParserCreator : public header_gen_class, public c_source_gen_class\n{\n protected:\n  char *parser_function_name;\n  char *filename;\n  char *args_info_name;\n  char *header_filename;\n  char *c_filename;\n  string output_dir;\n  string header_output_dir;\n  string src_output_dir;\n  string comment;\n  char *unamed_options;\n  string show_required_string;\n\n  bool long_help;\n  bool no_handle_help;\n  bool no_help;\n  bool no_handle_version;\n  bool no_version;\n  bool no_handle_error;\n  bool conf_parser;\n  bool string_parser;\n  bool gen_gengetopt_version;\n  bool gen_strdup;\n\n  unsigned int tab_indentation ; /* tab indentation level */\n\n  void inc_indent()\n    {\n      tab_indentation += TAB_LEN ;\n    }\n\n  void dec_indent()\n    {\n      tab_indentation -= TAB_LEN ;\n    }\n\n  void indent()\n    {\n      unsigned int i ;\n\n      for ( i = 1 ; i <= tab_indentation ; ++i )\n        printf (\" \");\n    }\n\n  void free_option(struct gengetopt_option *opt,\n                   ostream &stream, unsigned int indent);\n\n  int generate_header_file();\n  int generate_source();\n\n  string generate_getopt_string();\n\n  // to be implemented in header_gen_class\n  virtual void generate_enum_types(ostream &stream, unsigned int indent);\n  virtual void generate_option_arg(ostream &stream, unsigned int indent);\n  virtual void generate_option_given(ostream &stream, unsigned int indent);\n  virtual void generate_option_values_decl(ostream &stream, unsigned int indent);\n\n  // to be implemented in c_source_gen_class\n  virtual void generate_clear_arg(ostream &stream, unsigned int indent);\n  virtual void generate_given_init(ostream &stream, unsigned int indent);\n  virtual void generate_option_values(ostream &stream, unsigned int indent);\n\n  virtual void generate_handle_no_short_option(ostream &stream,\n                                               unsigned int indent);\n  virtual void generate_handle_option(ostream &stream, unsigned int indent);\n  virtual void generate_handle_required(ostream &stream, unsigned int indent);\n  virtual void generate_handle_dependencies(ostream &stream, unsigned int indent);\n  virtual void generate_handle_group(ostream &stream, unsigned int indent);\n  virtual void generate_group_counters(ostream &stream, unsigned int indent);\n  virtual void generate_mode_counters(ostream &stream, unsigned int indent);\n  virtual void generate_help_option_print(ostream &stream,\n                                          unsigned int indent);\n  virtual void generate_full_help_option_print(ostream &stream,\n                                          unsigned int indent);\n  virtual void generate_detailed_help_option_print(ostream &stream,\n                                          unsigned int indent);\n  virtual void generate_long_option_struct(ostream &stream,\n                                           unsigned int indent);\n  virtual void generate_reset_groups(ostream &stream, unsigned int indent);\n\n  virtual void generate_free(ostream &stream, unsigned int indent);\n  virtual void generate_list_free(ostream &stream, unsigned int indent);\n\n  virtual void generate_file_save_loop(ostream &stream, unsigned int indent);\n  virtual void generate_init_args_info(ostream &stream, unsigned int indent);\n\n  virtual void generate_custom_getopt(ostream &stream, unsigned int indent);\n\n  void generateBreak(ostream &stream, unsigned int indent = 0);\n\n  void handle_options(ostream &, unsigned int, bool has_short);\n\n public:\n\n  CmdlineParserCreator (char *function_name, char *struct_name,\n                        char *unamed_options,\n                        char *filename, char *header_ext, char *c_ext,\n                        bool long_help,\n                        bool no_handle_help, bool no_help,\n                        bool no_handle_version, bool no_version,\n                        bool no_handle_error, bool conf_parser, bool string_parser,\n                        bool gen_version, bool gen_getopt, bool no_options,\n                        const string &comment,\n                        const string &outdir,\n                        const string &header_outdir,\n                        const string &src_outdir,\n                        const string &show_required);\n\n  int generate();\n\n  virtual void generate_list_def(ostream &stream, unsigned int indent);\n  virtual void generate_multiple_fill_array(ostream &stream, unsigned int indent);\n  virtual void generate_update_multiple_given(ostream &stream, unsigned int indent);\n  virtual void generate_check_modes(ostream &stream, unsigned int indent);\n\n  const string generate_purpose();\n  const string generate_description();\n  const string generate_usage_string(bool use_config_package = true);\n\n  /**\n   * generate a list of option descriptions that will be printed in the\n   * help output\n   *\n   * @param generate_hidden if true, include also the hidden options\n   * @param generate_details if true, include also the hidden options and\n   * details for options that have them.\n   */\n  OptionHelpList *generate_help_option_list(bool generate_hidden = false,\n          bool generate_details = false);\n\n  /**\n   * generate the sharing between a list of help string, using the\n   * complete_list as the list with all the strings (both for hidden\n   * options and details, e.g.) and the smaller_list as the list\n   * with less strings\n   *\n   * @param target_array the name of the array to copy to\n   * @param source_array the name of the array to copy from\n   */\n  void generate_help_option_print_from_lists(ostream &stream,\n          unsigned int indent, OptionHelpList *complete_list,\n          OptionHelpList *smaller_list, const std::string &target_array,\n          const std::string &source_array);\n\n  /**\n   * Sets the has_arg_XXX by inspecting all the options types\n   */\n  void set_has_arg_types();\n};\n\n#endif /* _GM_H */\n"
  },
  {
    "path": "utilities/gengetopt/gm_utils.cpp",
    "content": "//\n// C++ Implementation: gm_utils\n//\n// Description:\n//\n//\n// Author: Lorenzo Bettini <https://www.lorenzobettini.it>, (C) 2004\n//\n// Copyright: See COPYING file that comes with this distribution\n//\n//\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include \"gm_utils.h\"\n#include \"my_sstream.h\"\n#include \"ggo_options.h\"\n#include \"argsdef.h\"\n#include \"groups.h\"\n\nextern groups_collection_t gengetopt_groups;\n\nchar *\ncanonize_names(const char *name) {\n    char *pvar;\n    char *p;\n\n    pvar = strdup(name);\n\n    for (p = pvar; *p; ++p)\n        if (*p == '.' || *p == '-')\n            *p = '_';\n\n    return pvar;\n}\n\n// remove the path from the file name\nconst string strip_path(const string &s) {\n    string::size_type pos_of_sep;\n\n    pos_of_sep = s.rfind(\"/\");\n    if (pos_of_sep == string::npos)\n        pos_of_sep = s.rfind(\"\\\\\"); // try also with DOS path sep\n\n    if (pos_of_sep == string::npos)\n        return s; // no path\n\n    return s.substr(pos_of_sep + 1);\n}\n\nconst string to_upper(const string &old) {\n    string upper = old;\n\n    for (string::iterator s = upper.begin(); s != upper.end(); ++s)\n        *s = toupper(*s);\n\n    return upper;\n}\n\nconst string canonize_name(const string &old) {\n    string canonized = old;\n\n    for (string::iterator s = canonized.begin(); s != canonized.end(); ++s)\n        if (*s == '.' || *s == '-' || *s == ' ')\n            *s = '_';\n\n    return canonized;\n}\n\nconst string canonize_enum(const string &old) {\n    string canonized;\n\n    for (string::const_iterator s = old.begin(); s != old.end(); ++s)\n        if (*s == '-')\n            canonized += \"MINUS_\";\n        else if (*s == '+')\n            canonized += \"PLUS_\";\n        else\n            canonized += *s;\n\n    return canonized;\n}\n\nbool has_multiple_options_all_string() {\n    if (!has_multiple_options())\n        return false;\n\n    struct gengetopt_option * opt = 0;\n\n    foropt {\n        if (opt->multiple && (opt->type && opt->type != ARG_STRING))\n            return false;\n    }\n\n    return true;\n}\n\nbool has_multiple_options_string() {\n    if (!has_multiple_options())\n        return false;\n\n    struct gengetopt_option * opt = 0;\n\n    foropt {\n        if (opt->multiple && opt->type == ARG_STRING)\n            return true;\n    }\n\n    return false;\n}\n\nbool has_multiple_options() {\n    struct gengetopt_option * opt = 0;\n\n    foropt {\n        if (opt->multiple)\n            return true;\n    }\n\n    return false;\n}\n\nbool has_multiple_options_with_type() {\n    gengetopt_option * opt = 0;\n\n    for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it\n            != gengetopt_options.end() && (opt = *it); ++it)\n        if (opt->multiple && opt->type)\n            return true;\n\n    return false;\n}\n\nbool has_multiple_options_with_default() {\n    gengetopt_option * opt = 0;\n\n    for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it\n            != gengetopt_options.end() && (opt = *it); ++it)\n        if (opt->multiple && opt->default_given)\n            return true;\n\n    return false;\n}\n\nbool has_options_with_details() {\n    gengetopt_option * opt = 0;\n\n    for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it\n            != gengetopt_options.end() && (opt = *it); ++it)\n        if (opt->details)\n            return true;\n\n    return false;\n}\n\nbool has_options_with_type() {\n    gengetopt_option * opt = 0;\n\n    for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it\n            != gengetopt_options.end() && (opt = *it); ++it)\n        if (opt->type && opt->type != ARG_FLAG)\n            return true;\n\n    return false;\n}\n\nbool has_options_with_mode() {\n    gengetopt_option * opt = 0;\n\n    for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it\n            != gengetopt_options.end() && (opt = *it); ++it)\n        if (opt->mode_value)\n            return true;\n\n    return false;\n}\n\nbool has_required() {\n    struct gengetopt_option * opt = 0;\n\n    foropt {\n        if (opt->required)\n            return true;\n    }\n\n    groups_collection_t::const_iterator end = gengetopt_groups.end();\n    for (groups_collection_t::const_iterator idx = gengetopt_groups.begin(); idx\n            != end; ++idx) {\n        if (idx->second.required) {\n            return true;\n        }\n    }\n\n    return false;\n}\n\nbool has_dependencies() {\n    struct gengetopt_option * opt = 0;\n\n    foropt {\n        if (opt->dependon)\n            return true;\n    }\n\n    return false;\n}\n\nbool has_options() {\n    struct gengetopt_option * opt = 0;\n\n    foropt {\n        if (opt->short_opt) {\n            if (opt->short_opt != 'h' && opt->short_opt != 'V')\n                return true;\n        }\n    }\n\n    return false;\n}\n\nbool has_hidden_options() {\n    struct gengetopt_option * opt = 0;\n\n    foropt {\n        if (opt->hidden) {\n            return true;\n        }\n    }\n\n    return false;\n}\n\nbool has_values() {\n    struct gengetopt_option * opt = 0;\n\n    for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it\n            != gengetopt_options.end(); ++it) {\n        opt = *it;\n        if (opt->acceptedvalues) {\n            return true;\n        }\n    }\n\n    return false;\n}\n\nint not_newlines(const string &buf, int &num_of_newlines) {\n    num_of_newlines = 0;\n    // searches for the first non newline char\n    string::size_type notnewline = buf.find_first_not_of(\"\\r\\n\");\n\n    if (notnewline == string::npos) {\n        // a string made only of newlines\n        num_of_newlines = buf.size();\n        return num_of_newlines;\n    }\n\n    if (notnewline) {\n        // everything before the non newline char is a newline\n        num_of_newlines = notnewline;\n        return notnewline;\n    }\n\n    return 0;\n}\n\nvoid wrap_cstr(string& wrapped, unsigned int from_column,\n        unsigned int second_indent, const string &orig) {\n    int next_space = from_column;\n    string next_word;\n    const char * out_buf = orig.c_str();\n    ostringstream stream;\n    const unsigned int second_line_column = from_column + second_indent;\n    string indent(second_line_column, ' ');\n    int newline_chars = 0;\n    int num_of_newlines = 0;\n\n    while (*out_buf) {\n        // check for a new line\n        if (*out_buf) {\n            if ((newline_chars = not_newlines(out_buf, num_of_newlines))) {\n                for (int i = 1; i <= num_of_newlines; ++i)\n                    stream << \"\\\\n\";\n\n                out_buf += newline_chars;\n\n                if (*out_buf) {\n                    stream << indent;\n                    next_space = second_line_column;\n                    continue;\n                } else\n                    break;\n            } else {\n                stream << *out_buf++;\n                next_space++;\n            }\n        }\n        // search next whitespace, i.e., next word\n        while ((*out_buf) && (*out_buf != ' ') &&\n                !not_newlines(out_buf, num_of_newlines)) {\n            next_word += *out_buf++;\n            next_space++;\n        }\n\n        // wrap line if it's too long\n        if (next_space > 79) {\n            stream << \"\\\\n\" << indent << next_word;\n            next_space = second_line_column + next_word.size();\n        } else\n            stream << next_word; // simply write word\n\n        next_word = \"\";\n    }\n\n    wrapped += stream.str();\n}\n\nbool is_numeric(const gengetopt_option *opt) {\n    switch (opt->type) {\n    case ARG_INT:\n    case ARG_SHORT:\n    case ARG_LONG:\n    case ARG_FLOAT:\n    case ARG_DOUBLE:\n    case ARG_LONGDOUBLE:\n    case ARG_LONGLONG:\n        return true;\n    default:\n        return false;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/gm_utils.h",
    "content": "//\n// C++ Interface: gm_utils\n//\n// Description:\n//\n//\n// Author: Lorenzo Bettini <https://www.lorenzobettini.it>, (C) 2004\n//\n// Copyright: See COPYING file that comes with this distribution\n//\n//\n\n#ifndef GM_UTILS_H\n#define GM_UTILS_H\n\n#include <string>\n#include <iostream>\n\n#include \"ggos.h\"\n\ntemplate< typename ArgumentType, typename ResultType >\nstruct unary_function\n{\n  using argument_type = ArgumentType;\n  using result_type = ResultType;\n};\n\nusing std::string;\n\n/**\n * @param name\n * @return a copy of the string passed after canonizing it (i.e. '-' and\n * '.' are transformed in '_').\n */\nchar *canonize_names(const char * name);\n\n/**\n * @param name\n * @return a copy of the string passed after canonizing it (i.e. '-' and\n * '.' are transformed in '_').\n */\nconst string canonize_name(const string &name);\n\n/**\n * @param s the string representing an enum value\n * @return a copy of the string passed after canonizing it (i.e. '-' and\n * becomes _MINUS_, '+' becomes _PLUS_)\n */\nconst string canonize_enum(const string &s);\n\nconst string strip_path(const string &);\nconst string to_upper(const string &);\n\n/**\n * All multiple options are of type string\n * @return All multiple options are of type string\n */\nbool has_multiple_options_all_string();\n\n/**\n * Has multiple options and at least one is of type string\n * @return Has multiple options and at least one is of type string\n */\nbool has_multiple_options_string();\n\n/**\n * Has multiple options and at least one has a default value\n * @return Has multiple options and at least one has a default value\n */\nbool has_multiple_options_with_default();\n\nbool has_multiple_options();\nbool has_multiple_options_with_type();\nbool has_required();\nbool has_dependencies();\nbool has_options_with_type();\nbool has_options_with_mode();\nbool has_options();\nbool has_hidden_options();\nbool has_options_with_details();\nbool has_values();\n\n/**\n * Whether the specified option deals with number\n *\n * @param opt\n * @return\n */\nbool is_numeric(const gengetopt_option *opt);\n\n/**\n * Performs word wrapping on the passed string (and return the result in the first\n * parameter).\n *\n * @param wrapped the output parameter\n * @param from_column the string start from this column\n * @param second_indent an additional indentation for lines after the\n * first one\n * @param orig the original string that must be wrapped\n */\nvoid wrap_cstr (string &wrapped, unsigned int from_column, unsigned int second_indent, const string &orig);\n\n/**\n * Searches for characters which are not newlines.\n *\n * @param buf where to search for new characters\n * @param num_of_newlines where the number of newlines\n * before the first non newline char will be stored\n * @return the position in the string after the (possible) new line char\n */\nint not_newlines(const string &buf, int &num_of_newlines);\n\n/**\n * Function object to print something into a stream (to be used with for_each)\n */\ntemplate<class T>\nstruct print_f : public unary_function<T, void >\n{\n    print_f(std::ostream& out, const string &s = \", \") : os(out), sep(s) {}\n    void operator() (T x) { os << x << sep; }\n    std::ostream& os;\n    const string &sep;\n};\n\n/**\n * Function object to print a pair into two streams (to be used with for_each)\n */\ntemplate<class T>\nstruct pair_print_f : public unary_function<T, void >\n{\n    pair_print_f(std::ostream& out1, std::ostream& out2, const string &s = \", \") :\n        os1(out1), os2(out2), sep(s) {}\n    void operator() (T x) { os1 << x.first << sep; os2 << x.second << sep;}\n    std::ostream &os1, &os2;\n    const string &sep;\n};\n\n#endif\n"
  },
  {
    "path": "utilities/gengetopt/groups.h",
    "content": "/**\n * Copyright (C) 1999, 2000, 2001, 2002, 2003  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n#ifndef GGO_GROUPS_H\n#define GGO_GROUPS_H\n\n#include \"my_string.h\"\n#include \"my_map.h\"\n\n/**\n * Represents a group of options\n */\nstruct Group\n{\n  string desc;\n  bool required;\n\n  Group(const string &s, bool r) : desc (s), required (r) {}\n};\n\ntypedef map<string,Group> groups_collection_t;\n\n/**\n * Represents a mode of options\n */\nstruct Mode\n{\n  string desc;\n\n  Mode(const string &s) : desc (s) {}\n};\n\ntypedef map<string,Mode> modes_collection_t;\n\n#endif // GROUPS_H\n"
  },
  {
    "path": "utilities/gengetopt/my_map.h",
    "content": "// handle namespaces\n\n#ifndef _MY_MAP_H\n#define _MY_MAP_H\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <map>\n\n#ifdef HAVE_NAMESPACES\nusing std::map;\nusing std::make_pair;\n#endif\n\n#endif // _MY_MAP_H\n"
  },
  {
    "path": "utilities/gengetopt/my_sstream.h",
    "content": "// deal with namespace problems\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif // HAVE_CONFIG_H\n\n#ifdef HAVE_SSTREAM\n#include <sstream>\n#else\n#include \"includes/sstream\"\n#endif\n\n#ifdef HAVE_NAMESPACES\nusing std::ostringstream;\n#endif\n"
  },
  {
    "path": "utilities/gengetopt/my_string.h",
    "content": "// deal with namespace problems\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif // HAVE_CONFIG_H\n\n#include <string>\n\n#ifdef HAVE_NAMESPACES\nusing std::string;\n#endif\n"
  },
  {
    "path": "utilities/gengetopt/parser.cc",
    "content": "\n/* A Bison parser, made by GNU Bison 2.4.1.  */\n\n/* Skeleton implementation for Bison's Yacc-like parsers in C\n\n      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006\n   Free Software Foundation, Inc.\n\n   This program is free software: you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation, either version 3 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n\n   You should have received a copy of the GNU General Public License\n   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* As a special exception, you may create a larger work that contains\n   part or all of the Bison parser skeleton and distribute that work\n   under terms of your choice, so long as that work isn't itself a\n   parser generator using the skeleton or a modified version thereof\n   as a parser skeleton.  Alternatively, if you modify or redistribute\n   the parser skeleton itself, you may (at your option) remove this\n   special exception, which will cause the skeleton and the resulting\n   Bison output files to be licensed under the GNU General Public\n   License without this special exception.\n\n   This special exception was added by the Free Software Foundation in\n   version 2.2 of Bison.  */\n\n/* C LALR(1) parser skeleton written by Richard Stallman, by\n   simplifying the original so-called \"semantic\" parser.  */\n\n/* All symbols defined below should begin with yy or YY, to avoid\n   infringing on user name space.  This should be done even for local\n   variables, as they might otherwise be expanded by user macros.\n   There are some unavoidable exceptions within include files to\n   define necessary library symbols; they are noted \"INFRINGES ON\n   USER NAME SPACE\" below.  */\n\n/* Identify Bison output.  */\n#define YYBISON 1\n\n/* Bison version.  */\n#define YYBISON_VERSION \"2.4.1\"\n\n/* Skeleton name.  */\n#define YYSKELETON_NAME \"yacc.c\"\n\n/* Pure parsers.  */\n#define YYPURE 0\n\n/* Push parsers.  */\n#define YYPUSH 0\n\n/* Pull parsers.  */\n#define YYPULL 1\n\n/* Using locations.  */\n#define YYLSP_NEEDED 1\n\n\n\n/* Copy the first part of user declarations.  */\n\n/* Line 189 of yacc.c  */\n#line 22 \"../../src/parser.yy\"\n\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <string>\n\n#include \"my_sstream.h\"\n\n#include \"acceptedvalues.h\"\n\n#include \"argsdef.h\"\n\n#include \"gengetopt.h\"\n#include \"errorcodes.h\"\n#include \"ggos.h\"\n#include \"yyerror.h\"\n\nextern int gengetopt_count_line;\nextern char * gengetopt_input_filename;\n\nstatic int gengetopt_package_given = 0;\nstatic int gengetopt_version_given = 0;\nstatic int gengetopt_purpose_given = 0;\nstatic int gengetopt_usage_given = 0;\nstatic int gengetopt_description_given = 0;\n\n/// the last option parsed\nstatic gengetopt_option *current_option = 0;\n\nextern int yylex (void) ;\n\n//#define YYERROR_VERBOSE 1\n\nvoid check_result(int o, gengetopt_option *opt)\n{\n  if (o)\n    {\n        ostringstream err;\n\n    switch (o)\n    {\n    case NOT_ENOUGH_MEMORY:\n        yyerror (opt, \"not enough memory\");\n    \tbreak;\n    case REQ_LONG_OPTION:\n        err << \"long option redefined \\'\" << opt->long_opt << \"\\'\";\n        yyerror (opt, err.str().c_str());\n\t\tbreak;\n    case REQ_SHORT_OPTION:\n        err << \"short option redefined \\'\" << opt->short_opt << \"\\'\";\n        yyerror (opt, err.str().c_str());\n        break;\n    case FOUND_BUG:\n        yyerror (opt, \"bug found!!\");\n        break;\n    case GROUP_UNDEFINED:\n        yyerror (opt, \"group undefined\");\n        break;\n    case MODE_UNDEFINED:\n        yyerror (opt, \"mode undefined\");\n        break;\n    case INVALID_DEFAULT_VALUE:\n        yyerror (opt, \"invalid default value\");\n        break;\n    case NOT_REQUESTED_TYPE:\n        yyerror (opt, \"type specification not requested\");\n        break;\n    case NOT_VALID_SPECIFICATION:\n      yyerror (opt, \"invalid specification for this kind of option\");\n      break;\n    case SPECIFY_FLAG_STAT:\n      yyerror (opt, \"you must specify the default flag status\");\n      break;\n    case NOT_GROUP_OPTION:\n      yyerror (opt, \"group specification for a non group option\");\n      break;\n    case NOT_MODE_OPTION:\n      yyerror (opt, \"mode specification for an option not belonging to a mode\");\n      break;\n    case SPECIFY_GROUP:\n      yyerror (opt, \"missing group specification\");\n      break;\n    case SPECIFY_MODE:\n      yyerror (opt, \"missing mode specification\");\n      break;\n    case INVALID_NUMERIC_VALUE:\n        yyerror (opt, \"invalid numeric value\");\n        break;\n    case INVALID_ENUM_TYPE_USE:\n    \tyyerror (opt, \"enum type can only be specified for options with values\");\n        break;\n    case HELP_REDEFINED:\n    \tyyerror (opt, \"if you want to redefine --help, please use option --no-help\");\n        break;\n    case VERSION_REDEFINED:\n    \tyyerror (opt, \"if you want to redefine --version, please use option --no-version\");\n        break;\n    }\n  }\n}\n\n/* the number of allowed occurrences of a multiple option */\nstruct multiple_size\n{\n    /* these strings are allocated dynamically and NOT\n      automatically freed upon destruction */\n    char *min;\n    char *max;\n\n    /* if no limit is specified then initialized to 0.\n       if the same size is specified for min and max, it means that an exact\n       number of occurrences is required*/\n    multiple_size(const char *m = \"0\", const char *M = \"0\") :\n        min(strdup(m)), max(strdup(M))\n    {}\n};\n\n#define check_error if (o) YYERROR;\n\n\n\n/* Line 189 of yacc.c  */\n#line 200 \"../../src/parser.cc\"\n\n/* Enabling traces.  */\n#ifndef YYDEBUG\n# define YYDEBUG 0\n#endif\n\n/* Enabling verbose error messages.  */\n#ifdef YYERROR_VERBOSE\n# undef YYERROR_VERBOSE\n# define YYERROR_VERBOSE 1\n#else\n# define YYERROR_VERBOSE 0\n#endif\n\n/* Enabling the token table.  */\n#ifndef YYTOKEN_TABLE\n# define YYTOKEN_TABLE 0\n#endif\n\n\n/* Tokens.  */\n#ifndef YYTOKENTYPE\n# define YYTOKENTYPE\n   /* Put the tokens into the symbol table, so that GDB and other debuggers\n      know about them.  */\n   enum yytokentype {\n     TOK_PACKAGE = 258,\n     TOK_VERSION = 259,\n     TOK_OPTION = 260,\n     TOK_DEFGROUP = 261,\n     TOK_GROUPOPTION = 262,\n     TOK_DEFMODE = 263,\n     TOK_MODEOPTION = 264,\n     TOK_YES = 265,\n     TOK_NO = 266,\n     TOK_ON = 267,\n     TOK_OFF = 268,\n     TOK_FLAG = 269,\n     TOK_PURPOSE = 270,\n     TOK_DESCRIPTION = 271,\n     TOK_USAGE = 272,\n     TOK_DEFAULT = 273,\n     TOK_GROUP = 274,\n     TOK_GROUPDESC = 275,\n     TOK_MODE = 276,\n     TOK_MODEDESC = 277,\n     TOK_MULTIPLE = 278,\n     TOK_ARGOPTIONAL = 279,\n     TOK_TYPESTR = 280,\n     TOK_SECTION = 281,\n     TOK_DETAILS = 282,\n     TOK_SECTIONDESC = 283,\n     TOK_TEXT = 284,\n     TOK_ARGS = 285,\n     TOK_VALUES = 286,\n     TOK_HIDDEN = 287,\n     TOK_DEPENDON = 288,\n     TOK_STRING = 289,\n     TOK_CHAR = 290,\n     TOK_ARGTYPE = 291,\n     TOK_SIZE = 292\n   };\n#endif\n/* Tokens.  */\n#define TOK_PACKAGE 258\n#define TOK_VERSION 259\n#define TOK_OPTION 260\n#define TOK_DEFGROUP 261\n#define TOK_GROUPOPTION 262\n#define TOK_DEFMODE 263\n#define TOK_MODEOPTION 264\n#define TOK_YES 265\n#define TOK_NO 266\n#define TOK_ON 267\n#define TOK_OFF 268\n#define TOK_FLAG 269\n#define TOK_PURPOSE 270\n#define TOK_DESCRIPTION 271\n#define TOK_USAGE 272\n#define TOK_DEFAULT 273\n#define TOK_GROUP 274\n#define TOK_GROUPDESC 275\n#define TOK_MODE 276\n#define TOK_MODEDESC 277\n#define TOK_MULTIPLE 278\n#define TOK_ARGOPTIONAL 279\n#define TOK_TYPESTR 280\n#define TOK_SECTION 281\n#define TOK_DETAILS 282\n#define TOK_SECTIONDESC 283\n#define TOK_TEXT 284\n#define TOK_ARGS 285\n#define TOK_VALUES 286\n#define TOK_HIDDEN 287\n#define TOK_DEPENDON 288\n#define TOK_STRING 289\n#define TOK_CHAR 290\n#define TOK_ARGTYPE 291\n#define TOK_SIZE 292\n\n\n\n\n#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED\ntypedef union YYSTYPE\n{\n\n/* Line 214 of yacc.c  */\n#line 148 \"../../src/parser.yy\"\n\n    char   *str;\n    char    chr;\n    int\t    argtype;\n    int\t    boolean;\n    class AcceptedValues *ValueList;\n    struct gengetopt_option *gengetopt_option;\n    struct multiple_size *multiple_size;\n\n\n\n/* Line 214 of yacc.c  */\n#line 322 \"../../src/parser.cc\"\n} YYSTYPE;\n# define YYSTYPE_IS_TRIVIAL 1\n# define yystype YYSTYPE /* obsolescent; will be withdrawn */\n# define YYSTYPE_IS_DECLARED 1\n#endif\n\n#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED\ntypedef struct YYLTYPE\n{\n  int first_line;\n  int first_column;\n  int last_line;\n  int last_column;\n} YYLTYPE;\n# define yyltype YYLTYPE /* obsolescent; will be withdrawn */\n# define YYLTYPE_IS_DECLARED 1\n# define YYLTYPE_IS_TRIVIAL 1\n#endif\n\n\n/* Copy the second part of user declarations.  */\n\n\n/* Line 264 of yacc.c  */\n#line 347 \"../../src/parser.cc\"\n\n#ifdef short\n# undef short\n#endif\n\n#ifdef YYTYPE_UINT8\ntypedef YYTYPE_UINT8 yytype_uint8;\n#else\ntypedef unsigned char yytype_uint8;\n#endif\n\n#ifdef YYTYPE_INT8\ntypedef YYTYPE_INT8 yytype_int8;\n#elif (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\ntypedef signed char yytype_int8;\n#else\ntypedef short int yytype_int8;\n#endif\n\n#ifdef YYTYPE_UINT16\ntypedef YYTYPE_UINT16 yytype_uint16;\n#else\ntypedef unsigned short int yytype_uint16;\n#endif\n\n#ifdef YYTYPE_INT16\ntypedef YYTYPE_INT16 yytype_int16;\n#else\ntypedef short int yytype_int16;\n#endif\n\n#ifndef YYSIZE_T\n# ifdef __SIZE_TYPE__\n#  define YYSIZE_T __SIZE_TYPE__\n# elif defined size_t\n#  define YYSIZE_T size_t\n# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\n#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */\n#  define YYSIZE_T size_t\n# else\n#  define YYSIZE_T unsigned int\n# endif\n#endif\n\n#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)\n\n#ifndef YY_\n# if YYENABLE_NLS\n#  if ENABLE_NLS\n#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */\n#   define YY_(msgid) dgettext (\"bison-runtime\", msgid)\n#  endif\n# endif\n# ifndef YY_\n#  define YY_(msgid) msgid\n# endif\n#endif\n\n/* Suppress unused-variable warnings by \"using\" E.  */\n#if ! defined lint || defined __GNUC__\n# define YYUSE(e) ((void) (e))\n#else\n# define YYUSE(e) /* empty */\n#endif\n\n/* Identity function, used to suppress warnings about constant conditions.  */\n#ifndef lint\n# define YYID(n) (n)\n#else\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic int\nYYID (int yyi)\n#else\nstatic int\nYYID (yyi)\n    int yyi;\n#endif\n{\n  return yyi;\n}\n#endif\n\n#if ! defined yyoverflow || YYERROR_VERBOSE\n\n/* The parser invokes alloca or malloc; define the necessary symbols.  */\n\n# ifdef YYSTACK_USE_ALLOCA\n#  if YYSTACK_USE_ALLOCA\n#   ifdef __GNUC__\n#    define YYSTACK_ALLOC __builtin_alloca\n#   elif defined __BUILTIN_VA_ARG_INCR\n#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */\n#   elif defined _AIX\n#    define YYSTACK_ALLOC __alloca\n#   elif defined _MSC_VER\n#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */\n#    define alloca _alloca\n#   else\n#    define YYSTACK_ALLOC alloca\n#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\n#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */\n#     ifndef _STDLIB_H\n#      define _STDLIB_H 1\n#     endif\n#    endif\n#   endif\n#  endif\n# endif\n\n# ifdef YYSTACK_ALLOC\n   /* Pacify GCC's `empty if-body' warning.  */\n#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))\n#  ifndef YYSTACK_ALLOC_MAXIMUM\n    /* The OS might guarantee only one guard page at the bottom of the stack,\n       and a page size can be as small as 4096 bytes.  So we cannot safely\n       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number\n       to allow for a few compiler-allocated temporary stack slots.  */\n#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */\n#  endif\n# else\n#  define YYSTACK_ALLOC YYMALLOC\n#  define YYSTACK_FREE YYFREE\n#  ifndef YYSTACK_ALLOC_MAXIMUM\n#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM\n#  endif\n#  if (defined __cplusplus && ! defined _STDLIB_H \\\n       && ! ((defined YYMALLOC || defined malloc) \\\n\t     && (defined YYFREE || defined free)))\n#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */\n#   ifndef _STDLIB_H\n#    define _STDLIB_H 1\n#   endif\n#  endif\n#  ifndef YYMALLOC\n#   define YYMALLOC malloc\n#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nvoid *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */\n#   endif\n#  endif\n#  ifndef YYFREE\n#   define YYFREE free\n#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nvoid free (void *); /* INFRINGES ON USER NAME SPACE */\n#   endif\n#  endif\n# endif\n#endif /* ! defined yyoverflow || YYERROR_VERBOSE */\n\n\n#if (! defined yyoverflow \\\n     && (! defined __cplusplus \\\n\t || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \\\n\t     && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))\n\n/* A type that is properly aligned for any stack member.  */\nunion yyalloc\n{\n  yytype_int16 yyss_alloc;\n  YYSTYPE yyvs_alloc;\n  YYLTYPE yyls_alloc;\n};\n\n/* The size of the maximum gap between one aligned stack and the next.  */\n# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)\n\n/* The size of an array large to enough to hold all stacks, each with\n   N elements.  */\n# define YYSTACK_BYTES(N) \\\n     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \\\n      + 2 * YYSTACK_GAP_MAXIMUM)\n\n/* Copy COUNT objects from FROM to TO.  The source and destination do\n   not overlap.  */\n# ifndef YYCOPY\n#  if defined __GNUC__ && 1 < __GNUC__\n#   define YYCOPY(To, From, Count) \\\n      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))\n#  else\n#   define YYCOPY(To, From, Count)\t\t\\\n      do\t\t\t\t\t\\\n\t{\t\t\t\t\t\\\n\t  YYSIZE_T yyi;\t\t\t\t\\\n\t  for (yyi = 0; yyi < (Count); yyi++)\t\\\n\t    (To)[yyi] = (From)[yyi];\t\t\\\n\t}\t\t\t\t\t\\\n      while (YYID (0))\n#  endif\n# endif\n\n/* Relocate STACK from its old location to the new one.  The\n   local variables YYSIZE and YYSTACKSIZE give the old and new number of\n   elements in the stack, and YYPTR gives the new location of the\n   stack.  Advance YYPTR to a properly aligned location for the next\n   stack.  */\n# define YYSTACK_RELOCATE(Stack_alloc, Stack)\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n      {\t\t\t\t\t\t\t\t\t\\\n\tYYSIZE_T yynewbytes;\t\t\t\t\t\t\\\n\tYYCOPY (&yyptr->Stack_alloc, Stack, yysize);\t\t\t\\\n\tStack = &yyptr->Stack_alloc;\t\t\t\t\t\\\n\tyynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \\\n\tyyptr += yynewbytes / sizeof (*yyptr);\t\t\t\t\\\n      }\t\t\t\t\t\t\t\t\t\\\n    while (YYID (0))\n\n#endif\n\n/* YYFINAL -- State number of the termination state.  */\n#define YYFINAL  43\n/* YYLAST -- Last index in YYTABLE.  */\n#define YYLAST   92\n\n/* YYNTOKENS -- Number of terminals.  */\n#define YYNTOKENS  43\n/* YYNNTS -- Number of nonterminals.  */\n#define YYNNTS  27\n/* YYNRULES -- Number of rules.  */\n#define YYNRULES  66\n/* YYNRULES -- Number of states.  */\n#define YYNSTATES  116\n\n/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */\n#define YYUNDEFTOK  2\n#define YYMAXUTOK   292\n\n#define YYTRANSLATE(YYX)\t\t\t\t\t\t\\\n  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)\n\n/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */\nstatic const yytype_uint8 yytranslate[] =\n{\n       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n      40,    41,     2,     2,    39,    42,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,    38,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,\n       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,\n      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,\n      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,\n      35,    36,    37\n};\n\n#if YYDEBUG\n/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in\n   YYRHS.  */\nstatic const yytype_uint8 yyprhs[] =\n{\n       0,     0,     3,     4,     7,     9,    11,    13,    15,    17,\n      19,    21,    23,    25,    27,    29,    31,    33,    36,    39,\n      42,    45,    48,    52,    55,    58,    63,    67,    73,    79,\n      85,    87,    90,    93,    98,   103,   108,   113,   118,   123,\n     128,   131,   135,   138,   141,   144,   145,   147,   149,   150,\n     152,   154,   156,   158,   159,   163,   164,   168,   169,   173,\n     175,   179,   181,   182,   186,   191,   196\n};\n\n/* YYRHS -- A `-1'-separated list of the rules' RHS.  */\nstatic const yytype_int8 yyrhs[] =\n{\n      44,     0,    -1,    -1,    45,    44,    -1,    46,    -1,    47,\n      -1,    53,    -1,    48,    -1,    49,    -1,    50,    -1,    51,\n      -1,    56,    -1,    52,    -1,    57,    -1,    54,    -1,    58,\n      -1,    55,    -1,     3,    34,    -1,     4,    34,    -1,    15,\n      59,    -1,    16,    59,    -1,    17,    59,    -1,    26,    59,\n      66,    -1,    29,    59,    -1,    30,    34,    -1,     6,    34,\n      64,    62,    -1,     8,    34,    65,    -1,     5,    34,    35,\n      59,    60,    -1,     7,    34,    35,    59,    60,    -1,     9,\n      34,    35,    59,    60,    -1,    34,    -1,    60,    63,    -1,\n      60,    36,    -1,    60,    25,    38,    34,    -1,    60,    27,\n      38,    59,    -1,    60,    31,    38,    67,    -1,    60,    18,\n      38,    34,    -1,    60,    19,    38,    34,    -1,    60,    21,\n      38,    34,    -1,    60,    33,    38,    34,    -1,    60,    24,\n      -1,    60,    23,    69,    -1,    60,    14,    -1,    60,    32,\n      -1,    60,    61,    -1,    -1,    12,    -1,    13,    -1,    -1,\n      10,    -1,    11,    -1,    10,    -1,    11,    -1,    -1,    20,\n      38,    34,    -1,    -1,    22,    38,    34,    -1,    -1,    28,\n      38,    34,    -1,    68,    -1,    67,    39,    68,    -1,    34,\n      -1,    -1,    40,    37,    41,    -1,    40,    37,    42,    41,\n      -1,    40,    42,    37,    41,    -1,    40,    37,    42,    37,\n      41,    -1\n};\n\n/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */\nstatic const yytype_uint16 yyrline[] =\n{\n       0,   209,   209,   211,   216,   217,   218,   219,   220,   221,\n     222,   223,   224,   225,   226,   227,   228,   233,   253,   273,\n     293,   313,   334,   341,   358,   365,   376,   387,   407,   426,\n     448,   451,   457,   462,   467,   472,   477,   482,   487,   492,\n     497,   502,   510,   515,   520,   525,   529,   530,   534,   535,\n     536,   540,   541,   545,   546,   550,   551,   555,   556,   560,\n     561,   565,   569,   570,   571,   572,   573\n};\n#endif\n\n#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE\n/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.\n   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */\nstatic const char *const yytname[] =\n{\n  \"$end\", \"error\", \"$undefined\", \"\\\"package\\\"\", \"\\\"version\\\"\",\n  \"\\\"option\\\"\", \"\\\"defgroup\\\"\", \"\\\"groupoption\\\"\", \"\\\"defmode\\\"\",\n  \"\\\"modeoption\\\"\", \"\\\"yes\\\"\", \"\\\"no\\\"\", \"\\\"on\\\"\", \"\\\"off\\\"\", \"\\\"flag\\\"\",\n  \"\\\"purpose\\\"\", \"\\\"description\\\"\", \"\\\"usage\\\"\", \"\\\"default\\\"\",\n  \"\\\"group\\\"\", \"\\\"groupdesc\\\"\", \"\\\"mode\\\"\", \"\\\"modedesc\\\"\", \"\\\"multiple\\\"\",\n  \"\\\"argoptional\\\"\", \"\\\"typestr\\\"\", \"\\\"section\\\"\", \"\\\"details\\\"\",\n  \"\\\"sectiondesc\\\"\", \"\\\"text\\\"\", \"\\\"args\\\"\", \"\\\"values\\\"\", \"\\\"hidden\\\"\",\n  \"\\\"dependon\\\"\", \"TOK_STRING\", \"TOK_CHAR\", \"TOK_ARGTYPE\", \"TOK_SIZE\",\n  \"'='\", \"','\", \"'('\", \"')'\", \"'-'\", \"$accept\", \"input\", \"statement\",\n  \"package\", \"version\", \"purpose\", \"description\", \"usage\", \"sectiondef\",\n  \"text\", \"args\", \"groupdef\", \"modedef\", \"option\", \"groupoption\",\n  \"modeoption\", \"quoted_string\", \"option_parts\", \"req_onoff\",\n  \"optional_yesno\", \"opt_yesno\", \"opt_groupdesc\", \"opt_modedesc\",\n  \"opt_sectiondesc\", \"listofvalues\", \"acceptedvalue\", \"multiple_size\", 0\n};\n#endif\n\n# ifdef YYPRINT\n/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to\n   token YYLEX-NUM.  */\nstatic const yytype_uint16 yytoknum[] =\n{\n       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,\n     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,\n     275,   276,   277,   278,   279,   280,   281,   282,   283,   284,\n     285,   286,   287,   288,   289,   290,   291,   292,    61,    44,\n      40,    41,    45\n};\n# endif\n\n/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */\nstatic const yytype_uint8 yyr1[] =\n{\n       0,    43,    44,    44,    45,    45,    45,    45,    45,    45,\n      45,    45,    45,    45,    45,    45,    45,    46,    47,    48,\n      49,    50,    51,    52,    53,    54,    55,    56,    57,    58,\n      59,    60,    60,    60,    60,    60,    60,    60,    60,    60,\n      60,    60,    60,    60,    60,    60,    61,    61,    62,    62,\n      62,    63,    63,    64,    64,    65,    65,    66,    66,    67,\n      67,    68,    69,    69,    69,    69,    69\n};\n\n/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */\nstatic const yytype_uint8 yyr2[] =\n{\n       0,     2,     0,     2,     1,     1,     1,     1,     1,     1,\n       1,     1,     1,     1,     1,     1,     1,     2,     2,     2,\n       2,     2,     3,     2,     2,     4,     3,     5,     5,     5,\n       1,     2,     2,     4,     4,     4,     4,     4,     4,     4,\n       2,     3,     2,     2,     2,     0,     1,     1,     0,     1,\n       1,     1,     1,     0,     3,     0,     3,     0,     3,     1,\n       3,     1,     0,     3,     4,     4,     5\n};\n\n/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state\n   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero\n   means the default is an error.  */\nstatic const yytype_uint8 yydefact[] =\n{\n       2,     0,     0,     0,     0,     0,     0,     0,     0,     0,\n       0,     0,     0,     0,     0,     2,     4,     5,     7,     8,\n       9,    10,    12,     6,    14,    16,    11,    13,    15,    17,\n      18,     0,    53,     0,    55,     0,    30,    19,    20,    21,\n      57,    23,    24,     1,     3,     0,     0,    48,     0,     0,\n      26,     0,     0,    22,    45,     0,    49,    50,    25,    45,\n       0,    45,     0,    27,    54,    28,    56,    29,    58,    51,\n      52,    46,    47,    42,     0,     0,     0,    62,    40,     0,\n       0,     0,    43,     0,    32,    44,    31,     0,     0,     0,\n       0,    41,     0,     0,     0,     0,    36,    37,    38,     0,\n       0,    33,    34,    61,    35,    59,    39,    63,     0,     0,\n       0,     0,    64,    65,    60,    66\n};\n\n/* YYDEFGOTO[NTERM-NUM].  */\nstatic const yytype_int8 yydefgoto[] =\n{\n      -1,    14,    15,    16,    17,    18,    19,    20,    21,    22,\n      23,    24,    25,    26,    27,    28,    37,    63,    85,    58,\n      86,    47,    50,    53,   104,   105,    91\n};\n\n/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing\n   STATE-NUM.  */\n#define YYPACT_NINF -40\nstatic const yytype_int8 yypact[] =\n{\n       1,   -13,    -8,    -6,    -5,    -2,    -1,     0,     3,     3,\n       3,     3,     3,     4,    25,     1,   -40,   -40,   -40,   -40,\n     -40,   -40,   -40,   -40,   -40,   -40,   -40,   -40,   -40,   -40,\n     -40,     5,    15,     6,    26,    14,   -40,   -40,   -40,   -40,\n      22,   -40,   -40,   -40,   -40,     3,    17,     2,     3,    21,\n     -40,     3,    23,   -40,   -40,    19,   -40,   -40,   -40,   -40,\n      28,   -40,    29,    33,   -40,    33,   -40,    33,   -40,   -40,\n     -40,   -40,   -40,   -40,    30,    32,    34,    27,   -40,    35,\n      36,    37,   -40,    38,   -40,   -40,   -40,    43,    44,    45,\n     -23,   -40,    46,     3,    47,    48,   -40,   -40,   -40,   -18,\n      49,   -40,   -40,   -40,    50,   -40,   -40,   -40,   -26,    42,\n      47,    51,   -40,   -40,   -40,   -40\n};\n\n/* YYPGOTO[NTERM-NUM].  */\nstatic const yytype_int8 yypgoto[] =\n{\n     -40,    56,   -40,   -40,   -40,   -40,   -40,   -40,   -40,   -40,\n     -40,   -40,   -40,   -40,   -40,   -40,    -9,   -39,   -40,   -40,\n     -40,   -40,   -40,   -40,   -40,   -25,   -40\n};\n\n/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If\n   positive, shift that token.  If negative, reduce the rule which\n   number is the opposite.  If zero, do what YYDEFACT says.\n   If YYTABLE_NINF, syntax error.  */\n#define YYTABLE_NINF -1\nstatic const yytype_uint8 yytable[] =\n{\n      38,    39,    40,    41,     1,     2,     3,     4,     5,     6,\n       7,   111,    56,    57,    99,   112,     8,     9,    10,   100,\n      65,    29,    67,   107,   108,    43,    30,    11,    31,    32,\n      12,    13,    33,    34,    35,    46,    54,    36,    42,    59,\n      45,    48,    61,    69,    70,    71,    72,    73,    49,    51,\n      52,    74,    75,    64,    76,    55,    77,    78,    79,    60,\n      80,    62,    66,    68,    81,    82,    83,    90,    87,    84,\n      88,    44,    89,    92,    93,    94,    95,    96,    97,    98,\n     101,   103,   106,   113,   102,   114,   109,     0,     0,   110,\n       0,     0,   115\n};\n\nstatic const yytype_int8 yycheck[] =\n{\n       9,    10,    11,    12,     3,     4,     5,     6,     7,     8,\n       9,    37,    10,    11,    37,    41,    15,    16,    17,    42,\n      59,    34,    61,    41,    42,     0,    34,    26,    34,    34,\n      29,    30,    34,    34,    34,    20,    45,    34,    34,    48,\n      35,    35,    51,    10,    11,    12,    13,    14,    22,    35,\n      28,    18,    19,    34,    21,    38,    23,    24,    25,    38,\n      27,    38,    34,    34,    31,    32,    33,    40,    38,    36,\n      38,    15,    38,    38,    38,    38,    38,    34,    34,    34,\n      34,    34,    34,    41,    93,   110,    37,    -1,    -1,    39,\n      -1,    -1,    41\n};\n\n/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing\n   symbol of state STATE-NUM.  */\nstatic const yytype_uint8 yystos[] =\n{\n       0,     3,     4,     5,     6,     7,     8,     9,    15,    16,\n      17,    26,    29,    30,    44,    45,    46,    47,    48,    49,\n      50,    51,    52,    53,    54,    55,    56,    57,    58,    34,\n      34,    34,    34,    34,    34,    34,    34,    59,    59,    59,\n      59,    59,    34,     0,    44,    35,    20,    64,    35,    22,\n      65,    35,    28,    66,    59,    38,    10,    11,    62,    59,\n      38,    59,    38,    60,    34,    60,    34,    60,    34,    10,\n      11,    12,    13,    14,    18,    19,    21,    23,    24,    25,\n      27,    31,    32,    33,    36,    61,    63,    38,    38,    38,\n      40,    69,    38,    38,    38,    38,    34,    34,    34,    37,\n      42,    34,    59,    34,    67,    68,    34,    41,    42,    37,\n      39,    37,    41,    41,    68,    41\n};\n\n#define yyerrok\t\t(yyerrstatus = 0)\n#define yyclearin\t(yychar = YYEMPTY)\n#define YYEMPTY\t\t(-2)\n#define YYEOF\t\t0\n\n#define YYACCEPT\tgoto yyacceptlab\n#define YYABORT\t\tgoto yyabortlab\n#define YYERROR\t\tgoto yyerrorlab\n\n\n/* Like YYERROR except do call yyerror.  This remains here temporarily\n   to ease the transition to the new meaning of YYERROR, for GCC.\n   Once GCC version 2 has supplanted version 1, this can go.  */\n\n#define YYFAIL\t\tgoto yyerrlab\n\n#define YYRECOVERING()  (!!yyerrstatus)\n\n#define YYBACKUP(Token, Value)\t\t\t\t\t\\\ndo\t\t\t\t\t\t\t\t\\\n  if (yychar == YYEMPTY && yylen == 1)\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      yychar = (Token);\t\t\t\t\t\t\\\n      yylval = (Value);\t\t\t\t\t\t\\\n      yytoken = YYTRANSLATE (yychar);\t\t\t\t\\\n      YYPOPSTACK (1);\t\t\t\t\t\t\\\n      goto yybackup;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\\\n  else\t\t\t\t\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      yyerror (YY_(\"syntax error: cannot back up\")); \\\n      YYERROR;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\\\nwhile (YYID (0))\n\n\n#define YYTERROR\t1\n#define YYERRCODE\t256\n\n\n/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].\n   If N is 0, then set CURRENT to the empty location which ends\n   the previous symbol: RHS[0] (always defined).  */\n\n#define YYRHSLOC(Rhs, K) ((Rhs)[K])\n#ifndef YYLLOC_DEFAULT\n# define YYLLOC_DEFAULT(Current, Rhs, N)\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n      if (YYID (N))                                                    \\\n\t{\t\t\t\t\t\t\t\t\\\n\t  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;\t\\\n\t  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;\t\\\n\t  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;\t\t\\\n\t  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;\t\\\n\t}\t\t\t\t\t\t\t\t\\\n      else\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\\\n\t  (Current).first_line   = (Current).last_line   =\t\t\\\n\t    YYRHSLOC (Rhs, 0).last_line;\t\t\t\t\\\n\t  (Current).first_column = (Current).last_column =\t\t\\\n\t    YYRHSLOC (Rhs, 0).last_column;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    while (YYID (0))\n#endif\n\n\n/* YY_LOCATION_PRINT -- Print the location on the stream.\n   This macro was not mandated originally: define only if we know\n   we won't break user code: when these are the locations we know.  */\n\n#ifndef YY_LOCATION_PRINT\n# if YYLTYPE_IS_TRIVIAL\n#  define YY_LOCATION_PRINT(File, Loc)\t\t\t\\\n     fprintf (File, \"%d.%d-%d.%d\",\t\t\t\\\n\t      (Loc).first_line, (Loc).first_column,\t\\\n\t      (Loc).last_line,  (Loc).last_column)\n# else\n#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)\n# endif\n#endif\n\n\n/* YYLEX -- calling `yylex' with the right arguments.  */\n\n#ifdef YYLEX_PARAM\n# define YYLEX yylex (YYLEX_PARAM)\n#else\n# define YYLEX yylex ()\n#endif\n\n/* Enable debugging if requested.  */\n#if YYDEBUG\n\n# ifndef YYFPRINTF\n#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */\n#  define YYFPRINTF fprintf\n# endif\n\n# define YYDPRINTF(Args)\t\t\t\\\ndo {\t\t\t\t\t\t\\\n  if (yydebug)\t\t\t\t\t\\\n    YYFPRINTF Args;\t\t\t\t\\\n} while (YYID (0))\n\n# define YY_SYMBOL_PRINT(Title, Type, Value, Location)\t\t\t  \\\ndo {\t\t\t\t\t\t\t\t\t  \\\n  if (yydebug)\t\t\t\t\t\t\t\t  \\\n    {\t\t\t\t\t\t\t\t\t  \\\n      YYFPRINTF (stderr, \"%s \", Title);\t\t\t\t\t  \\\n      yy_symbol_print (stderr,\t\t\t\t\t\t  \\\n\t\t  Type, Value, Location); \\\n      YYFPRINTF (stderr, \"\\n\");\t\t\t\t\t\t  \\\n    }\t\t\t\t\t\t\t\t\t  \\\n} while (YYID (0))\n\n\n/*--------------------------------.\n| Print this symbol on YYOUTPUT.  |\n`--------------------------------*/\n\n/*ARGSUSED*/\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)\n#else\nstatic void\nyy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)\n    FILE *yyoutput;\n    int yytype;\n    YYSTYPE const * const yyvaluep;\n    YYLTYPE const * const yylocationp;\n#endif\n{\n  if (!yyvaluep)\n    return;\n  YYUSE (yylocationp);\n# ifdef YYPRINT\n  if (yytype < YYNTOKENS)\n    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);\n# else\n  YYUSE (yyoutput);\n# endif\n  switch (yytype)\n    {\n      default:\n\tbreak;\n    }\n}\n\n\n/*--------------------------------.\n| Print this symbol on YYOUTPUT.  |\n`--------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)\n#else\nstatic void\nyy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)\n    FILE *yyoutput;\n    int yytype;\n    YYSTYPE const * const yyvaluep;\n    YYLTYPE const * const yylocationp;\n#endif\n{\n  if (yytype < YYNTOKENS)\n    YYFPRINTF (yyoutput, \"token %s (\", yytname[yytype]);\n  else\n    YYFPRINTF (yyoutput, \"nterm %s (\", yytname[yytype]);\n\n  YY_LOCATION_PRINT (yyoutput, *yylocationp);\n  YYFPRINTF (yyoutput, \": \");\n  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp);\n  YYFPRINTF (yyoutput, \")\");\n}\n\n/*------------------------------------------------------------------.\n| yy_stack_print -- Print the state stack from its BOTTOM up to its |\n| TOP (included).                                                   |\n`------------------------------------------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)\n#else\nstatic void\nyy_stack_print (yybottom, yytop)\n    yytype_int16 *yybottom;\n    yytype_int16 *yytop;\n#endif\n{\n  YYFPRINTF (stderr, \"Stack now\");\n  for (; yybottom <= yytop; yybottom++)\n    {\n      int yybot = *yybottom;\n      YYFPRINTF (stderr, \" %d\", yybot);\n    }\n  YYFPRINTF (stderr, \"\\n\");\n}\n\n# define YY_STACK_PRINT(Bottom, Top)\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\\\n  if (yydebug)\t\t\t\t\t\t\t\\\n    yy_stack_print ((Bottom), (Top));\t\t\t\t\\\n} while (YYID (0))\n\n\n/*------------------------------------------------.\n| Report that the YYRULE is going to be reduced.  |\n`------------------------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)\n#else\nstatic void\nyy_reduce_print (yyvsp, yylsp, yyrule)\n    YYSTYPE *yyvsp;\n    YYLTYPE *yylsp;\n    int yyrule;\n#endif\n{\n  int yynrhs = yyr2[yyrule];\n  int yyi;\n  unsigned long int yylno = yyrline[yyrule];\n  YYFPRINTF (stderr, \"Reducing stack by rule %d (line %lu):\\n\",\n\t     yyrule - 1, yylno);\n  /* The symbols being reduced.  */\n  for (yyi = 0; yyi < yynrhs; yyi++)\n    {\n      YYFPRINTF (stderr, \"   $%d = \", yyi + 1);\n      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],\n\t\t       &(yyvsp[(yyi + 1) - (yynrhs)])\n\t\t       , &(yylsp[(yyi + 1) - (yynrhs)])\t\t       );\n      YYFPRINTF (stderr, \"\\n\");\n    }\n}\n\n# define YY_REDUCE_PRINT(Rule)\t\t\\\ndo {\t\t\t\t\t\\\n  if (yydebug)\t\t\t\t\\\n    yy_reduce_print (yyvsp, yylsp, Rule); \\\n} while (YYID (0))\n\n/* Nonzero means print parse trace.  It is left uninitialized so that\n   multiple parsers can coexist.  */\nint yydebug;\n#else /* !YYDEBUG */\n# define YYDPRINTF(Args)\n# define YY_SYMBOL_PRINT(Title, Type, Value, Location)\n# define YY_STACK_PRINT(Bottom, Top)\n# define YY_REDUCE_PRINT(Rule)\n#endif /* !YYDEBUG */\n\n\n/* YYINITDEPTH -- initial size of the parser's stacks.  */\n#ifndef\tYYINITDEPTH\n# define YYINITDEPTH 200\n#endif\n\n/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only\n   if the built-in stack extension method is used).\n\n   Do not make this value too large; the results are undefined if\n   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)\n   evaluated with infinite-precision integer arithmetic.  */\n\n#ifndef YYMAXDEPTH\n# define YYMAXDEPTH 10000\n#endif\n\n\f\n\n#if YYERROR_VERBOSE\n\n# ifndef yystrlen\n#  if defined __GLIBC__ && defined _STRING_H\n#   define yystrlen strlen\n#  else\n/* Return the length of YYSTR.  */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic YYSIZE_T\nyystrlen (const char *yystr)\n#else\nstatic YYSIZE_T\nyystrlen (yystr)\n    const char *yystr;\n#endif\n{\n  YYSIZE_T yylen;\n  for (yylen = 0; yystr[yylen]; yylen++)\n    continue;\n  return yylen;\n}\n#  endif\n# endif\n\n# ifndef yystpcpy\n#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE\n#   define yystpcpy stpcpy\n#  else\n/* Copy YYSRC to YYDEST, returning the address of the terminating '\\0' in\n   YYDEST.  */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic char *\nyystpcpy (char *yydest, const char *yysrc)\n#else\nstatic char *\nyystpcpy (yydest, yysrc)\n    char *yydest;\n    const char *yysrc;\n#endif\n{\n  char *yyd = yydest;\n  const char *yys = yysrc;\n\n  while ((*yyd++ = *yys++) != '\\0')\n    continue;\n\n  return yyd - 1;\n}\n#  endif\n# endif\n\n# ifndef yytnamerr\n/* Copy to YYRES the contents of YYSTR after stripping away unnecessary\n   quotes and backslashes, so that it's suitable for yyerror.  The\n   heuristic is that double-quoting is unnecessary unless the string\n   contains an apostrophe, a comma, or backslash (other than\n   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is\n   null, do not copy; instead, return the length of what the result\n   would have been.  */\nstatic YYSIZE_T\nyytnamerr (char *yyres, const char *yystr)\n{\n  if (*yystr == '\"')\n    {\n      YYSIZE_T yyn = 0;\n      char const *yyp = yystr;\n\n      for (;;)\n\tswitch (*++yyp)\n\t  {\n\t  case '\\'':\n\t  case ',':\n\t    goto do_not_strip_quotes;\n\n\t  case '\\\\':\n\t    if (*++yyp != '\\\\')\n\t      goto do_not_strip_quotes;\n\t    /* Fall through.  */\n\t  default:\n\t    if (yyres)\n\t      yyres[yyn] = *yyp;\n\t    yyn++;\n\t    break;\n\n\t  case '\"':\n\t    if (yyres)\n\t      yyres[yyn] = '\\0';\n\t    return yyn;\n\t  }\n    do_not_strip_quotes: ;\n    }\n\n  if (! yyres)\n    return yystrlen (yystr);\n\n  return yystpcpy (yyres, yystr) - yyres;\n}\n# endif\n\n/* Copy into YYRESULT an error message about the unexpected token\n   YYCHAR while in state YYSTATE.  Return the number of bytes copied,\n   including the terminating null byte.  If YYRESULT is null, do not\n   copy anything; just return the number of bytes that would be\n   copied.  As a special case, return 0 if an ordinary \"syntax error\"\n   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during\n   size calculation.  */\nstatic YYSIZE_T\nyysyntax_error (char *yyresult, int yystate, int yychar)\n{\n  int yyn = yypact[yystate];\n\n  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))\n    return 0;\n  else\n    {\n      int yytype = YYTRANSLATE (yychar);\n      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);\n      YYSIZE_T yysize = yysize0;\n      YYSIZE_T yysize1;\n      int yysize_overflow = 0;\n      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };\n      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];\n      int yyx;\n\n# if 0\n      /* This is so xgettext sees the translatable formats that are\n\t constructed on the fly.  */\n      YY_(\"syntax error, unexpected %s\");\n      YY_(\"syntax error, unexpected %s, expecting %s\");\n      YY_(\"syntax error, unexpected %s, expecting %s or %s\");\n      YY_(\"syntax error, unexpected %s, expecting %s or %s or %s\");\n      YY_(\"syntax error, unexpected %s, expecting %s or %s or %s or %s\");\n# endif\n      char *yyfmt;\n      char const *yyf;\n      static char const yyunexpected[] = \"syntax error, unexpected %s\";\n      static char const yyexpecting[] = \", expecting %s\";\n      static char const yyor[] = \" or %s\";\n      char yyformat[sizeof yyunexpected\n\t\t    + sizeof yyexpecting - 1\n\t\t    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)\n\t\t       * (sizeof yyor - 1))];\n      char const *yyprefix = yyexpecting;\n\n      /* Start YYX at -YYN if negative to avoid negative indexes in\n\t YYCHECK.  */\n      int yyxbegin = yyn < 0 ? -yyn : 0;\n\n      /* Stay within bounds of both yycheck and yytname.  */\n      int yychecklim = YYLAST - yyn + 1;\n      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;\n      int yycount = 1;\n\n      yyarg[0] = yytname[yytype];\n      yyfmt = yystpcpy (yyformat, yyunexpected);\n\n      for (yyx = yyxbegin; yyx < yyxend; ++yyx)\n\tif (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)\n\t  {\n\t    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)\n\t      {\n\t\tyycount = 1;\n\t\tyysize = yysize0;\n\t\tyyformat[sizeof yyunexpected - 1] = '\\0';\n\t\tbreak;\n\t      }\n\t    yyarg[yycount++] = yytname[yyx];\n\t    yysize1 = yysize + yytnamerr (0, yytname[yyx]);\n\t    yysize_overflow |= (yysize1 < yysize);\n\t    yysize = yysize1;\n\t    yyfmt = yystpcpy (yyfmt, yyprefix);\n\t    yyprefix = yyor;\n\t  }\n\n      yyf = YY_(yyformat);\n      yysize1 = yysize + yystrlen (yyf);\n      yysize_overflow |= (yysize1 < yysize);\n      yysize = yysize1;\n\n      if (yysize_overflow)\n\treturn YYSIZE_MAXIMUM;\n\n      if (yyresult)\n\t{\n\t  /* Avoid sprintf, as that infringes on the user's name space.\n\t     Don't have undefined behavior even if the translation\n\t     produced a string with the wrong number of \"%s\"s.  */\n\t  char *yyp = yyresult;\n\t  int yyi = 0;\n\t  while ((*yyp = *yyf) != '\\0')\n\t    {\n\t      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)\n\t\t{\n\t\t  yyp += yytnamerr (yyp, yyarg[yyi++]);\n\t\t  yyf += 2;\n\t\t}\n\t      else\n\t\t{\n\t\t  yyp++;\n\t\t  yyf++;\n\t\t}\n\t    }\n\t}\n      return yysize;\n    }\n}\n#endif /* YYERROR_VERBOSE */\n\f\n\n/*-----------------------------------------------.\n| Release the memory associated to this symbol.  |\n`-----------------------------------------------*/\n\n/*ARGSUSED*/\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nyydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)\n#else\nstatic void\nyydestruct (yymsg, yytype, yyvaluep, yylocationp)\n    const char *yymsg;\n    int yytype;\n    YYSTYPE *yyvaluep;\n    YYLTYPE *yylocationp;\n#endif\n{\n  YYUSE (yyvaluep);\n  YYUSE (yylocationp);\n\n  if (!yymsg)\n    yymsg = \"Deleting\";\n  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);\n\n  switch (yytype)\n    {\n\n      default:\n\tbreak;\n    }\n}\n\n/* Prevent warnings from -Wmissing-prototypes.  */\n#ifdef YYPARSE_PARAM\n#if defined __STDC__ || defined __cplusplus\nint yyparse (void *YYPARSE_PARAM);\n#else\nint yyparse ();\n#endif\n#else /* ! YYPARSE_PARAM */\n#if defined __STDC__ || defined __cplusplus\nint yyparse (void);\n#else\nint yyparse ();\n#endif\n#endif /* ! YYPARSE_PARAM */\n\n\n/* The lookahead symbol.  */\nint yychar;\n\n/* The semantic value of the lookahead symbol.  */\nYYSTYPE yylval;\n\n/* Location data for the lookahead symbol.  */\nYYLTYPE yylloc;\n\n/* Number of syntax errors so far.  */\nint yynerrs;\n\n\n\n/*-------------------------.\n| yyparse or yypush_parse.  |\n`-------------------------*/\n\n#ifdef YYPARSE_PARAM\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nint\nyyparse (void *YYPARSE_PARAM)\n#else\nint\nyyparse (YYPARSE_PARAM)\n    void *YYPARSE_PARAM;\n#endif\n#else /* ! YYPARSE_PARAM */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nint\nyyparse (void)\n#else\nint\nyyparse ()\n\n#endif\n#endif\n{\n\n\n    int yystate;\n    /* Number of tokens to shift before error messages enabled.  */\n    int yyerrstatus;\n\n    /* The stacks and their tools:\n       `yyss': related to states.\n       `yyvs': related to semantic values.\n       `yyls': related to locations.\n\n       Refer to the stacks thru separate pointers, to allow yyoverflow\n       to reallocate them elsewhere.  */\n\n    /* The state stack.  */\n    yytype_int16 yyssa[YYINITDEPTH];\n    yytype_int16 *yyss;\n    yytype_int16 *yyssp;\n\n    /* The semantic value stack.  */\n    YYSTYPE yyvsa[YYINITDEPTH];\n    YYSTYPE *yyvs;\n    YYSTYPE *yyvsp;\n\n    /* The location stack.  */\n    YYLTYPE yylsa[YYINITDEPTH];\n    YYLTYPE *yyls;\n    YYLTYPE *yylsp;\n\n    /* The locations where the error started and ended.  */\n    YYLTYPE yyerror_range[2];\n\n    YYSIZE_T yystacksize;\n\n  int yyn;\n  int yyresult;\n  /* Lookahead token as an internal (translated) token number.  */\n  int yytoken;\n  /* The variables used to return semantic value and location from the\n     action routines.  */\n  YYSTYPE yyval;\n  YYLTYPE yyloc;\n\n#if YYERROR_VERBOSE\n  /* Buffer for error messages, and its allocated size.  */\n  char yymsgbuf[128];\n  char *yymsg = yymsgbuf;\n  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;\n#endif\n\n#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N), yylsp -= (N))\n\n  /* The number of symbols on the RHS of the reduced rule.\n     Keep to zero when no symbol should be popped.  */\n  int yylen = 0;\n\n  yytoken = 0;\n  yyss = yyssa;\n  yyvs = yyvsa;\n  yyls = yylsa;\n  yystacksize = YYINITDEPTH;\n\n  YYDPRINTF ((stderr, \"Starting parse\\n\"));\n\n  yystate = 0;\n  yyerrstatus = 0;\n  yynerrs = 0;\n  yychar = YYEMPTY; /* Cause a token to be read.  */\n\n  /* Initialize stack pointers.\n     Waste one element of value and location stack\n     so that they stay on the same level as the state stack.\n     The wasted elements are never initialized.  */\n  yyssp = yyss;\n  yyvsp = yyvs;\n  yylsp = yyls;\n\n#if YYLTYPE_IS_TRIVIAL\n  /* Initialize the default location before parsing starts.  */\n  yylloc.first_line   = yylloc.last_line   = 1;\n  yylloc.first_column = yylloc.last_column = 1;\n#endif\n\n  goto yysetstate;\n\n/*------------------------------------------------------------.\n| yynewstate -- Push a new state, which is found in yystate.  |\n`------------------------------------------------------------*/\n yynewstate:\n  /* In all cases, when you get here, the value and location stacks\n     have just been pushed.  So pushing a state here evens the stacks.  */\n  yyssp++;\n\n yysetstate:\n  *yyssp = yystate;\n\n  if (yyss + yystacksize - 1 <= yyssp)\n    {\n      /* Get the current used size of the three stacks, in elements.  */\n      YYSIZE_T yysize = yyssp - yyss + 1;\n\n#ifdef yyoverflow\n      {\n\t/* Give user a chance to reallocate the stack.  Use copies of\n\t   these so that the &'s don't force the real ones into\n\t   memory.  */\n\tYYSTYPE *yyvs1 = yyvs;\n\tyytype_int16 *yyss1 = yyss;\n\tYYLTYPE *yyls1 = yyls;\n\n\t/* Each stack pointer address is followed by the size of the\n\t   data in use in that stack, in bytes.  This used to be a\n\t   conditional around just the two extra args, but that might\n\t   be undefined if yyoverflow is a macro.  */\n\tyyoverflow (YY_(\"memory exhausted\"),\n\t\t    &yyss1, yysize * sizeof (*yyssp),\n\t\t    &yyvs1, yysize * sizeof (*yyvsp),\n\t\t    &yyls1, yysize * sizeof (*yylsp),\n\t\t    &yystacksize);\n\n\tyyls = yyls1;\n\tyyss = yyss1;\n\tyyvs = yyvs1;\n      }\n#else /* no yyoverflow */\n# ifndef YYSTACK_RELOCATE\n      goto yyexhaustedlab;\n# else\n      /* Extend the stack our own way.  */\n      if (YYMAXDEPTH <= yystacksize)\n\tgoto yyexhaustedlab;\n      yystacksize *= 2;\n      if (YYMAXDEPTH < yystacksize)\n\tyystacksize = YYMAXDEPTH;\n\n      {\n\tyytype_int16 *yyss1 = yyss;\n\tunion yyalloc *yyptr =\n\t  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));\n\tif (! yyptr)\n\t  goto yyexhaustedlab;\n\tYYSTACK_RELOCATE (yyss_alloc, yyss);\n\tYYSTACK_RELOCATE (yyvs_alloc, yyvs);\n\tYYSTACK_RELOCATE (yyls_alloc, yyls);\n#  undef YYSTACK_RELOCATE\n\tif (yyss1 != yyssa)\n\t  YYSTACK_FREE (yyss1);\n      }\n# endif\n#endif /* no yyoverflow */\n\n      yyssp = yyss + yysize - 1;\n      yyvsp = yyvs + yysize - 1;\n      yylsp = yyls + yysize - 1;\n\n      YYDPRINTF ((stderr, \"Stack size increased to %lu\\n\",\n\t\t  (unsigned long int) yystacksize));\n\n      if (yyss + yystacksize - 1 <= yyssp)\n\tYYABORT;\n    }\n\n  YYDPRINTF ((stderr, \"Entering state %d\\n\", yystate));\n\n  if (yystate == YYFINAL)\n    YYACCEPT;\n\n  goto yybackup;\n\n/*-----------.\n| yybackup.  |\n`-----------*/\nyybackup:\n\n  /* Do appropriate processing given the current state.  Read a\n     lookahead token if we need one and don't already have one.  */\n\n  /* First try to decide what to do without reference to lookahead token.  */\n  yyn = yypact[yystate];\n  if (yyn == YYPACT_NINF)\n    goto yydefault;\n\n  /* Not known => get a lookahead token if don't already have one.  */\n\n  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */\n  if (yychar == YYEMPTY)\n    {\n      YYDPRINTF ((stderr, \"Reading a token: \"));\n      yychar = YYLEX;\n    }\n\n  if (yychar <= YYEOF)\n    {\n      yychar = yytoken = YYEOF;\n      YYDPRINTF ((stderr, \"Now at end of input.\\n\"));\n    }\n  else\n    {\n      yytoken = YYTRANSLATE (yychar);\n      YY_SYMBOL_PRINT (\"Next token is\", yytoken, &yylval, &yylloc);\n    }\n\n  /* If the proper action on seeing token YYTOKEN is to reduce or to\n     detect an error, take that action.  */\n  yyn += yytoken;\n  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)\n    goto yydefault;\n  yyn = yytable[yyn];\n  if (yyn <= 0)\n    {\n      if (yyn == 0 || yyn == YYTABLE_NINF)\n\tgoto yyerrlab;\n      yyn = -yyn;\n      goto yyreduce;\n    }\n\n  /* Count tokens shifted since error; after three, turn off error\n     status.  */\n  if (yyerrstatus)\n    yyerrstatus--;\n\n  /* Shift the lookahead token.  */\n  YY_SYMBOL_PRINT (\"Shifting\", yytoken, &yylval, &yylloc);\n\n  /* Discard the shifted token.  */\n  yychar = YYEMPTY;\n\n  yystate = yyn;\n  *++yyvsp = yylval;\n  *++yylsp = yylloc;\n  goto yynewstate;\n\n\n/*-----------------------------------------------------------.\n| yydefault -- do the default action for the current state.  |\n`-----------------------------------------------------------*/\nyydefault:\n  yyn = yydefact[yystate];\n  if (yyn == 0)\n    goto yyerrlab;\n  goto yyreduce;\n\n\n/*-----------------------------.\n| yyreduce -- Do a reduction.  |\n`-----------------------------*/\nyyreduce:\n  /* yyn is the number of a rule to reduce with.  */\n  yylen = yyr2[yyn];\n\n  /* If YYLEN is nonzero, implement the default value of the action:\n     `$$ = $1'.\n\n     Otherwise, the following line sets YYVAL to garbage.\n     This behavior is undocumented and Bison\n     users should not rely upon it.  Assigning to YYVAL\n     unconditionally makes the parser a bit smaller, and it avoids a\n     GCC warning that YYVAL may be used uninitialized.  */\n  yyval = yyvsp[1-yylen];\n\n  /* Default location.  */\n  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);\n  YY_REDUCE_PRINT (yyn);\n  switch (yyn)\n    {\n        case 17:\n\n/* Line 1455 of yacc.c  */\n#line 234 \"../../src/parser.yy\"\n    {\n\t      if (gengetopt_package_given)\n\t\t{\n\t\t  yyerror (\"package redefined\");\n\t\t  YYERROR;\n\t\t}\n\t      else\n\t\t{\n\t\t  gengetopt_package_given = 1;\n\t\t  if (gengetopt_define_package ((yyvsp[(2) - (2)].str)))\n\t\t    {\n\t\t      yyerror (\"not enough memory\");\n\t\t      YYERROR;\n\t\t    }\n\t\t}\n\t    }\n    break;\n\n  case 18:\n\n/* Line 1455 of yacc.c  */\n#line 254 \"../../src/parser.yy\"\n    {\n\t      if (gengetopt_version_given)\n\t\t{\n\t\t  yyerror (\"version redefined\");\n\t\t  YYERROR;\n\t\t}\n\t      else\n\t\t{\n\t\t  gengetopt_version_given = 1;\n\t\t  if (gengetopt_define_version ((yyvsp[(2) - (2)].str)))\n\t\t    {\n\t\t      yyerror (\"not enough memory\");\n\t\t      YYERROR;\n\t\t    }\n\t\t}\n\t    }\n    break;\n\n  case 19:\n\n/* Line 1455 of yacc.c  */\n#line 274 \"../../src/parser.yy\"\n    {\n\t      if (gengetopt_purpose_given)\n\t\t{\n\t\t  yyerror (\"purpose redefined\");\n\t\t  YYERROR;\n\t\t}\n\t      else\n\t\t{\n\t\t  gengetopt_purpose_given = 1;\n\t\t  if (gengetopt_define_purpose ((yyvsp[(2) - (2)].str)))\n\t\t    {\n\t\t      yyerror (\"not enough memory\");\n\t\t      YYERROR;\n\t\t    }\n\t\t}\n\t    }\n    break;\n\n  case 20:\n\n/* Line 1455 of yacc.c  */\n#line 294 \"../../src/parser.yy\"\n    {\n\t      if (gengetopt_description_given)\n\t\t{\n\t\t  yyerror (\"description redefined\");\n\t\t  YYERROR;\n\t\t}\n\t      else\n\t\t{\n\t\t  gengetopt_description_given = 1;\n\t\t  if (gengetopt_define_description ((yyvsp[(2) - (2)].str)))\n\t\t    {\n\t\t      yyerror (\"not enough memory\");\n\t\t      YYERROR;\n\t\t    }\n\t\t}\n\t    }\n    break;\n\n  case 21:\n\n/* Line 1455 of yacc.c  */\n#line 314 \"../../src/parser.yy\"\n    {\n      if (gengetopt_usage_given)\n      {\n\t  yyerror (\"usage redefined\");\n\t  YYERROR;\n      }\n      else\n      {\n\t  gengetopt_usage_given = 1;\n\t  if (gengetopt_define_usage ((yyvsp[(2) - (2)].str)))\n          {\n\t      yyerror (\"not enough memory\");\n\t      YYERROR;\n          }\n      }\n  }\n    break;\n\n  case 22:\n\n/* Line 1455 of yacc.c  */\n#line 335 \"../../src/parser.yy\"\n    {\n                gengetopt_set_section ((yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str));\n              }\n    break;\n\n  case 23:\n\n/* Line 1455 of yacc.c  */\n#line 342 \"../../src/parser.yy\"\n    {\n            \tif (current_option) {\n            \t\tstd::string current_option_text;\n            \t\tif (current_option->text_after) {\n            \t\t\tcurrent_option_text = std::string(current_option->text_after) + (yyvsp[(2) - (2)].str);\n            \t\t\tcurrent_option->text_after = strdup(current_option_text.c_str());\n            \t\t} else {\n\t            \t\tcurrent_option->text_after = strdup((yyvsp[(2) - (2)].str));\n\t            \t}\n            \t} else {\n\t\t\t\t\tgengetopt_set_text((yyvsp[(2) - (2)].str));\n  \t\t\t\t}\n            }\n    break;\n\n  case 24:\n\n/* Line 1455 of yacc.c  */\n#line 359 \"../../src/parser.yy\"\n    {\n  gengetopt_set_args((yyvsp[(2) - (2)].str));\n            }\n    break;\n\n  case 25:\n\n/* Line 1455 of yacc.c  */\n#line 366 \"../../src/parser.yy\"\n    {\n              if (gengetopt_add_group ((yyvsp[(2) - (4)].str), (yyvsp[(3) - (4)].str), (yyvsp[(4) - (4)].boolean)))\n                {\n\t\t  \tyyerror (\"group redefined\");\n\t\t  \tYYERROR;\n\t\t  }\n\t    }\n    break;\n\n  case 26:\n\n/* Line 1455 of yacc.c  */\n#line 377 \"../../src/parser.yy\"\n    {\n              if (gengetopt_add_mode ((yyvsp[(2) - (3)].str), (yyvsp[(3) - (3)].str)))\n                {\n\t\t  \tyyerror (\"mode redefined\");\n\t\t  \tYYERROR;\n\t\t  }\n\t    }\n    break;\n\n  case 27:\n\n/* Line 1455 of yacc.c  */\n#line 389 \"../../src/parser.yy\"\n    {\n          (yyvsp[(5) - (5)].gengetopt_option)->filename = gengetopt_input_filename;\n          (yyvsp[(5) - (5)].gengetopt_option)->linenum = (yylsp[(1) - (5)]).first_line;\n\t      (yyvsp[(5) - (5)].gengetopt_option)->long_opt = strdup((yyvsp[(2) - (5)].str));\n\t      if ((yyvsp[(3) - (5)].chr) != '-')\n\t      \t(yyvsp[(5) - (5)].gengetopt_option)->short_opt = (yyvsp[(3) - (5)].chr);\n\t      (yyvsp[(5) - (5)].gengetopt_option)->desc = strdup((yyvsp[(4) - (5)].str));\n\t      int o = gengetopt_check_option ((yyvsp[(5) - (5)].gengetopt_option), false);\n\t      check_result(o, (yyvsp[(5) - (5)].gengetopt_option));\n          check_error;\n\t      o = gengetopt_add_option ((yyvsp[(5) - (5)].gengetopt_option));\n\t      check_result(o, (yyvsp[(5) - (5)].gengetopt_option));\n\t      check_error;\n\t      current_option = (yyvsp[(5) - (5)].gengetopt_option);\n\t    }\n    break;\n\n  case 28:\n\n/* Line 1455 of yacc.c  */\n#line 409 \"../../src/parser.yy\"\n    {\n          (yyvsp[(5) - (5)].gengetopt_option)->filename = gengetopt_input_filename;\n          (yyvsp[(5) - (5)].gengetopt_option)->linenum = (yylsp[(1) - (5)]).first_line;\n\t      (yyvsp[(5) - (5)].gengetopt_option)->long_opt = strdup((yyvsp[(2) - (5)].str));\n          if ((yyvsp[(3) - (5)].chr) != '-')\n            (yyvsp[(5) - (5)].gengetopt_option)->short_opt = (yyvsp[(3) - (5)].chr);\n          (yyvsp[(5) - (5)].gengetopt_option)->desc = strdup((yyvsp[(4) - (5)].str));\n          int o = gengetopt_check_option ((yyvsp[(5) - (5)].gengetopt_option), true);\n          check_result(o, (yyvsp[(5) - (5)].gengetopt_option));\n          check_error;\n          o = gengetopt_add_option ((yyvsp[(5) - (5)].gengetopt_option));\n          check_result(o, (yyvsp[(5) - (5)].gengetopt_option));\n          check_error;\n\t    }\n    break;\n\n  case 29:\n\n/* Line 1455 of yacc.c  */\n#line 428 \"../../src/parser.yy\"\n    {\n          (yyvsp[(5) - (5)].gengetopt_option)->filename = gengetopt_input_filename;\n          (yyvsp[(5) - (5)].gengetopt_option)->linenum = (yylsp[(1) - (5)]).first_line;\n\t      (yyvsp[(5) - (5)].gengetopt_option)->long_opt = strdup((yyvsp[(2) - (5)].str));\n          if ((yyvsp[(3) - (5)].chr) != '-')\n            (yyvsp[(5) - (5)].gengetopt_option)->short_opt = (yyvsp[(3) - (5)].chr);\n          (yyvsp[(5) - (5)].gengetopt_option)->desc = strdup((yyvsp[(4) - (5)].str));\n          int o = gengetopt_check_option ((yyvsp[(5) - (5)].gengetopt_option), false, true);\n          check_result(o, (yyvsp[(5) - (5)].gengetopt_option));\n          check_error;\n          o = gengetopt_add_option ((yyvsp[(5) - (5)].gengetopt_option));\n          check_result(o, (yyvsp[(5) - (5)].gengetopt_option));\n          check_error;\n\t    }\n    break;\n\n  case 31:\n\n/* Line 1455 of yacc.c  */\n#line 452 \"../../src/parser.yy\"\n    {\n\t\t\t  \t(yyval.gengetopt_option) = (yyvsp[(1) - (2)].gengetopt_option);\n\t\t\t  \t(yyval.gengetopt_option)->required = (yyvsp[(2) - (2)].boolean);\n\t\t\t  \t(yyval.gengetopt_option)->required_set = true;\n\t\t\t  }\n    break;\n\n  case 32:\n\n/* Line 1455 of yacc.c  */\n#line 458 \"../../src/parser.yy\"\n    {\n\t\t\t  \t(yyval.gengetopt_option) = (yyvsp[(1) - (2)].gengetopt_option);\n\t\t\t  \t(yyval.gengetopt_option)->type = (yyvsp[(2) - (2)].argtype);\n\t\t\t  }\n    break;\n\n  case 33:\n\n/* Line 1455 of yacc.c  */\n#line 463 \"../../src/parser.yy\"\n    {\n\t\t\t  \t(yyval.gengetopt_option) = (yyvsp[(1) - (4)].gengetopt_option);\n\t\t\t  \t(yyval.gengetopt_option)->type_str = strdup((yyvsp[(4) - (4)].str));\n\t\t\t  }\n    break;\n\n  case 34:\n\n/* Line 1455 of yacc.c  */\n#line 468 \"../../src/parser.yy\"\n    {\n\t\t\t  \t(yyval.gengetopt_option) = (yyvsp[(1) - (4)].gengetopt_option);\n\t\t\t  \t(yyval.gengetopt_option)->details = strdup((yyvsp[(4) - (4)].str));\n\t\t\t  }\n    break;\n\n  case 35:\n\n/* Line 1455 of yacc.c  */\n#line 473 \"../../src/parser.yy\"\n    {\n\t\t\t  \t(yyval.gengetopt_option) = (yyvsp[(1) - (4)].gengetopt_option);\n\t\t\t  \t(yyval.gengetopt_option)->acceptedvalues = (yyvsp[(4) - (4)].ValueList);\n\t\t\t  }\n    break;\n\n  case 36:\n\n/* Line 1455 of yacc.c  */\n#line 478 \"../../src/parser.yy\"\n    {\n\t\t\t  \t(yyval.gengetopt_option) = (yyvsp[(1) - (4)].gengetopt_option);\n\t\t\t  \t(yyval.gengetopt_option)->default_string = strdup((yyvsp[(4) - (4)].str));\n\t\t\t  }\n    break;\n\n  case 37:\n\n/* Line 1455 of yacc.c  */\n#line 483 \"../../src/parser.yy\"\n    {\n                (yyval.gengetopt_option) = (yyvsp[(1) - (4)].gengetopt_option);\n                (yyval.gengetopt_option)->group_value = strdup((yyvsp[(4) - (4)].str));\n              }\n    break;\n\n  case 38:\n\n/* Line 1455 of yacc.c  */\n#line 488 \"../../src/parser.yy\"\n    {\n                (yyval.gengetopt_option) = (yyvsp[(1) - (4)].gengetopt_option);\n                (yyval.gengetopt_option)->mode_value = strdup((yyvsp[(4) - (4)].str));\n              }\n    break;\n\n  case 39:\n\n/* Line 1455 of yacc.c  */\n#line 493 \"../../src/parser.yy\"\n    {\n                (yyval.gengetopt_option) = (yyvsp[(1) - (4)].gengetopt_option);\n                (yyval.gengetopt_option)->dependon = strdup((yyvsp[(4) - (4)].str));\n              }\n    break;\n\n  case 40:\n\n/* Line 1455 of yacc.c  */\n#line 498 \"../../src/parser.yy\"\n    {\n\t\t\t  \t(yyval.gengetopt_option) = (yyvsp[(1) - (2)].gengetopt_option);\n\t\t\t  \t(yyval.gengetopt_option)->arg_is_optional = true;\n\t\t\t  }\n    break;\n\n  case 41:\n\n/* Line 1455 of yacc.c  */\n#line 503 \"../../src/parser.yy\"\n    {\n\t\t\t  \t(yyval.gengetopt_option) = (yyvsp[(1) - (3)].gengetopt_option);\n\t\t\t  \t(yyval.gengetopt_option)->multiple = true;\n                (yyval.gengetopt_option)->multiple_min = (yyvsp[(3) - (3)].multiple_size)->min;\n                (yyval.gengetopt_option)->multiple_max = (yyvsp[(3) - (3)].multiple_size)->max;\n                delete (yyvsp[(3) - (3)].multiple_size);\n\t\t\t  }\n    break;\n\n  case 42:\n\n/* Line 1455 of yacc.c  */\n#line 511 \"../../src/parser.yy\"\n    {\n          (yyval.gengetopt_option) = (yyvsp[(1) - (2)].gengetopt_option);\n          (yyval.gengetopt_option)->type = ARG_FLAG;\n        }\n    break;\n\n  case 43:\n\n/* Line 1455 of yacc.c  */\n#line 516 \"../../src/parser.yy\"\n    {\n          (yyval.gengetopt_option) = (yyvsp[(1) - (2)].gengetopt_option);\n          (yyval.gengetopt_option)->hidden = true;\n        }\n    break;\n\n  case 44:\n\n/* Line 1455 of yacc.c  */\n#line 521 \"../../src/parser.yy\"\n    {\n          (yyval.gengetopt_option) = (yyvsp[(1) - (2)].gengetopt_option);\n          (yyval.gengetopt_option)->flagstat = (yyvsp[(2) - (2)].boolean);\n        }\n    break;\n\n  case 45:\n\n/* Line 1455 of yacc.c  */\n#line 525 \"../../src/parser.yy\"\n    { (yyval.gengetopt_option) = new gengetopt_option; }\n    break;\n\n  case 46:\n\n/* Line 1455 of yacc.c  */\n#line 529 \"../../src/parser.yy\"\n    { (yyval.boolean) = 1; }\n    break;\n\n  case 47:\n\n/* Line 1455 of yacc.c  */\n#line 530 \"../../src/parser.yy\"\n    { (yyval.boolean) = 0; }\n    break;\n\n  case 48:\n\n/* Line 1455 of yacc.c  */\n#line 534 \"../../src/parser.yy\"\n    { (yyval.boolean) = 0; }\n    break;\n\n  case 49:\n\n/* Line 1455 of yacc.c  */\n#line 535 \"../../src/parser.yy\"\n    { (yyval.boolean) = 1; }\n    break;\n\n  case 50:\n\n/* Line 1455 of yacc.c  */\n#line 536 \"../../src/parser.yy\"\n    { (yyval.boolean) = 0; }\n    break;\n\n  case 51:\n\n/* Line 1455 of yacc.c  */\n#line 540 \"../../src/parser.yy\"\n    { (yyval.boolean) = 1; }\n    break;\n\n  case 52:\n\n/* Line 1455 of yacc.c  */\n#line 541 \"../../src/parser.yy\"\n    { (yyval.boolean) = 0; }\n    break;\n\n  case 53:\n\n/* Line 1455 of yacc.c  */\n#line 545 \"../../src/parser.yy\"\n    { (yyval.str) = 0; }\n    break;\n\n  case 54:\n\n/* Line 1455 of yacc.c  */\n#line 546 \"../../src/parser.yy\"\n    { (yyval.str) = (yyvsp[(3) - (3)].str); }\n    break;\n\n  case 55:\n\n/* Line 1455 of yacc.c  */\n#line 550 \"../../src/parser.yy\"\n    { (yyval.str) = 0; }\n    break;\n\n  case 56:\n\n/* Line 1455 of yacc.c  */\n#line 551 \"../../src/parser.yy\"\n    { (yyval.str) = (yyvsp[(3) - (3)].str); }\n    break;\n\n  case 57:\n\n/* Line 1455 of yacc.c  */\n#line 555 \"../../src/parser.yy\"\n    { (yyval.str) = 0; }\n    break;\n\n  case 58:\n\n/* Line 1455 of yacc.c  */\n#line 556 \"../../src/parser.yy\"\n    { (yyval.str) = (yyvsp[(3) - (3)].str); }\n    break;\n\n  case 59:\n\n/* Line 1455 of yacc.c  */\n#line 560 \"../../src/parser.yy\"\n    { (yyval.ValueList) = new AcceptedValues; (yyval.ValueList)->insert((yyvsp[(1) - (1)].str)); }\n    break;\n\n  case 60:\n\n/* Line 1455 of yacc.c  */\n#line 561 \"../../src/parser.yy\"\n    { (yyvsp[(1) - (3)].ValueList)->insert((yyvsp[(3) - (3)].str)); (yyval.ValueList) = (yyvsp[(1) - (3)].ValueList); }\n    break;\n\n  case 61:\n\n/* Line 1455 of yacc.c  */\n#line 565 \"../../src/parser.yy\"\n    { (yyval.str) = (yyvsp[(1) - (1)].str); }\n    break;\n\n  case 62:\n\n/* Line 1455 of yacc.c  */\n#line 569 \"../../src/parser.yy\"\n    { (yyval.multiple_size) = new multiple_size; }\n    break;\n\n  case 63:\n\n/* Line 1455 of yacc.c  */\n#line 570 \"../../src/parser.yy\"\n    { (yyval.multiple_size) = new multiple_size((yyvsp[(2) - (3)].str), (yyvsp[(2) - (3)].str)); }\n    break;\n\n  case 64:\n\n/* Line 1455 of yacc.c  */\n#line 571 \"../../src/parser.yy\"\n    { (yyval.multiple_size) = new multiple_size((yyvsp[(2) - (4)].str), \"0\"); free((yyvsp[(2) - (4)].str)); }\n    break;\n\n  case 65:\n\n/* Line 1455 of yacc.c  */\n#line 572 \"../../src/parser.yy\"\n    { (yyval.multiple_size) = new multiple_size(\"0\", (yyvsp[(3) - (4)].str)); free((yyvsp[(3) - (4)].str)); }\n    break;\n\n  case 66:\n\n/* Line 1455 of yacc.c  */\n#line 573 \"../../src/parser.yy\"\n    { (yyval.multiple_size) = new multiple_size((yyvsp[(2) - (5)].str), (yyvsp[(4) - (5)].str)); free((yyvsp[(2) - (5)].str)); free((yyvsp[(4) - (5)].str)); }\n    break;\n\n\n\n/* Line 1455 of yacc.c  */\n#line 2212 \"../../src/parser.cc\"\n      default: break;\n    }\n  YY_SYMBOL_PRINT (\"-> $$ =\", yyr1[yyn], &yyval, &yyloc);\n\n  YYPOPSTACK (yylen);\n  yylen = 0;\n  YY_STACK_PRINT (yyss, yyssp);\n\n  *++yyvsp = yyval;\n  *++yylsp = yyloc;\n\n  /* Now `shift' the result of the reduction.  Determine what state\n     that goes to, based on the state we popped back to and the rule\n     number reduced by.  */\n\n  yyn = yyr1[yyn];\n\n  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;\n  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)\n    yystate = yytable[yystate];\n  else\n    yystate = yydefgoto[yyn - YYNTOKENS];\n\n  goto yynewstate;\n\n\n/*------------------------------------.\n| yyerrlab -- here on detecting error |\n`------------------------------------*/\nyyerrlab:\n  /* If not already recovering from an error, report this error.  */\n  if (!yyerrstatus)\n    {\n      ++yynerrs;\n#if ! YYERROR_VERBOSE\n      yyerror (YY_(\"syntax error\"));\n#else\n      {\n\tYYSIZE_T yysize = yysyntax_error (0, yystate, yychar);\n\tif (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)\n\t  {\n\t    YYSIZE_T yyalloc = 2 * yysize;\n\t    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))\n\t      yyalloc = YYSTACK_ALLOC_MAXIMUM;\n\t    if (yymsg != yymsgbuf)\n\t      YYSTACK_FREE (yymsg);\n\t    yymsg = (char *) YYSTACK_ALLOC (yyalloc);\n\t    if (yymsg)\n\t      yymsg_alloc = yyalloc;\n\t    else\n\t      {\n\t\tyymsg = yymsgbuf;\n\t\tyymsg_alloc = sizeof yymsgbuf;\n\t      }\n\t  }\n\n\tif (0 < yysize && yysize <= yymsg_alloc)\n\t  {\n\t    (void) yysyntax_error (yymsg, yystate, yychar);\n\t    yyerror (yymsg);\n\t  }\n\telse\n\t  {\n\t    yyerror (YY_(\"syntax error\"));\n\t    if (yysize != 0)\n\t      goto yyexhaustedlab;\n\t  }\n      }\n#endif\n    }\n\n  yyerror_range[0] = yylloc;\n\n  if (yyerrstatus == 3)\n    {\n      /* If just tried and failed to reuse lookahead token after an\n\t error, discard it.  */\n\n      if (yychar <= YYEOF)\n\t{\n\t  /* Return failure if at end of input.  */\n\t  if (yychar == YYEOF)\n\t    YYABORT;\n\t}\n      else\n\t{\n\t  yydestruct (\"Error: discarding\",\n\t\t      yytoken, &yylval, &yylloc);\n\t  yychar = YYEMPTY;\n\t}\n    }\n\n  /* Else will try to reuse lookahead token after shifting the error\n     token.  */\n  goto yyerrlab1;\n\n\n/*---------------------------------------------------.\n| yyerrorlab -- error raised explicitly by YYERROR.  |\n`---------------------------------------------------*/\nyyerrorlab:\n\n  /* Pacify compilers like GCC when the user code never invokes\n     YYERROR and the label yyerrorlab therefore never appears in user\n     code.  */\n  if (/*CONSTCOND*/ 0)\n     goto yyerrorlab;\n\n  yyerror_range[0] = yylsp[1-yylen];\n  /* Do not reclaim the symbols of the rule which action triggered\n     this YYERROR.  */\n  YYPOPSTACK (yylen);\n  yylen = 0;\n  YY_STACK_PRINT (yyss, yyssp);\n  yystate = *yyssp;\n  goto yyerrlab1;\n\n\n/*-------------------------------------------------------------.\n| yyerrlab1 -- common code for both syntax error and YYERROR.  |\n`-------------------------------------------------------------*/\nyyerrlab1:\n  yyerrstatus = 3;\t/* Each real token shifted decrements this.  */\n\n  for (;;)\n    {\n      yyn = yypact[yystate];\n      if (yyn != YYPACT_NINF)\n\t{\n\t  yyn += YYTERROR;\n\t  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)\n\t    {\n\t      yyn = yytable[yyn];\n\t      if (0 < yyn)\n\t\tbreak;\n\t    }\n\t}\n\n      /* Pop the current state because it cannot handle the error token.  */\n      if (yyssp == yyss)\n\tYYABORT;\n\n      yyerror_range[0] = *yylsp;\n      yydestruct (\"Error: popping\",\n\t\t  yystos[yystate], yyvsp, yylsp);\n      YYPOPSTACK (1);\n      yystate = *yyssp;\n      YY_STACK_PRINT (yyss, yyssp);\n    }\n\n  *++yyvsp = yylval;\n\n  yyerror_range[1] = yylloc;\n  /* Using YYLLOC is tempting, but would change the location of\n     the lookahead.  YYLOC is available though.  */\n  YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);\n  *++yylsp = yyloc;\n\n  /* Shift the error token.  */\n  YY_SYMBOL_PRINT (\"Shifting\", yystos[yyn], yyvsp, yylsp);\n\n  yystate = yyn;\n  goto yynewstate;\n\n\n/*-------------------------------------.\n| yyacceptlab -- YYACCEPT comes here.  |\n`-------------------------------------*/\nyyacceptlab:\n  yyresult = 0;\n  goto yyreturn;\n\n/*-----------------------------------.\n| yyabortlab -- YYABORT comes here.  |\n`-----------------------------------*/\nyyabortlab:\n  yyresult = 1;\n  goto yyreturn;\n\n#if !defined(yyoverflow) || YYERROR_VERBOSE\n/*-------------------------------------------------.\n| yyexhaustedlab -- memory exhaustion comes here.  |\n`-------------------------------------------------*/\nyyexhaustedlab:\n  yyerror (YY_(\"memory exhausted\"));\n  yyresult = 2;\n  /* Fall through.  */\n#endif\n\nyyreturn:\n  if (yychar != YYEMPTY)\n     yydestruct (\"Cleanup: discarding lookahead\",\n\t\t yytoken, &yylval, &yylloc);\n  /* Do not reclaim the symbols of the rule which action triggered\n     this YYABORT or YYACCEPT.  */\n  YYPOPSTACK (yylen);\n  YY_STACK_PRINT (yyss, yyssp);\n  while (yyssp != yyss)\n    {\n      yydestruct (\"Cleanup: popping\",\n\t\t  yystos[*yyssp], yyvsp, yylsp);\n      YYPOPSTACK (1);\n    }\n#ifndef yyoverflow\n  if (yyss != yyssa)\n    YYSTACK_FREE (yyss);\n#endif\n#if YYERROR_VERBOSE\n  if (yymsg != yymsgbuf)\n    YYSTACK_FREE (yymsg);\n#endif\n  /* Make sure YYID is used.  */\n  return YYID (yyresult);\n}\n\n\n\n/* Line 1675 of yacc.c  */\n#line 576 \"../../src/parser.yy\"\n\n\n"
  },
  {
    "path": "utilities/gengetopt/parser.h",
    "content": "\n/* A Bison parser, made by GNU Bison 2.4.1.  */\n\n/* Skeleton interface for Bison's Yacc-like parsers in C\n\n      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006\n   Free Software Foundation, Inc.\n\n   This program is free software: you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation, either version 3 of the License, or\n   (at your option) any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n\n   You should have received a copy of the GNU General Public License\n   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */\n\n/* As a special exception, you may create a larger work that contains\n   part or all of the Bison parser skeleton and distribute that work\n   under terms of your choice, so long as that work isn't itself a\n   parser generator using the skeleton or a modified version thereof\n   as a parser skeleton.  Alternatively, if you modify or redistribute\n   the parser skeleton itself, you may (at your option) remove this\n   special exception, which will cause the skeleton and the resulting\n   Bison output files to be licensed under the GNU General Public\n   License without this special exception.\n\n   This special exception was added by the Free Software Foundation in\n   version 2.2 of Bison.  */\n\n\n/* Tokens.  */\n#ifndef YYTOKENTYPE\n# define YYTOKENTYPE\n   /* Put the tokens into the symbol table, so that GDB and other debuggers\n      know about them.  */\n   enum yytokentype {\n     TOK_PACKAGE = 258,\n     TOK_VERSION = 259,\n     TOK_OPTION = 260,\n     TOK_DEFGROUP = 261,\n     TOK_GROUPOPTION = 262,\n     TOK_DEFMODE = 263,\n     TOK_MODEOPTION = 264,\n     TOK_YES = 265,\n     TOK_NO = 266,\n     TOK_ON = 267,\n     TOK_OFF = 268,\n     TOK_FLAG = 269,\n     TOK_PURPOSE = 270,\n     TOK_DESCRIPTION = 271,\n     TOK_USAGE = 272,\n     TOK_DEFAULT = 273,\n     TOK_GROUP = 274,\n     TOK_GROUPDESC = 275,\n     TOK_MODE = 276,\n     TOK_MODEDESC = 277,\n     TOK_MULTIPLE = 278,\n     TOK_ARGOPTIONAL = 279,\n     TOK_TYPESTR = 280,\n     TOK_SECTION = 281,\n     TOK_DETAILS = 282,\n     TOK_SECTIONDESC = 283,\n     TOK_TEXT = 284,\n     TOK_ARGS = 285,\n     TOK_VALUES = 286,\n     TOK_HIDDEN = 287,\n     TOK_DEPENDON = 288,\n     TOK_STRING = 289,\n     TOK_CHAR = 290,\n     TOK_ARGTYPE = 291,\n     TOK_SIZE = 292\n   };\n#endif\n/* Tokens.  */\n#define TOK_PACKAGE 258\n#define TOK_VERSION 259\n#define TOK_OPTION 260\n#define TOK_DEFGROUP 261\n#define TOK_GROUPOPTION 262\n#define TOK_DEFMODE 263\n#define TOK_MODEOPTION 264\n#define TOK_YES 265\n#define TOK_NO 266\n#define TOK_ON 267\n#define TOK_OFF 268\n#define TOK_FLAG 269\n#define TOK_PURPOSE 270\n#define TOK_DESCRIPTION 271\n#define TOK_USAGE 272\n#define TOK_DEFAULT 273\n#define TOK_GROUP 274\n#define TOK_GROUPDESC 275\n#define TOK_MODE 276\n#define TOK_MODEDESC 277\n#define TOK_MULTIPLE 278\n#define TOK_ARGOPTIONAL 279\n#define TOK_TYPESTR 280\n#define TOK_SECTION 281\n#define TOK_DETAILS 282\n#define TOK_SECTIONDESC 283\n#define TOK_TEXT 284\n#define TOK_ARGS 285\n#define TOK_VALUES 286\n#define TOK_HIDDEN 287\n#define TOK_DEPENDON 288\n#define TOK_STRING 289\n#define TOK_CHAR 290\n#define TOK_ARGTYPE 291\n#define TOK_SIZE 292\n\n\n\n\n#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED\ntypedef union YYSTYPE\n{\n\n/* Line 1676 of yacc.c  */\n#line 148 \"../../src/parser.yy\"\n\n    char   *str;\n    char    chr;\n    int\t    argtype;\n    int\t    boolean;\n    class AcceptedValues *ValueList;\n    struct gengetopt_option *gengetopt_option;\n    struct multiple_size *multiple_size;\n\n\n\n/* Line 1676 of yacc.c  */\n#line 138 \"../../src/parser.h\"\n} YYSTYPE;\n# define YYSTYPE_IS_TRIVIAL 1\n# define yystype YYSTYPE /* obsolescent; will be withdrawn */\n# define YYSTYPE_IS_DECLARED 1\n#endif\n\nextern YYSTYPE yylval;\n\n#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED\ntypedef struct YYLTYPE\n{\n  int first_line;\n  int first_column;\n  int last_line;\n  int last_column;\n} YYLTYPE;\n# define yyltype YYLTYPE /* obsolescent; will be withdrawn */\n# define YYLTYPE_IS_DECLARED 1\n# define YYLTYPE_IS_TRIVIAL 1\n#endif\n\nextern YYLTYPE yylloc;\n\n"
  },
  {
    "path": "utilities/gengetopt/parser.yy",
    "content": "/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n\n\n%{\n\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <string>\n\n#include \"my_sstream.h\"\n\n#include \"acceptedvalues.h\"\n\n#include \"argsdef.h\"\n\n#include \"gengetopt.h\"\n#include \"errorcodes.h\"\n#include \"ggos.h\"\n#include \"yyerror.h\"\n\nextern int gengetopt_count_line;\nextern char * gengetopt_input_filename;\n\nstatic int gengetopt_package_given = 0;\nstatic int gengetopt_version_given = 0;\nstatic int gengetopt_purpose_given = 0;\nstatic int gengetopt_usage_given = 0;\nstatic int gengetopt_description_given = 0;\n\n/// the last option parsed\nstatic gengetopt_option *current_option = 0;\n\nextern int yylex (void) ;\n\n//#define YYERROR_VERBOSE 1\n\nvoid check_result(int o, gengetopt_option *opt)\n{\n  if (o)\n    {\n        ostringstream err;\n\n    switch (o)\n    {\n    case NOT_ENOUGH_MEMORY:\n        yyerror (opt, \"not enough memory\");\n    \tbreak;\n    case REQ_LONG_OPTION:\n        err << \"long option redefined \\'\" << opt->long_opt << \"\\'\";\n        yyerror (opt, err.str().c_str());\n\t\tbreak;\n    case REQ_SHORT_OPTION:\n        err << \"short option redefined \\'\" << opt->short_opt << \"\\'\";\n        yyerror (opt, err.str().c_str());\n        break;\n    case FOUND_BUG:\n        yyerror (opt, \"bug found!!\");\n        break;\n    case GROUP_UNDEFINED:\n        yyerror (opt, \"group undefined\");\n        break;\n    case MODE_UNDEFINED:\n        yyerror (opt, \"mode undefined\");\n        break;\n    case INVALID_DEFAULT_VALUE:\n        yyerror (opt, \"invalid default value\");\n        break;\n    case NOT_REQUESTED_TYPE:\n        yyerror (opt, \"type specification not requested\");\n        break;\n    case NOT_VALID_SPECIFICATION:\n      yyerror (opt, \"invalid specification for this kind of option\");\n      break;\n    case SPECIFY_FLAG_STAT:\n      yyerror (opt, \"you must specify the default flag status\");\n      break;\n    case NOT_GROUP_OPTION:\n      yyerror (opt, \"group specification for a non group option\");\n      break;\n    case NOT_MODE_OPTION:\n      yyerror (opt, \"mode specification for an option not belonging to a mode\");\n      break;\n    case SPECIFY_GROUP:\n      yyerror (opt, \"missing group specification\");\n      break;\n    case SPECIFY_MODE:\n      yyerror (opt, \"missing mode specification\");\n      break;\n    case INVALID_NUMERIC_VALUE:\n        yyerror (opt, \"invalid numeric value\");\n        break;\n    case INVALID_ENUM_TYPE_USE:\n    \tyyerror (opt, \"enum type can only be specified for options with values\");\n        break;\n    case HELP_REDEFINED:\n    \tyyerror (opt, \"if you want to redefine --help, please use option --no-help\");\n        break;\n    case VERSION_REDEFINED:\n    \tyyerror (opt, \"if you want to redefine --version, please use option --no-version\");\n        break;\n    }\n  }\n}\n\n/* the number of allowed occurrences of a multiple option */\nstruct multiple_size\n{\n    /* these strings are allocated dynamically and NOT\n      automatically freed upon destruction */\n    char *min;\n    char *max;\n\n    /* if no limit is specified then initialized to 0.\n       if the same size is specified for min and max, it means that an exact\n       number of occurrences is required*/\n    multiple_size(const char *m = \"0\", const char *M = \"0\") :\n        min(strdup(m)), max(strdup(M))\n    {}\n};\n\n#define check_error if (o) YYERROR;\n\n%}\n\n%union {\n    char   *str;\n    char    chr;\n    int\t    argtype;\n    int\t    boolean;\n    class AcceptedValues *ValueList;\n    struct gengetopt_option *gengetopt_option;\n    struct multiple_size *multiple_size;\n}\n\n%token\t\t    TOK_PACKAGE\t\t\"package\"\n%token              TOK_VERSION\t\t\"version\"\n%token              TOK_OPTION\t\t\"option\"\n%token              TOK_DEFGROUP\t\"defgroup\"\n%token              TOK_GROUPOPTION\t\"groupoption\"\n%token              TOK_DEFMODE\t\t\"defmode\"\n%token              TOK_MODEOPTION\t\"modeoption\"\n%token              TOK_YES\t\t\"yes\"\n%token              TOK_NO\t\t\"no\"\n%token              TOK_ON\t\t\"on\"\n%token              TOK_OFF\t\t\"off\"\n%token              TOK_FLAG\t\t\"flag\"\n%token              TOK_PURPOSE\t\t\"purpose\"\n%token              TOK_DESCRIPTION\t\"description\"\n%token              TOK_USAGE\t\t\"usage\"\n%token              TOK_DEFAULT\t\t\"default\"\n%token              TOK_GROUP\t\t\"group\"\n%token              TOK_GROUPDESC\t\"groupdesc\"\n%token              TOK_MODE\t\t\"mode\"\n%token              TOK_MODEDESC\t\"modedesc\"\n%token              TOK_MULTIPLE\t\"multiple\"\n%token              TOK_ARGOPTIONAL\t\"argoptional\"\n%token              TOK_TYPESTR\t\t\"typestr\"\n%token              TOK_SECTION\t\t\"section\"\n%token              TOK_DETAILS\t\t\"details\"\n%token              TOK_SECTIONDESC\t\"sectiondesc\"\n%token              TOK_TEXT    \t\"text\"\n%token              TOK_ARGS    \t\"args\"\n%token              TOK_VALUES          \"values\"\n%token              TOK_HIDDEN      \"hidden\"\n%token              TOK_DEPENDON      \"dependon\"\n%token <str>        TOK_STRING\n%token <chr>        TOK_CHAR\n%token <argtype>    TOK_ARGTYPE\n%token <str>        TOK_SIZE\n\n%type  <boolean>    req_onoff\n%type  <boolean>    opt_yesno optional_yesno\n%type  <str>        quoted_string\n%type  <str>        opt_groupdesc\n%type  <str>        opt_sectiondesc\n%type  <str>        opt_modedesc\n%type  <ValueList>  listofvalues\n%type  <str>        acceptedvalue\n%type  <gengetopt_option> option_parts\n%type  <multiple_size> multiple_size\n\n\n%% /* ====================================================================== */\n\n\ninput\n\t: /* empty */\n\t| statement input\n\t;\n\n\nstatement\n\t: package\n\t| version\n\t| args\n\t| purpose\n\t| description\n\t| usage\n\t| sectiondef\n\t| option\n\t| text\n\t| groupoption\n\t| groupdef\n\t| modeoption\n\t| modedef\n\t;\n\n\npackage\n\t: TOK_PACKAGE TOK_STRING\n\t    {\n\t      if (gengetopt_package_given)\n\t\t{\n\t\t  yyerror (\"package redefined\");\n\t\t  YYERROR;\n\t\t}\n\t      else\n\t\t{\n\t\t  gengetopt_package_given = 1;\n\t\t  if (gengetopt_define_package ($2))\n\t\t    {\n\t\t      yyerror (\"not enough memory\");\n\t\t      YYERROR;\n\t\t    }\n\t\t}\n\t    }\n\t;\n\nversion\n\t: TOK_VERSION TOK_STRING\n\t    {\n\t      if (gengetopt_version_given)\n\t\t{\n\t\t  yyerror (\"version redefined\");\n\t\t  YYERROR;\n\t\t}\n\t      else\n\t\t{\n\t\t  gengetopt_version_given = 1;\n\t\t  if (gengetopt_define_version ($2))\n\t\t    {\n\t\t      yyerror (\"not enough memory\");\n\t\t      YYERROR;\n\t\t    }\n\t\t}\n\t    }\n\t;\n\npurpose\n\t: TOK_PURPOSE quoted_string\n\t    {\n\t      if (gengetopt_purpose_given)\n\t\t{\n\t\t  yyerror (\"purpose redefined\");\n\t\t  YYERROR;\n\t\t}\n\t      else\n\t\t{\n\t\t  gengetopt_purpose_given = 1;\n\t\t  if (gengetopt_define_purpose ($2))\n\t\t    {\n\t\t      yyerror (\"not enough memory\");\n\t\t      YYERROR;\n\t\t    }\n\t\t}\n\t    }\n\t;\n\ndescription\n\t: TOK_DESCRIPTION quoted_string\n\t    {\n\t      if (gengetopt_description_given)\n\t\t{\n\t\t  yyerror (\"description redefined\");\n\t\t  YYERROR;\n\t\t}\n\t      else\n\t\t{\n\t\t  gengetopt_description_given = 1;\n\t\t  if (gengetopt_define_description ($2))\n\t\t    {\n\t\t      yyerror (\"not enough memory\");\n\t\t      YYERROR;\n\t\t    }\n\t\t}\n\t    }\n\t;\n\nusage\n  : TOK_USAGE quoted_string\n  {\n      if (gengetopt_usage_given)\n      {\n\t  yyerror (\"usage redefined\");\n\t  YYERROR;\n      }\n      else\n      {\n\t  gengetopt_usage_given = 1;\n\t  if (gengetopt_define_usage ($2))\n          {\n\t      yyerror (\"not enough memory\");\n\t      YYERROR;\n          }\n      }\n  }\n        ;\n\n\nsectiondef\n          : TOK_SECTION quoted_string opt_sectiondesc\n              {\n                gengetopt_set_section ($2, $3);\n              }\n          ;\n\ntext\n  : TOK_TEXT quoted_string\n            {\n            \tif (current_option) {\n            \t\tstd::string current_option_text;\n            \t\tif (current_option->text_after) {\n            \t\t\tcurrent_option_text = std::string(current_option->text_after) + $2;\n            \t\t\tcurrent_option->text_after = strdup(current_option_text.c_str());\n            \t\t} else {\n\t            \t\tcurrent_option->text_after = strdup($2);\n\t            \t}\n            \t} else {\n\t\t\t\t\tgengetopt_set_text($2);\n  \t\t\t\t}\n            }\n        ;\n\nargs\n  : TOK_ARGS TOK_STRING\n            {\n  gengetopt_set_args($2);\n            }\n        ;\n\ngroupdef\n\t: TOK_DEFGROUP TOK_STRING opt_groupdesc optional_yesno\n\t    {\n              if (gengetopt_add_group ($2, $3, $4))\n                {\n\t\t  \tyyerror (\"group redefined\");\n\t\t  \tYYERROR;\n\t\t  }\n\t    }\n\t;\n\nmodedef\n\t: TOK_DEFMODE TOK_STRING opt_modedesc\n\t    {\n              if (gengetopt_add_mode ($2, $3))\n                {\n\t\t  \tyyerror (\"mode redefined\");\n\t\t  \tYYERROR;\n\t\t  }\n\t    }\n\t;\n\noption\n\t: TOK_OPTION TOK_STRING TOK_CHAR quoted_string\n\t\toption_parts\n\t    {\n          $5->filename = gengetopt_input_filename;\n          $5->linenum = @1.first_line;\n\t      $5->long_opt = strdup($2);\n\t      if ($3 != '-')\n\t      \t$5->short_opt = $3;\n\t      $5->desc = strdup($4);\n\t      int o = gengetopt_check_option ($5, false);\n\t      check_result(o, $5);\n          check_error;\n\t      o = gengetopt_add_option ($5);\n\t      check_result(o, $5);\n\t      check_error;\n\t      current_option = $5;\n\t    }\n\t;\n\ngroupoption\n\t: TOK_GROUPOPTION TOK_STRING TOK_CHAR quoted_string\n                option_parts\n\t    {\n          $5->filename = gengetopt_input_filename;\n          $5->linenum = @1.first_line;\n\t      $5->long_opt = strdup($2);\n          if ($3 != '-')\n            $5->short_opt = $3;\n          $5->desc = strdup($4);\n          int o = gengetopt_check_option ($5, true);\n          check_result(o, $5);\n          check_error;\n          o = gengetopt_add_option ($5);\n          check_result(o, $5);\n          check_error;\n\t    }\n        ;\n\nmodeoption\n\t: TOK_MODEOPTION TOK_STRING TOK_CHAR quoted_string\n                option_parts\n\t    {\n          $5->filename = gengetopt_input_filename;\n          $5->linenum = @1.first_line;\n\t      $5->long_opt = strdup($2);\n          if ($3 != '-')\n            $5->short_opt = $3;\n          $5->desc = strdup($4);\n          int o = gengetopt_check_option ($5, false, true);\n          check_result(o, $5);\n          check_error;\n          o = gengetopt_add_option ($5);\n          check_result(o, $5);\n          check_error;\n\t    }\n        ;\n\n\n/* ---------------------------------------------------------------------- */\n\nquoted_string\n\t: TOK_STRING\n\t;\n\noption_parts: option_parts opt_yesno\n\t\t\t  {\n\t\t\t  \t$$ = $1;\n\t\t\t  \t$$->required = $2;\n\t\t\t  \t$$->required_set = true;\n\t\t\t  }\n\t\t\t| option_parts TOK_ARGTYPE\n\t\t\t  {\n\t\t\t  \t$$ = $1;\n\t\t\t  \t$$->type = $2;\n\t\t\t  }\n\t\t\t| option_parts TOK_TYPESTR '=' TOK_STRING\n\t\t\t  {\n\t\t\t  \t$$ = $1;\n\t\t\t  \t$$->type_str = strdup($4);\n\t\t\t  }\n\t\t\t| option_parts TOK_DETAILS '=' quoted_string\n\t\t\t  {\n\t\t\t  \t$$ = $1;\n\t\t\t  \t$$->details = strdup($4);\n\t\t\t  }\n\t\t\t| option_parts TOK_VALUES '=' listofvalues\n\t\t\t  {\n\t\t\t  \t$$ = $1;\n\t\t\t  \t$$->acceptedvalues = $4;\n\t\t\t  }\n\t\t\t| option_parts TOK_DEFAULT '=' TOK_STRING\n\t\t\t  {\n\t\t\t  \t$$ = $1;\n\t\t\t  \t$$->default_string = strdup($4);\n\t\t\t  }\n            | option_parts TOK_GROUP '=' TOK_STRING\n              {\n                $$ = $1;\n                $$->group_value = strdup($4);\n              }\n            | option_parts TOK_MODE '=' TOK_STRING\n              {\n                $$ = $1;\n                $$->mode_value = strdup($4);\n              }\n            | option_parts TOK_DEPENDON '=' TOK_STRING\n              {\n                $$ = $1;\n                $$->dependon = strdup($4);\n              }\n\t\t\t| option_parts TOK_ARGOPTIONAL\n\t\t\t  {\n\t\t\t  \t$$ = $1;\n\t\t\t  \t$$->arg_is_optional = true;\n\t\t\t  }\n\t\t\t| option_parts TOK_MULTIPLE multiple_size\n\t\t\t  {\n\t\t\t  \t$$ = $1;\n\t\t\t  \t$$->multiple = true;\n                $$->multiple_min = $3->min;\n                $$->multiple_max = $3->max;\n                delete $3;\n\t\t\t  }\n      | option_parts TOK_FLAG\n        {\n          $$ = $1;\n          $$->type = ARG_FLAG;\n        }\n      | option_parts TOK_HIDDEN\n        {\n          $$ = $1;\n          $$->hidden = true;\n        }\n      | option_parts req_onoff\n        {\n          $$ = $1;\n          $$->flagstat = $2;\n        }\n      | { $$ = new gengetopt_option; }\n      ;\n\nreq_onoff\n\t: TOK_ON\t{ $$ = 1; }\n\t| TOK_OFF\t{ $$ = 0; }\n\t;\n\noptional_yesno\n\t: /* empty */\t{ $$ = 0; }\n\t| TOK_YES\t{ $$ = 1; }\n\t| TOK_NO\t{ $$ = 0; }\n\t;\n\nopt_yesno\n    : TOK_YES   { $$ = 1; }\n    | TOK_NO    { $$ = 0; }\n    ;\n\nopt_groupdesc\n\t: /* empty */\t\t\t{ $$ = 0; }\n        | TOK_GROUPDESC '=' TOK_STRING\t{ $$ = $3; }\n\t;\n\nopt_modedesc\n\t: /* empty */\t\t\t{ $$ = 0; }\n        | TOK_MODEDESC '=' TOK_STRING\t{ $$ = $3; }\n\t;\n\nopt_sectiondesc\n        : /* empty */\t\t\t{ $$ = 0; }\n        | TOK_SECTIONDESC '=' TOK_STRING\t{ $$ = $3; }\n        ;\n\nlistofvalues\n        : acceptedvalue { $$ = new AcceptedValues; $$->insert($1); }\n        | listofvalues ',' acceptedvalue { $1->insert($3); $$ = $1; }\n        ;\n\nacceptedvalue\n        : TOK_STRING { $$ = $1; }\n        ;\n\nmultiple_size\n    : { $$ = new multiple_size; }\n    | '(' TOK_SIZE ')' { $$ = new multiple_size($2, $2); }\n    | '(' TOK_SIZE '-' ')' { $$ = new multiple_size($2, \"0\"); free($2); }\n    | '(' '-' TOK_SIZE  ')' { $$ = new multiple_size(\"0\", $3); free($3); }\n    | '(' TOK_SIZE '-' TOK_SIZE  ')' { $$ = new multiple_size($2, $4); free($2); free($4); }\n    ;\n\n%%\n"
  },
  {
    "path": "utilities/gengetopt/scanner.cc",
    "content": "#line 2 \"../../src/scanner.cc\"\n\n#line 4 \"../../src/scanner.cc\"\n\n#define  YY_INT_ALIGNED short int\n\n/* A lexical scanner generated by flex */\n\n#define FLEX_SCANNER\n#define YY_FLEX_MAJOR_VERSION 2\n#define YY_FLEX_MINOR_VERSION 5\n#define YY_FLEX_SUBMINOR_VERSION 35\n#if YY_FLEX_SUBMINOR_VERSION > 0\n#define FLEX_BETA\n#endif\n\n/* First, we deal with  platform-specific or compiler-specific issues. */\n\n/* begin standard C headers. */\n#include <stdio.h>\n#include <string.h>\n#include <errno.h>\n#include <stdlib.h>\n\n/* end standard C headers. */\n\n/* flex integer type definitions */\n\n#ifndef FLEXINT_H\n#define FLEXINT_H\n\n/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */\n\n#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n\n/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,\n * if you want the limit (max/min) macros for int types.\n */\n#ifndef __STDC_LIMIT_MACROS\n#define __STDC_LIMIT_MACROS 1\n#endif\n\n#include <inttypes.h>\ntypedef int8_t flex_int8_t;\ntypedef uint8_t flex_uint8_t;\ntypedef int16_t flex_int16_t;\ntypedef uint16_t flex_uint16_t;\ntypedef int32_t flex_int32_t;\ntypedef uint32_t flex_uint32_t;\n#else\ntypedef signed char flex_int8_t;\ntypedef short int flex_int16_t;\ntypedef int flex_int32_t;\ntypedef unsigned char flex_uint8_t;\ntypedef unsigned short int flex_uint16_t;\ntypedef unsigned int flex_uint32_t;\n\n/* Limits of integral types. */\n#ifndef INT8_MIN\n#define INT8_MIN               (-128)\n#endif\n#ifndef INT16_MIN\n#define INT16_MIN              (-32767-1)\n#endif\n#ifndef INT32_MIN\n#define INT32_MIN              (-2147483647-1)\n#endif\n#ifndef INT8_MAX\n#define INT8_MAX               (127)\n#endif\n#ifndef INT16_MAX\n#define INT16_MAX              (32767)\n#endif\n#ifndef INT32_MAX\n#define INT32_MAX              (2147483647)\n#endif\n#ifndef UINT8_MAX\n#define UINT8_MAX              (255U)\n#endif\n#ifndef UINT16_MAX\n#define UINT16_MAX             (65535U)\n#endif\n#ifndef UINT32_MAX\n#define UINT32_MAX             (4294967295U)\n#endif\n\n#endif /* ! C99 */\n\n#endif /* ! FLEXINT_H */\n\n#ifdef __cplusplus\n\n/* The \"const\" storage-class-modifier is valid. */\n#define YY_USE_CONST\n\n#else\t/* ! __cplusplus */\n\n/* C99 requires __STDC__ to be defined as 1. */\n#if defined (__STDC__)\n\n#define YY_USE_CONST\n\n#endif\t/* defined (__STDC__) */\n#endif\t/* ! __cplusplus */\n\n#ifdef YY_USE_CONST\n#define yyconst const\n#else\n#define yyconst\n#endif\n\n/* Returned upon end-of-file. */\n#define YY_NULL 0\n\n/* Promotes a possibly negative, possibly signed char to an unsigned\n * integer for use as an array index.  If the signed char is negative,\n * we want to instead treat it as an 8-bit unsigned char, hence the\n * double cast.\n */\n#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)\n\n/* Enter a start condition.  This macro really ought to take a parameter,\n * but we do it the disgusting crufty way forced on us by the ()-less\n * definition of BEGIN.\n */\n#define BEGIN (yy_start) = 1 + 2 *\n\n/* Translate the current start state into a value that can be later handed\n * to BEGIN to return to the state.  The YYSTATE alias is for lex\n * compatibility.\n */\n#define YY_START (((yy_start) - 1) / 2)\n#define YYSTATE YY_START\n\n/* Action number for EOF rule of a given start state. */\n#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)\n\n/* Special action meaning \"start processing a new file\". */\n#define YY_NEW_FILE yyrestart(yyin  )\n\n#define YY_END_OF_BUFFER_CHAR 0\n\n/* Size of default input buffer. */\n#ifndef YY_BUF_SIZE\n#ifdef __ia64__\n/* On IA-64, the buffer size is 16k, not 8k.\n * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.\n * Ditto for the __ia64__ case accordingly.\n */\n#define YY_BUF_SIZE 32768\n#else\n#define YY_BUF_SIZE 16384\n#endif /* __ia64__ */\n#endif\n\n/* The state buf must be large enough to hold one state per character in the main buffer.\n */\n#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))\n\n#ifndef YY_TYPEDEF_YY_BUFFER_STATE\n#define YY_TYPEDEF_YY_BUFFER_STATE\ntypedef struct yy_buffer_state *YY_BUFFER_STATE;\n#endif\n\nextern int yyleng;\n\nextern FILE *yyin, *yyout;\n\n#define EOB_ACT_CONTINUE_SCAN 0\n#define EOB_ACT_END_OF_FILE 1\n#define EOB_ACT_LAST_MATCH 2\n\n    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires\n     *       access to the local variable yy_act. Since yyless() is a macro, it would break\n     *       existing scanners that call yyless() from OUTSIDE yylex.\n     *       One obvious solution it to make yy_act a global. I tried that, and saw\n     *       a 5% performance hit in a non-yylineno scanner, because yy_act is\n     *       normally declared as a register variable-- so it is not worth it.\n     */\n    #define  YY_LESS_LINENO(n) \\\n            do { \\\n                int yyl;\\\n                for ( yyl = n; yyl < yyleng; ++yyl )\\\n                    if ( yytext[yyl] == '\\n' )\\\n                        --yylineno;\\\n            }while(0)\n\n/* Return all but the first \"n\" matched characters back to the input stream. */\n#define yyless(n) \\\n\tdo \\\n\t\t{ \\\n\t\t/* Undo effects of setting up yytext. */ \\\n        int yyless_macro_arg = (n); \\\n        YY_LESS_LINENO(yyless_macro_arg);\\\n\t\t*yy_cp = (yy_hold_char); \\\n\t\tYY_RESTORE_YY_MORE_OFFSET \\\n\t\t(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \\\n\t\tYY_DO_BEFORE_ACTION; /* set up yytext again */ \\\n\t\t} \\\n\twhile ( 0 )\n\n#define unput(c) yyunput( c, (yytext_ptr)  )\n\n#ifndef YY_TYPEDEF_YY_SIZE_T\n#define YY_TYPEDEF_YY_SIZE_T\ntypedef size_t yy_size_t;\n#endif\n\n#ifndef YY_STRUCT_YY_BUFFER_STATE\n#define YY_STRUCT_YY_BUFFER_STATE\nstruct yy_buffer_state\n\t{\n\tFILE *yy_input_file;\n\n\tchar *yy_ch_buf;\t\t/* input buffer */\n\tchar *yy_buf_pos;\t\t/* current position in input buffer */\n\n\t/* Size of input buffer in bytes, not including room for EOB\n\t * characters.\n\t */\n\tyy_size_t yy_buf_size;\n\n\t/* Number of characters read into yy_ch_buf, not including EOB\n\t * characters.\n\t */\n\tint yy_n_chars;\n\n\t/* Whether we \"own\" the buffer - i.e., we know we created it,\n\t * and can realloc() it to grow it, and should free() it to\n\t * delete it.\n\t */\n\tint yy_is_our_buffer;\n\n\t/* Whether this is an \"interactive\" input source; if so, and\n\t * if we're using stdio for input, then we want to use getc()\n\t * instead of fread(), to make sure we stop fetching input after\n\t * each newline.\n\t */\n\tint yy_is_interactive;\n\n\t/* Whether we're considered to be at the beginning of a line.\n\t * If so, '^' rules will be active on the next match, otherwise\n\t * not.\n\t */\n\tint yy_at_bol;\n\n    int yy_bs_lineno; /**< The line count. */\n    int yy_bs_column; /**< The column count. */\n\n\t/* Whether to try to fill the input buffer when we reach the\n\t * end of it.\n\t */\n\tint yy_fill_buffer;\n\n\tint yy_buffer_status;\n\n#define YY_BUFFER_NEW 0\n#define YY_BUFFER_NORMAL 1\n\t/* When an EOF's been seen but there's still some text to process\n\t * then we mark the buffer as YY_EOF_PENDING, to indicate that we\n\t * shouldn't try reading from the input source any more.  We might\n\t * still have a bunch of tokens to match, though, because of\n\t * possible backing-up.\n\t *\n\t * When we actually see the EOF, we change the status to \"new\"\n\t * (via yyrestart()), so that the user can continue scanning by\n\t * just pointing yyin at a new input file.\n\t */\n#define YY_BUFFER_EOF_PENDING 2\n\n\t};\n#endif /* !YY_STRUCT_YY_BUFFER_STATE */\n\n/* Stack of input buffers. */\nstatic size_t yy_buffer_stack_top = 0; /**< index of top of stack. */\nstatic size_t yy_buffer_stack_max = 0; /**< capacity of stack. */\nstatic YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */\n\n/* We provide macros for accessing buffer states in case in the\n * future we want to put the buffer states in a more general\n * \"scanner state\".\n *\n * Returns the top of the stack, or NULL.\n */\n#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \\\n                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \\\n                          : NULL)\n\n/* Same as previous macro, but useful when we know that the buffer stack is not\n * NULL or when we need an lvalue. For internal use only.\n */\n#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]\n\n/* yy_hold_char holds the character lost when yytext is formed. */\nstatic char yy_hold_char;\nstatic int yy_n_chars;\t\t/* number of characters read into yy_ch_buf */\nint yyleng;\n\n/* Points to current character in buffer. */\nstatic char *yy_c_buf_p = (char *) 0;\nstatic int yy_init = 0;\t\t/* whether we need to initialize */\nstatic int yy_start = 0;\t/* start state number */\n\n/* Flag which is used to allow yywrap()'s to do buffer switches\n * instead of setting up a fresh yyin.  A bit of a hack ...\n */\nstatic int yy_did_buffer_switch_on_eof;\n\nvoid yyrestart (FILE *input_file  );\nvoid yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );\nYY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );\nvoid yy_delete_buffer (YY_BUFFER_STATE b  );\nvoid yy_flush_buffer (YY_BUFFER_STATE b  );\nvoid yypush_buffer_state (YY_BUFFER_STATE new_buffer  );\nvoid yypop_buffer_state (void );\n\nstatic void yyensure_buffer_stack (void );\nstatic void yy_load_buffer_state (void );\nstatic void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );\n\n#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )\n\nYY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );\nYY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );\nYY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len  );\n\nvoid *yyalloc (yy_size_t  );\nvoid *yyrealloc (void *,yy_size_t  );\nvoid yyfree (void *  );\n\n#define yy_new_buffer yy_create_buffer\n\n#define yy_set_interactive(is_interactive) \\\n\t{ \\\n\tif ( ! YY_CURRENT_BUFFER ){ \\\n        yyensure_buffer_stack (); \\\n\t\tYY_CURRENT_BUFFER_LVALUE =    \\\n            yy_create_buffer(yyin,YY_BUF_SIZE ); \\\n\t} \\\n\tYY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \\\n\t}\n\n#define yy_set_bol(at_bol) \\\n\t{ \\\n\tif ( ! YY_CURRENT_BUFFER ){\\\n        yyensure_buffer_stack (); \\\n\t\tYY_CURRENT_BUFFER_LVALUE =    \\\n            yy_create_buffer(yyin,YY_BUF_SIZE ); \\\n\t} \\\n\tYY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \\\n\t}\n\n#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)\n\n/* Begin user sect3 */\n\n#define yywrap(n) 1\n#define YY_SKIP_YYWRAP\n\ntypedef unsigned char YY_CHAR;\n\nFILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;\n\ntypedef int yy_state_type;\n\nextern int yylineno;\n\nint yylineno = 1;\n\nextern char *yytext;\n#define yytext_ptr yytext\n\nstatic yy_state_type yy_get_previous_state (void );\nstatic yy_state_type yy_try_NUL_trans (yy_state_type current_state  );\nstatic int yy_get_next_buffer (void );\nstatic void yy_fatal_error (yyconst char msg[]  );\n\n/* Done after the current pattern has been matched and before the\n * corresponding action - sets up yytext.\n */\n#define YY_DO_BEFORE_ACTION \\\n\t(yytext_ptr) = yy_bp; \\\n\tyyleng = (size_t) (yy_cp - yy_bp); \\\n\t(yy_hold_char) = *yy_cp; \\\n\t*yy_cp = '\\0'; \\\n\t(yy_c_buf_p) = yy_cp;\n\n#define YY_NUM_RULES 62\n#define YY_END_OF_BUFFER 63\n/* This struct is not used in this scanner,\n   but its presence is necessary. */\nstruct yy_trans_info\n\t{\n\tflex_int32_t yy_verify;\n\tflex_int32_t yy_nxt;\n\t};\nstatic yyconst flex_int16_t yy_accept[246] =\n    {   0,\n        0,    0,    0,    0,    0,    0,   63,   61,   57,   59,\n       60,   56,   48,   58,   43,   42,   47,   41,   47,   47,\n       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,\n       47,   47,   47,   47,   47,   47,   62,   46,   44,   45,\n       55,   51,   55,   54,   55,   57,   59,   56,   58,    0,\n        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,\n       15,    0,   18,    0,    0,    0,    0,    0,    0,    0,\n        0,    0,    0,    0,    0,    0,   45,   51,   52,    0,\n       53,    0,   50,    0,    0,    0,    0,    0,    0,    0,\n        0,    0,    0,    0,    2,    0,    0,    0,   19,    0,\n\n        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,\n        0,   14,   49,    0,   40,    0,    0,    0,    0,    0,\n        0,    0,    9,   17,    0,    0,    0,    4,   28,    0,\n        0,    0,    0,    0,    0,    0,    0,   39,    0,    0,\n        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,\n        5,   25,    0,    0,    0,    0,    0,    0,    0,    0,\n        0,    0,    0,    3,    0,    0,   22,    0,    0,    0,\n        0,    0,    0,    0,    0,    0,    6,    0,    0,   36,\n        0,    0,    0,    0,    0,   16,    0,    0,    0,    0,\n        1,    0,   35,    0,    0,   23,    0,   30,    0,    0,\n\n       38,    0,    0,    0,    0,    0,    0,    0,    0,   10,\n       20,    0,   34,   24,   11,    0,   27,   37,    0,    0,\n        0,    0,    8,   29,    0,   31,    0,    0,    0,   26,\n        0,    0,    0,    0,    0,    0,    0,    7,   13,    0,\n       32,   21,   12,   33,    0\n    } ;\n\nstatic yyconst flex_int32_t yy_ec[256] =\n    {   0,\n        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,\n        1,    1,    4,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    5,    1,    6,    7,    1,    1,    1,    1,    8,\n        9,    1,    1,   10,   11,    1,    1,   12,   12,   12,\n       12,   12,   12,   12,   12,   12,   12,    1,    1,    1,\n       13,    1,   14,    1,   15,   15,   15,   15,   15,   15,\n       15,   15,   15,   15,   15,   15,   15,   15,   15,   15,\n       15,   15,   15,   15,   15,   15,   15,   15,   15,   15,\n        1,   16,    1,    1,    1,    1,   17,   18,   19,   20,\n\n       21,   22,   23,   24,   25,   15,   26,   27,   28,   29,\n       30,   31,   32,   33,   34,   35,   36,   37,   15,   38,\n       39,   15,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1\n    } ;\n\nstatic yyconst flex_int32_t yy_meta[40] =\n    {   0,\n        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1\n    } ;\n\nstatic yyconst flex_int16_t yy_base[250] =\n    {   0,\n        0,    0,   37,   47,   39,   57,  271,  272,  268,    0,\n      272,  264,  272,    0,  272,  272,  272,  272,  235,   32,\n      238,  239,  232,  239,  234,  232,   34,  231,   43,   30,\n      239,   47,   36,  225,   59,  237,  272,  272,  272,  245,\n      272,  253,  272,  272,   78,  253,    0,  249,    0,  230,\n       55,  216,  215,   61,  220,  229,  213,  218,  226,  218,\n      272,  222,  272,  208,  223,  208,  208,  220,  208,  204,\n      198,  204,  217,  206,  199,  197,  218,  226,  272,   64,\n      272,  199,  272,   58,   70,  206,  207,  208,  206,  195,\n      199,  204,  184,  199,  272,  195,  196,  181,  272,  190,\n\n      188,  182,  176,  176,  177,  184,  173,  186,  183,  169,\n      170,  272,  272,  172,  272,  166,  168,  170,  170,  165,\n      172,  169,  272,  272,  160,  163,  172,   75,   76,  167,\n      161,  173,  159,  163,  162,  151,  156,  272,  150,  162,\n      161,  156,  145,  152,  148,  157,  156,  150,  147,  152,\n      272,   79,  143,  141,  140,  148,  137,  136,  137,  142,\n      130,  130,  132,  272,  138,  125,  272,  125,  128,  132,\n      121,  119,  133,  123,  121,  117,  272,  129,  118,  272,\n      112,  118,  112,  110,  117,  126,  121,  120,  119,  110,\n      272,  105,  272,  108,  106,  272,  104,  272,  105,   98,\n\n      272,   98,   96,  112,  106,  109,  102,  105,   98,  272,\n      272,  104,  103,  272,  272,   93,  272,  272,   96,  101,\n       94,   91,  272,  272,   87,  272,   95,   98,   84,  272,\n       78,   84,   75,   69,   74,   71,   68,  272,  272,   66,\n      272,  272,  272,  272,  272,  109,  111,   78,   51\n    } ;\n\nstatic yyconst flex_int16_t yy_def[250] =\n    {   0,\n      245,    1,  246,  246,  247,  247,  245,  245,  245,  248,\n      245,  245,  245,  249,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  248,  245,  249,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,    0,  245,  245,  245,  245\n    } ;\n\nstatic yyconst flex_int16_t yy_nxt[312] =\n    {   0,\n        8,    9,   10,   11,   12,   13,   14,   15,    8,   16,\n       17,   17,   18,   17,   17,    8,   19,   17,   17,   20,\n       21,   22,   23,   24,   25,   17,   26,   27,   28,   29,\n       30,   17,   31,   32,   33,   34,   35,   17,   36,   37,\n       11,   42,   43,   14,   44,   38,   65,   39,   40,   37,\n       11,   49,   51,   14,   45,   38,   71,   39,   40,   42,\n       43,   52,   44,   59,   62,   66,   79,   68,   80,   60,\n       69,   63,   45,   64,   72,   74,   85,   91,   47,   75,\n       79,   70,   80,   81,  244,   86,  116,  114,   87,   88,\n       92,  115,  117,   82,  154,  156,  243,  118,  178,  242,\n\n      241,  155,  240,  239,  238,  157,   83,  237,  179,    8,\n        8,   41,   41,  236,  235,  234,  233,  232,  231,  230,\n      229,  228,  227,  112,   61,  226,  225,  224,  223,  222,\n      221,  220,  219,  218,  217,  216,  215,  214,  213,  212,\n      211,  210,  209,  208,  207,  206,  205,  204,  203,  202,\n      201,  200,  199,  198,  197,  196,  195,  194,  193,  192,\n      191,  190,  189,  188,  187,  186,  185,  184,  183,  182,\n      181,  180,  177,  176,  175,  174,  173,  172,  171,  170,\n      169,  168,  167,  166,  165,  164,  163,  162,  161,  160,\n      159,  158,  153,  152,  151,  150,  149,  148,  147,  146,\n\n      145,  144,  143,  142,  141,  140,  139,  138,  137,  136,\n      135,  134,  133,  132,  131,  130,  129,  128,  127,  126,\n      125,  124,  123,  122,  121,  120,  119,  113,   78,   77,\n      112,  111,  110,  109,  108,  107,  106,  105,  104,  103,\n      102,  101,  100,   99,   98,   97,   96,   95,   94,   93,\n       90,   89,   84,   48,   46,   78,   77,   76,   73,   67,\n       61,   58,   57,   56,   55,   54,   53,   50,   48,   46,\n      245,    7,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245\n    } ;\n\nstatic yyconst flex_int16_t yy_chk[312] =\n    {   0,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    3,\n        3,    5,    5,    3,    5,    3,   30,    3,    3,    4,\n        4,  249,   20,    4,    5,    4,   33,    4,    4,    6,\n        6,   20,    6,   27,   29,   30,   80,   32,   80,   27,\n       32,   29,    6,   29,   33,   35,   51,   54,  248,   35,\n       45,   32,   45,   45,  240,   51,   85,   84,   51,   51,\n       54,   84,   85,   45,  128,  129,  237,   85,  152,  236,\n\n      235,  128,  234,  233,  232,  129,   45,  231,  152,  246,\n      246,  247,  247,  229,  228,  227,  225,  222,  221,  220,\n      219,  216,  213,  212,  209,  208,  207,  206,  205,  204,\n      203,  202,  200,  199,  197,  195,  194,  192,  190,  189,\n      188,  187,  186,  185,  184,  183,  182,  181,  179,  178,\n      176,  175,  174,  173,  172,  171,  170,  169,  168,  166,\n      165,  163,  162,  161,  160,  159,  158,  157,  156,  155,\n      154,  153,  150,  149,  148,  147,  146,  145,  144,  143,\n      142,  141,  140,  139,  137,  136,  135,  134,  133,  132,\n      131,  130,  127,  126,  125,  122,  121,  120,  119,  118,\n\n      117,  116,  114,  111,  110,  109,  108,  107,  106,  105,\n      104,  103,  102,  101,  100,   98,   97,   96,   94,   93,\n       92,   91,   90,   89,   88,   87,   86,   82,   78,   77,\n       76,   75,   74,   73,   72,   71,   70,   69,   68,   67,\n       66,   65,   64,   62,   60,   59,   58,   57,   56,   55,\n       53,   52,   50,   48,   46,   42,   40,   36,   34,   31,\n       28,   26,   25,   24,   23,   22,   21,   19,   12,    9,\n        7,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n\n      245,  245,  245,  245,  245,  245,  245,  245,  245,  245,\n      245\n    } ;\n\n/* Table of booleans, true if rule could match eol. */\nstatic yyconst flex_int32_t yy_rule_can_match_eol[63] =\n    {   0,\n0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1,\n    0, 0, 0,     };\n\nstatic yy_state_type yy_last_accepting_state;\nstatic char *yy_last_accepting_cpos;\n\nextern int yy_flex_debug;\nint yy_flex_debug = 0;\n\n/* The intent behind this definition is that it'll catch\n * any uses of REJECT which flex missed.\n */\n#define REJECT reject_used_but_not_detected\n#define yymore() yymore_used_but_not_detected\n#define YY_MORE_ADJ 0\n#define YY_RESTORE_YY_MORE_OFFSET\nchar *yytext;\n#line 1 \"../../src/scanner.ll\"\n/**\n * Copyright (C) 1999-2007  Free Software Foundation, Inc.\n *\n * This file is part of GNU gengetopt\n *\n * GNU gengetopt is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 3, or (at your option)\n * any later version.\n *\n * GNU gengetopt is distributed in the hope that it will be useful, but\n * WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n * Public License for more details.\n *\n * You should have received a copy of the GNU General Public License along\n * with gengetopt; see the file COPYING. If not, write to the Free Software\n * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n */\n#line 23 \"../../src/scanner.ll\"\n#ifdef HAVE_CONFIG_H\n#include \"config.h\"\n#endif\n\n#include <string.h>\n\n#include \"argsdef.h\"\n#include \"parser.h\"\nextern int gengetopt_count_line;\n\n#include \"my_sstream.h\"\n\nstatic void update_count_line (char *str);\nstatic void updateTokenInfo (int pos);\n\n// the buffer for strings (possibly spanning more lines)\nstatic std::ostringstream buff;\n\nstatic void buffer(const char *s);\nstatic char *flush_buffer();\n\n#define LINEBUF_LEN 1024\n\n#define PUSH(s) yy_push_state(s);\n#define POP() yy_pop_state();\n\nint tokenpos = 0;\nchar linebuf[LINEBUF_LEN] ; /* current line */\n\n//#define DEBUG_SCANNER\n#ifdef DEBUG_SCANNER\n#include <iostream> // for debug\n#define DEB(s) std::cerr << s << std::endl;\n#define DEB2(s,s2) std::cerr << s << \": \" << s2 << std::endl;\n#else\n#define DEB(s)\n#define DEB2(s,s2)\n#endif\n\n\n#line 692 \"../../src/scanner.cc\"\n\n#define INITIAL 0\n#define SIZE_STATE 1\n#define STRING_STATE 2\n\n#ifndef YY_NO_UNISTD_H\n/* Special case for \"unistd.h\", since it is non-ANSI. We include it way\n * down here because we want the user's section 1 to have been scanned first.\n * The user has a chance to override it with an option.\n */\n#include <unistd.h>\n#endif\n\n#ifndef YY_EXTRA_TYPE\n#define YY_EXTRA_TYPE void *\n#endif\n\nstatic int yy_init_globals (void );\n\n/* Accessor methods to globals.\n   These are made visible to non-reentrant scanners for convenience. */\n\nint yylex_destroy (void );\n\nint yyget_debug (void );\n\nvoid yyset_debug (int debug_flag  );\n\nYY_EXTRA_TYPE yyget_extra (void );\n\nvoid yyset_extra (YY_EXTRA_TYPE user_defined  );\n\nFILE *yyget_in (void );\n\nvoid yyset_in  (FILE * in_str  );\n\nFILE *yyget_out (void );\n\nvoid yyset_out  (FILE * out_str  );\n\nint yyget_leng (void );\n\nchar *yyget_text (void );\n\nint yyget_lineno (void );\n\nvoid yyset_lineno (int line_number  );\n\n/* Macros after this point can all be overridden by user definitions in\n * section 1.\n */\n\n#ifndef YY_SKIP_YYWRAP\n#ifdef __cplusplus\nextern \"C\" int yywrap (void );\n#else\nextern int yywrap (void );\n#endif\n#endif\n\n#ifndef yytext_ptr\nstatic void yy_flex_strncpy (char *,yyconst char *,int );\n#endif\n\n#ifdef YY_NEED_STRLEN\nstatic int yy_flex_strlen (yyconst char * );\n#endif\n\n#ifndef YY_NO_INPUT\n\n#ifdef __cplusplus\nstatic int yyinput (void );\n#else\nstatic int input (void );\n#endif\n\n#endif\n\n        static int yy_start_stack_ptr = 0;\n        static int yy_start_stack_depth = 0;\n        static int *yy_start_stack = NULL;\n\n    static void yy_push_state (int new_state );\n\n    static void yy_pop_state (void );\n\n    static int yy_top_state (void );\n\n/* Amount of stuff to slurp up with each read. */\n#ifndef YY_READ_BUF_SIZE\n#ifdef __ia64__\n/* On IA-64, the buffer size is 16k, not 8k */\n#define YY_READ_BUF_SIZE 16384\n#else\n#define YY_READ_BUF_SIZE 8192\n#endif /* __ia64__ */\n#endif\n\n/* Copy whatever the last rule matched to the standard output. */\n#ifndef ECHO\n/* This used to be an fputs(), but since the string might contain NUL's,\n * we now use fwrite().\n */\n#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)\n#endif\n\n/* Gets input and stuffs it into \"buf\".  number of characters read, or YY_NULL,\n * is returned in \"result\".\n */\n#ifndef YY_INPUT\n#define YY_INPUT(buf,result,max_size) \\\n\tif ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \\\n\t\t{ \\\n\t\tint c = '*'; \\\n\t\tsize_t n; \\\n\t\tfor ( n = 0; n < max_size && \\\n\t\t\t     (c = getc( yyin )) != EOF && c != '\\n'; ++n ) \\\n\t\t\tbuf[n] = (char) c; \\\n\t\tif ( c == '\\n' ) \\\n\t\t\tbuf[n++] = (char) c; \\\n\t\tif ( c == EOF && ferror( yyin ) ) \\\n\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\\n\t\tresult = n; \\\n\t\t} \\\n\telse \\\n\t\t{ \\\n\t\terrno=0; \\\n\t\twhile ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \\\n\t\t\t{ \\\n\t\t\tif( errno != EINTR) \\\n\t\t\t\t{ \\\n\t\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\\n\t\t\t\tbreak; \\\n\t\t\t\t} \\\n\t\t\terrno=0; \\\n\t\t\tclearerr(yyin); \\\n\t\t\t} \\\n\t\t}\\\n\\\n\n#endif\n\n/* No semi-colon after return; correct usage is to write \"yyterminate();\" -\n * we don't want an extra ';' after the \"return\" because that will cause\n * some compilers to complain about unreachable statements.\n */\n#ifndef yyterminate\n#define yyterminate() return YY_NULL\n#endif\n\n/* Number of entries by which start-condition stack grows. */\n#ifndef YY_START_STACK_INCR\n#define YY_START_STACK_INCR 25\n#endif\n\n/* Report a fatal error. */\n#ifndef YY_FATAL_ERROR\n#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )\n#endif\n\n/* end tables serialization structures and prototypes */\n\n/* Default declaration of generated scanner - a define so the user can\n * easily add parameters.\n */\n#ifndef YY_DECL\n#define YY_DECL_IS_OURS 1\n\nextern int yylex (void);\n\n#define YY_DECL int yylex (void)\n#endif /* !YY_DECL */\n\n/* Code executed at the beginning of each rule, after yytext and yyleng\n * have been set up.\n */\n#ifndef YY_USER_ACTION\n#define YY_USER_ACTION\n#endif\n\n/* Code executed at the end of each rule. */\n#ifndef YY_BREAK\n#define YY_BREAK break;\n#endif\n\n#define YY_RULE_SETUP \\\n\tYY_USER_ACTION\n\n/** The main scanner function which does all the work.\n */\nYY_DECL\n{\n\tyy_state_type yy_current_state;\n\tchar *yy_cp, *yy_bp;\n\tint yy_act;\n\n#line 71 \"../../src/scanner.ll\"\n\n\n\n#line 893 \"../../src/scanner.cc\"\n\n\tif ( !(yy_init) )\n\t\t{\n\t\t(yy_init) = 1;\n\n#ifdef YY_USER_INIT\n\t\tYY_USER_INIT;\n#endif\n\n\t\tif ( ! (yy_start) )\n\t\t\t(yy_start) = 1;\t/* first start state */\n\n\t\tif ( ! yyin )\n\t\t\tyyin = stdin;\n\n\t\tif ( ! yyout )\n\t\t\tyyout = stdout;\n\n\t\tif ( ! YY_CURRENT_BUFFER ) {\n\t\t\tyyensure_buffer_stack ();\n\t\t\tYY_CURRENT_BUFFER_LVALUE =\n\t\t\t\tyy_create_buffer(yyin,YY_BUF_SIZE );\n\t\t}\n\n\t\tyy_load_buffer_state( );\n\t\t}\n\n\twhile ( 1 )\t\t/* loops until end-of-file is reached */\n\t\t{\n\t\tyy_cp = (yy_c_buf_p);\n\n\t\t/* Support of yytext. */\n\t\t*yy_cp = (yy_hold_char);\n\n\t\t/* yy_bp points to the position in yy_ch_buf of the start of\n\t\t * the current run.\n\t\t */\n\t\tyy_bp = yy_cp;\n\n\t\tyy_current_state = (yy_start);\nyy_match:\n\t\tdo\n\t\t\t{\n\t\t\tYY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];\n\t\t\tif ( yy_accept[yy_current_state] )\n\t\t\t\t{\n\t\t\t\t(yy_last_accepting_state) = yy_current_state;\n\t\t\t\t(yy_last_accepting_cpos) = yy_cp;\n\t\t\t\t}\n\t\t\twhile ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )\n\t\t\t\t{\n\t\t\t\tyy_current_state = (int) yy_def[yy_current_state];\n\t\t\t\tif ( yy_current_state >= 246 )\n\t\t\t\t\tyy_c = yy_meta[(unsigned int) yy_c];\n\t\t\t\t}\n\t\t\tyy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];\n\t\t\t++yy_cp;\n\t\t\t}\n\t\twhile ( yy_base[yy_current_state] != 272 );\n\nyy_find_action:\n\t\tyy_act = yy_accept[yy_current_state];\n\t\tif ( yy_act == 0 )\n\t\t\t{ /* have to back up */\n\t\t\tyy_cp = (yy_last_accepting_cpos);\n\t\t\tyy_current_state = (yy_last_accepting_state);\n\t\t\tyy_act = yy_accept[yy_current_state];\n\t\t\t}\n\n\t\tYY_DO_BEFORE_ACTION;\n\n\t\tif ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )\n\t\t\t{\n\t\t\tint yyl;\n\t\t\tfor ( yyl = 0; yyl < yyleng; ++yyl )\n\t\t\t\tif ( yytext[yyl] == '\\n' )\n\t\t\t\t\t\n    yylineno++;\n;\n\t\t\t}\n\ndo_action:\t/* This label is used only to access EOF actions. */\n\n\t\tswitch ( yy_act )\n\t{ /* beginning of action switch */\n\t\t\tcase 0: /* must back up */\n\t\t\t/* undo the effects of YY_DO_BEFORE_ACTION */\n\t\t\t*yy_cp = (yy_hold_char);\n\t\t\tyy_cp = (yy_last_accepting_cpos);\n\t\t\tyy_current_state = (yy_last_accepting_state);\n\t\t\tgoto yy_find_action;\n\ncase 1:\nYY_RULE_SETUP\n#line 74 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_STRING; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 2:\nYY_RULE_SETUP\n#line 75 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_INT; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 3:\nYY_RULE_SETUP\n#line 76 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_SHORT; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 4:\nYY_RULE_SETUP\n#line 77 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_LONG; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 5:\nYY_RULE_SETUP\n#line 78 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_FLOAT; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 6:\nYY_RULE_SETUP\n#line 79 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_DOUBLE; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 7:\nYY_RULE_SETUP\n#line 80 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_LONGDOUBLE; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 8:\nYY_RULE_SETUP\n#line 81 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_LONGLONG; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 9:\nYY_RULE_SETUP\n#line 82 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.argtype = ARG_ENUM; return TOK_ARGTYPE;\n\tYY_BREAK\ncase 10:\nYY_RULE_SETUP\n#line 84 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_PACKAGE;\n\tYY_BREAK\ncase 11:\nYY_RULE_SETUP\n#line 85 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_VERSION;\n\tYY_BREAK\ncase 12:\nYY_RULE_SETUP\n#line 86 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_GROUPOPTION;\n\tYY_BREAK\ncase 13:\nYY_RULE_SETUP\n#line 87 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_MODEOPTION;\n\tYY_BREAK\ncase 14:\nYY_RULE_SETUP\n#line 88 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_YES;\n\tYY_BREAK\ncase 15:\nYY_RULE_SETUP\n#line 89 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_NO;\n\tYY_BREAK\ncase 16:\nYY_RULE_SETUP\n#line 90 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylloc.first_line = gengetopt_count_line; return TOK_OPTION;\n\tYY_BREAK\ncase 17:\nYY_RULE_SETUP\n#line 91 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_FLAG;\n\tYY_BREAK\ncase 18:\nYY_RULE_SETUP\n#line 92 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_ON;\n\tYY_BREAK\ncase 19:\nYY_RULE_SETUP\n#line 93 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_OFF;\n\tYY_BREAK\ncase 20:\nYY_RULE_SETUP\n#line 94 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_PURPOSE;\n\tYY_BREAK\ncase 21:\nYY_RULE_SETUP\n#line 95 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_DESCRIPTION;\n\tYY_BREAK\ncase 22:\nYY_RULE_SETUP\n#line 96 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_USAGE;\n\tYY_BREAK\ncase 23:\nYY_RULE_SETUP\n#line 97 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_DEFAULT;\n\tYY_BREAK\ncase 24:\nYY_RULE_SETUP\n#line 98 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_TYPESTR;\n\tYY_BREAK\ncase 25:\nYY_RULE_SETUP\n#line 99 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_GROUP;\n\tYY_BREAK\ncase 26:\nYY_RULE_SETUP\n#line 100 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_GROUPDESC;\n\tYY_BREAK\ncase 27:\nYY_RULE_SETUP\n#line 101 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_DEFGROUP;\n\tYY_BREAK\ncase 28:\nYY_RULE_SETUP\n#line 102 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_MODE;\n\tYY_BREAK\ncase 29:\nYY_RULE_SETUP\n#line 103 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_MODEDESC;\n\tYY_BREAK\ncase 30:\nYY_RULE_SETUP\n#line 104 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_DEFMODE;\n\tYY_BREAK\ncase 31:\nYY_RULE_SETUP\n#line 105 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_MULTIPLE;\n\tYY_BREAK\ncase 32:\nYY_RULE_SETUP\n#line 106 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_ARGOPTIONAL;\n\tYY_BREAK\ncase 33:\nYY_RULE_SETUP\n#line 107 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_SECTIONDESC;\n\tYY_BREAK\ncase 34:\nYY_RULE_SETUP\n#line 108 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_SECTION;\n\tYY_BREAK\ncase 35:\nYY_RULE_SETUP\n#line 109 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_VALUES;\n\tYY_BREAK\ncase 36:\nYY_RULE_SETUP\n#line 110 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_HIDDEN;\n\tYY_BREAK\ncase 37:\nYY_RULE_SETUP\n#line 111 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_DEPENDON;\n\tYY_BREAK\ncase 38:\nYY_RULE_SETUP\n#line 112 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_DETAILS;\n\tYY_BREAK\ncase 39:\nYY_RULE_SETUP\n#line 113 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_TEXT;\n\tYY_BREAK\ncase 40:\nYY_RULE_SETUP\n#line 114 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); return TOK_ARGS;\n\tYY_BREAK\ncase 41:\nYY_RULE_SETUP\n#line 116 \"../../src/scanner.ll\"\n{ updateTokenInfo (-1); return '='; }\n\tYY_BREAK\ncase 42:\nYY_RULE_SETUP\n#line 117 \"../../src/scanner.ll\"\n{ updateTokenInfo (-1); return ','; }\n\tYY_BREAK\ncase 43:\nYY_RULE_SETUP\n#line 119 \"../../src/scanner.ll\"\n{ PUSH(SIZE_STATE); updateTokenInfo (-1); return '('; }\n\tYY_BREAK\ncase 44:\nYY_RULE_SETUP\n#line 120 \"../../src/scanner.ll\"\n{ updateTokenInfo (-1); return '-'; }\n\tYY_BREAK\ncase 45:\nYY_RULE_SETUP\n#line 121 \"../../src/scanner.ll\"\n{ updateTokenInfo (-1); yylval.str = strdup(yytext); return TOK_SIZE; }\n\tYY_BREAK\ncase 46:\nYY_RULE_SETUP\n#line 122 \"../../src/scanner.ll\"\n{ POP(); updateTokenInfo (-1); return ')'; }\n\tYY_BREAK\ncase 47:\nYY_RULE_SETUP\n#line 124 \"../../src/scanner.ll\"\nupdateTokenInfo (-1); yylval.chr = yytext[0]; return TOK_CHAR;\n\tYY_BREAK\ncase 48:\nYY_RULE_SETUP\n#line 126 \"../../src/scanner.ll\"\n{ updateTokenInfo (-1); DEB(\"start string\"); PUSH(STRING_STATE) ; }\n\tYY_BREAK\ncase 49:\nYY_RULE_SETUP\n#line 127 \"../../src/scanner.ll\"\n{ updateTokenInfo (2); buffer(\"\\\\\\\\n\"); }\n\tYY_BREAK\ncase 50:\nYY_RULE_SETUP\n#line 128 \"../../src/scanner.ll\"\n{ updateTokenInfo (1); buffer(\"\\n\"); }\n\tYY_BREAK\ncase 51:\n/* rule 51 can match eol */\nYY_RULE_SETUP\n#line 129 \"../../src/scanner.ll\"\n{  update_count_line (yytext); buffer( yytext ) ; }\n\tYY_BREAK\ncase 52:\n/* rule 52 can match eol */\nYY_RULE_SETUP\n#line 130 \"../../src/scanner.ll\"\n{ update_count_line (yytext); /* a line break */ }\n\tYY_BREAK\ncase 53:\nYY_RULE_SETUP\n#line 131 \"../../src/scanner.ll\"\n{ updateTokenInfo (-1); buffer(yytext); }\n\tYY_BREAK\ncase 54:\nYY_RULE_SETUP\n#line 132 \"../../src/scanner.ll\"\n{ updateTokenInfo (-1); DEB(\"end string\"); POP() ; yylval.str = flush_buffer(); return TOK_STRING; }\n\tYY_BREAK\ncase 55:\nYY_RULE_SETUP\n#line 133 \"../../src/scanner.ll\"\n{  updateTokenInfo (-1); buffer( yytext ) ; }\n\tYY_BREAK\ncase 56:\nYY_RULE_SETUP\n#line 135 \"../../src/scanner.ll\"\nupdateTokenInfo (-1);\n\tYY_BREAK\ncase 57:\nYY_RULE_SETUP\n#line 136 \"../../src/scanner.ll\"\nupdateTokenInfo (8*yyleng);\n\tYY_BREAK\ncase 58:\nYY_RULE_SETUP\n#line 138 \"../../src/scanner.ll\"\n/* comments begin with # in any place (but strings) */\n\tYY_BREAK\ncase 59:\n/* rule 59 can match eol */\nYY_RULE_SETUP\n#line 139 \"../../src/scanner.ll\"\nupdate_count_line (0); yyless(1) ; /* give back all but the \\n to rescan */\n\tYY_BREAK\ncase 60:\nYY_RULE_SETUP\n#line 141 \"../../src/scanner.ll\"\n{}\n\tYY_BREAK\ncase 61:\nYY_RULE_SETUP\n#line 143 \"../../src/scanner.ll\"\n{\n  return 1000; /* little hack to produce a parse error too. */\n}\n\tYY_BREAK\ncase 62:\nYY_RULE_SETUP\n#line 147 \"../../src/scanner.ll\"\nECHO;\n\tYY_BREAK\n#line 1301 \"../../src/scanner.cc\"\ncase YY_STATE_EOF(INITIAL):\ncase YY_STATE_EOF(SIZE_STATE):\ncase YY_STATE_EOF(STRING_STATE):\n\tyyterminate();\n\n\tcase YY_END_OF_BUFFER:\n\t\t{\n\t\t/* Amount of text matched not including the EOB char. */\n\t\tint yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;\n\n\t\t/* Undo the effects of YY_DO_BEFORE_ACTION. */\n\t\t*yy_cp = (yy_hold_char);\n\t\tYY_RESTORE_YY_MORE_OFFSET\n\n\t\tif ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )\n\t\t\t{\n\t\t\t/* We're scanning a new file or input source.  It's\n\t\t\t * possible that this happened because the user\n\t\t\t * just pointed yyin at a new source and called\n\t\t\t * yylex().  If so, then we have to assure\n\t\t\t * consistency between YY_CURRENT_BUFFER and our\n\t\t\t * globals.  Here is the right place to do so, because\n\t\t\t * this is the first action (other than possibly a\n\t\t\t * back-up) that will match for the new input source.\n\t\t\t */\n\t\t\t(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;\n\t\t\t}\n\n\t\t/* Note that here we test for yy_c_buf_p \"<=\" to the position\n\t\t * of the first EOB in the buffer, since yy_c_buf_p will\n\t\t * already have been incremented past the NUL character\n\t\t * (since all states make transitions on EOB to the\n\t\t * end-of-buffer state).  Contrast this with the test\n\t\t * in input().\n\t\t */\n\t\tif ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )\n\t\t\t{ /* This was really a NUL. */\n\t\t\tyy_state_type yy_next_state;\n\n\t\t\t(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;\n\n\t\t\tyy_current_state = yy_get_previous_state(  );\n\n\t\t\t/* Okay, we're now positioned to make the NUL\n\t\t\t * transition.  We couldn't have\n\t\t\t * yy_get_previous_state() go ahead and do it\n\t\t\t * for us because it doesn't know how to deal\n\t\t\t * with the possibility of jamming (and we don't\n\t\t\t * want to build jamming into it because then it\n\t\t\t * will run more slowly).\n\t\t\t */\n\n\t\t\tyy_next_state = yy_try_NUL_trans( yy_current_state );\n\n\t\t\tyy_bp = (yytext_ptr) + YY_MORE_ADJ;\n\n\t\t\tif ( yy_next_state )\n\t\t\t\t{\n\t\t\t\t/* Consume the NUL. */\n\t\t\t\tyy_cp = ++(yy_c_buf_p);\n\t\t\t\tyy_current_state = yy_next_state;\n\t\t\t\tgoto yy_match;\n\t\t\t\t}\n\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tyy_cp = (yy_c_buf_p);\n\t\t\t\tgoto yy_find_action;\n\t\t\t\t}\n\t\t\t}\n\n\t\telse switch ( yy_get_next_buffer(  ) )\n\t\t\t{\n\t\t\tcase EOB_ACT_END_OF_FILE:\n\t\t\t\t{\n\t\t\t\t(yy_did_buffer_switch_on_eof) = 0;\n\n\t\t\t\tif ( yywrap( ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* Note: because we've taken care in\n\t\t\t\t\t * yy_get_next_buffer() to have set up\n\t\t\t\t\t * yytext, we can now set up\n\t\t\t\t\t * yy_c_buf_p so that if some total\n\t\t\t\t\t * hoser (like flex itself) wants to\n\t\t\t\t\t * call the scanner after we return the\n\t\t\t\t\t * YY_NULL, it'll still work - another\n\t\t\t\t\t * YY_NULL will get returned.\n\t\t\t\t\t */\n\t\t\t\t\t(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;\n\n\t\t\t\t\tyy_act = YY_STATE_EOF(YY_START);\n\t\t\t\t\tgoto do_action;\n\t\t\t\t\t}\n\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif ( ! (yy_did_buffer_switch_on_eof) )\n\t\t\t\t\t\tYY_NEW_FILE;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase EOB_ACT_CONTINUE_SCAN:\n\t\t\t\t(yy_c_buf_p) =\n\t\t\t\t\t(yytext_ptr) + yy_amount_of_matched_text;\n\n\t\t\t\tyy_current_state = yy_get_previous_state(  );\n\n\t\t\t\tyy_cp = (yy_c_buf_p);\n\t\t\t\tyy_bp = (yytext_ptr) + YY_MORE_ADJ;\n\t\t\t\tgoto yy_match;\n\n\t\t\tcase EOB_ACT_LAST_MATCH:\n\t\t\t\t(yy_c_buf_p) =\n\t\t\t\t&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];\n\n\t\t\t\tyy_current_state = yy_get_previous_state(  );\n\n\t\t\t\tyy_cp = (yy_c_buf_p);\n\t\t\t\tyy_bp = (yytext_ptr) + YY_MORE_ADJ;\n\t\t\t\tgoto yy_find_action;\n\t\t\t}\n\t\tbreak;\n\t\t}\n\n\tdefault:\n\t\tYY_FATAL_ERROR(\n\t\t\t\"fatal flex scanner internal error--no action found\" );\n\t} /* end of action switch */\n\t\t} /* end of scanning one token */\n} /* end of yylex */\n\n/* yy_get_next_buffer - try to read in a new buffer\n *\n * Returns a code representing an action:\n *\tEOB_ACT_LAST_MATCH -\n *\tEOB_ACT_CONTINUE_SCAN - continue scanning from current position\n *\tEOB_ACT_END_OF_FILE - end of file\n */\nstatic int yy_get_next_buffer (void)\n{\n    \tchar *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;\n\tchar *source = (yytext_ptr);\n\tint number_to_move, i;\n\tint ret_val;\n\n\tif ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )\n\t\tYY_FATAL_ERROR(\n\t\t\"fatal flex scanner internal error--end of buffer missed\" );\n\n\tif ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )\n\t\t{ /* Don't try to fill the buffer, so this is an EOF. */\n\t\tif ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )\n\t\t\t{\n\t\t\t/* We matched a single character, the EOB, so\n\t\t\t * treat this as a final EOF.\n\t\t\t */\n\t\t\treturn EOB_ACT_END_OF_FILE;\n\t\t\t}\n\n\t\telse\n\t\t\t{\n\t\t\t/* We matched some text prior to the EOB, first\n\t\t\t * process it.\n\t\t\t */\n\t\t\treturn EOB_ACT_LAST_MATCH;\n\t\t\t}\n\t\t}\n\n\t/* Try to read more data. */\n\n\t/* First move last chars to start of buffer. */\n\tnumber_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;\n\n\tfor ( i = 0; i < number_to_move; ++i )\n\t\t*(dest++) = *(source++);\n\n\tif ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )\n\t\t/* don't do the read, it's not guaranteed to return an EOF,\n\t\t * just force an EOF\n\t\t */\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;\n\n\telse\n\t\t{\n\t\t\tint num_to_read =\n\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;\n\n\t\twhile ( num_to_read <= 0 )\n\t\t\t{ /* Not enough room in the buffer - grow it. */\n\n\t\t\t/* just a shorter name for the current buffer */\n\t\t\tYY_BUFFER_STATE b = YY_CURRENT_BUFFER;\n\n\t\t\tint yy_c_buf_p_offset =\n\t\t\t\t(int) ((yy_c_buf_p) - b->yy_ch_buf);\n\n\t\t\tif ( b->yy_is_our_buffer )\n\t\t\t\t{\n\t\t\t\tint new_size = b->yy_buf_size * 2;\n\n\t\t\t\tif ( new_size <= 0 )\n\t\t\t\t\tb->yy_buf_size += b->yy_buf_size / 8;\n\t\t\t\telse\n\t\t\t\t\tb->yy_buf_size *= 2;\n\n\t\t\t\tb->yy_ch_buf = (char *)\n\t\t\t\t\t/* Include room in for 2 EOB chars. */\n\t\t\t\t\tyyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t/* Can't grow it, we don't own it. */\n\t\t\t\tb->yy_ch_buf = 0;\n\n\t\t\tif ( ! b->yy_ch_buf )\n\t\t\t\tYY_FATAL_ERROR(\n\t\t\t\t\"fatal error - scanner input buffer overflow\" );\n\n\t\t\t(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];\n\n\t\t\tnum_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -\n\t\t\t\t\t\tnumber_to_move - 1;\n\n\t\t\t}\n\n\t\tif ( num_to_read > YY_READ_BUF_SIZE )\n\t\t\tnum_to_read = YY_READ_BUF_SIZE;\n\n\t\t/* Read in more data. */\n\t\tYY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),\n\t\t\t(yy_n_chars), (size_t) num_to_read );\n\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);\n\t\t}\n\n\tif ( (yy_n_chars) == 0 )\n\t\t{\n\t\tif ( number_to_move == YY_MORE_ADJ )\n\t\t\t{\n\t\t\tret_val = EOB_ACT_END_OF_FILE;\n\t\t\tyyrestart(yyin  );\n\t\t\t}\n\n\t\telse\n\t\t\t{\n\t\t\tret_val = EOB_ACT_LAST_MATCH;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->yy_buffer_status =\n\t\t\t\tYY_BUFFER_EOF_PENDING;\n\t\t\t}\n\t\t}\n\n\telse\n\t\tret_val = EOB_ACT_CONTINUE_SCAN;\n\n\tif ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {\n\t\t/* Extend the array by 50%, plus the number we really need. */\n\t\tyy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );\n\t\tif ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in yy_get_next_buffer()\" );\n\t}\n\n\t(yy_n_chars) += number_to_move;\n\tYY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;\n\tYY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;\n\n\t(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];\n\n\treturn ret_val;\n}\n\n/* yy_get_previous_state - get the state just before the EOB char was reached */\n\n    static yy_state_type yy_get_previous_state (void)\n{\n\tyy_state_type yy_current_state;\n\tchar *yy_cp;\n\n\tyy_current_state = (yy_start);\n\n\tfor ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )\n\t\t{\n\t\tYY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);\n\t\tif ( yy_accept[yy_current_state] )\n\t\t\t{\n\t\t\t(yy_last_accepting_state) = yy_current_state;\n\t\t\t(yy_last_accepting_cpos) = yy_cp;\n\t\t\t}\n\t\twhile ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )\n\t\t\t{\n\t\t\tyy_current_state = (int) yy_def[yy_current_state];\n\t\t\tif ( yy_current_state >= 246 )\n\t\t\t\tyy_c = yy_meta[(unsigned int) yy_c];\n\t\t\t}\n\t\tyy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];\n\t\t}\n\n\treturn yy_current_state;\n}\n\n/* yy_try_NUL_trans - try to make a transition on the NUL character\n *\n * synopsis\n *\tnext_state = yy_try_NUL_trans( current_state );\n */\n    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )\n{\n\tint yy_is_jam;\n    \tchar *yy_cp = (yy_c_buf_p);\n\n\tYY_CHAR yy_c = 1;\n\tif ( yy_accept[yy_current_state] )\n\t\t{\n\t\t(yy_last_accepting_state) = yy_current_state;\n\t\t(yy_last_accepting_cpos) = yy_cp;\n\t\t}\n\twhile ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )\n\t\t{\n\t\tyy_current_state = (int) yy_def[yy_current_state];\n\t\tif ( yy_current_state >= 246 )\n\t\t\tyy_c = yy_meta[(unsigned int) yy_c];\n\t\t}\n\tyy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];\n\tyy_is_jam = (yy_current_state == 245);\n\n\treturn yy_is_jam ? 0 : yy_current_state;\n}\n\n#ifndef YY_NO_INPUT\n#ifdef __cplusplus\n    static int yyinput (void)\n#else\n    static int input  (void)\n#endif\n\n{\n\tint c;\n\n\t*(yy_c_buf_p) = (yy_hold_char);\n\n\tif ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )\n\t\t{\n\t\t/* yy_c_buf_p now points to the character we want to return.\n\t\t * If this occurs *before* the EOB characters, then it's a\n\t\t * valid NUL; if not, then we've hit the end of the buffer.\n\t\t */\n\t\tif ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )\n\t\t\t/* This was really a NUL. */\n\t\t\t*(yy_c_buf_p) = '\\0';\n\n\t\telse\n\t\t\t{ /* need more input */\n\t\t\tint offset = (yy_c_buf_p) - (yytext_ptr);\n\t\t\t++(yy_c_buf_p);\n\n\t\t\tswitch ( yy_get_next_buffer(  ) )\n\t\t\t\t{\n\t\t\t\tcase EOB_ACT_LAST_MATCH:\n\t\t\t\t\t/* This happens because yy_g_n_b()\n\t\t\t\t\t * sees that we've accumulated a\n\t\t\t\t\t * token and flags that we need to\n\t\t\t\t\t * try matching the token before\n\t\t\t\t\t * proceeding.  But for input(),\n\t\t\t\t\t * there's no matching to consider.\n\t\t\t\t\t * So convert the EOB_ACT_LAST_MATCH\n\t\t\t\t\t * to EOB_ACT_END_OF_FILE.\n\t\t\t\t\t */\n\n\t\t\t\t\t/* Reset buffer status. */\n\t\t\t\t\tyyrestart(yyin );\n\n\t\t\t\t\t/*FALLTHROUGH*/\n\n\t\t\t\tcase EOB_ACT_END_OF_FILE:\n\t\t\t\t\t{\n\t\t\t\t\tif ( yywrap( ) )\n\t\t\t\t\t\treturn EOF;\n\n\t\t\t\t\tif ( ! (yy_did_buffer_switch_on_eof) )\n\t\t\t\t\t\tYY_NEW_FILE;\n#ifdef __cplusplus\n\t\t\t\t\treturn yyinput();\n#else\n\t\t\t\t\treturn input();\n#endif\n\t\t\t\t\t}\n\n\t\t\t\tcase EOB_ACT_CONTINUE_SCAN:\n\t\t\t\t\t(yy_c_buf_p) = (yytext_ptr) + offset;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tc = *(unsigned char *) (yy_c_buf_p);\t/* cast for 8-bit char's */\n\t*(yy_c_buf_p) = '\\0';\t/* preserve yytext */\n\t(yy_hold_char) = *++(yy_c_buf_p);\n\n\tif ( c == '\\n' )\n\t\t\n    yylineno++;\n;\n\n\treturn c;\n}\n#endif\t/* ifndef YY_NO_INPUT */\n\n/** Immediately switch to a different input stream.\n * @param input_file A readable stream.\n *\n * @note This function does not reset the start condition to @c INITIAL .\n */\n    void yyrestart  (FILE * input_file )\n{\n\n\tif ( ! YY_CURRENT_BUFFER ){\n        yyensure_buffer_stack ();\n\t\tYY_CURRENT_BUFFER_LVALUE =\n            yy_create_buffer(yyin,YY_BUF_SIZE );\n\t}\n\n\tyy_init_buffer(YY_CURRENT_BUFFER,input_file );\n\tyy_load_buffer_state( );\n}\n\n/** Switch to a different input buffer.\n * @param new_buffer The new input buffer.\n *\n */\n    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )\n{\n\n\t/* TODO. We should be able to replace this entire function body\n\t * with\n\t *\t\tyypop_buffer_state();\n\t *\t\tyypush_buffer_state(new_buffer);\n     */\n\tyyensure_buffer_stack ();\n\tif ( YY_CURRENT_BUFFER == new_buffer )\n\t\treturn;\n\n\tif ( YY_CURRENT_BUFFER )\n\t\t{\n\t\t/* Flush out information for old buffer. */\n\t\t*(yy_c_buf_p) = (yy_hold_char);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);\n\t\t}\n\n\tYY_CURRENT_BUFFER_LVALUE = new_buffer;\n\tyy_load_buffer_state( );\n\n\t/* We don't actually know whether we did this switch during\n\t * EOF (yywrap()) processing, but the only time this flag\n\t * is looked at is after yywrap() is called, so it's safe\n\t * to go ahead and always set it.\n\t */\n\t(yy_did_buffer_switch_on_eof) = 1;\n}\n\nstatic void yy_load_buffer_state  (void)\n{\n    \t(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;\n\t(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;\n\tyyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;\n\t(yy_hold_char) = *(yy_c_buf_p);\n}\n\n/** Allocate and initialize an input buffer state.\n * @param file A readable stream.\n * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.\n *\n * @return the allocated buffer state.\n */\n    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )\n{\n\tYY_BUFFER_STATE b;\n\n\tb = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in yy_create_buffer()\" );\n\n\tb->yy_buf_size = size;\n\n\t/* yy_ch_buf has to be 2 characters longer than the size given because\n\t * we need to put in 2 end-of-buffer characters.\n\t */\n\tb->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );\n\tif ( ! b->yy_ch_buf )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in yy_create_buffer()\" );\n\n\tb->yy_is_our_buffer = 1;\n\n\tyy_init_buffer(b,file );\n\n\treturn b;\n}\n\n/** Destroy the buffer.\n * @param b a buffer created with yy_create_buffer()\n *\n */\n    void yy_delete_buffer (YY_BUFFER_STATE  b )\n{\n\n\tif ( ! b )\n\t\treturn;\n\n\tif ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */\n\t\tYY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;\n\n\tif ( b->yy_is_our_buffer )\n\t\tyyfree((void *) b->yy_ch_buf  );\n\n\tyyfree((void *) b  );\n}\n\n#ifndef __cplusplus\nextern int isatty (int );\n#endif /* __cplusplus */\n\n/* Initializes or reinitializes a buffer.\n * This function is sometimes called more than once on the same buffer,\n * such as during a yyrestart() or at EOF.\n */\n    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )\n\n{\n\tint oerrno = errno;\n\n\tyy_flush_buffer(b );\n\n\tb->yy_input_file = file;\n\tb->yy_fill_buffer = 1;\n\n    /* If b is the current buffer, then yy_init_buffer was _probably_\n     * called from yyrestart() or through yy_get_next_buffer.\n     * In that case, we don't want to reset the lineno or column.\n     */\n    if (b != YY_CURRENT_BUFFER){\n        b->yy_bs_lineno = 1;\n        b->yy_bs_column = 0;\n    }\n\n        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;\n\n\terrno = oerrno;\n}\n\n/** Discard all buffered characters. On the next scan, YY_INPUT will be called.\n * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.\n *\n */\n    void yy_flush_buffer (YY_BUFFER_STATE  b )\n{\n    \tif ( ! b )\n\t\treturn;\n\n\tb->yy_n_chars = 0;\n\n\t/* We always need two end-of-buffer characters.  The first causes\n\t * a transition to the end-of-buffer state.  The second causes\n\t * a jam in that state.\n\t */\n\tb->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;\n\tb->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;\n\n\tb->yy_buf_pos = &b->yy_ch_buf[0];\n\n\tb->yy_at_bol = 1;\n\tb->yy_buffer_status = YY_BUFFER_NEW;\n\n\tif ( b == YY_CURRENT_BUFFER )\n\t\tyy_load_buffer_state( );\n}\n\n/** Pushes the new state onto the stack. The new state becomes\n *  the current state. This function will allocate the stack\n *  if necessary.\n *  @param new_buffer The new state.\n *\n */\nvoid yypush_buffer_state (YY_BUFFER_STATE new_buffer )\n{\n    \tif (new_buffer == NULL)\n\t\treturn;\n\n\tyyensure_buffer_stack();\n\n\t/* This block is copied from yy_switch_to_buffer. */\n\tif ( YY_CURRENT_BUFFER )\n\t\t{\n\t\t/* Flush out information for old buffer. */\n\t\t*(yy_c_buf_p) = (yy_hold_char);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);\n\t\tYY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);\n\t\t}\n\n\t/* Only push if top exists. Otherwise, replace top. */\n\tif (YY_CURRENT_BUFFER)\n\t\t(yy_buffer_stack_top)++;\n\tYY_CURRENT_BUFFER_LVALUE = new_buffer;\n\n\t/* copied from yy_switch_to_buffer. */\n\tyy_load_buffer_state( );\n\t(yy_did_buffer_switch_on_eof) = 1;\n}\n\n/** Removes and deletes the top of the stack, if present.\n *  The next element becomes the new top.\n *\n */\nvoid yypop_buffer_state (void)\n{\n    \tif (!YY_CURRENT_BUFFER)\n\t\treturn;\n\n\tyy_delete_buffer(YY_CURRENT_BUFFER );\n\tYY_CURRENT_BUFFER_LVALUE = NULL;\n\tif ((yy_buffer_stack_top) > 0)\n\t\t--(yy_buffer_stack_top);\n\n\tif (YY_CURRENT_BUFFER) {\n\t\tyy_load_buffer_state( );\n\t\t(yy_did_buffer_switch_on_eof) = 1;\n\t}\n}\n\n/* Allocates the stack if it does not exist.\n *  Guarantees space for at least one push.\n */\nstatic void yyensure_buffer_stack (void)\n{\n\tint num_to_alloc;\n\n\tif (!(yy_buffer_stack)) {\n\n\t\t/* First allocation is just for 2 elements, since we don't know if this\n\t\t * scanner will even need a stack. We use 2 instead of 1 to avoid an\n\t\t * immediate realloc on the next call.\n         */\n\t\tnum_to_alloc = 1;\n\t\t(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc\n\t\t\t\t\t\t\t\t(num_to_alloc * sizeof(struct yy_buffer_state*)\n\t\t\t\t\t\t\t\t);\n\t\tif ( ! (yy_buffer_stack) )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in yyensure_buffer_stack()\" );\n\t\t\t\t\t\t\t\t\n\t\tmemset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));\n\t\t\t\t\n\t\t(yy_buffer_stack_max) = num_to_alloc;\n\t\t(yy_buffer_stack_top) = 0;\n\t\treturn;\n\t}\n\n\tif ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){\n\n\t\t/* Increase the buffer to prepare for a possible push. */\n\t\tint grow_size = 8 /* arbitrary grow size */;\n\n\t\tnum_to_alloc = (yy_buffer_stack_max) + grow_size;\n\t\t(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc\n\t\t\t\t\t\t\t\t((yy_buffer_stack),\n\t\t\t\t\t\t\t\tnum_to_alloc * sizeof(struct yy_buffer_state*)\n\t\t\t\t\t\t\t\t);\n\t\tif ( ! (yy_buffer_stack) )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in yyensure_buffer_stack()\" );\n\n\t\t/* zero only the new slots.*/\n\t\tmemset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));\n\t\t(yy_buffer_stack_max) = num_to_alloc;\n\t}\n}\n\n/** Setup the input buffer state to scan directly from a user-specified character buffer.\n * @param base the character buffer\n * @param size the size in bytes of the character buffer\n *\n * @return the newly allocated buffer state object.\n */\nYY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )\n{\n\tYY_BUFFER_STATE b;\n\n\tif ( size < 2 ||\n\t     base[size-2] != YY_END_OF_BUFFER_CHAR ||\n\t     base[size-1] != YY_END_OF_BUFFER_CHAR )\n\t\t/* They forgot to leave room for the EOB's. */\n\t\treturn 0;\n\n\tb = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in yy_scan_buffer()\" );\n\n\tb->yy_buf_size = size - 2;\t/* \"- 2\" to take care of EOB's */\n\tb->yy_buf_pos = b->yy_ch_buf = base;\n\tb->yy_is_our_buffer = 0;\n\tb->yy_input_file = 0;\n\tb->yy_n_chars = b->yy_buf_size;\n\tb->yy_is_interactive = 0;\n\tb->yy_at_bol = 1;\n\tb->yy_fill_buffer = 0;\n\tb->yy_buffer_status = YY_BUFFER_NEW;\n\n\tyy_switch_to_buffer(b  );\n\n\treturn b;\n}\n\n/** Setup the input buffer state to scan a string. The next call to yylex() will\n * scan from a @e copy of @a str.\n * @param yystr a NUL-terminated string to scan\n *\n * @return the newly allocated buffer state object.\n * @note If you want to scan bytes that may contain NUL values, then use\n *       yy_scan_bytes() instead.\n */\nYY_BUFFER_STATE yy_scan_string (yyconst char * yystr )\n{\n\n\treturn yy_scan_bytes(yystr,strlen(yystr) );\n}\n\n/** Setup the input buffer state to scan the given bytes. The next call to yylex() will\n * scan from a @e copy of @a bytes.\n * @param yybytes the byte buffer to scan\n * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.\n *\n * @return the newly allocated buffer state object.\n */\nYY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )\n{\n\tYY_BUFFER_STATE b;\n\tchar *buf;\n\tyy_size_t n;\n\tint i;\n\n\t/* Get memory for full buffer, including space for trailing EOB's. */\n\tn = _yybytes_len + 2;\n\tbuf = (char *) yyalloc(n  );\n\tif ( ! buf )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in yy_scan_bytes()\" );\n\n\tfor ( i = 0; i < _yybytes_len; ++i )\n\t\tbuf[i] = yybytes[i];\n\n\tbuf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;\n\n\tb = yy_scan_buffer(buf,n );\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"bad buffer in yy_scan_bytes()\" );\n\n\t/* It's okay to grow etc. this buffer, and we should throw it\n\t * away when we're done.\n\t */\n\tb->yy_is_our_buffer = 1;\n\n\treturn b;\n}\n\n    static void yy_push_state (int  new_state )\n{\n    \tif ( (yy_start_stack_ptr) >= (yy_start_stack_depth) )\n\t\t{\n\t\tyy_size_t new_size;\n\n\t\t(yy_start_stack_depth) += YY_START_STACK_INCR;\n\t\tnew_size = (yy_start_stack_depth) * sizeof( int );\n\n\t\tif ( ! (yy_start_stack) )\n\t\t\t(yy_start_stack) = (int *) yyalloc(new_size  );\n\n\t\telse\n\t\t\t(yy_start_stack) = (int *) yyrealloc((void *) (yy_start_stack),new_size  );\n\n\t\tif ( ! (yy_start_stack) )\n\t\t\tYY_FATAL_ERROR( \"out of memory expanding start-condition stack\" );\n\t\t}\n\n\t(yy_start_stack)[(yy_start_stack_ptr)++] = YY_START;\n\n\tBEGIN(new_state);\n}\n\n    static void yy_pop_state  (void)\n{\n    \tif ( --(yy_start_stack_ptr) < 0 )\n\t\tYY_FATAL_ERROR( \"start-condition stack underflow\" );\n\n\tBEGIN((yy_start_stack)[(yy_start_stack_ptr)]);\n}\n\n    static int yy_top_state  (void)\n{\n    \treturn (yy_start_stack)[(yy_start_stack_ptr) - 1];\n}\n\n#ifndef YY_EXIT_FAILURE\n#define YY_EXIT_FAILURE 2\n#endif\n\nstatic void yy_fatal_error (yyconst char* msg )\n{\n    \t(void) fprintf( stderr, \"%s\\n\", msg );\n\texit( YY_EXIT_FAILURE );\n}\n\n/* Redefine yyless() so it works in section 3 code. */\n\n#undef yyless\n#define yyless(n) \\\n\tdo \\\n\t\t{ \\\n\t\t/* Undo effects of setting up yytext. */ \\\n        int yyless_macro_arg = (n); \\\n        YY_LESS_LINENO(yyless_macro_arg);\\\n\t\tyytext[yyleng] = (yy_hold_char); \\\n\t\t(yy_c_buf_p) = yytext + yyless_macro_arg; \\\n\t\t(yy_hold_char) = *(yy_c_buf_p); \\\n\t\t*(yy_c_buf_p) = '\\0'; \\\n\t\tyyleng = yyless_macro_arg; \\\n\t\t} \\\n\twhile ( 0 )\n\n/* Accessor  methods (get/set functions) to struct members. */\n\n/** Get the current line number.\n *\n */\nint yyget_lineno  (void)\n{\n\n    return yylineno;\n}\n\n/** Get the input stream.\n *\n */\nFILE *yyget_in  (void)\n{\n        return yyin;\n}\n\n/** Get the output stream.\n *\n */\nFILE *yyget_out  (void)\n{\n        return yyout;\n}\n\n/** Get the length of the current token.\n *\n */\nint yyget_leng  (void)\n{\n        return yyleng;\n}\n\n/** Get the current token.\n *\n */\n\nchar *yyget_text  (void)\n{\n        return yytext;\n}\n\n/** Set the current line number.\n * @param line_number\n *\n */\nvoid yyset_lineno (int  line_number )\n{\n\n    yylineno = line_number;\n}\n\n/** Set the input stream. This does not discard the current\n * input buffer.\n * @param in_str A readable stream.\n *\n * @see yy_switch_to_buffer\n */\nvoid yyset_in (FILE *  in_str )\n{\n        yyin = in_str ;\n}\n\nvoid yyset_out (FILE *  out_str )\n{\n        yyout = out_str ;\n}\n\nint yyget_debug  (void)\n{\n        return yy_flex_debug;\n}\n\nvoid yyset_debug (int  bdebug )\n{\n        yy_flex_debug = bdebug ;\n}\n\nstatic int yy_init_globals (void)\n{\n        /* Initialization is the same as for the non-reentrant scanner.\n     * This function is called from yylex_destroy(), so don't allocate here.\n     */\n\n    /* We do not touch yylineno unless the option is enabled. */\n    yylineno =  1;\n\n    (yy_buffer_stack) = 0;\n    (yy_buffer_stack_top) = 0;\n    (yy_buffer_stack_max) = 0;\n    (yy_c_buf_p) = (char *) 0;\n    (yy_init) = 0;\n    (yy_start) = 0;\n\n    (yy_start_stack_ptr) = 0;\n    (yy_start_stack_depth) = 0;\n    (yy_start_stack) =  NULL;\n\n/* Defined in main.c */\n#ifdef YY_STDINIT\n    yyin = stdin;\n    yyout = stdout;\n#else\n    yyin = (FILE *) 0;\n    yyout = (FILE *) 0;\n#endif\n\n    /* For future reference: Set errno on error, since we are called by\n     * yylex_init()\n     */\n    return 0;\n}\n\n/* yylex_destroy is for both reentrant and non-reentrant scanners. */\nint yylex_destroy  (void)\n{\n\n    /* Pop the buffer stack, destroying each element. */\n\twhile(YY_CURRENT_BUFFER){\n\t\tyy_delete_buffer(YY_CURRENT_BUFFER  );\n\t\tYY_CURRENT_BUFFER_LVALUE = NULL;\n\t\tyypop_buffer_state();\n\t}\n\n\t/* Destroy the stack itself. */\n\tyyfree((yy_buffer_stack) );\n\t(yy_buffer_stack) = NULL;\n\n    /* Destroy the start condition stack. */\n        yyfree((yy_start_stack)  );\n        (yy_start_stack) = NULL;\n\n    /* Reset the globals. This is important in a non-reentrant scanner so the next time\n     * yylex() is called, initialization will occur. */\n    yy_init_globals( );\n\n    return 0;\n}\n\n/*\n * Internal utility routines.\n */\n\n#ifndef yytext_ptr\nstatic void yy_flex_strncpy (char* s1, yyconst char * s2, int n )\n{\n\tint i;\n\tfor ( i = 0; i < n; ++i )\n\t\ts1[i] = s2[i];\n}\n#endif\n\n#ifdef YY_NEED_STRLEN\nstatic int yy_flex_strlen (yyconst char * s )\n{\n\tint n;\n\tfor ( n = 0; s[n]; ++n )\n\t\t;\n\n\treturn n;\n}\n#endif\n\nvoid *yyalloc (yy_size_t  size )\n{\n\treturn (void *) malloc( size );\n}\n\nvoid *yyrealloc  (void * ptr, yy_size_t  size )\n{\n\t/* The cast to (char *) in the following accommodates both\n\t * implementations that use char* generic pointers, and those\n\t * that use void* generic pointers.  It works with the latter\n\t * because both ANSI C and C++ allow castless assignment from\n\t * any pointer type to void*, and deal with argument conversions\n\t * as though doing an assignment.\n\t */\n\treturn (void *) realloc( (char *) ptr, size );\n}\n\nvoid yyfree (void * ptr )\n{\n\tfree( (char *) ptr );\t/* see yyrealloc() for (char *) cast */\n}\n\n#define YYTABLES_NAME \"yytables\"\n\n#line 147 \"../../src/scanner.ll\"\n\n\n\n/*\n  Otherwise '\\n' within a TOK_MLSTRING would not be counted\n*/\nvoid\nupdate_count_line (char *str)\n{\n  if (str)\n    {\n      char *p;\n      for (p = str; *p; ++p)\n        if (*p == '\\n') {\n          ++gengetopt_count_line;\n          tokenpos = 0 ; /* reset token position */\n          strncpy (linebuf, ( (p+1) ? p+1 : \"\"), LINEBUF_LEN - 1);\n        }\n    }\n  else\n    {\n      ++gengetopt_count_line;\n      tokenpos = 0 ; /* reset token position */\n      strncpy (linebuf, yytext+1, LINEBUF_LEN - 1); /* save the next line */\n    }\n}\n\nvoid\nupdateTokenInfo( int pos )\n{\n  if ( pos >= 0 )\n    tokenpos += pos ;\n  else\n    tokenpos += yyleng ;\n}\n\nvoid buffer(const char *s)\n{\n  buff << s;\n}\n\nchar *flush_buffer()\n{\n  char *ret = strdup(buff.str().c_str());\n  buff.str(\"\");\n  return ret;\n}\n\n"
  },
  {
    "path": "utilities/gengetopt/skels/Makefile.am",
    "content": "# Copyright (C) 1999-2008 Free Software Foundation, Inc.\n#\n# This file is free software; as a special exception the author gives\n# unlimited permission to copy and/or distribute it, with or without\n# modifications, as long as this notice is preserved.\n#\n# This program is distributed in the hope that it will be useful, but\n# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the\n# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n# if gengen is not installed we simply ignore the changes\n\nSUFFIXES = .h_skel\n\nif NO_GENGEN\n#.h_skel.cc:\n#\techo \"Not regenerating $@ since gengen is not installed\"\n# better not to use touch, otherwise we will create an empty file in\n# the build directory\n#\ttouch $@\n\nelse\nGENERATE = $(GENGEN)\n\n.h_skel.cc:\n\tname=\"`echo $* | sed 's/^.*\\///g'`\"; \\\n\techo \"$$name\"; \\\n\t$(GENERATE) -i $< -F $*.h -f $$name --separate-files --expand-tabs --output-dir=$(srcdir) --force\nendif\n\nINCLUDES = -I@top_srcdir@/src\n\nnoinst_LTLIBRARIES = libgen.la\n\nlibgen_la_SOURCES = $(BUILT_SOURCES)\n\nBUILT_SOURCES = header.h header.cc c_source.h c_source.cc \\\nhandle_help.h handle_version.h handle_help.cc handle_version.cc \\\ngeneric_option.h required_option.h dependant_option.h \\\ngeneric_option.cc required_option.cc dependant_option.cc \\\ngroup_counter.h group_option.h \\\ngroup_counter.cc group_option.cc \\\nprint_help_string.h print_help_string.cc \\\nmultiple_opt_list.cc multiple_opt_list.h \\\nmultiple_fill_array.cc multiple_fill_array.h \\\ncopyright.cc copyright.h \\\nfree_string.cc free_string.h \\\nfree_multiple.cc free_multiple.h \\\nreset_group.cc reset_group.h \\\nexit_failure.cc exit_failure.h \\\nupdate_given.cc update_given.h \\\noption_arg.cc option_arg.h \\\ngiven_field.cc given_field.h \\\nclear_given.cc clear_given.h \\\nclear_arg.cc clear_arg.h \\\nfree_list.cc free_list.h \\\nfile_save.cc file_save.h \\\nfile_save_multiple.cc file_save_multiple.h \\\ninit_args_info.cc init_args_info.h \\\ncustom_getopt_gen.cc custom_getopt_gen.h \\\ncheck_modes.cc check_modes.h \\\nenum_decl.cc enum_decl.h\n\nEXTRA_DIST = header.h_skel c_source.h_skel handle_help.h_skel \\\nhandle_version.h_skel generic_option.h_skel \\\nrequired_option.h_skel dependant_option.h_skel \\\ngroup_counter.h_skel group_option.h_skel \\\nprint_help_string.h_skel \\\nmultiple_opt_list.h_skel \\\nmultiple_fill_array.h_skel \\\ncopyright.h_skel free_string.h_skel \\\nfree_multiple.h_skel \\\nreset_group.h_skel \\\nexit_failure.h_skel \\\nupdate_given.h_skel \\\noption_arg.h_skel \\\ngiven_field.h_skel \\\nclear_given.h_skel \\\nclear_arg.h_skel \\\nfree_list.h_skel \\\nfile_save.h_skel \\\nfile_save_multiple.h_skel \\\ninit_args_info.h_skel \\\ncustom_getopt_gen.h_skel \\\ncheck_modes.h_skel \\\nenum_decl.h_skel \\\n$(BUILT_SOURCES)\n\nbuilt-clean:\n\tcd @srcdir@ && rm -f $(BUILT_SOURCES)\n"
  },
  {
    "path": "utilities/gengetopt/skels/c_source.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"c_source.h\"\n\nvoid\nc_source_gen_class::generate_c_source(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  File autogenerated by gengetopt \";\n  generate_string (generator_version, stream, indent + indent_str.length ());\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  generated with the following command:\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (command_line, stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  The developers of gengetopt consider the fixed text that goes in all\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  gengetopt output files to be in the public domain:\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  we make no copyright claims on it.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"*/\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/* If we use autoconf.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifdef HAVE_CONFIG_H\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#include \\\"config.h\\\"\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#include <stdio.h>\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#include <stdlib.h>\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#include <string.h>\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifndef FIX_UNUSED\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (( ! include_getopt ))\n    {\n      stream << \"#include <getopt.h>\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#include \\\"\";\n  generate_string (source_name, stream, indent + indent_str.length ());\n  stream << \".\";\n  generate_string (header_file_ext, stream, indent + indent_str.length ());\n  stream << \"\\\"\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"const char *\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_purpose = \\\"\";\n  generate_string (purpose, stream, indent + indent_str.length ());\n  stream << \"\\\";\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"const char *\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_usage = \\\"Usage: \";\n  if (no_package)\n    {\n      stream << \"\\\" \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \" \\\"\";\n    }\n  generate_string (usage_string, stream, indent + indent_str.length ());\n  stream << \"\\\";\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"const char *\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_description = \\\"\";\n  generate_string (description, stream, indent + indent_str.length ());\n  stream << \"\\\";\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (( has_hidden || has_details ))\n    {\n      if (has_details)\n        {\n          stream << \"const char *\";\n          generate_string (args_info, stream, indent + indent_str.length ());\n          stream << \"_detailed_help[] = {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          indent = 2;\n          stream << \"  \";\n          if (detailed_help_option_print.size () > 0)\n            generate_string (detailed_help_option_print, stream, indent + indent_str.length ());\n          else\n            generate_detailed_help_option_print (stream, indent + indent_str.length ());\n          stream << \"  0\";\n          indent = 0;\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"};\";\n          stream << \"\\n\";\n          stream << indent_str;\n          if (has_hidden)\n            {\n              stream << \"static void\";\n              stream << \"\\n\";\n              stream << indent_str;\n              stream << \"init_full_help_array(void)\";\n              stream << \"\\n\";\n              stream << indent_str;\n              stream << \"{\";\n              stream << \"\\n\";\n              stream << indent_str;\n              indent = 2;\n              stream << \"  \";\n              if (full_help_option_print.size () > 0)\n                generate_string (full_help_option_print, stream, indent + indent_str.length ());\n              else\n                generate_full_help_option_print (stream, indent + indent_str.length ());\n              indent = 0;\n              stream << \"\\n\";\n              stream << indent_str;\n              stream << \"}\";\n              stream << \"\\n\";\n              stream << indent_str;\n              stream << \"\\n\";\n              stream << indent_str;\n              stream << \"const char *\";\n              generate_string (args_info, stream, indent + indent_str.length ());\n              stream << \"_full_help[\";\n              generate_string (help_string_num, stream, indent + indent_str.length ());\n              stream << \"];\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n        }\n      else\n        {\n          if (has_hidden)\n            {\n              stream << \"const char *\";\n              generate_string (args_info, stream, indent + indent_str.length ());\n              stream << \"_full_help[] = {\";\n              stream << \"\\n\";\n              stream << indent_str;\n              indent = 2;\n              stream << \"  \";\n              if (full_help_option_print.size () > 0)\n                generate_string (full_help_option_print, stream, indent + indent_str.length ());\n              else\n                generate_full_help_option_print (stream, indent + indent_str.length ());\n              stream << \"  0\";\n              indent = 0;\n              stream << \"\\n\";\n              stream << indent_str;\n              stream << \"};\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n        }\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static void\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"init_help_array(void)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      if (help_option_print.size () > 0)\n        generate_string (help_option_print, stream, indent + indent_str.length ());\n      else\n        generate_help_option_print (stream, indent + indent_str.length ());\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"const char *\";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \"_help[\";\n      generate_string (help_string_num, stream, indent + indent_str.length ());\n      stream << \"];\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"const char *\";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \"_help[] = {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      if (help_option_print.size () > 0)\n        generate_string (help_option_print, stream, indent + indent_str.length ());\n      else\n        generate_help_option_print (stream, indent + indent_str.length ());\n      stream << \"  0\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"};\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"typedef enum {ARG_NO\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (has_arg_flag)\n    {\n      stream << \"  , ARG_FLAG\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_string)\n    {\n      stream << \"  , ARG_STRING\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_int)\n    {\n      stream << \"  , ARG_INT\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_short)\n    {\n      stream << \"  , ARG_SHORT\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_long)\n    {\n      stream << \"  , ARG_LONG\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_float)\n    {\n      stream << \"  , ARG_FLOAT\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_double)\n    {\n      stream << \"  , ARG_DOUBLE\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_longdouble)\n    {\n      stream << \"  , ARG_LONGDOUBLE\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_longlong)\n    {\n      stream << \"  , ARG_LONGLONG\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_arg_enum)\n    {\n      stream << \"  , ARG_ENUM\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"} \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_arg_type;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void clear_given (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void clear_args (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_internal (int argc, char **argv, struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"                        struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *params, const char *additional_error);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (check_required_options)\n    {\n      stream << \"static int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_required2 (struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info, const char *prog_name, const char *additional_error);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (cmd_list)\n    {\n      stream << \"struct line_list\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char * string_arg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct line_list * next;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"};\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static struct line_list *cmd_line_list = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static struct line_list *cmd_line_list_tmp = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static void\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"free_cmd_list(void)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  /* free the list of a previous call */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (cmd_line_list)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      while (cmd_line_list) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        cmd_line_list_tmp = cmd_line_list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        cmd_line_list = cmd_line_list->next;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        free (cmd_line_list_tmp->string_arg);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        free (cmd_line_list_tmp);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  if (option_values.size () > 0)\n    generate_string (option_values, stream, indent + indent_str.length ());\n  else\n    generate_option_values (stream, indent + indent_str.length ());\n  stream << indent_str;\n  if (do_generate_strdup)\n    {\n      stream << \"static char *\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"gengetopt_strdup (const char *s);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"static\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void clear_given (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  if (given_init.size () > 0)\n    generate_string (given_init, stream, indent + indent_str.length ());\n  else\n    generate_given_init (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void clear_args (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  FIX_UNUSED (args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  if (clear_arg.size () > 0)\n    generate_string (clear_arg, stream, indent + indent_str.length ());\n  else\n    generate_clear_arg (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void init_args_info(struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (( has_hidden && has_details ))\n    {\n      stream << \"  init_full_help_array(); \";\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  if (( has_hidden || has_details ))\n    {\n      stream << \"  init_help_array(); \";\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  if (init_args_info.size () > 0)\n    generate_string (init_args_info, stream, indent + indent_str.length ());\n  else\n    generate_init_args_info (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_print_version (void)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  printf (\\\"%s %s\\\\n\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"     (strlen(\";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \"_NAME) ? \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \"_NAME : \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \"),\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 5;\n  stream << \"     \";\n  generate_string (version_var_name, stream, indent + indent_str.length ());\n  stream << \");\";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static void print_help_common(void) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_print_version ();\";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if (strlen(\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_purpose) > 0)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    printf(\\\"\\\\n%s\\\\n\\\", \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_purpose);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if (strlen(\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_usage) > 0)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    printf(\\\"\\\\n%s\\\\n\\\", \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_usage);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  printf(\\\"\\\\n\\\");\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if (strlen(\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_description) > 0)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    printf(\\\"%s\\\\n\\\\n\\\", \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_description);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_print_help (void)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int i = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  print_help_common();\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  while (\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_help[i])\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    printf(\\\"%s\\\\n\\\", \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_help[i++]);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (has_hidden)\n    {\n      stream << \"void\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_print_full_help (void)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int i = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  print_help_common();\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while (\";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \"_full_help[i])\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    printf(\\\"%s\\\\n\\\", \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \"_full_help[i++]);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_details)\n    {\n      stream << \"void\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_print_detailed_help (void)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int i = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  print_help_common();\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while (\";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \"_detailed_help[i])\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    printf(\\\"%s\\\\n\\\", \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \"_detailed_help[i++]);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"void\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_init (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  clear_given (args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  clear_args (args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  init_args_info (args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (handle_unamed)\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  args_info->inputs = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  args_info->inputs_num = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params_init(struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *params)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if (params)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    { \";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      params->override = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      params->initialize = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      params->check_required = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      params->check_ambiguity = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      params->print_errors = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    }\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params_create(void)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *params = \";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    (struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *)malloc(sizeof(struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params));\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params_init(params);  \";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  return params;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (has_typed_options)\n    {\n      stream << \"static void\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"free_string_field (char **s)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (*s)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      free (*s);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      *s = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  if (multiple_token_functions)\n    {\n      stream << \"/** \";\n      stream << \"@\";\n      stream << \"brief generic value variable */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"union generic_value {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (( has_arg_int || has_arg_enum ))\n        {\n          stream << \"    int int_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_short)\n        {\n          stream << \"    short short_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_long)\n        {\n          stream << \"    long long_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_float)\n        {\n          stream << \"    float float_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_double)\n        {\n          stream << \"    double double_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longdouble)\n        {\n          stream << \"    long double longdouble_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longlong)\n        {\n          stream << \"#ifdef HAVE_LONG_LONG\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    long long int longlong_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#else\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    long longlong_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#endif\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"    char *string_arg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    const char *default_string_arg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"};\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"/** \";\n      stream << \"@\";\n      stream << \"brief holds temporary values for multiple options */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"struct generic_list\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  union generic_value arg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *orig;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct generic_list *next;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"};\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"brief add a node at the head of the list \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static void add_node(struct generic_list **list) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct generic_list *new_node = (struct generic_list *) malloc (sizeof (struct generic_list));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  new_node->next = *list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  *list = new_node;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  new_node->arg.string_arg = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  new_node->orig = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      if (( ( ! multiple_options_all_string ) && multiple_token_functions ))\n        {\n          stream << \"/**\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \" * The passed arg parameter is NOT set to 0 from this function\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \" */\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"static void\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"free_multiple_field(unsigned int len, void *arg, char ***orig)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"{\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  unsigned int i;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  if (arg) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    for (i = 0; i < len; ++i)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        free_string_field(&((*orig)[i]));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    free (arg);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    free (*orig);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    *orig = 0;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"}\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"\\n\";\n      stream << indent_str;\n      if (multiple_options_string)\n        {\n          stream << \"static void\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"free_multiple_string_field(unsigned int len, char ***arg, char ***orig)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"{\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  unsigned int i;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  if (*arg) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    for (i = 0; i < len; ++i)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        free_string_field(&((*arg)[i]));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        free_string_field(&((*orig)[i]));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    free_string_field(&((*arg)[0])); /* free default string */\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    free (*arg);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    *arg = 0;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    free (*orig);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    *orig = 0;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"}\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static void\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_release (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (handle_unamed)\n    {\n      stream << \"  unsigned int i;\";\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  if (free.size () > 0)\n    generate_string (free, stream, indent + indent_str.length ());\n  else\n    generate_free (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (handle_unamed)\n    {\n      stream << \"  for (i = 0; i < args_info->inputs_num; ++i)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    free (args_info->inputs [i]);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (args_info->inputs_num)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    free (args_info->inputs);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  clear_given (args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (check_possible_values)\n    {\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param val the value to check\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param values the possible values\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"return the index of the matched value:\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * -1 if no value matched,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * -2 if more than one value has matched\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"check_possible_values(const char *val, const char *values[])\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int i, found, last;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  size_t len;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (!val)   /* otherwise strlen() crashes below */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return -1; /* -1 means no argument for the option */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  found = last = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  for (i = 0, len = strlen(val); values[i]; ++i)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (strncmp(val, values[i], len) == 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          ++found;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          last = i;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          if (strlen(values[i]) == len)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            return i; /* exact macth no need to check more */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (found == 1) /* one match: OK */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return last;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return (found ? -2 : -1); /* return many values or none matched */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static void\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (check_possible_values)\n    {\n      stream << \"  int found = -1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"  FIX_UNUSED (values);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"  if (arg) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (check_possible_values)\n    {\n      stream << \"    if (values) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      found = check_possible_values(arg, values);      \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    if (found >= 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      fprintf(outfile, \\\"%s=\\\\\\\"%s\\\\\\\" # %s\\\\n\\\", opt, arg, values[found]);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      fprintf(outfile, \\\"%s=\\\\\\\"%s\\\\\\\"\\\\n\\\", opt, arg);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"    fprintf(outfile, \\\"%s=\\\\\\\"%s\\\\\\\"\\\\n\\\", opt, arg);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"  } else {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    fprintf(outfile, \\\"%s\\\\n\\\", opt);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  }\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (multiple_options)\n    {\n      stream << \"static void\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"write_multiple_into_file(FILE *outfile, int len, const char *opt, char **arg, const char *values[])\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int i;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  for (i = 0; i < len; ++i)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    write_into_file(outfile, opt, (arg ? arg[i] : 0), values);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_dump(FILE *outfile, struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int i = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if (!outfile)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      fprintf (stderr, \\\"%s: cannot dump options to stream\\\\n\\\", \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \");\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      return EXIT_FAILURE;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    }\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  if (file_save_loop.size () > 0)\n    generate_string (file_save_loop, stream, indent + indent_str.length ());\n  else\n    generate_file_save_loop (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  i = EXIT_SUCCESS;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  return i;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_file_save(const char *filename, struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  FILE *outfile;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int i = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  outfile = fopen(filename, \\\"w\\\");\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if (!outfile)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      fprintf (stderr, \\\"%s: cannot open file for writing: %s\\\\n\\\", \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \", filename);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      return EXIT_FAILURE;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    }\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  i = \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_dump(outfile, args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  fclose (outfile);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  return i;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_free (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_release (args_info);\";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (do_generate_strdup)\n    {\n      stream << \"/** \";\n      stream << \"@\";\n      stream << \"brief replacement of strdup, which is not standard */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"char *\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"gengetopt_strdup (const char *s)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *result = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (!s)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return result;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  result = (char*)malloc(strlen(s) + 1);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (result == (char*)0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return (char*)0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  strcpy(result, s);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return result;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (multiple_token_functions)\n    {\n      stream << \"static char *\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"get_multiple_arg_token(const char *arg)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  const char *tok;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *ret;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  size_t len, num_of_escape, i, j;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (!arg)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  tok = strchr (arg, ',');\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  num_of_escape = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  /* make sure it is not escaped */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while (tok)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (*(tok-1) == '\\\\\\\\')\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          /* find the next one */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          tok = strchr (tok+1, ',');\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          ++num_of_escape;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (tok)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    len = (size_t)(tok - arg + 1);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    len = strlen (arg) + 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  len -= num_of_escape;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  ret = (char *) malloc (len);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  i = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  j = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while (arg[i] && (j < len-1))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (arg[i] == '\\\\\\\\' && \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\t  arg[ i + 1 ] && \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\t  arg[ i + 1 ] == ',')\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        ++i;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      ret[j++] = arg[i++];\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  ret[len-1] = '\\\\0';\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return ret;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static const char *\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"get_multiple_arg_token_next(const char *arg)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  const char *tok;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (!arg)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  tok = strchr (arg, ',');\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  /* make sure it is not escaped */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while (tok)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (*(tok-1) == '\\\\\\\\')\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          /* find the next one */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          tok = strchr (tok+1, ',');\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (! tok || strlen(tok) == 1)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return tok+1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (multiple_options)\n    {\n      stream << \"static int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int error = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (option_given && (min > 0 || max > 0))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (min > 0 && max > 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          if (min == max)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              /* specific occurrences */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              if (option_given != (unsigned int) min)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                  fprintf (stderr, \\\"%s: %s option occurrences must be %d\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                    prog_name, option_desc, min);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                  error = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          else if (option_given < (unsigned int) min\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                || option_given > (unsigned int) max)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              /* range occurrences */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              fprintf (stderr, \\\"%s: %s option occurrences must be between %d and %d\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                prog_name, option_desc, min, max);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              error = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      else if (min > 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          /* at least check */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          if (option_given < min)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              fprintf (stderr, \\\"%s: %s option occurrences must be at least %d\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                prog_name, option_desc, min);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              error = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      else if (max > 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          /* at most check */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          if (option_given > max)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              fprintf (stderr, \\\"%s: %s option occurrences must be at most %d\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                prog_name, option_desc, max);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              error = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 4;\n      stream << \"    \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return error;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (reset_groups.size () > 0)\n    generate_string (reset_groups, stream, indent + indent_str.length ());\n  else\n    generate_reset_groups (stream, indent + indent_str.length ());\n  stream << indent_str;\n  stream << \"int\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \" (int argc, char **argv, struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  return \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"2 (argc, argv, args_info, 0, 1, 1);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_ext (int argc, char **argv, struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"                   struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *params)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int result;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  result = \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_internal (argc, argv, args_info, params, 0);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (final_exit, stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"2 (int argc, char **argv, struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info, int override, int initialize, int check_required)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int result;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params params;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  params.override = override;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  params.initialize = initialize;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  params.check_required = check_required;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  params.check_ambiguity = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  params.print_errors = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  result = \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_internal (argc, argv, args_info, &params, 0);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (final_exit, stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_required (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info, const char *prog_name)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (check_required_options)\n    {\n      stream << \"  int result = EXIT_SUCCESS;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (\";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_required2(args_info, prog_name, 0) > 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    result = EXIT_FAILURE;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      generate_string (final_exit, stream, indent + indent_str.length ());\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"  FIX_UNUSED (args_info);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  FIX_UNUSED (prog_name);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return EXIT_SUCCESS;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (check_required_options)\n    {\n      stream << \"int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_required2 (struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info, const char *prog_name, const char *additional_error)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int error = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  FIX_UNUSED (additional_error);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  /* checks for required options */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      if (handle_required.size () > 0)\n        generate_string (handle_required, stream, indent + indent_str.length ());\n      else\n        generate_handle_required (stream, indent + indent_str.length ());\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  /* checks for dependences among options */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      if (handle_dependencies.size () > 0)\n        generate_string (handle_dependencies, stream, indent + indent_str.length ());\n      else\n        generate_handle_dependencies (stream, indent + indent_str.length ());\n      indent = 0;\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return error;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (include_getopt)\n    {\n      if (custom_getopt.size () > 0)\n        generate_string (custom_getopt, stream, indent + indent_str.length ());\n      else\n        generate_custom_getopt (stream, indent + indent_str.length ());\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static char *package_name = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (( ! no_options ))\n    {\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"brief updates an option\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param field the generic pointer to the field to update\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param orig_field the pointer to the orig field\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param field_given the pointer to the number of occurrence of this option\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param prev_given the pointer to the number of occurrence already seen\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param value the argument for this option (if null no arg was specified)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param possible_values the possible values for this option (if specified)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param default_value the default value (in case the option only accepts fixed values)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param arg_type the type of this option\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param check_ambiguity \";\n      stream << \"@\";\n      stream << \"see \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_params.check_ambiguity\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param override \";\n      stream << \"@\";\n      stream << \"see \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_params.override\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param no_free whether to free a possible previous value\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param multiple_option whether this is a multiple option\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param long_opt the corresponding long option\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param short_opt the corresponding short option (or '-' if none)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param additional_error possible further error specification\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int update_arg(void *field, char **orig_field,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               unsigned int *field_given, unsigned int *prev_given, \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               char *value, const char *possible_values[],\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               const char *default_value,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 15;\n      stream << \"               \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_arg_type arg_type,\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               int check_ambiguity, int override,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               int no_free, int multiple_option,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               const char *long_opt, char short_opt,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               const char *additional_error)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *stop_char = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  const char *val = value;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int found;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (has_arg_string)\n        {\n          stream << \"  char **string_field;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"  FIX_UNUSED (field);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  stop_char = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  found = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (short_opt != '-')\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        fprintf (stderr, \\\"%s: `--%s' (`-%c') option given more than once%s\\\\n\\\", \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               package_name, long_opt, short_opt,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               (additional_error ? additional_error : \\\"\\\"));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        fprintf (stderr, \\\"%s: `--%s' option given more than once%s\\\\n\\\", \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               package_name, long_opt,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               (additional_error ? additional_error : \\\"\\\"));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      return 1; /* failure */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      if (check_possible_values)\n        {\n          stream << \"  if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      if (short_opt != '-')\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        fprintf (stderr, \\\"%s: %s argument, \\\\\\\"%s\\\\\\\", for option `--%s' (`-%c')%s\\\\n\\\", \";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          package_name, (found == -2) ? \\\"ambiguous\\\" : \\\"invalid\\\", value, long_opt, short_opt,\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (additional_error ? additional_error : \\\"\\\"));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      else\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        fprintf (stderr, \\\"%s: %s argument, \\\\\\\"%s\\\\\\\", for option `--%s'%s\\\\n\\\", \";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          package_name, (found == -2) ? \\\"ambiguous\\\" : \\\"invalid\\\", value, long_opt,\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (additional_error ? additional_error : \\\"\\\"));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      return 1; /* failure */\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    }\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      else\n        {\n          stream << \"  FIX_UNUSED (default_value);\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"    \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (field_given && *field_given && ! override)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (prev_given)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    (*prev_given)++;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (field_given)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    (*field_given)++;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (possible_values)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    val = possible_values[found];\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  switch(arg_type) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (has_arg_flag)\n        {\n          stream << \"  case ARG_FLAG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    *((int *)field) = !*((int *)field);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_int)\n        {\n          stream << \"  case ARG_INT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((int *)field) = strtol (val, &stop_char, 0);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_short)\n        {\n          stream << \"  case ARG_SHORT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((short *)field) = (short)strtol (val, &stop_char, 0);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_long)\n        {\n          stream << \"  case ARG_LONG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((long *)field) = (long)strtol (val, &stop_char, 0);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_float)\n        {\n          stream << \"  case ARG_FLOAT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((float *)field) = (float)strtod (val, &stop_char);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_double)\n        {\n          stream << \"  case ARG_DOUBLE:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((double *)field) = strtod (val, &stop_char);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longdouble)\n        {\n          stream << \"  case ARG_LONGDOUBLE:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((long double *)field) = (long double)strtod (val, &stop_char);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longlong)\n        {\n          stream << \"  case ARG_LONGLONG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#ifdef HAVE_LONG_LONG\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((long long int*)field) = (long long int) strtol (val, &stop_char, 0);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#else\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((long *)field) = (long)strtol (val, &stop_char, 0);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#endif\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_enum)\n        {\n          stream << \"  case ARG_ENUM:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) *((int *)field) = found;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_string)\n        {\n          stream << \"  case ARG_STRING:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    if (val) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      string_field = (char **)field;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      if (!no_free && *string_field)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        free (*string_field); /* free previous string */\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *string_field = gengetopt_strdup (val);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"  default:\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  };\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      if (( ( ( ( ( ( has_arg_int || has_arg_short ) || has_arg_long ) || has_arg_float ) || has_arg_double ) || has_arg_longdouble ) || has_arg_longlong ))\n        {\n          stream << \"  /* check numeric conversion */\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  switch(arg_type) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          if (has_arg_int)\n            {\n              stream << \"  case ARG_INT:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          if (has_arg_short)\n            {\n              stream << \"  case ARG_SHORT:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          if (has_arg_long)\n            {\n              stream << \"  case ARG_LONG:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          if (has_arg_float)\n            {\n              stream << \"  case ARG_FLOAT:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          if (has_arg_double)\n            {\n              stream << \"  case ARG_DOUBLE:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          if (has_arg_longdouble)\n            {\n              stream << \"  case ARG_LONGDOUBLE:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          if (has_arg_longlong)\n            {\n              stream << \"  case ARG_LONGLONG:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          stream << \"    if (val && !(stop_char && *stop_char == '\\\\0')) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      fprintf(stderr, \\\"%s: invalid numeric value: %s\\\\n\\\", package_name, val);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      return 1; /* failure */\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  default:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    ;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  };\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  /* store the original value */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  switch(arg_type) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  case ARG_NO:\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (has_arg_flag)\n        {\n          stream << \"  case ARG_FLAG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"    break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  default:\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    if (value && orig_field) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (no_free) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        *orig_field = value;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      } else {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        if (*orig_field)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          free (*orig_field); /* free previous string */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        *orig_field = gengetopt_strdup (value);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  };\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return 0; /* OK */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  if (multiple_token_functions)\n    {\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"brief store information about a multiple option in a temporary list\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param list where to (temporarily) store multiple options\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int update_multiple_arg_temp(struct generic_list **list,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               unsigned int *prev_given, const char *val,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               const char *possible_values[], const char *default_value,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 15;\n      stream << \"               \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_arg_type arg_type,\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               const char *long_opt, char short_opt,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               const char *additional_error)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  /* store single arguments */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *multi_token;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  const char *multi_next;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (arg_type == ARG_NO) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    (*prev_given)++;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    return 0; /* OK */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  multi_token = get_multiple_arg_token(val);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  multi_next = get_multiple_arg_token_next (val);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while (1)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      add_node (list);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (update_arg((void *)&((*list)->arg), &((*list)->orig), 0,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          prev_given, multi_token, possible_values, default_value, \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          arg_type, 0, 1, 1, 1, long_opt, short_opt, additional_error)) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        if (multi_token) free(multi_token);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        return 1; /* failure */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (multi_next)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          multi_token = get_multiple_arg_token(multi_next);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          multi_next = get_multiple_arg_token_next (multi_next);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return 0; /* OK */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"brief free the passed list (including possible string argument)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"void free_list(struct generic_list *list, short string_arg)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (list) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    struct generic_list *tmp;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    while (list)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        tmp = list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        if (string_arg && list->arg.string_arg)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          free (list->arg.string_arg);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        if (list->orig)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          free (list->orig);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        list = list->next;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        free (tmp);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"brief updates a multiple option starting from the passed list\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"void update_multiple_arg(void *field, char ***orig_field,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               unsigned int field_given, unsigned int prev_given, union generic_value *default_value,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 15;\n      stream << \"               \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_arg_type arg_type,\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"               struct generic_list *list)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int i;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct generic_list *tmp;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (prev_given && list) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    *orig_field = (char **) realloc (*orig_field, (field_given + prev_given) * sizeof (char *));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    switch(arg_type) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (( has_arg_int || has_arg_enum ))\n        {\n          if (has_arg_int)\n            {\n              stream << \"    case ARG_INT:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          if (has_arg_enum)\n            {\n              stream << \"    case ARG_ENUM:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          stream << \"      *((int **)field) = (int *)realloc (*((int **)field), (field_given + prev_given) * sizeof (int)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_short)\n        {\n          stream << \"    case ARG_SHORT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *((short **)field) = (short *)realloc (*((short **)field), (field_given + prev_given) * sizeof (short)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_long)\n        {\n          stream << \"    case ARG_LONG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *((long **)field) = (long *)realloc (*((long **)field), (field_given + prev_given) * sizeof (long)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_float)\n        {\n          stream << \"    case ARG_FLOAT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *((float **)field) = (float *)realloc (*((float **)field), (field_given + prev_given) * sizeof (float)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_double)\n        {\n          stream << \"    case ARG_DOUBLE:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *((double **)field) = (double *)realloc (*((double **)field), (field_given + prev_given) * sizeof (double)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longdouble)\n        {\n          stream << \"    case ARG_LONGDOUBLE:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *((long double **)field) = (long double *)realloc (*((long double **)field), (field_given + prev_given) * sizeof (long double)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longlong)\n        {\n          stream << \"    case ARG_LONGLONG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#ifdef HAVE_LONG_LONG\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *((long long int **)field) = (long long int *)realloc (*((long long int **)field), (field_given + prev_given) * sizeof (long long int)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#else\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *((long **)field) = (long *)realloc (*((long **)field), (field_given + prev_given) * sizeof (long)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#endif\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_string)\n        {\n          stream << \"    case ARG_STRING:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      *((char ***)field) = (char **)realloc (*((char ***)field), (field_given + prev_given) * sizeof (char *)); break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"    default:\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    };\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 4;\n      stream << \"    \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    for (i = (prev_given - 1); i >= 0; --i)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        tmp = list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 8;\n      stream << \"        \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        switch(arg_type) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (has_arg_int)\n        {\n          stream << \"        case ARG_INT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((int **)field))[i + field_given] = tmp->arg.int_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_short)\n        {\n          stream << \"        case ARG_SHORT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((short **)field))[i + field_given] = tmp->arg.short_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_long)\n        {\n          stream << \"        case ARG_LONG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((long **)field))[i + field_given] = tmp->arg.long_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_float)\n        {\n          stream << \"        case ARG_FLOAT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((float **)field))[i + field_given] = tmp->arg.float_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_double)\n        {\n          stream << \"        case ARG_DOUBLE:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((double **)field))[i + field_given] = tmp->arg.double_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longdouble)\n        {\n          stream << \"        case ARG_LONGDOUBLE:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((long double **)field))[i + field_given] = tmp->arg.longdouble_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longlong)\n        {\n          stream << \"        case ARG_LONGLONG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#ifdef HAVE_LONG_LONG\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((long long int **)field))[i + field_given] = tmp->arg.longlong_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#else\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((long **)field))[i + field_given] = tmp->arg.longlong_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#endif\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_enum)\n        {\n          stream << \"        case ARG_ENUM:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((int **)field))[i + field_given] = tmp->arg.int_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_string)\n        {\n          stream << \"        case ARG_STRING:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((char ***)field))[i + field_given] = tmp->arg.string_arg; break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"        default:\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }        \";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        (*orig_field) [i + field_given] = list->orig;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        list = list->next;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        free (tmp);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  } else { /* set the default value */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    if (default_value && ! field_given) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      switch(arg_type) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (( has_arg_int || has_arg_enum ))\n        {\n          if (has_arg_int)\n            {\n              stream << \"      case ARG_INT:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          if (has_arg_enum)\n            {\n              stream << \"      case ARG_ENUM:\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          stream << \"        if (! *((int **)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((int **)field) = (int *)malloc (sizeof (int));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((int **)field))[0] = default_value->int_arg; \";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_short)\n        {\n          stream << \"      case ARG_SHORT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (! *((short **)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((short **)field) = (short *)malloc (sizeof (short));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((short **)field))[0] = default_value->short_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_long)\n        {\n          stream << \"      case ARG_LONG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (! *((long **)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((long **)field) = (long *)malloc (sizeof (long));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((long **)field))[0] = default_value->long_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_float)\n        {\n          stream << \"      case ARG_FLOAT:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (! *((float **)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((float **)field) = (float *)malloc (sizeof (float));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((float **)field))[0] = default_value->float_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_double)\n        {\n          stream << \"      case ARG_DOUBLE:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (! *((double **)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((double **)field) = (double *)malloc (sizeof (double));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((double **)field))[0] = default_value->double_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longdouble)\n        {\n          stream << \"      case ARG_LONGDOUBLE:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (! *((long double **)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((long double **)field) = (long double *)malloc (sizeof (long double));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((long double **)field))[0] = default_value->longdouble_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_longlong)\n        {\n          stream << \"      case ARG_LONGLONG:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#ifdef HAVE_LONG_LONG\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (! *((long long int **)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((long long int **)field) = (long long int *)malloc (sizeof (long long int));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((long long int **)field))[0] = default_value->longlong_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#else\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (! *((long **)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((long **)field) = (long *)malloc (sizeof (long));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((long **)field))[0] = default_value->longlong_arg;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"#endif\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (has_arg_string)\n        {\n          stream << \"      case ARG_STRING:\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (! *((char ***)field)) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          *((char ***)field) = (char **)malloc (sizeof (char *));\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          (*((char ***)field))[0] = gengetopt_strdup(default_value->string_arg);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"      default: break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (!(*orig_field)) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        *orig_field = (char **) malloc (sizeof (char *));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        (*orig_field)[0] = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_modes)\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static int check_modes(\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int given1[], const char *options1[],\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                       int given2[], const char *options2[])\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int i = 0, j = 0, errors = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while (given1[i] >= 0) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    if (given1[i]) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      while (given2[j] >= 0) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        if (given2[j]) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          ++errors;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          fprintf(stderr, \\\"%s: option %s conflicts with option %s\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                  package_name, options1[i], options2[j]);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        ++j;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    ++i;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return errors;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int\";\n  stream << \"\\n\";\n  stream << indent_str;\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_internal (\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int argc, char **argv, struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"                        struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *params, const char *additional_error)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int c;\t/* Character of the parsed option.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (multiple_options_with_default)\n    {\n      stream << \"  union generic_value multiple_default_value;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  if (list_def.size () > 0)\n    generate_string (list_def, stream, indent + indent_str.length ());\n  else\n    generate_list_def (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  stream << \"  int error = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" local_args_info;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int override;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int initialize;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int check_required;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int check_ambiguity;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (include_getopt)\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *optarg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int optind;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int opterr;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int optopt;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"  \";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  package_name = argv[0];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  override = params->override;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  initialize = params->initialize;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  check_required = params->check_required;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  check_ambiguity = params->check_ambiguity;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if (initialize)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 4;\n  stream << \"    \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_init (args_info);\";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_init (&local_args_info);\";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  optarg = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  optind = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  opterr = params->print_errors;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  optopt = '?';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  while (1)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      int option_index = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      static struct option long_options[] = {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 8;\n  if (long_option_struct.size () > 0)\n    generate_string (long_option_struct, stream, indent + indent_str.length ());\n  else\n    generate_long_option_struct (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  stream << \"        { 0,  0, 0, 0 }\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      };\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (include_getopt)\n    {\n      stream << \"      custom_optarg = optarg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      custom_optind = optind;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      custom_opterr = opterr;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      custom_optopt = optopt;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      c = custom_getopt_long (argc, argv, \\\"\";\n      generate_string (getopt_string, stream, indent + indent_str.length ());\n      stream << \"\\\", long_options, &option_index);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      optarg = custom_optarg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      optind = custom_optind;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      opterr = custom_opterr;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      optopt = custom_optopt;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"      c = getopt_long (argc, argv, \\\"\";\n      generate_string (getopt_string, stream, indent + indent_str.length ());\n      stream << \"\\\", long_options, &option_index);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      if (c == -1) break;\t/* Exit from `while (1)' loop.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"      switch (c)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"        {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 8;\n  if (handle_option.size () > 0)\n    generate_string (handle_option, stream, indent + indent_str.length ());\n  else\n    generate_handle_option (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"        case 0:\t/* Long option with no short option */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 10;\n  if (handle_no_short_option.size () > 0)\n    generate_string (handle_no_short_option, stream, indent + indent_str.length ());\n  else\n    generate_handle_no_short_option (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  if (handle_question_mark)\n    {\n      stream << \"        case '?':\t/* Invalid option.  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          /* `getopt_long' already printed an error message.  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          goto failure;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"        default:\t/* bug: option not considered.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"          fprintf (stderr, \\\"%s: option unknown: %c%s\\\\n\\\", \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \", c, (additional_error ? additional_error : \\\"\\\"));\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"          abort ();\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"        } /* switch */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    } /* while */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  if (handle_group.size () > 0)\n    generate_string (handle_group, stream, indent + indent_str.length ());\n  else\n    generate_handle_group (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  if (multiple_fill_array.size () > 0)\n    generate_string (multiple_fill_array, stream, indent + indent_str.length ());\n  else\n    generate_multiple_fill_array (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  indent = 2;\n  if (update_multiple_given.size () > 0)\n    generate_string (update_multiple_given, stream, indent + indent_str.length ());\n  else\n    generate_update_multiple_given (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  indent = 2;\n  if (check_modes.size () > 0)\n    generate_string (check_modes, stream, indent + indent_str.length ());\n  else\n    generate_check_modes (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (check_required_options)\n    {\n      stream << \"  if (check_required)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      error += \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_required2 (args_info, argv[0], additional_error);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_release (&local_args_info);\";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if ( error )\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    return (EXIT_FAILURE);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (handle_unamed)\n    {\n      stream << \"  if (optind < argc)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      int i = 0 ;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      int found_prog_name = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* whether program name, i.e., argv[0], is in the remaining args\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"         (this may happen with some implementations of getopt,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          but surely not with the one included by gengetopt) */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      if (include_getopt)\n        {\n\n\n        }\n      else\n        {\n          stream << \"      i = optind;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      while (i < argc)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        if (argv[i++] == argv[0]) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          found_prog_name = 1;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          break;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"        }\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      i = 0;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      args_info->inputs_num = argc - optind - found_prog_name;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      args_info->inputs =\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      while (optind < argc)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (include_getopt)\n        {\n          stream << \"        args_info->inputs[ i++ ] = gengetopt_strdup (argv[optind++]) ;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      else\n        {\n          stream << \"        if (argv[optind++] != argv[0])\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"          args_info->inputs[ i++ ] = gengetopt_strdup (argv[optind-1]) ;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"  return 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"failure:\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  if (list_free.size () > 0)\n    generate_string (list_free, stream, indent + indent_str.length ());\n  else\n    generate_list_free (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_release (&local_args_info);\";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  return (EXIT_FAILURE);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (conf_parser)\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#ifndef CONFIG_FILE_LINE_SIZE\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#define CONFIG_FILE_LINE_SIZE 2048\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#endif\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#define ADDITIONAL_ERROR \\\" in configuration file \\\"\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#define CONFIG_FILE_LINE_BUFFER_SIZE (CONFIG_FILE_LINE_SIZE+3)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"/* 3 is for \\\"--\\\" and \\\"=\\\" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"_\";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_configfile (const char *filename, int *my_argc)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  FILE* file;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char my_argv[CONFIG_FILE_LINE_BUFFER_SIZE+1];\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char linebuf[CONFIG_FILE_LINE_SIZE];\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int line_num = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int result = 0, equal;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *fopt, *farg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *str_index;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  size_t len, next_token;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char delimiter;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if ((file = fopen(filename, \\\"r\\\")) == 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      fprintf (stderr, \\\"%s: Error opening configuration file '%s'\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 15;\n      stream << \"               \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \", filename);\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      return EXIT_FAILURE;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while ((fgets(linebuf, CONFIG_FILE_LINE_SIZE, file)) != 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      ++line_num;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      my_argv[0] = '\\\\0';\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      len = strlen(linebuf);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (len > (CONFIG_FILE_LINE_BUFFER_SIZE-1))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          fprintf (stderr, \\\"%s:%s:%d: Line too long in configuration file\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 19;\n      stream << \"                   \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \", filename, line_num);\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          result = EXIT_FAILURE;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* find first non-whitespace character in the line */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      next_token = strspn (linebuf, \\\" \\\\t\\\\r\\\\n\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      str_index  = linebuf + next_token;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if ( str_index[0] == '\\\\0' || str_index[0] == '#')\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        continue; /* empty line or comment line is skipped */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      fopt = str_index;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* truncate fopt at the end of the first non-valid character */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      next_token = strcspn (fopt, \\\" \\\\t\\\\r\\\\n=\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (fopt[next_token] == '\\\\0') /* the line is over */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          farg  = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          equal = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          goto noarg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* remember if equal sign is present */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      equal = (fopt[next_token] == '=');\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      fopt[next_token++] = '\\\\0';\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* advance pointers to the next token after the end of fopt */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      next_token += strspn (fopt + next_token, \\\" \\\\t\\\\r\\\\n\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* check for the presence of equal sign, and if so, skip it */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if ( !equal )\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        if ((equal = (fopt[next_token] == '=')))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            next_token++;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            next_token += strspn (fopt + next_token, \\\" \\\\t\\\\r\\\\n\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      str_index  += next_token;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* find argument */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      farg = str_index;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if ( farg[0] == '\\\\\\\"' || farg[0] == '\\\\'' )\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        { /* quoted argument */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          str_index = strchr (++farg, str_index[0] ); /* skip opening quote */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          if (! str_index)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              fprintf\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                (stderr,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                 \\\"%s:%s:%d: unterminated string in configuration file\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 17;\n      stream << \"                 \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \", filename, line_num);\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              result = EXIT_FAILURE;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        { /* read up the remaining part up to a delimiter */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          next_token = strcspn (farg, \\\" \\\\t\\\\r\\\\n#\\\\'\\\\\\\"\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          str_index += next_token;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* truncate farg at the delimiter and store it for further check */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      delimiter = *str_index, *str_index++ = '\\\\0';\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      /* everything but comment is illegal at the end of line */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (delimiter != '\\\\0' && delimiter != '#')\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          str_index += strspn(str_index, \\\" \\\\t\\\\r\\\\n\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          if (*str_index != '\\\\0' && *str_index != '#')\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              fprintf\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                (stderr,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                 \\\"%s:%s:%d: malformed string in configuration file\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 17;\n      stream << \"                 \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \", filename, line_num);\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              result = EXIT_FAILURE;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"              break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"            }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    noarg:\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (!strcmp(fopt,\\\"include\\\")) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        if (farg && *farg) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          result = _\";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_configfile(farg, my_argc);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        } else {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          fprintf(stderr, \\\"%s:%s:%d: include requires a filename argument.\\\\n\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 18;\n      stream << \"                  \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \", filename, line_num);\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        continue;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      len = strlen(fopt);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      strcat (my_argv, len > 1 ? \\\"--\\\" : \\\"-\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      strcat (my_argv, fopt);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (len > 1 && ((farg && *farg) || equal))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        strcat (my_argv, \\\"=\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (farg && *farg)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        strcat (my_argv, farg);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      ++(*my_argc);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      cmd_line_list_tmp->next = cmd_line_list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      cmd_line_list = cmd_line_list_tmp;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      cmd_line_list->string_arg = gengetopt_strdup(my_argv);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    } /* while */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (file)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    fclose(file);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return result;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_configfile (\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  const char *filename,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                           struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                           int override, int initialize, int check_required)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_params params;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.override = override;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.initialize = initialize;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.check_required = check_required;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.check_ambiguity = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.print_errors = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_config_file (filename, args_info, &params);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_config_file (const char *filename,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                           struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                           struct \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_params *params)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int i, result;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int my_argc = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char **my_argv_arg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *additional_error;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  /* store the program name */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  cmd_line_list_tmp->next = cmd_line_list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  cmd_line_list = cmd_line_list_tmp;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  cmd_line_list->string_arg = gengetopt_strdup (\";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  result = _\";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_configfile(filename, &my_argc);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (result != EXIT_FAILURE) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    my_argv_arg = (char **) malloc((my_argc+1) * sizeof(char *));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    cmd_line_list_tmp = cmd_line_list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    for (i = my_argc - 1; i >= 0; --i) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      my_argv_arg[i] = cmd_line_list_tmp->string_arg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      cmd_line_list_tmp = cmd_line_list_tmp->next;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    my_argv_arg[my_argc] = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    additional_error = (char *)malloc(strlen(filename) + strlen(ADDITIONAL_ERROR) + 1);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    strcpy (additional_error, ADDITIONAL_ERROR);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    strcat (additional_error, filename);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    result =\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 6;\n      stream << \"      \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_internal (my_argc, my_argv_arg, args_info,\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                              params,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"                              additional_error);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    free (additional_error);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    free (my_argv_arg);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  free_cmd_list();\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      generate_string (final_exit, stream, indent + indent_str.length ());\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (generate_string_parser)\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"static unsigned int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_create_argv(const char *cmdline_, char ***argv_ptr, const char *prog_name)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char *cmdline, *p;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  size_t n = 0, j;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int i;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (prog_name) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    cmd_line_list_tmp->next = cmd_line_list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    cmd_line_list = cmd_line_list_tmp;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    cmd_line_list->string_arg = gengetopt_strdup (prog_name);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    ++n;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  cmdline = gengetopt_strdup(cmdline_);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  p = cmdline;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  while (p && strlen(p))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      j = strcspn(p, \\\" \\\\t\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      ++n;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      if (j && j < strlen(p))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          p[j] = '\\\\0';\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          cmd_line_list_tmp->next = cmd_line_list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          cmd_line_list = cmd_line_list_tmp;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          cmd_line_list->string_arg = gengetopt_strdup (p);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          p += (j+1);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          p += strspn(p, \\\" \\\\t\\\");\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          cmd_line_list_tmp->next = cmd_line_list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          cmd_line_list = cmd_line_list_tmp;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          cmd_line_list->string_arg = gengetopt_strdup (p);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"          break;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"        }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  *argv_ptr = (char **) malloc((n + 1) * sizeof(char *));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  cmd_line_list_tmp = cmd_line_list;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  for (i = (n-1); i >= 0; --i)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      (*argv_ptr)[i] = cmd_line_list_tmp->string_arg;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      cmd_line_list_tmp = cmd_line_list_tmp->next;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  (*argv_ptr)[n] = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  free(cmdline);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return n;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string(const char *cmdline, struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info, const char *prog_name)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string2(cmdline, args_info, prog_name, 0, 1, 1);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string2(const char *cmdline, struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info, const char *prog_name,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    int override, int initialize, int check_required)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_params params;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.override = override;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.initialize = initialize;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.check_required = check_required;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.check_ambiguity = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  params.print_errors = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  return \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string_ext(cmdline, args_info, prog_name, &params);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string_ext(const char *cmdline, struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info, const char *prog_name,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    struct \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_params *params)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  char **argv_ptr = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int result;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  unsigned int argc;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  argc = \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_create_argv(cmdline, &argv_ptr, prog_name);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  result =\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 4;\n      stream << \"    \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_internal (argc, argv_ptr, args_info, params, 0);\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  if (argv_ptr)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"      free (argv_ptr);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  free_cmd_list();\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      generate_string (final_exit, stream, indent + indent_str.length ());\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/c_source.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef C_SOURCE_GEN_CLASS_H\n#define C_SOURCE_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass c_source_gen_class\n{\n protected:\n  string args_info;\n  string check_modes;\n  bool check_possible_values;\n  bool check_required_options;\n  string clear_arg;\n  bool cmd_list;\n  string command_line;\n  bool conf_parser;\n  string custom_getopt;\n  string description;\n  string detailed_help_option_print;\n  bool do_generate_strdup;\n  string file_save_loop;\n  string final_exit;\n  string free;\n  string full_help_option_print;\n  bool generate_string_parser;\n  string generator_version;\n  string getopt_string;\n  string given_init;\n  string handle_dependencies;\n  string handle_group;\n  string handle_no_short_option;\n  string handle_option;\n  bool handle_question_mark;\n  string handle_required;\n  bool handle_unamed;\n  bool has_arg_double;\n  bool has_arg_enum;\n  bool has_arg_flag;\n  bool has_arg_float;\n  bool has_arg_int;\n  bool has_arg_long;\n  bool has_arg_longdouble;\n  bool has_arg_longlong;\n  bool has_arg_short;\n  bool has_arg_string;\n  bool has_details;\n  bool has_hidden;\n  bool has_modes;\n  bool has_typed_options;\n  string header_file_ext;\n  string help_option_print;\n  string help_string_num;\n  bool include_getopt;\n  string init_args_info;\n  string list_def;\n  string list_free;\n  string long_option_struct;\n  string multiple_fill_array;\n  bool multiple_options;\n  bool multiple_options_all_string;\n  bool multiple_options_string;\n  bool multiple_options_with_default;\n  bool multiple_token_functions;\n  bool no_options;\n  bool no_package;\n  string option_values;\n  string package_var_name;\n  string parser_name;\n  string purpose;\n  string reset_groups;\n  string source_name;\n  string update_multiple_given;\n  string usage_string;\n  string version_var_name;\n\n public:\n  c_source_gen_class() :\n    check_possible_values (false), check_required_options (false), cmd_list (false), conf_parser (false), do_generate_strdup (false), generate_string_parser (false), handle_question_mark (false), handle_unamed (false), has_arg_double (false), has_arg_enum (false), has_arg_flag (false), has_arg_float (false), has_arg_int (false), has_arg_long (false), has_arg_longdouble (false), has_arg_longlong (false), has_arg_short (false), has_arg_string (false), has_details (false), has_hidden (false), has_modes (false), has_typed_options (false), include_getopt (false), multiple_options (false), multiple_options_all_string (false), multiple_options_string (false), multiple_options_with_default (false), multiple_token_functions (false), no_options (false), no_package (false)\n  {\n  }\n\n  c_source_gen_class(const string &_args_info, const string &_check_modes, bool _check_possible_values, bool _check_required_options, const string &_clear_arg, bool _cmd_list, const string &_command_line, bool _conf_parser, const string &_custom_getopt, const string &_description, const string &_detailed_help_option_print, bool _do_generate_strdup, const string &_file_save_loop, const string &_final_exit, const string &_free, const string &_full_help_option_print, bool _generate_string_parser, const string &_generator_version, const string &_getopt_string, const string &_given_init, const string &_handle_dependencies, const string &_handle_group, const string &_handle_no_short_option, const string &_handle_option, bool _handle_question_mark, const string &_handle_required, bool _handle_unamed, bool _has_arg_double, bool _has_arg_enum, bool _has_arg_flag, bool _has_arg_float, bool _has_arg_int, bool _has_arg_long, bool _has_arg_longdouble, bool _has_arg_longlong, bool _has_arg_short, bool _has_arg_string, bool _has_details, bool _has_hidden, bool _has_modes, bool _has_typed_options, const string &_header_file_ext, const string &_help_option_print, const string &_help_string_num, bool _include_getopt, const string &_init_args_info, const string &_list_def, const string &_list_free, const string &_long_option_struct, const string &_multiple_fill_array, bool _multiple_options, bool _multiple_options_all_string, bool _multiple_options_string, bool _multiple_options_with_default, bool _multiple_token_functions, bool _no_options, bool _no_package, const string &_option_values, const string &_package_var_name, const string &_parser_name, const string &_purpose, const string &_reset_groups, const string &_source_name, const string &_update_multiple_given, const string &_usage_string, const string &_version_var_name) :\n    args_info (_args_info), check_modes (_check_modes), check_possible_values (_check_possible_values), check_required_options (_check_required_options), clear_arg (_clear_arg), cmd_list (_cmd_list), command_line (_command_line), conf_parser (_conf_parser), custom_getopt (_custom_getopt), description (_description), detailed_help_option_print (_detailed_help_option_print), do_generate_strdup (_do_generate_strdup), file_save_loop (_file_save_loop), final_exit (_final_exit), free (_free), full_help_option_print (_full_help_option_print), generate_string_parser (_generate_string_parser), generator_version (_generator_version), getopt_string (_getopt_string), given_init (_given_init), handle_dependencies (_handle_dependencies), handle_group (_handle_group), handle_no_short_option (_handle_no_short_option), handle_option (_handle_option), handle_question_mark (_handle_question_mark), handle_required (_handle_required), handle_unamed (_handle_unamed), has_arg_double (_has_arg_double), has_arg_enum (_has_arg_enum), has_arg_flag (_has_arg_flag), has_arg_float (_has_arg_float), has_arg_int (_has_arg_int), has_arg_long (_has_arg_long), has_arg_longdouble (_has_arg_longdouble), has_arg_longlong (_has_arg_longlong), has_arg_short (_has_arg_short), has_arg_string (_has_arg_string), has_details (_has_details), has_hidden (_has_hidden), has_modes (_has_modes), has_typed_options (_has_typed_options), header_file_ext (_header_file_ext), help_option_print (_help_option_print), help_string_num (_help_string_num), include_getopt (_include_getopt), init_args_info (_init_args_info), list_def (_list_def), list_free (_list_free), long_option_struct (_long_option_struct), multiple_fill_array (_multiple_fill_array), multiple_options (_multiple_options), multiple_options_all_string (_multiple_options_all_string), multiple_options_string (_multiple_options_string), multiple_options_with_default (_multiple_options_with_default), multiple_token_functions (_multiple_token_functions), no_options (_no_options), no_package (_no_package), option_values (_option_values), package_var_name (_package_var_name), parser_name (_parser_name), purpose (_purpose), reset_groups (_reset_groups), source_name (_source_name), update_multiple_given (_update_multiple_given), usage_string (_usage_string), version_var_name (_version_var_name)\n  {\n  }\n\n  virtual ~c_source_gen_class()\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_args_info(const string &_args_info)\n  {\n    args_info = _args_info;\n  }\n\n  virtual void generate_check_modes(ostream &stream, unsigned int indent) = 0;\n\n  void set_check_modes(const string &_check_modes)\n  {\n    check_modes = _check_modes;\n  }\n\n  void set_check_possible_values(bool _check_possible_values)\n  {\n    check_possible_values = _check_possible_values;\n  }\n\n  void set_check_required_options(bool _check_required_options)\n  {\n    check_required_options = _check_required_options;\n  }\n\n  virtual void generate_clear_arg(ostream &stream, unsigned int indent) = 0;\n\n  void set_clear_arg(const string &_clear_arg)\n  {\n    clear_arg = _clear_arg;\n  }\n\n  void set_cmd_list(bool _cmd_list)\n  {\n    cmd_list = _cmd_list;\n  }\n\n  void set_command_line(const string &_command_line)\n  {\n    command_line = _command_line;\n  }\n\n  void set_conf_parser(bool _conf_parser)\n  {\n    conf_parser = _conf_parser;\n  }\n\n  virtual void generate_custom_getopt(ostream &stream, unsigned int indent) = 0;\n\n  void set_custom_getopt(const string &_custom_getopt)\n  {\n    custom_getopt = _custom_getopt;\n  }\n\n  void set_description(const string &_description)\n  {\n    description = _description;\n  }\n\n  virtual void generate_detailed_help_option_print(ostream &stream, unsigned int indent) = 0;\n\n  void set_detailed_help_option_print(const string &_detailed_help_option_print)\n  {\n    detailed_help_option_print = _detailed_help_option_print;\n  }\n\n  void set_do_generate_strdup(bool _do_generate_strdup)\n  {\n    do_generate_strdup = _do_generate_strdup;\n  }\n\n  virtual void generate_file_save_loop(ostream &stream, unsigned int indent) = 0;\n\n  void set_file_save_loop(const string &_file_save_loop)\n  {\n    file_save_loop = _file_save_loop;\n  }\n\n  void set_final_exit(const string &_final_exit)\n  {\n    final_exit = _final_exit;\n  }\n\n  virtual void generate_free(ostream &stream, unsigned int indent) = 0;\n\n  void set_free(const string &_free)\n  {\n    free = _free;\n  }\n\n  virtual void generate_full_help_option_print(ostream &stream, unsigned int indent) = 0;\n\n  void set_full_help_option_print(const string &_full_help_option_print)\n  {\n    full_help_option_print = _full_help_option_print;\n  }\n\n  void set_generate_string_parser(bool _generate_string_parser)\n  {\n    generate_string_parser = _generate_string_parser;\n  }\n\n  void set_generator_version(const string &_generator_version)\n  {\n    generator_version = _generator_version;\n  }\n\n  void set_getopt_string(const string &_getopt_string)\n  {\n    getopt_string = _getopt_string;\n  }\n\n  virtual void generate_given_init(ostream &stream, unsigned int indent) = 0;\n\n  void set_given_init(const string &_given_init)\n  {\n    given_init = _given_init;\n  }\n\n  virtual void generate_handle_dependencies(ostream &stream, unsigned int indent) = 0;\n\n  void set_handle_dependencies(const string &_handle_dependencies)\n  {\n    handle_dependencies = _handle_dependencies;\n  }\n\n  virtual void generate_handle_group(ostream &stream, unsigned int indent) = 0;\n\n  void set_handle_group(const string &_handle_group)\n  {\n    handle_group = _handle_group;\n  }\n\n  virtual void generate_handle_no_short_option(ostream &stream, unsigned int indent) = 0;\n\n  void set_handle_no_short_option(const string &_handle_no_short_option)\n  {\n    handle_no_short_option = _handle_no_short_option;\n  }\n\n  virtual void generate_handle_option(ostream &stream, unsigned int indent) = 0;\n\n  void set_handle_option(const string &_handle_option)\n  {\n    handle_option = _handle_option;\n  }\n\n  void set_handle_question_mark(bool _handle_question_mark)\n  {\n    handle_question_mark = _handle_question_mark;\n  }\n\n  virtual void generate_handle_required(ostream &stream, unsigned int indent) = 0;\n\n  void set_handle_required(const string &_handle_required)\n  {\n    handle_required = _handle_required;\n  }\n\n  void set_handle_unamed(bool _handle_unamed)\n  {\n    handle_unamed = _handle_unamed;\n  }\n\n  void set_has_arg_double(bool _has_arg_double)\n  {\n    has_arg_double = _has_arg_double;\n  }\n\n  void set_has_arg_enum(bool _has_arg_enum)\n  {\n    has_arg_enum = _has_arg_enum;\n  }\n\n  void set_has_arg_flag(bool _has_arg_flag)\n  {\n    has_arg_flag = _has_arg_flag;\n  }\n\n  void set_has_arg_float(bool _has_arg_float)\n  {\n    has_arg_float = _has_arg_float;\n  }\n\n  void set_has_arg_int(bool _has_arg_int)\n  {\n    has_arg_int = _has_arg_int;\n  }\n\n  void set_has_arg_long(bool _has_arg_long)\n  {\n    has_arg_long = _has_arg_long;\n  }\n\n  void set_has_arg_longdouble(bool _has_arg_longdouble)\n  {\n    has_arg_longdouble = _has_arg_longdouble;\n  }\n\n  void set_has_arg_longlong(bool _has_arg_longlong)\n  {\n    has_arg_longlong = _has_arg_longlong;\n  }\n\n  void set_has_arg_short(bool _has_arg_short)\n  {\n    has_arg_short = _has_arg_short;\n  }\n\n  void set_has_arg_string(bool _has_arg_string)\n  {\n    has_arg_string = _has_arg_string;\n  }\n\n  void set_has_details(bool _has_details)\n  {\n    has_details = _has_details;\n  }\n\n  void set_has_hidden(bool _has_hidden)\n  {\n    has_hidden = _has_hidden;\n  }\n\n  void set_has_modes(bool _has_modes)\n  {\n    has_modes = _has_modes;\n  }\n\n  void set_has_typed_options(bool _has_typed_options)\n  {\n    has_typed_options = _has_typed_options;\n  }\n\n  void set_header_file_ext(const string &_header_file_ext)\n  {\n    header_file_ext = _header_file_ext;\n  }\n\n  virtual void generate_help_option_print(ostream &stream, unsigned int indent) = 0;\n\n  void set_help_option_print(const string &_help_option_print)\n  {\n    help_option_print = _help_option_print;\n  }\n\n  void set_help_string_num(const string &_help_string_num)\n  {\n    help_string_num = _help_string_num;\n  }\n\n  void set_include_getopt(bool _include_getopt)\n  {\n    include_getopt = _include_getopt;\n  }\n\n  virtual void generate_init_args_info(ostream &stream, unsigned int indent) = 0;\n\n  void set_init_args_info(const string &_init_args_info)\n  {\n    init_args_info = _init_args_info;\n  }\n\n  virtual void generate_list_def(ostream &stream, unsigned int indent) = 0;\n\n  void set_list_def(const string &_list_def)\n  {\n    list_def = _list_def;\n  }\n\n  virtual void generate_list_free(ostream &stream, unsigned int indent) = 0;\n\n  void set_list_free(const string &_list_free)\n  {\n    list_free = _list_free;\n  }\n\n  virtual void generate_long_option_struct(ostream &stream, unsigned int indent) = 0;\n\n  void set_long_option_struct(const string &_long_option_struct)\n  {\n    long_option_struct = _long_option_struct;\n  }\n\n  virtual void generate_multiple_fill_array(ostream &stream, unsigned int indent) = 0;\n\n  void set_multiple_fill_array(const string &_multiple_fill_array)\n  {\n    multiple_fill_array = _multiple_fill_array;\n  }\n\n  void set_multiple_options(bool _multiple_options)\n  {\n    multiple_options = _multiple_options;\n  }\n\n  void set_multiple_options_all_string(bool _multiple_options_all_string)\n  {\n    multiple_options_all_string = _multiple_options_all_string;\n  }\n\n  void set_multiple_options_string(bool _multiple_options_string)\n  {\n    multiple_options_string = _multiple_options_string;\n  }\n\n  void set_multiple_options_with_default(bool _multiple_options_with_default)\n  {\n    multiple_options_with_default = _multiple_options_with_default;\n  }\n\n  void set_multiple_token_functions(bool _multiple_token_functions)\n  {\n    multiple_token_functions = _multiple_token_functions;\n  }\n\n  void set_no_options(bool _no_options)\n  {\n    no_options = _no_options;\n  }\n\n  void set_no_package(bool _no_package)\n  {\n    no_package = _no_package;\n  }\n\n  virtual void generate_option_values(ostream &stream, unsigned int indent) = 0;\n\n  void set_option_values(const string &_option_values)\n  {\n    option_values = _option_values;\n  }\n\n  void set_package_var_name(const string &_package_var_name)\n  {\n    package_var_name = _package_var_name;\n  }\n\n  void set_parser_name(const string &_parser_name)\n  {\n    parser_name = _parser_name;\n  }\n\n  void set_purpose(const string &_purpose)\n  {\n    purpose = _purpose;\n  }\n\n  virtual void generate_reset_groups(ostream &stream, unsigned int indent) = 0;\n\n  void set_reset_groups(const string &_reset_groups)\n  {\n    reset_groups = _reset_groups;\n  }\n\n  void set_source_name(const string &_source_name)\n  {\n    source_name = _source_name;\n  }\n\n  virtual void generate_update_multiple_given(ostream &stream, unsigned int indent) = 0;\n\n  void set_update_multiple_given(const string &_update_multiple_given)\n  {\n    update_multiple_given = _update_multiple_given;\n  }\n\n  void set_usage_string(const string &_usage_string)\n  {\n    usage_string = _usage_string;\n  }\n\n  void set_version_var_name(const string &_version_var_name)\n  {\n    version_var_name = _version_var_name;\n  }\n\n  void generate_c_source(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // C_SOURCE_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/check_modes.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"check_modes.h\"\n\nvoid\ncheck_modes_gen_class::generate_check_modes(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"if (args_info->\";\n  generate_string (mode1_name, stream, indent + indent_str.length ());\n  stream << \"_mode_counter && args_info->\";\n  generate_string (mode2_name, stream, indent + indent_str.length ());\n  stream << \"_mode_counter) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int \";\n  generate_string (mode1_name, stream, indent + indent_str.length ());\n  stream << \"_given[] = {\";\n  generate_string (mode1_given_fields, stream, indent + indent_str.length ());\n  stream << \" -1};\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  const char *\";\n  generate_string (mode1_name, stream, indent + indent_str.length ());\n  stream << \"_desc[] = {\";\n  generate_string (mode1_options, stream, indent + indent_str.length ());\n  stream << \" 0};\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int \";\n  generate_string (mode2_name, stream, indent + indent_str.length ());\n  stream << \"_given[] = {\";\n  generate_string (mode2_given_fields, stream, indent + indent_str.length ());\n  stream << \" -1};\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  const char *\";\n  generate_string (mode2_name, stream, indent + indent_str.length ());\n  stream << \"_desc[] = {\";\n  generate_string (mode2_options, stream, indent + indent_str.length ());\n  stream << \" 0};\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  error += check_modes(\";\n  generate_string (mode1_name, stream, indent + indent_str.length ());\n  stream << \"_given, \";\n  generate_string (mode1_name, stream, indent + indent_str.length ());\n  stream << \"_desc, \";\n  generate_string (mode2_name, stream, indent + indent_str.length ());\n  stream << \"_given, \";\n  generate_string (mode2_name, stream, indent + indent_str.length ());\n  stream << \"_desc);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/check_modes.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef CHECK_MODES_GEN_CLASS_H\n#define CHECK_MODES_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass check_modes_gen_class\n{\n protected:\n  string mode1_given_fields;\n  string mode1_name;\n  string mode1_options;\n  string mode2_given_fields;\n  string mode2_name;\n  string mode2_options;\n\n public:\n  check_modes_gen_class()\n  {\n  }\n\n  check_modes_gen_class(const string &_mode1_given_fields, const string &_mode1_name, const string &_mode1_options, const string &_mode2_given_fields, const string &_mode2_name, const string &_mode2_options) :\n    mode1_given_fields (_mode1_given_fields), mode1_name (_mode1_name), mode1_options (_mode1_options), mode2_given_fields (_mode2_given_fields), mode2_name (_mode2_name), mode2_options (_mode2_options)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_mode1_given_fields(const string &_mode1_given_fields)\n  {\n    mode1_given_fields = _mode1_given_fields;\n  }\n\n  void set_mode1_name(const string &_mode1_name)\n  {\n    mode1_name = _mode1_name;\n  }\n\n  void set_mode1_options(const string &_mode1_options)\n  {\n    mode1_options = _mode1_options;\n  }\n\n  void set_mode2_given_fields(const string &_mode2_given_fields)\n  {\n    mode2_given_fields = _mode2_given_fields;\n  }\n\n  void set_mode2_name(const string &_mode2_name)\n  {\n    mode2_name = _mode2_name;\n  }\n\n  void set_mode2_options(const string &_mode2_options)\n  {\n    mode2_options = _mode2_options;\n  }\n\n  void generate_check_modes(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // CHECK_MODES_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/clear_arg.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"clear_arg.h\"\n\nvoid\nclear_arg_gen_class::generate_clear_arg(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (has_arg)\n    {\n      stream << \"args_info->\";\n      generate_string (name, stream, indent + indent_str.length ());\n      stream << \"_\";\n      generate_string (suffix, stream, indent + indent_str.length ());\n      stream << \" = \";\n      generate_string (value, stream, indent + indent_str.length ());\n      stream << \";\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_orig)\n    {\n      stream << \"args_info->\";\n      generate_string (name, stream, indent + indent_str.length ());\n      stream << \"_orig = NULL;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/clear_arg.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef CLEAR_ARG_GEN_CLASS_H\n#define CLEAR_ARG_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass clear_arg_gen_class\n{\n protected:\n  bool has_arg;\n  bool has_orig;\n  string name;\n  string suffix;\n  string value;\n\n public:\n  clear_arg_gen_class() :\n    has_arg (false), has_orig (false)\n  {\n  }\n\n  clear_arg_gen_class(bool _has_arg, bool _has_orig, const string &_name, const string &_suffix, const string &_value) :\n    has_arg (_has_arg), has_orig (_has_orig), name (_name), suffix (_suffix), value (_value)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_has_arg(bool _has_arg)\n  {\n    has_arg = _has_arg;\n  }\n\n  void set_has_orig(bool _has_orig)\n  {\n    has_orig = _has_orig;\n  }\n\n  void set_name(const string &_name)\n  {\n    name = _name;\n  }\n\n  void set_suffix(const string &_suffix)\n  {\n    suffix = _suffix;\n  }\n\n  void set_value(const string &_value)\n  {\n    value = _value;\n  }\n\n  void generate_clear_arg(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // CLEAR_ARG_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/clear_given.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"clear_given.h\"\n\nvoid\nclear_given_gen_class::generate_clear_given(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  generate_string (arg_struct, stream, indent + indent_str.length ());\n  stream << \"->\";\n  generate_string (var_arg, stream, indent + indent_str.length ());\n  stream << \"_given = 0 ;\";\n  if (group)\n    {\n      indent = 1;\n      stream << \" \";\n      generate_string (arg_struct, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (var_arg, stream, indent + indent_str.length ());\n      stream << \"_group = 0 ;\";\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/clear_given.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef CLEAR_GIVEN_GEN_CLASS_H\n#define CLEAR_GIVEN_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass clear_given_gen_class\n{\n protected:\n  string arg_struct;\n  bool group;\n  string var_arg;\n\n public:\n  clear_given_gen_class() :\n    group (false)\n  {\n  }\n\n  clear_given_gen_class(const string &_arg_struct, bool _group, const string &_var_arg) :\n    arg_struct (_arg_struct), group (_group), var_arg (_var_arg)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_arg_struct(const string &_arg_struct)\n  {\n    arg_struct = _arg_struct;\n  }\n\n  void set_group(bool _group)\n  {\n    group = _group;\n  }\n\n  void set_var_arg(const string &_var_arg)\n  {\n    var_arg = _var_arg;\n  }\n\n  void generate_clear_given(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // CLEAR_GIVEN_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/copyright.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"copyright.h\"\n\nvoid\ncopyright_gen_class::generate_copyright(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"Copyright (C) \";\n  generate_string (year, stream, indent + indent_str.length ());\n  stream << \"  Free Software Foundation Inc.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"This program comes with ABSOLUTELY NO WARRANTY; for details\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"please see the file 'COPYING' supplied with the source code.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"This is free software, and you are welcome to redistribute it\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"under certain conditions; again, see 'COPYING' for details.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"This program is released under the GNU General Public License.\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/copyright.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef COPYRIGHT_GEN_CLASS_H\n#define COPYRIGHT_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass copyright_gen_class\n{\n protected:\n  string year;\n\n public:\n  copyright_gen_class()\n  {\n  }\n\n  copyright_gen_class(const string &_year) :\n    year (_year)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_year(const string &_year)\n  {\n    year = _year;\n  }\n\n  void generate_copyright(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // COPYRIGHT_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/custom_getopt_gen.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"custom_getopt_gen.h\"\n\nvoid\ncustom_getopt_gen_gen_class::generate_custom_getopt_gen(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Extracted from the glibc source tree, version 2.3.6\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Licensed under the GPL as per the whole glibc source tree.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * This file was modified so that getopt_long can be called\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * many times without risking previous memory to be spoiled.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Modified by Andre Noll and Lorenzo Bettini for use in\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * GNU gengetopt generated files.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/* \";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * we must include anything we need since this file is not thought to be\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * inserted in a file already using getopt.h\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Lorenzo\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"struct option\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  const char *name;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  /* has_arg can't be an enum because some compilers complain about\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"     type mismatches in all the code that assumes it is an int.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int has_arg;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int *flag;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int val;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"};\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/* This version of `getopt' appears to the caller like standard Unix `getopt'\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   but it behaves differently for the user, since it allows the user\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   to intersperse the options with the other arguments.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   As `getopt' works, it permutes the elements of ARGV so that,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   when it is done, all the options precede everything else.  Thus\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   all application programs are extended to handle flexible argument order.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"*/\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   If the field `flag' is not NULL, it points to a variable that is set\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   to the value given in the field `val' when the option is found, but\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   left unchanged if the option is not found.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   To have a long-named option do something other than set an `int' to\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   a compiled-in constant, such as set a value from `custom_optarg', set the\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   option's `flag' field to zero and its `val' field to a nonzero\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   value (the equivalent single-letter option character, if there is\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   one).  For long options that have a zero `flag' field, `getopt'\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"   returns the contents of the `val' field.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/* Names for the values of the `has_arg' field of `struct option'.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifndef no_argument\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#define no_argument\t\t0\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifndef required_argument\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#define required_argument\t1\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifndef optional_argument\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#define optional_argument\t2\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"struct custom_getopt_data {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * These have exactly the same meaning as the corresponding global variables,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * except that they are used for the reentrant versions of getopt.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint custom_opterr;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint custom_optopt;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tchar *custom_optarg;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/* True if the internal members have been initialized.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint initialized;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * The next char to be scanned in the option-element in which the last option\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * character we returned was found.  This allows us to pick up the scan where\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * we left off.  If this is zero, or a null string, it means resume the scan by\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * advancing to the next ARGV-element.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tchar *nextchar;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * Describe the part of ARGV that contains non-options that have been skipped.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * the index after the last of them.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint first_nonopt;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint last_nonopt;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"};\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * the variables optarg, optind, opterr and optopt are renamed with\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * the custom_ prefix so that they don't interfere with getopt ones.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Moreover they're static so they are visible only from within the\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * file where this very file will be included.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * For communication from `custom_getopt' to the caller.  When `custom_getopt' finds an\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * option that takes an argument, the argument value is returned here.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static char *custom_optarg;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Index in ARGV of the next element to be scanned.  This is used for\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * communication to and from the caller and for communication between\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * successive calls to `custom_getopt'.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * On entry to `custom_getopt', 1 means this is the first call; initialize.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * When `custom_getopt' returns -1, this is the index of the first of the non-option\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * elements that the caller should itself scan.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Otherwise, `custom_optind' communicates from one call to the next how much of ARGV\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * has been scanned so far.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * 1003.2 says this must be 1 before any call.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int custom_optind = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Callers store zero here to inhibit the error message for unrecognized\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * options.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int custom_opterr = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Set to an option character which was unrecognized.  This must be initialized\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * on some systems to avoid linking in the system's own getopt implementation.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int custom_optopt = '?';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Exchange two adjacent subsequences of ARGV.  One subsequence is elements\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * [first_nonopt,last_nonopt) which contains all the non-options that have been\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * skipped so far.  The other is elements [last_nonopt,custom_optind), which contains\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * all the options processed since those non-options were skipped.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * `first_nonopt' and `last_nonopt' are relocated so that they describe the new\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * indices of the non-options in ARGV after they are moved.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static void exchange(char **argv, struct custom_getopt_data *d)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint bottom = d->first_nonopt;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint middle = d->last_nonopt;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint top = d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tchar *tem;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * Exchange the shorter segment with the far end of the longer segment.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * That puts the shorter segment into the right place.  It leaves the\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * longer segment in the right place overall, but it consists of two\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * parts that need to be swapped next.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\twhile (top > middle && middle > bottom) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (top - middle > middle - bottom) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* Bottom segment is the short one.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tint len = middle - bottom;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tint i;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* Swap it with the top part of the top segment.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tfor (i = 0; i < len; i++) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\ttem = argv[bottom + i];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\targv[bottom + i] =\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\targv[top - (middle - bottom) + i];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\targv[top - (middle - bottom) + i] = tem;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* Exclude the moved bottom segment from further swapping.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\ttop -= len;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t} else {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* Top segment is the short one.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tint len = top - middle;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tint i;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* Swap it with the bottom part of the bottom segment.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tfor (i = 0; i < len; i++) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\ttem = argv[bottom + i];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\targv[bottom + i] = argv[middle + i];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\targv[middle + i] = tem;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* Exclude the moved top segment from further swapping.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tbottom += len;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/* Update records for the slots the non-options now occupy.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->first_nonopt += (d->custom_optind - d->last_nonopt);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->last_nonopt = d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/* Initialize the internal data when the first call is made.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static void custom_getopt_initialize(struct custom_getopt_data *d)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * Start processing options with ARGV-element 1 (since ARGV-element 0\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * is the program name); the sequence of previously skipped non-option\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * ARGV-elements is empty.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->first_nonopt = d->last_nonopt = d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->nextchar = NULL;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->initialized = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#define NONOPTION_P (argv[d->custom_optind][0] != '-' || argv[d->custom_optind][1] == '\\\\0')\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/* return: zero: continue, nonzero: return given value to user */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int shuffle_argv(int argc, char *const *argv,const struct option *longopts,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tstruct custom_getopt_data *d)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * Give FIRST_NONOPT & LAST_NONOPT rational values if CUSTOM_OPTIND has been\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * moved back by the user (who may also have changed the arguments).\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (d->last_nonopt > d->custom_optind)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->last_nonopt = d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (d->first_nonopt > d->custom_optind)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->first_nonopt = d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * If we have just processed some options following some\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * non-options, exchange them so that the options come first.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (d->first_nonopt != d->last_nonopt &&\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\td->last_nonopt != d->custom_optind)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\texchange((char **) argv, d);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\telse if (d->last_nonopt != d->custom_optind)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->first_nonopt = d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * Skip any additional non-options and extend the range of\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * non-options previously skipped.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\twhile (d->custom_optind < argc && NONOPTION_P)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->custom_optind++;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->last_nonopt = d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * The special ARGV-element `--' means premature end of options.  Skip\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * it like a null option, then exchange with previous non-options as if\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * it were an option, then skip everything else like a non-option.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (d->custom_optind != argc && !strcmp(argv[d->custom_optind], \\\"--\\\")) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->custom_optind++;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (d->first_nonopt != d->last_nonopt\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t&& d->last_nonopt != d->custom_optind)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\texchange((char **) argv, d);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\telse if (d->first_nonopt == d->last_nonopt)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\td->first_nonopt = d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->last_nonopt = argc;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->custom_optind = argc;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * If we have done all the ARGV-elements, stop the scan and back over\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * any non-options that we skipped and permuted.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (d->custom_optind == argc) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t * Set the next-arg-index to point at the non-options that we\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t * previously skipped, so the caller will digest them.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (d->first_nonopt != d->last_nonopt)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\td->custom_optind = d->first_nonopt;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\treturn -1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * If we have come to a non-option and did not permute it, either stop\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * the scan or describe it to the caller and pass it by.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (NONOPTION_P) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->custom_optarg = argv[d->custom_optind++];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\treturn 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * We have found another option-ARGV-element. Skip the initial\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * punctuation.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->nextchar = (argv[d->custom_optind] + 1 + (longopts != NULL && argv[d->custom_optind][1] == '-'));\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\treturn 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Check whether the ARGV-element is a long option.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * If there's a long option \\\"fubar\\\" and the ARGV-element is \\\"-fu\\\", consider\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * that an abbreviation of the long option, just like \\\"--fu\\\", and not \\\"-f\\\" with\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * arg \\\"u\\\".\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * This distinction seems to be the most useful approach.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int check_long_opt(int argc, char *const *argv, const char *optstring,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tconst struct option *longopts, int *longind,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tint print_errors, struct custom_getopt_data *d)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tchar *nameend;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tconst struct option *p;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tconst struct option *pfound = NULL;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint exact = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint ambig = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint indfound = -1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint option_index;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tfor (nameend = d->nextchar; *nameend && *nameend != '='; nameend++)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t/* Do nothing.  */ ;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/* Test all long options for either exact match or abbreviated matches */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tfor (p = longopts, option_index = 0; p->name; p++, option_index++)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (!strncmp(p->name, d->nextchar, nameend - d->nextchar)) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tif ((unsigned int) (nameend - d->nextchar)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t== (unsigned int) strlen(p->name)) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t/* Exact match found.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tpfound = p;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tindfound = option_index;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\texact = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tbreak;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t} else if (pfound == NULL) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t/* First nonexact match found.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tpfound = p;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tindfound = option_index;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t} else if (pfound->has_arg != p->has_arg\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t|| pfound->flag != p->flag\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t|| pfound->val != p->val)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t/* Second or later nonexact match found.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tambig = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (ambig && !exact) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (print_errors) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tfprintf(stderr,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\\\"%s: option `%s' is ambiguous\\\\n\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\targv[0], argv[d->custom_optind]);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->nextchar += strlen(d->nextchar);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->custom_optind++;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->custom_optopt = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\treturn '?';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (pfound) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\toption_index = indfound;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->custom_optind++;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (*nameend) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tif (pfound->has_arg != no_argument)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optarg = nameend + 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\telse {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tif (print_errors) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\tif (argv[d->custom_optind - 1][1] == '-') {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\t/* --option */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\tfprintf(stderr, \\\"%s: option `--%s' doesn't allow an argument\\\\n\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\t\targv[0], pfound->name);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t} else {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\t/* +option or -option */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\tfprintf(stderr, \\\"%s: option `%c%s' doesn't allow an argument\\\\n\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\t\targv[0], argv[d->custom_optind - 1][0], pfound->name);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->nextchar += strlen(d->nextchar);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optopt = pfound->val;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\treturn '?';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t} else if (pfound->has_arg == required_argument) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tif (d->custom_optind < argc)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optarg = argv[d->custom_optind++];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\telse {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tif (print_errors) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\tfprintf(stderr,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\t\\\"%s: option `%s' requires an argument\\\\n\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\targv[0],\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\targv[d->custom_optind - 1]);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->nextchar += strlen(d->nextchar);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optopt = pfound->val;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\treturn optstring[0] == ':' ? ':' : '?';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->nextchar += strlen(d->nextchar);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (longind != NULL)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t*longind = option_index;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (pfound->flag) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t*(pfound->flag) = pfound->val;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\treturn 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\treturn pfound->val;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * Can't find it as a long option.  If this is not getopt_long_only, or\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * the option starts with '--' or is not a valid short option, then\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * it's an error.  Otherwise interpret it as a short option.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (print_errors) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (argv[d->custom_optind][1] == '-') {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* --option */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tfprintf(stderr,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\\\"%s: unrecognized option `--%s'\\\\n\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\targv[0], d->nextchar);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t} else {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* +option or -option */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tfprintf(stderr,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\\\"%s: unrecognized option `%c%s'\\\\n\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\targv[0], argv[d->custom_optind][0],\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->nextchar);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->nextchar = (char *) \\\"\\\";\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->custom_optind++;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->custom_optopt = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\treturn '?';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int check_short_opt(int argc, char *const *argv, const char *optstring,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tint print_errors, struct custom_getopt_data *d)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tchar c = *d->nextchar++;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tconst char *temp = strchr(optstring, c);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/* Increment `custom_optind' when we start to process its last character.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (*d->nextchar == '\\\\0')\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t++d->custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (!temp || c == ':') {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (print_errors)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tfprintf(stderr, \\\"%s: invalid option -- %c\\\\n\\\", argv[0], c);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\td->custom_optopt = c;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\treturn '?';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (temp[1] == ':') {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (temp[2] == ':') {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* This is an option that accepts an argument optionally.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tif (*d->nextchar != '\\\\0') {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optarg = d->nextchar;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optind++;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t} else\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optarg = NULL;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\td->nextchar = NULL;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t} else {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t/* This is an option that requires an argument.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tif (*d->nextchar != '\\\\0') {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optarg = d->nextchar;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t * If we end this ARGV-element by taking the\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t * rest as an arg, we must advance to the next\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t * element now.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optind++;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t} else if (d->custom_optind == argc) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tif (print_errors) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\tfprintf(stderr,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\t\\\"%s: option requires an argument -- %c\\\\n\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\t\targv[0], c);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optopt = c;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\tif (optstring[0] == ':')\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\tc = ':';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\telse\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t\tc = '?';\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t} else\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t * We already incremented `custom_optind' once;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t * increment it again when taking next ARGV-elt\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t * as argument.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\t\td->custom_optarg = argv[d->custom_optind++];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\td->nextchar = NULL;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\treturn c;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/*\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Scan elements of ARGV for option characters given in OPTSTRING.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * If an element of ARGV starts with '-', and is not exactly \\\"-\\\" or \\\"--\\\",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * then it is an option element.  The characters of this element\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * (aside from the initial '-') are option characters.  If `getopt'\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * is called repeatedly, it returns successively each of the option characters\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * from each of the option elements.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * If `getopt' finds another option character, it returns that character,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * updating `custom_optind' and `nextchar' so that the next call to `getopt' can\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * resume the scan with the following option character or ARGV-element.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * If there are no more option characters, `getopt' returns -1.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Then `custom_optind' is the index in ARGV of the first ARGV-element\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * that is not an option.  (The ARGV-elements have been permuted\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * so that those that are not options now come last.)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * OPTSTRING is a string containing the legitimate option characters.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * If an option character is seen that is not listed in OPTSTRING,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * return '?' after printing an error message.  If you set `custom_opterr' to\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * zero, the error message is suppressed but we still return '?'.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * If a char in OPTSTRING is followed by a colon, that means it wants an arg,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * so the following text in the same ARGV-element, or the text of the following\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * ARGV-element, is returned in `custom_optarg'.  Two colons mean an option that\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * wants an optional arg; if there is text in the current ARGV-element,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * it is returned in `custom_optarg', otherwise `custom_optarg' is set to zero.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * If OPTSTRING starts with `-' or `+', it requests different methods of\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * handling the non-option ARGV-elements.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Long-named options begin with `--' instead of `-'.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Their names may be abbreviated as long as the abbreviation is unique\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * or is an exact match for some defined option.  If they have an\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * argument, it follows the option name in the same ARGV-element, separated\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * from the option name by a `=', or else the in next ARGV-element.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * When `getopt' finds a long-named option, it returns 0 if that option's\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * `flag' field is nonzero, the value of the option's `val' field\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * if the `flag' field is zero.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * The elements of ARGV aren't really const, because we permute them.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * But we pretend they're const in the prototype to be compatible\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * with other systems.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * LONGOPTS is a vector of `struct option' terminated by an\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * element containing a name which is zero.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * LONGIND returns the index in LONGOPT of the long-named option found.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * It is only valid when a long-named option has been found by the most\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * recent call.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Return the option character from OPTS just read.  Return -1 when there are\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * no more options.  For unrecognized options, or options missing arguments,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * `custom_optopt' is set to the option letter, and '?' is returned.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * The OPTS string is a list of characters which are recognized option letters,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * optionally followed by colons, specifying that that letter takes an\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * argument, to be placed in `custom_optarg'.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * If a letter in OPTS is followed by two colons, its argument is optional.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * This behavior is specific to the GNU `getopt'.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * The argument `--' causes premature termination of argument scanning,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * explicitly telling `getopt' that there are no more options.  If OPTS begins\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * with `--', then non-option arguments are treated as arguments to the option\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * '\\\\0'.  This behavior is specific to the GNU `getopt'.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int getopt_internal_r(int argc, char *const *argv, const char *optstring,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tconst struct option *longopts, int *longind,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tstruct custom_getopt_data *d)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint ret, print_errors = d->custom_opterr;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (optstring[0] == ':')\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tprint_errors = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (argc < 1)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\treturn -1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td->custom_optarg = NULL;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/* \";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * This is a big difference with GNU getopt, since optind == 0\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t * means initialization while here 1 means first call.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (d->custom_optind == 0 || !d->initialized) {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (d->custom_optind == 0)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\td->custom_optind = 1;\t/* Don't scan ARGV[0], the program name.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tcustom_getopt_initialize(d);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (d->nextchar == NULL || *d->nextchar == '\\\\0') {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tret = shuffle_argv(argc, argv, longopts, d);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tif (ret)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\treturn ret;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tif (longopts && (argv[d->custom_optind][1] == '-' ))\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\treturn check_long_opt(argc, argv, optstring, longopts,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\t\tlongind, print_errors, d);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\treturn check_short_opt(argc, argv, optstring, print_errors, d);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int custom_getopt_internal(int argc, char *const *argv, const char *optstring,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tconst struct option *longopts, int *longind)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tint result;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t/* Keep a global copy of all internal members of d */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tstatic struct custom_getopt_data d;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td.custom_optind = custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\td.custom_opterr = custom_opterr;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tresult = getopt_internal_r(argc, argv, optstring, longopts,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\tlongind, &d);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tcustom_optind = d.custom_optind;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tcustom_optarg = d.custom_optarg;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tcustom_optopt = d.custom_optopt;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\treturn result;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"static int custom_getopt_long (int argc, char *const *argv, const char *options,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\tconst struct option *long_options, int *opt_index)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\treturn custom_getopt_internal(argc, argv, options, long_options,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\t\topt_index);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/custom_getopt_gen.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef CUSTOM_GETOPT_GEN_GEN_CLASS_H\n#define CUSTOM_GETOPT_GEN_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass custom_getopt_gen_gen_class\n{\n protected:\n\n public:\n  custom_getopt_gen_gen_class()\n  {\n  }\n\n\n  void generate_custom_getopt_gen(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // CUSTOM_GETOPT_GEN_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/dependant_option.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"dependant_option.h\"\n\nvoid\ndependant_option_gen_class::generate_dependant_option(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"if (args_info->\";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_given && ! args_info->\";\n  generate_string (dep_option, stream, indent + indent_str.length ());\n  stream << \"_given)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    fprintf (stderr, \\\"%s: \";\n  generate_string (option_descr, stream, indent + indent_str.length ());\n  stream << \" option depends on option '\";\n  generate_string (dep_option_descr, stream, indent + indent_str.length ());\n  stream << \"'%s\\\\n\\\", \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \", (additional_error ? additional_error : \\\"\\\"));\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    error = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  }\";\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/dependant_option.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef DEPENDANT_OPTION_GEN_CLASS_H\n#define DEPENDANT_OPTION_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass dependant_option_gen_class\n{\n protected:\n  string dep_option;\n  string dep_option_descr;\n  string option_descr;\n  string option_var_name;\n  string package_var_name;\n\n public:\n  dependant_option_gen_class()\n  {\n  }\n\n  dependant_option_gen_class(const string &_dep_option, const string &_dep_option_descr, const string &_option_descr, const string &_option_var_name, const string &_package_var_name) :\n    dep_option (_dep_option), dep_option_descr (_dep_option_descr), option_descr (_option_descr), option_var_name (_option_var_name), package_var_name (_package_var_name)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_dep_option(const string &_dep_option)\n  {\n    dep_option = _dep_option;\n  }\n\n  void set_dep_option_descr(const string &_dep_option_descr)\n  {\n    dep_option_descr = _dep_option_descr;\n  }\n\n  void set_option_descr(const string &_option_descr)\n  {\n    option_descr = _option_descr;\n  }\n\n  void set_option_var_name(const string &_option_var_name)\n  {\n    option_var_name = _option_var_name;\n  }\n\n  void set_package_var_name(const string &_package_var_name)\n  {\n    package_var_name = _package_var_name;\n  }\n\n  void generate_dependant_option(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // DEPENDANT_OPTION_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/enum_decl.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"enum_decl.h\"\n\nvoid\nenum_decl_gen_class::generate_enum_decl(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"enum enum_\";\n  generate_string (var_arg, stream, indent + indent_str.length ());\n  stream << \" { \";\n  generate_string (var_arg, stream, indent + indent_str.length ());\n  stream << \"__NULL = -1\";\n  generate_string (enum_values, stream, indent + indent_str.length ());\n  stream << \" };\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/enum_decl.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef ENUM_DECL_GEN_CLASS_H\n#define ENUM_DECL_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass enum_decl_gen_class\n{\n protected:\n  string enum_values;\n  string var_arg;\n\n public:\n  enum_decl_gen_class()\n  {\n  }\n\n  enum_decl_gen_class(const string &_enum_values, const string &_var_arg) :\n    enum_values (_enum_values), var_arg (_var_arg)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_enum_values(const string &_enum_values)\n  {\n    enum_values = _enum_values;\n  }\n\n  void set_var_arg(const string &_var_arg)\n  {\n    var_arg = _var_arg;\n  }\n\n  void generate_enum_decl(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // ENUM_DECL_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/exit_failure.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"exit_failure.h\"\n\nvoid\nexit_failure_gen_class::generate_exit_failure(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (handle_error)\n    {\n      stream << \"if (result == EXIT_FAILURE)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 4;\n      stream << \"    \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_free (args_info);\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    exit (EXIT_FAILURE);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"return result;\";\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/exit_failure.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef EXIT_FAILURE_GEN_CLASS_H\n#define EXIT_FAILURE_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass exit_failure_gen_class\n{\n protected:\n  bool handle_error;\n  string parser_name;\n\n public:\n  exit_failure_gen_class() :\n    handle_error (false)\n  {\n  }\n\n  exit_failure_gen_class(bool _handle_error, const string &_parser_name) :\n    handle_error (_handle_error), parser_name (_parser_name)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_handle_error(bool _handle_error)\n  {\n    handle_error = _handle_error;\n  }\n\n  void set_parser_name(const string &_parser_name)\n  {\n    parser_name = _parser_name;\n  }\n\n  void generate_exit_failure(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // EXIT_FAILURE_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/file_save.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"file_save.h\"\n\nvoid\nfile_save_gen_class::generate_file_save(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"if (args_info->\";\n  generate_string (given, stream, indent + indent_str.length ());\n  stream << \")\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  write_into_file(outfile, \\\"\";\n  generate_string (opt_name, stream, indent + indent_str.length ());\n  stream << \"\\\", \";\n  if (( arg == \"\" ))\n    {\n      stream << \"0, 0 \";\n    }\n  else\n    {\n      stream << \"args_info->\";\n      generate_string (arg, stream, indent + indent_str.length ());\n      stream << \", \";\n      generate_string (values, stream, indent + indent_str.length ());\n    }\n  stream << \");\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/file_save.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef FILE_SAVE_GEN_CLASS_H\n#define FILE_SAVE_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass file_save_gen_class\n{\n protected:\n  string arg;\n  string given;\n  string opt_name;\n  string values;\n\n public:\n  file_save_gen_class()\n  {\n  }\n\n  file_save_gen_class(const string &_arg, const string &_given, const string &_opt_name, const string &_values) :\n    arg (_arg), given (_given), opt_name (_opt_name), values (_values)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_arg(const string &_arg)\n  {\n    arg = _arg;\n  }\n\n  void set_given(const string &_given)\n  {\n    given = _given;\n  }\n\n  void set_opt_name(const string &_opt_name)\n  {\n    opt_name = _opt_name;\n  }\n\n  void set_values(const string &_values)\n  {\n    values = _values;\n  }\n\n  void generate_file_save(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // FILE_SAVE_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/file_save_multiple.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"file_save_multiple.h\"\n\nvoid\nfile_save_multiple_gen_class::generate_file_save_multiple(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (has_arg)\n    {\n      stream << \"write_multiple_into_file(outfile, args_info->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_given, \\\"\";\n      generate_string (opt_name, stream, indent + indent_str.length ());\n      stream << \"\\\", args_info->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_orig, \";\n      generate_string (values, stream, indent + indent_str.length ());\n      stream << \");\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"write_multiple_into_file(outfile, args_info->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_given, \\\"\";\n      generate_string (opt_name, stream, indent + indent_str.length ());\n      stream << \"\\\", 0, 0);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/file_save_multiple.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef FILE_SAVE_MULTIPLE_GEN_CLASS_H\n#define FILE_SAVE_MULTIPLE_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass file_save_multiple_gen_class\n{\n protected:\n  bool has_arg;\n  string opt_name;\n  string opt_var;\n  string values;\n\n public:\n  file_save_multiple_gen_class() :\n    has_arg (false)\n  {\n  }\n\n  file_save_multiple_gen_class(bool _has_arg, const string &_opt_name, const string &_opt_var, const string &_values) :\n    has_arg (_has_arg), opt_name (_opt_name), opt_var (_opt_var), values (_values)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_has_arg(bool _has_arg)\n  {\n    has_arg = _has_arg;\n  }\n\n  void set_opt_name(const string &_opt_name)\n  {\n    opt_name = _opt_name;\n  }\n\n  void set_opt_var(const string &_opt_var)\n  {\n    opt_var = _opt_var;\n  }\n\n  void set_values(const string &_values)\n  {\n    values = _values;\n  }\n\n  void generate_file_save_multiple(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // FILE_SAVE_MULTIPLE_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/free_list.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"free_list.h\"\n\nvoid\nfree_list_gen_class::generate_free_list(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"free_list (\";\n  generate_string (list_name, stream, indent + indent_str.length ());\n  stream << \"_list, \";\n  if (string_list)\n    {\n      stream << \"1 \";\n    }\n  else\n    {\n      stream << \"0 \";\n    }\n  stream << \");\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/free_list.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef FREE_LIST_GEN_CLASS_H\n#define FREE_LIST_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass free_list_gen_class\n{\n protected:\n  string list_name;\n  bool string_list;\n\n public:\n  free_list_gen_class() :\n    string_list (false)\n  {\n  }\n\n  free_list_gen_class(const string &_list_name, bool _string_list) :\n    list_name (_list_name), string_list (_string_list)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_list_name(const string &_list_name)\n  {\n    list_name = _list_name;\n  }\n\n  void set_string_list(bool _string_list)\n  {\n    string_list = _string_list;\n  }\n\n  void generate_free_list(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // FREE_LIST_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/free_multiple.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"free_multiple.h\"\n\nvoid\nfree_multiple_gen_class::generate_free_multiple(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (has_string_type)\n    {\n      stream << \"free_multiple_string_field (\";\n      generate_string (structure, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_given, &(\";\n      generate_string (structure, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_arg), &(\";\n      generate_string (structure, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_orig));\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"free_multiple_field (\";\n      generate_string (structure, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_given, (void *)(\";\n      generate_string (structure, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_arg), &(\";\n      generate_string (structure, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_orig));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (structure, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_arg = 0;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/free_multiple.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef FREE_MULTIPLE_GEN_CLASS_H\n#define FREE_MULTIPLE_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass free_multiple_gen_class\n{\n protected:\n  bool has_string_type;\n  string opt_var;\n  string structure;\n\n public:\n  free_multiple_gen_class() :\n    has_string_type (false)\n  {\n  }\n\n  free_multiple_gen_class(bool _has_string_type, const string &_opt_var, const string &_structure) :\n    has_string_type (_has_string_type), opt_var (_opt_var), structure (_structure)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_has_string_type(bool _has_string_type)\n  {\n    has_string_type = _has_string_type;\n  }\n\n  void set_opt_var(const string &_opt_var)\n  {\n    opt_var = _opt_var;\n  }\n\n  void set_structure(const string &_structure)\n  {\n    structure = _structure;\n  }\n\n  void generate_free_multiple(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // FREE_MULTIPLE_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/free_string.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"free_string.h\"\n\nvoid\nfree_string_gen_class::generate_free_string(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (has_string_type)\n    {\n      stream << \"free_string_field (&(\";\n      generate_string (structure, stream, indent + indent_str.length ());\n      stream << \"->\";\n      generate_string (opt_var, stream, indent + indent_str.length ());\n      stream << \"_arg));\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"free_string_field (&(\";\n  generate_string (structure, stream, indent + indent_str.length ());\n  stream << \"->\";\n  generate_string (opt_var, stream, indent + indent_str.length ());\n  stream << \"_orig));\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/free_string.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef FREE_STRING_GEN_CLASS_H\n#define FREE_STRING_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass free_string_gen_class\n{\n protected:\n  bool has_string_type;\n  string opt_var;\n  string structure;\n\n public:\n  free_string_gen_class() :\n    has_string_type (false)\n  {\n  }\n\n  free_string_gen_class(bool _has_string_type, const string &_opt_var, const string &_structure) :\n    has_string_type (_has_string_type), opt_var (_opt_var), structure (_structure)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_has_string_type(bool _has_string_type)\n  {\n    has_string_type = _has_string_type;\n  }\n\n  void set_opt_var(const string &_opt_var)\n  {\n    opt_var = _opt_var;\n  }\n\n  void set_structure(const string &_structure)\n  {\n    structure = _structure;\n  }\n\n  void generate_free_string(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // FREE_STRING_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/generic_option.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"generic_option.h\"\n\nvoid\ngeneric_option_gen_class::generate_generic_option(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (has_short_option)\n    {\n      stream << \"case '\";\n      generate_string (short_option, stream, indent + indent_str.length ());\n      stream << \"':\t/* \";\n      generate_string (option_comment, stream, indent + indent_str.length ());\n      stream << \".  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      if (( short_option == \"?\" ))\n        {\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  if (optopt) /* '?' represents an unrecognized option */\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    goto failure;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n    }\n  else\n    {\n      stream << \"/* \";\n      generate_string (option_comment, stream, indent + indent_str.length ());\n      stream << \".  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (gen_else, stream, indent + indent_str.length ());\n      stream << \"if (strcmp (long_options[option_index].name, \\\"\";\n      generate_string (long_option, stream, indent + indent_str.length ());\n      stream << \"\\\") == 0)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"{\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (option_has_mode)\n    {\n      stream << \"  args_info->\";\n      generate_string (group_var_name, stream, indent + indent_str.length ());\n      stream << \"_mode_counter += 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  if (multiple)\n    {\n      if (option_has_type)\n        {\n          stream << \"  if (update_multiple_arg_temp(&\";\n          generate_string (structure, stream, indent + indent_str.length ());\n          stream << \", \";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      &(local_args_info.\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_given), optarg, \";\n          generate_string (possible_values, stream, indent + indent_str.length ());\n          stream << \", \";\n          generate_string (default_value, stream, indent + indent_str.length ());\n          stream << \", \";\n          generate_string (arg_type, stream, indent + indent_str.length ());\n          stream << \",\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      \\\"\";\n          generate_string (long_option, stream, indent + indent_str.length ());\n          stream << \"\\\", '\";\n          generate_string (short_option, stream, indent + indent_str.length ());\n          stream << \"',\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      additional_error))\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    goto failure;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      else\n        {\n          stream << \"  local_args_info.\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_given++;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (option_has_group)\n        {\n          stream << \"  if (!args_info->\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_group)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      args_info->\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_group = 1;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      args_info->\";\n          generate_string (group_var_name, stream, indent + indent_str.length ());\n          stream << \"_group_counter += 1;\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    }\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n    }\n  else\n    {\n      if (option_has_group)\n        {\n          stream << \"  if (args_info->\";\n          generate_string (group_var_name, stream, indent + indent_str.length ());\n          stream << \"_group_counter && override)\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    reset_group_\";\n          generate_string (group_var_name, stream, indent + indent_str.length ());\n          stream << \" (args_info);\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"  args_info->\";\n          generate_string (group_var_name, stream, indent + indent_str.length ());\n          stream << \"_group_counter += 1;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      stream << \"\\n\";\n      stream << indent_str;\n      if (( arg_type == \"ARG_FLAG\" ))\n        {\n          stream << \"  if (update_arg((void *)&(args_info->\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_flag), 0, &(args_info->\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_given),\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      &(local_args_info.\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_given), optarg, 0, 0, \";\n          generate_string (arg_type, stream, indent + indent_str.length ());\n          stream << \",\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      check_ambiguity, override, 1, 0, \\\"\";\n          generate_string (long_option, stream, indent + indent_str.length ());\n          stream << \"\\\", '\";\n          generate_string (short_option, stream, indent + indent_str.length ());\n          stream << \"',\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      additional_error))\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    goto failure;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      else\n        {\n          stream << \"  if (update_arg(\";\n          if (( arg_type == \"ARG_NO\" ))\n            {\n              stream << \" 0 \";\n            }\n          else\n            {\n              stream << \" (void *)&(args_info->\";\n              generate_string (option_var_name, stream, indent + indent_str.length ());\n              stream << \"_arg)\";\n            }\n          stream << \", \";\n          stream << \"\\n\";\n          stream << indent_str;\n          indent = 6;\n          stream << \"      \";\n          if (( arg_type == \"ARG_NO\" ))\n            {\n              stream << \" 0 \";\n            }\n          else\n            {\n              stream << \" &(args_info->\";\n              generate_string (option_var_name, stream, indent + indent_str.length ());\n              stream << \"_orig)\";\n            }\n          stream << \", &(args_info->\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_given),\";\n          indent = 0;\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      &(local_args_info.\";\n          generate_string (option_var_name, stream, indent + indent_str.length ());\n          stream << \"_given), optarg, \";\n          generate_string (possible_values, stream, indent + indent_str.length ());\n          stream << \", \";\n          generate_string (default_value, stream, indent + indent_str.length ());\n          stream << \", \";\n          generate_string (arg_type, stream, indent + indent_str.length ());\n          stream << \",\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      check_ambiguity, override, 0, 0,\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      \\\"\";\n          generate_string (long_option, stream, indent + indent_str.length ());\n          stream << \"\\\", '\";\n          generate_string (short_option, stream, indent + indent_str.length ());\n          stream << \"',\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"      additional_error))\";\n          stream << \"\\n\";\n          stream << indent_str;\n          stream << \"    goto failure;\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      if (( final_instructions != \"\" ))\n        {\n          indent = 2;\n          stream << \"  \";\n          generate_string (final_instructions, stream, indent + indent_str.length ());\n          indent = 0;\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n    }\n  if (has_short_option)\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  break;\";\n    }\n  else\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/generic_option.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef GENERIC_OPTION_GEN_CLASS_H\n#define GENERIC_OPTION_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass generic_option_gen_class\n{\n protected:\n  string arg_type;\n  string default_value;\n  string final_instructions;\n  string gen_else;\n  string group_var_name;\n  bool has_short_option;\n  string long_option;\n  bool multiple;\n  string option_comment;\n  bool option_has_group;\n  bool option_has_mode;\n  bool option_has_type;\n  string option_var_name;\n  string possible_values;\n  string short_option;\n  string structure;\n\n public:\n  generic_option_gen_class() :\n    has_short_option (false), multiple (false), option_has_group (false), option_has_mode (false), option_has_type (false)\n  {\n  }\n\n  generic_option_gen_class(const string &_arg_type, const string &_default_value, const string &_final_instructions, const string &_gen_else, const string &_group_var_name, bool _has_short_option, const string &_long_option, bool _multiple, const string &_option_comment, bool _option_has_group, bool _option_has_mode, bool _option_has_type, const string &_option_var_name, const string &_possible_values, const string &_short_option, const string &_structure) :\n    arg_type (_arg_type), default_value (_default_value), final_instructions (_final_instructions), gen_else (_gen_else), group_var_name (_group_var_name), has_short_option (_has_short_option), long_option (_long_option), multiple (_multiple), option_comment (_option_comment), option_has_group (_option_has_group), option_has_mode (_option_has_mode), option_has_type (_option_has_type), option_var_name (_option_var_name), possible_values (_possible_values), short_option (_short_option), structure (_structure)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_arg_type(const string &_arg_type)\n  {\n    arg_type = _arg_type;\n  }\n\n  void set_default_value(const string &_default_value)\n  {\n    default_value = _default_value;\n  }\n\n  void set_final_instructions(const string &_final_instructions)\n  {\n    final_instructions = _final_instructions;\n  }\n\n  void set_gen_else(const string &_gen_else)\n  {\n    gen_else = _gen_else;\n  }\n\n  void set_group_var_name(const string &_group_var_name)\n  {\n    group_var_name = _group_var_name;\n  }\n\n  void set_has_short_option(bool _has_short_option)\n  {\n    has_short_option = _has_short_option;\n  }\n\n  void set_long_option(const string &_long_option)\n  {\n    long_option = _long_option;\n  }\n\n  void set_multiple(bool _multiple)\n  {\n    multiple = _multiple;\n  }\n\n  void set_option_comment(const string &_option_comment)\n  {\n    option_comment = _option_comment;\n  }\n\n  void set_option_has_group(bool _option_has_group)\n  {\n    option_has_group = _option_has_group;\n  }\n\n  void set_option_has_mode(bool _option_has_mode)\n  {\n    option_has_mode = _option_has_mode;\n  }\n\n  void set_option_has_type(bool _option_has_type)\n  {\n    option_has_type = _option_has_type;\n  }\n\n  void set_option_var_name(const string &_option_var_name)\n  {\n    option_var_name = _option_var_name;\n  }\n\n  void set_possible_values(const string &_possible_values)\n  {\n    possible_values = _possible_values;\n  }\n\n  void set_short_option(const string &_short_option)\n  {\n    short_option = _short_option;\n  }\n\n  void set_structure(const string &_structure)\n  {\n    structure = _structure;\n  }\n\n  void generate_generic_option(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // GENERIC_OPTION_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/given_field.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"given_field.h\"\n\nvoid\ngiven_field_gen_class::generate_given_field(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"unsigned int \";\n  generate_string (arg_name, stream, indent + indent_str.length ());\n  stream << \"_given ;\t/**< \";\n  stream << \"@\";\n  stream << \"brief Whether \";\n  generate_string (long_opt, stream, indent + indent_str.length ());\n  stream << \" was given.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (group)\n    {\n      stream << \"  int \";\n      generate_string (arg_name, stream, indent + indent_str.length ());\n      stream << \"_group ; /**< \";\n      stream << \"@\";\n      stream << \"brief Whether \";\n      generate_string (long_opt, stream, indent + indent_str.length ());\n      stream << \"'s was updated.  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/given_field.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef GIVEN_FIELD_GEN_CLASS_H\n#define GIVEN_FIELD_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass given_field_gen_class\n{\n protected:\n  string arg_name;\n  bool group;\n  string long_opt;\n\n public:\n  given_field_gen_class() :\n    group (false)\n  {\n  }\n\n  given_field_gen_class(const string &_arg_name, bool _group, const string &_long_opt) :\n    arg_name (_arg_name), group (_group), long_opt (_long_opt)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_arg_name(const string &_arg_name)\n  {\n    arg_name = _arg_name;\n  }\n\n  void set_group(bool _group)\n  {\n    group = _group;\n  }\n\n  void set_long_opt(const string &_long_opt)\n  {\n    long_opt = _long_opt;\n  }\n\n  void generate_given_field(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // GIVEN_FIELD_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/group_counter.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.3 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"group_counter.h\"\n\nvoid\ngroup_counter_gen_class::generate_group_counter(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"int \";\n  generate_string (group_name, stream, indent + indent_str.length ());\n  stream << \"_\";\n  generate_string (name, stream, indent + indent_str.length ());\n  stream << \"_counter; /**< \";\n  stream << \"@\";\n  stream << \"brief Counter for \";\n  generate_string (name, stream, indent + indent_str.length ());\n  stream << \" \";\n  generate_string (group_name, stream, indent + indent_str.length ());\n  stream << \" */\";\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/group_counter.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.3 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef GROUP_COUNTER_GEN_CLASS_H\n#define GROUP_COUNTER_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass group_counter_gen_class\n{\n protected:\n  string group_name;\n  string name;\n\n public:\n  group_counter_gen_class()\n  {\n  }\n\n  group_counter_gen_class(const string &_group_name, const string &_name) :\n    group_name (_group_name), name (_name)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_group_name(const string &_group_name)\n  {\n    group_name = _group_name;\n  }\n\n  void set_name(const string &_name)\n  {\n    name = _name;\n  }\n\n  void generate_group_counter(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // GROUP_COUNTER_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/group_option.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"group_option.h\"\n\nvoid\ngroup_option_gen_class::generate_group_option(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"if (args_info->\";\n  generate_string (group_var_name, stream, indent + indent_str.length ());\n  stream << \"_group_counter \";\n  generate_string (Comparison_rule, stream, indent + indent_str.length ());\n  stream << \")\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    fprintf (stderr, \\\"%s: %d options of group \";\n  generate_string (group_name, stream, indent + indent_str.length ());\n  stream << \" were given. \";\n  generate_string (number_required, stream, indent + indent_str.length ());\n  stream << \" is required%s.\\\\n\\\", \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \", args_info->\";\n  generate_string (group_var_name, stream, indent + indent_str.length ());\n  stream << \"_group_counter, (additional_error ? additional_error : \\\"\\\"));\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    error = 1;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  }\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/group_option.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef GROUP_OPTION_GEN_CLASS_H\n#define GROUP_OPTION_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass group_option_gen_class\n{\n protected:\n  string Comparison_rule;\n  string group_name;\n  string group_var_name;\n  string number_required;\n  string package_var_name;\n\n public:\n  group_option_gen_class()\n  {\n  }\n\n  group_option_gen_class(const string &_Comparison_rule, const string &_group_name, const string &_group_var_name, const string &_number_required, const string &_package_var_name) :\n    Comparison_rule (_Comparison_rule), group_name (_group_name), group_var_name (_group_var_name), number_required (_number_required), package_var_name (_package_var_name)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_Comparison_rule(const string &_Comparison_rule)\n  {\n    Comparison_rule = _Comparison_rule;\n  }\n\n  void set_group_name(const string &_group_name)\n  {\n    group_name = _group_name;\n  }\n\n  void set_group_var_name(const string &_group_var_name)\n  {\n    group_var_name = _group_var_name;\n  }\n\n  void set_number_required(const string &_number_required)\n  {\n    number_required = _number_required;\n  }\n\n  void set_package_var_name(const string &_package_var_name)\n  {\n    package_var_name = _package_var_name;\n  }\n\n  void generate_group_option(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // GROUP_OPTION_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/handle_help.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"handle_help.h\"\n\nvoid\nhandle_help_gen_class::generate_handle_help(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (detailed_help)\n    {\n      stream << \"if (strcmp (long_options[option_index].name, \\\"detailed-help\\\") == 0) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      indent = 2;\n      stream << \"  \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_print_detailed_help ();\";\n      indent = 0;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      if (full_help)\n        {\n          stream << \"if (strcmp (long_options[option_index].name, \\\"full-help\\\") == 0) {\";\n          stream << \"\\n\";\n          stream << indent_str;\n          indent = 2;\n          stream << \"  \";\n          generate_string (parser_name, stream, indent + indent_str.length ());\n          stream << \"_print_full_help ();\";\n          indent = 0;\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      else\n        {\n          if (short_opt)\n            {\n              stream << \"case 'h':\t/* Print help and exit.  */\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          else\n            {\n              stream << \"if (strcmp (long_options[option_index].name, \\\"help\\\") == 0) {\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n          stream << \"  \";\n          generate_string (parser_name, stream, indent + indent_str.length ());\n          stream << \"_print_help ();\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n    }\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_free (&local_args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  exit (EXIT_SUCCESS);\";\n  if (( full_help || ( ! short_opt ) ))\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/handle_help.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef HANDLE_HELP_GEN_CLASS_H\n#define HANDLE_HELP_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass handle_help_gen_class\n{\n protected:\n  bool detailed_help;\n  bool full_help;\n  string parser_name;\n  bool short_opt;\n\n public:\n  handle_help_gen_class() :\n    detailed_help (false), full_help (false), short_opt (false)\n  {\n  }\n\n  handle_help_gen_class(bool _detailed_help, bool _full_help, const string &_parser_name, bool _short_opt) :\n    detailed_help (_detailed_help), full_help (_full_help), parser_name (_parser_name), short_opt (_short_opt)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_detailed_help(bool _detailed_help)\n  {\n    detailed_help = _detailed_help;\n  }\n\n  void set_full_help(bool _full_help)\n  {\n    full_help = _full_help;\n  }\n\n  void set_parser_name(const string &_parser_name)\n  {\n    parser_name = _parser_name;\n  }\n\n  void set_short_opt(bool _short_opt)\n  {\n    short_opt = _short_opt;\n  }\n\n  void generate_handle_help(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // HANDLE_HELP_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/handle_version.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"handle_version.h\"\n\nvoid\nhandle_version_gen_class::generate_handle_version(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (short_opt)\n    {\n      stream << \"case 'V':\t/* Print version and exit.  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"if (strcmp (long_options[option_index].name, \\\"version\\\") == 0) {\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_print_version ();\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_free (&local_args_info);\";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  exit (EXIT_SUCCESS);\";\n  if (( ! short_opt ))\n    {\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"}\";\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/handle_version.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4.1 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef HANDLE_VERSION_GEN_CLASS_H\n#define HANDLE_VERSION_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass handle_version_gen_class\n{\n protected:\n  string parser_name;\n  bool short_opt;\n\n public:\n  handle_version_gen_class() :\n    short_opt (false)\n  {\n  }\n\n  handle_version_gen_class(const string &_parser_name, bool _short_opt) :\n    parser_name (_parser_name), short_opt (_short_opt)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_parser_name(const string &_parser_name)\n  {\n    parser_name = _parser_name;\n  }\n\n  void set_short_opt(bool _short_opt)\n  {\n    short_opt = _short_opt;\n  }\n\n  void generate_handle_version(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // HANDLE_VERSION_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/header.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.4 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"header.h\"\n\nvoid\nheader_gen_class::generate_header(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"file \";\n  generate_string (header_file_name, stream, indent + indent_str.length ());\n  stream << \".\";\n  generate_string (header_file_ext, stream, indent + indent_str.length ());\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *  \";\n  stream << \"@\";\n  stream << \"brief The header file for the command line option parser\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *  generated by GNU Gengetopt \";\n  generate_string (generator_version, stream, indent + indent_str.length ());\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *  https://www.gnu.org/software/gengetopt.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *  DO NOT modify this file, since it can be overwritten\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *  \";\n  stream << \"@\";\n  stream << \"author GNU Gengetopt by Lorenzo Bettini */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifndef \";\n  generate_string (ifndefname, stream, indent + indent_str.length ());\n  stream << \"_H\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#define \";\n  generate_string (ifndefname, stream, indent + indent_str.length ());\n  stream << \"_H\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/* If we use autoconf.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifdef HAVE_CONFIG_H\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#include \\\"config.h\\\"\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#include <stdio.h> /* for FILE */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifdef __cplusplus\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"extern \\\"C\\\" {\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif /* __cplusplus */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifndef \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"brief the program name (used for printing errors) */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#define \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \" \";\n  generate_string (package_var_val, stream, indent + indent_str.length ());\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifndef \";\n  generate_string (package_var_name, stream, indent + indent_str.length ());\n  stream << \"_NAME\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"brief the complete program name (used for help and version) */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (( package_var_val != \"PACKAGE\" ))\n    {\n      stream << \"#define \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \"_NAME \";\n      generate_string (package_var_val, stream, indent + indent_str.length ());\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"#ifdef PACKAGE_NAME\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#define \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \"_NAME PACKAGE_NAME\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#define \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \"_NAME PACKAGE\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#endif\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifndef \";\n  generate_string (version_var_name, stream, indent + indent_str.length ());\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"brief the program version */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#define \";\n  generate_string (version_var_name, stream, indent + indent_str.length ());\n  stream << \" \";\n  generate_string (version_var_val, stream, indent + indent_str.length ());\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (enum_types.size () > 0)\n    generate_string (enum_types, stream, indent + indent_str.length ());\n  else\n    generate_enum_types (stream, indent + indent_str.length ());\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"brief Where the command line options are stored */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  if (option_arg.size () > 0)\n    generate_string (option_arg, stream, indent + indent_str.length ());\n  else\n    generate_option_arg (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  if (option_given.size () > 0)\n    generate_string (option_given, stream, indent + indent_str.length ());\n  else\n    generate_option_given (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  if (group_counters.size () > 0)\n    generate_string (group_counters, stream, indent + indent_str.length ());\n  else\n    generate_group_counters (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  indent = 2;\n  if (mode_counters.size () > 0)\n    generate_string (mode_counters, stream, indent + indent_str.length ());\n  else\n    generate_mode_counters (stream, indent + indent_str.length ());\n  indent = 0;\n  stream << indent_str;\n  stream << \"} ;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"brief The additional parameters to pass to parser functions */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int override; /**< \";\n  stream << \"@\";\n  stream << \"brief whether to override possibly already present options (default 0) */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int initialize; /**< \";\n  stream << \"@\";\n  stream << \"brief whether to initialize the option structure \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" (default 1) */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int check_required; /**< \";\n  stream << \"@\";\n  stream << \"brief whether to check that all required options were provided (default 1) */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int check_ambiguity; /**< \";\n  stream << \"@\";\n  stream << \"brief whether to check for options already specified in the option structure \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" (default 0) */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int print_errors; /**< \";\n  stream << \"@\";\n  stream << \"brief whether getopt_long should print an error message for a bad option (default 1) */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"} ;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"brief the purpose string of the program */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"extern const char *\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_purpose;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"brief the usage string of the program */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"extern const char *\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_usage;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/** \";\n  stream << \"@\";\n  stream << \"brief all the lines making the help output */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"extern const char *\";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \"_help[];\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (has_hidden)\n    {\n      stream << \"/** \";\n      stream << \"@\";\n      stream << \"brief all the lines making the full help output (including hidden options) */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"extern const char *\";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \"_full_help[];\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_details)\n    {\n      stream << \"/** \";\n      stream << \"@\";\n      stream << \"brief all the lines making the detailed help output (including hidden options and details) */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"extern const char *\";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \"_detailed_help[];\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * The command line parser\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param argc the number of command line options\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param argv the command line options\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param args_info the structure where option information will be stored\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \" (int argc, char **argv,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * The command line parser (version with additional parameters - deprecated)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param argc the number of command line options\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param argv the command line options\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param args_info the structure where option information will be stored\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param override whether to override possibly already present options\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param initialize whether to initialize the option structure my_args_info\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param check_required whether to check that all required options were provided\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"deprecated use \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_ext() instead\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"2 (int argc, char **argv,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  int override, int initialize, int check_required);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * The command line parser (version with additional parameters)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param argc the number of command line options\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param argv the command line options\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param args_info the structure where option information will be stored\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param params additional parameters for the parser\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_ext (int argc, char **argv,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *params);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Save the contents of the option struct into an already open FILE stream.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param outfile the stream where to dump options\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param args_info the option struct to dump\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_dump(FILE *outfile,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Save the contents of the option struct into a (text) file.\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * This file can be read by the config file parser (if generated by gengetopt)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param filename the file where to save\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param args_info the option struct to save\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_file_save(const char *filename,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Print the help\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_print_help(void);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (has_hidden)\n    {\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * Print the full help (including hidden options)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"void \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_print_full_help(void);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (has_details)\n    {\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * Print the detailed help (including hidden options and details)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"void \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_print_detailed_help(void);\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Print the version\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_print_version(void);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Initializes all the fields a \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params structure \";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * to their default values\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param params the structure to initialize\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params_init(struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *params);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Allocates dynamically a \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params structure and initializes\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * all its fields to their default values\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"return the created and initialized \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params structure\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"struct \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params *\";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_params_create(void);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Initializes the passed \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" structure's fields\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * (also set default values for options that have a default)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param args_info the structure to initialize\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_init (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Deallocates the string fields of the \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" structure\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * (but does not deallocate the structure itself)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param args_info the structure to deallocate\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"void \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_free (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (generate_config_parser)\n    {\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * The config file parser (deprecated version)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param filename the name of the config file\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param args_info the structure where option information will be stored\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param override whether to override possibly already present options\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param initialize whether to initialize the option structure my_args_info\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param check_required whether to check that all required options were provided\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"deprecated use \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_config_file() instead\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_configfile (const char *filename,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int override, int initialize, int check_required);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * The config file parser\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param filename the name of the config file\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param args_info the structure where option information will be stored\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param params additional parameters for the parser\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_config_file (const char *filename,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_params *params);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  if (generate_string_parser)\n    {\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * The string parser (interprets the passed string as a command line)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param cmdline the command line stirng\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param args_info the structure where option information will be stored\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param prog_name the name of the program that will be used to print\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" *   possible errors\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string (const char *cmdline, struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  const char *prog_name);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * The string parser (version with additional parameters - deprecated)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param cmdline the command line stirng\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param args_info the structure where option information will be stored\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param prog_name the name of the program that will be used to print\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" *   possible errors\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param override whether to override possibly already present options\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param initialize whether to initialize the option structure my_args_info\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param check_required whether to check that all required options were provided\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"deprecated use \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string_ext() instead\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string2 (const char *cmdline, struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  const char *prog_name,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  int override, int initialize, int check_required);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"/**\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * The string parser (version with additional parameters)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param cmdline the command line stirng\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param args_info the structure where option information will be stored\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param prog_name the name of the program that will be used to print\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" *   possible errors\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"param params additional parameters for the parser\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" * \";\n      stream << \"@\";\n      stream << \"return 0 if everything went fine, NON 0 if an error took place\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \" */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"int \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_string_ext (const char *cmdline, struct \";\n      generate_string (args_info, stream, indent + indent_str.length ());\n      stream << \" *args_info,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  const char *prog_name,\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  struct \";\n      generate_string (parser_name, stream, indent + indent_str.length ());\n      stream << \"_params *params);\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"/**\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * Checks that all the required options were specified\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param args_info the structure to check\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"param prog_name the name of the program that will be used to print\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" *   possible errors\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" * \";\n  stream << \"@\";\n  stream << \"return\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \" */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"int \";\n  generate_string (parser_name, stream, indent + indent_str.length ());\n  stream << \"_required (struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  const char *prog_name);\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  if (option_values_decl.size () > 0)\n    generate_string (option_values_decl, stream, indent + indent_str.length ());\n  else\n    generate_option_values_decl (stream, indent + indent_str.length ());\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#ifdef __cplusplus\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif /* __cplusplus */\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"#endif /* \";\n  generate_string (ifndefname, stream, indent + indent_str.length ());\n  stream << \"_H */\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/header.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.4 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef HEADER_GEN_CLASS_H\n#define HEADER_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass header_gen_class\n{\n protected:\n  string args_info;\n  string enum_types;\n  bool generate_config_parser;\n  bool generate_string_parser;\n  string generator_version;\n  string group_counters;\n  bool has_details;\n  bool has_hidden;\n  string header_file_ext;\n  string header_file_name;\n  string ifndefname;\n  string mode_counters;\n  string option_arg;\n  string option_given;\n  string option_values_decl;\n  string package_var_name;\n  string package_var_val;\n  string parser_name;\n  string version_var_name;\n  string version_var_val;\n\n public:\n  header_gen_class() :\n    generate_config_parser (false), generate_string_parser (false), has_details (false), has_hidden (false)\n  {\n  }\n\n  header_gen_class(const string &_args_info, const string &_enum_types, bool _generate_config_parser, bool _generate_string_parser, const string &_generator_version, const string &_group_counters, bool _has_details, bool _has_hidden, const string &_header_file_ext, const string &_header_file_name, const string &_ifndefname, const string &_mode_counters, const string &_option_arg, const string &_option_given, const string &_option_values_decl, const string &_package_var_name, const string &_package_var_val, const string &_parser_name, const string &_version_var_name, const string &_version_var_val) :\n    args_info (_args_info), enum_types (_enum_types), generate_config_parser (_generate_config_parser), generate_string_parser (_generate_string_parser), generator_version (_generator_version), group_counters (_group_counters), has_details (_has_details), has_hidden (_has_hidden), header_file_ext (_header_file_ext), header_file_name (_header_file_name), ifndefname (_ifndefname), mode_counters (_mode_counters), option_arg (_option_arg), option_given (_option_given), option_values_decl (_option_values_decl), package_var_name (_package_var_name), package_var_val (_package_var_val), parser_name (_parser_name), version_var_name (_version_var_name), version_var_val (_version_var_val)\n  {\n  }\n\n  virtual ~header_gen_class()\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_args_info(const string &_args_info)\n  {\n    args_info = _args_info;\n  }\n\n  virtual void generate_enum_types(ostream &stream, unsigned int indent) = 0;\n\n  void set_enum_types(const string &_enum_types)\n  {\n    enum_types = _enum_types;\n  }\n\n  void set_generate_config_parser(bool _generate_config_parser)\n  {\n    generate_config_parser = _generate_config_parser;\n  }\n\n  void set_generate_string_parser(bool _generate_string_parser)\n  {\n    generate_string_parser = _generate_string_parser;\n  }\n\n  void set_generator_version(const string &_generator_version)\n  {\n    generator_version = _generator_version;\n  }\n\n  virtual void generate_group_counters(ostream &stream, unsigned int indent) = 0;\n\n  void set_group_counters(const string &_group_counters)\n  {\n    group_counters = _group_counters;\n  }\n\n  void set_has_details(bool _has_details)\n  {\n    has_details = _has_details;\n  }\n\n  void set_has_hidden(bool _has_hidden)\n  {\n    has_hidden = _has_hidden;\n  }\n\n  void set_header_file_ext(const string &_header_file_ext)\n  {\n    header_file_ext = _header_file_ext;\n  }\n\n  void set_header_file_name(const string &_header_file_name)\n  {\n    header_file_name = _header_file_name;\n  }\n\n  void set_ifndefname(const string &_ifndefname)\n  {\n    ifndefname = _ifndefname;\n  }\n\n  virtual void generate_mode_counters(ostream &stream, unsigned int indent) = 0;\n\n  void set_mode_counters(const string &_mode_counters)\n  {\n    mode_counters = _mode_counters;\n  }\n\n  virtual void generate_option_arg(ostream &stream, unsigned int indent) = 0;\n\n  void set_option_arg(const string &_option_arg)\n  {\n    option_arg = _option_arg;\n  }\n\n  virtual void generate_option_given(ostream &stream, unsigned int indent) = 0;\n\n  void set_option_given(const string &_option_given)\n  {\n    option_given = _option_given;\n  }\n\n  virtual void generate_option_values_decl(ostream &stream, unsigned int indent) = 0;\n\n  void set_option_values_decl(const string &_option_values_decl)\n  {\n    option_values_decl = _option_values_decl;\n  }\n\n  void set_package_var_name(const string &_package_var_name)\n  {\n    package_var_name = _package_var_name;\n  }\n\n  void set_package_var_val(const string &_package_var_val)\n  {\n    package_var_val = _package_var_val;\n  }\n\n  void set_parser_name(const string &_parser_name)\n  {\n    parser_name = _parser_name;\n  }\n\n  void set_version_var_name(const string &_version_var_name)\n  {\n    version_var_name = _version_var_name;\n  }\n\n  void set_version_var_val(const string &_version_var_val)\n  {\n    version_var_val = _version_var_val;\n  }\n\n  void generate_header(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // HEADER_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/init_args_info.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"init_args_info.h\"\n\nvoid\ninit_args_info_gen_class::generate_init_args_info(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"args_info->\";\n  generate_string (var_arg, stream, indent + indent_str.length ());\n  stream << \"_help = \";\n  generate_string (help_strings, stream, indent + indent_str.length ());\n  stream << \"[\";\n  generate_string (num, stream, indent + indent_str.length ());\n  stream << \"] ;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  if (multiple)\n    {\n      stream << \"args_info->\";\n      generate_string (var_arg, stream, indent + indent_str.length ());\n      stream << \"_min = \";\n      generate_string (min, stream, indent + indent_str.length ());\n      stream << \";\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"args_info->\";\n      generate_string (var_arg, stream, indent + indent_str.length ());\n      stream << \"_max = \";\n      generate_string (max, stream, indent + indent_str.length ());\n      stream << \";\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/init_args_info.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef INIT_ARGS_INFO_GEN_CLASS_H\n#define INIT_ARGS_INFO_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass init_args_info_gen_class\n{\n protected:\n  string help_strings;\n  string max;\n  string min;\n  bool multiple;\n  string num;\n  string var_arg;\n\n public:\n  init_args_info_gen_class() :\n    multiple (false)\n  {\n  }\n\n  init_args_info_gen_class(const string &_help_strings, const string &_max, const string &_min, bool _multiple, const string &_num, const string &_var_arg) :\n    help_strings (_help_strings), max (_max), min (_min), multiple (_multiple), num (_num), var_arg (_var_arg)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_help_strings(const string &_help_strings)\n  {\n    help_strings = _help_strings;\n  }\n\n  void set_max(const string &_max)\n  {\n    max = _max;\n  }\n\n  void set_min(const string &_min)\n  {\n    min = _min;\n  }\n\n  void set_multiple(bool _multiple)\n  {\n    multiple = _multiple;\n  }\n\n  void set_num(const string &_num)\n  {\n    num = _num;\n  }\n\n  void set_var_arg(const string &_var_arg)\n  {\n    var_arg = _var_arg;\n  }\n\n  void generate_init_args_info(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // INIT_ARGS_INFO_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/multiple_fill_array.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"multiple_fill_array.h\"\n\nvoid\nmultiple_fill_array_gen_class::generate_multiple_fill_array(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (( default_value != \"0\" ))\n    {\n      stream << \"multiple_default_value.\";\n      if (( arg_type == \"ARG_STRING\" ))\n        {\n          stream << \"default_\";\n        }\n      generate_string (type, stream, indent + indent_str.length ());\n      stream << \"_arg = \";\n      generate_string (default_value, stream, indent + indent_str.length ());\n      stream << \";\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"update_multiple_arg((void *)&(args_info->\";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_arg),\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  &(args_info->\";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_orig), args_info->\";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_given,\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  local_args_info.\";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_given, \";\n  if (( default_value != \"0\" ))\n    {\n      stream << \"&multiple_default_value\";\n    }\n  else\n    {\n      stream << \"0\";\n    }\n  stream << \",\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (arg_type, stream, indent + indent_str.length ());\n  stream << \", \";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_list);\";\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/multiple_fill_array.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef MULTIPLE_FILL_ARRAY_GEN_CLASS_H\n#define MULTIPLE_FILL_ARRAY_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass multiple_fill_array_gen_class\n{\n protected:\n  string arg_type;\n  string default_value;\n  string option_var_name;\n  string type;\n\n public:\n  multiple_fill_array_gen_class()\n  {\n  }\n\n  multiple_fill_array_gen_class(const string &_arg_type, const string &_default_value, const string &_option_var_name, const string &_type) :\n    arg_type (_arg_type), default_value (_default_value), option_var_name (_option_var_name), type (_type)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_arg_type(const string &_arg_type)\n  {\n    arg_type = _arg_type;\n  }\n\n  void set_default_value(const string &_default_value)\n  {\n    default_value = _default_value;\n  }\n\n  void set_option_var_name(const string &_option_var_name)\n  {\n    option_var_name = _option_var_name;\n  }\n\n  void set_type(const string &_type)\n  {\n    type = _type;\n  }\n\n  void generate_multiple_fill_array(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // MULTIPLE_FILL_ARRAY_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/multiple_opt_list.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"multiple_opt_list.h\"\n\nvoid\nmultiple_opt_list_gen_class::generate_multiple_opt_list(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"struct generic_list * \";\n  generate_string (arg_name, stream, indent + indent_str.length ());\n  stream << \"_list = NULL;\";\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/multiple_opt_list.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef MULTIPLE_OPT_LIST_GEN_CLASS_H\n#define MULTIPLE_OPT_LIST_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass multiple_opt_list_gen_class\n{\n protected:\n  string arg_name;\n\n public:\n  multiple_opt_list_gen_class()\n  {\n  }\n\n  multiple_opt_list_gen_class(const string &_arg_name) :\n    arg_name (_arg_name)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_arg_name(const string &_arg_name)\n  {\n    arg_name = _arg_name;\n  }\n\n  void generate_multiple_opt_list(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // MULTIPLE_OPT_LIST_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/option_arg.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.3 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"option_arg.h\"\n\nvoid\noption_arg_gen_class::generate_option_arg(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (long_long_arg)\n    {\n      stream << \"#ifdef HAVE_LONG_LONG\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (type, stream, indent + indent_str.length ());\n      stream << \" \";\n      generate_string (name, stream, indent + indent_str.length ());\n      stream << \"_arg;\t/**< \";\n      stream << \"@\";\n      stream << \"brief \";\n      generate_string (desc, stream, indent + indent_str.length ());\n      if (has_default)\n        {\n          stream << \" (default=\";\n          generate_string (default_value, stream, indent + indent_str.length ());\n          stream << \")\";\n        }\n      stream << \".  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#else\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (longtype, stream, indent + indent_str.length ());\n      stream << \" \";\n      generate_string (name, stream, indent + indent_str.length ());\n      stream << \"_arg;\t/**< \";\n      stream << \"@\";\n      stream << \"brief \";\n      generate_string (desc, stream, indent + indent_str.length ());\n      if (has_default)\n        {\n          stream << \" (default=\";\n          generate_string (default_value, stream, indent + indent_str.length ());\n          stream << \")\";\n        }\n      stream << \".  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"#endif\";\n      stream << \"\\n\";\n      stream << indent_str;\n      generate_string (origtype, stream, indent + indent_str.length ());\n      stream << \" \";\n      generate_string (name, stream, indent + indent_str.length ());\n      stream << \"_orig;\t/**< \";\n      stream << \"@\";\n      stream << \"brief \";\n      generate_string (desc, stream, indent + indent_str.length ());\n      stream << \" original value given at command line.  */\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      if (flag_arg)\n        {\n          generate_string (type, stream, indent + indent_str.length ());\n          stream << \" \";\n          generate_string (name, stream, indent + indent_str.length ());\n          stream << \"_flag;\t/**< \";\n          stream << \"@\";\n          stream << \"brief \";\n          generate_string (desc, stream, indent + indent_str.length ());\n          stream << \" (default=\";\n          if (default_on)\n            {\n              stream << \"on\";\n            }\n          else\n            {\n              stream << \"off\";\n            }\n          stream << \").  */\";\n          stream << \"\\n\";\n          stream << indent_str;\n        }\n      else\n        {\n          if (has_arg)\n            {\n              if (has_enum)\n                {\n                  stream << \"enum enum_\";\n                  generate_string (name, stream, indent + indent_str.length ());\n                  stream << \" \";\n                  if (multiple)\n                    {\n                      stream << \"*\";\n                    }\n                  generate_string (name, stream, indent + indent_str.length ());\n                  stream << \"_arg;\t/**< \";\n                  stream << \"@\";\n                  stream << \"brief \";\n                  generate_string (desc, stream, indent + indent_str.length ());\n                  if (has_default)\n                    {\n                      stream << \" (default='\";\n                      generate_string (default_value, stream, indent + indent_str.length ());\n                      stream << \"')\";\n                    }\n                  stream << \".  */\";\n                  stream << \"\\n\";\n                  stream << indent_str;\n                }\n              else\n                {\n                  generate_string (type, stream, indent + indent_str.length ());\n                  stream << \" \";\n                  generate_string (name, stream, indent + indent_str.length ());\n                  stream << \"_arg;\t/**< \";\n                  stream << \"@\";\n                  stream << \"brief \";\n                  generate_string (desc, stream, indent + indent_str.length ());\n                  if (has_default)\n                    {\n                      stream << \" (default='\";\n                      generate_string (default_value, stream, indent + indent_str.length ());\n                      stream << \"')\";\n                    }\n                  stream << \".  */\";\n                  stream << \"\\n\";\n                  stream << indent_str;\n                }\n              generate_string (origtype, stream, indent + indent_str.length ());\n              stream << \" \";\n              generate_string (name, stream, indent + indent_str.length ());\n              stream << \"_orig;\t/**< \";\n              stream << \"@\";\n              stream << \"brief \";\n              generate_string (desc, stream, indent + indent_str.length ());\n              stream << \" original value given at command line.  */\";\n              stream << \"\\n\";\n              stream << indent_str;\n            }\n        }\n    }\n  if (multiple)\n    {\n      stream << \"unsigned int \";\n      generate_string (name, stream, indent + indent_str.length ());\n      stream << \"_min; /**< \";\n      stream << \"@\";\n      stream << \"brief \";\n      generate_string (desc, stream, indent + indent_str.length ());\n      stream << \"'s minimum occurreces */\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"unsigned int \";\n      generate_string (name, stream, indent + indent_str.length ());\n      stream << \"_max; /**< \";\n      stream << \"@\";\n      stream << \"brief \";\n      generate_string (desc, stream, indent + indent_str.length ());\n      stream << \"'s maximum occurreces */\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  stream << \"const char *\";\n  generate_string (name, stream, indent + indent_str.length ());\n  stream << \"_help; /**< \";\n  stream << \"@\";\n  stream << \"brief \";\n  generate_string (desc, stream, indent + indent_str.length ());\n  stream << \" help description.  */\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/option_arg.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.3 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef OPTION_ARG_GEN_CLASS_H\n#define OPTION_ARG_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass option_arg_gen_class\n{\n protected:\n  bool default_on;\n  string default_value;\n  string desc;\n  bool flag_arg;\n  bool has_arg;\n  bool has_default;\n  bool has_enum;\n  bool long_long_arg;\n  string longtype;\n  bool multiple;\n  string name;\n  string origtype;\n  string type;\n\n public:\n  option_arg_gen_class() :\n    default_on (false), flag_arg (false), has_arg (false), has_default (false), has_enum (false), long_long_arg (false), multiple (false)\n  {\n  }\n\n  option_arg_gen_class(bool _default_on, const string &_default_value, const string &_desc, bool _flag_arg, bool _has_arg, bool _has_default, bool _has_enum, bool _long_long_arg, const string &_longtype, bool _multiple, const string &_name, const string &_origtype, const string &_type) :\n    default_on (_default_on), default_value (_default_value), desc (_desc), flag_arg (_flag_arg), has_arg (_has_arg), has_default (_has_default), has_enum (_has_enum), long_long_arg (_long_long_arg), longtype (_longtype), multiple (_multiple), name (_name), origtype (_origtype), type (_type)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_default_on(bool _default_on)\n  {\n    default_on = _default_on;\n  }\n\n  void set_default_value(const string &_default_value)\n  {\n    default_value = _default_value;\n  }\n\n  void set_desc(const string &_desc)\n  {\n    desc = _desc;\n  }\n\n  void set_flag_arg(bool _flag_arg)\n  {\n    flag_arg = _flag_arg;\n  }\n\n  void set_has_arg(bool _has_arg)\n  {\n    has_arg = _has_arg;\n  }\n\n  void set_has_default(bool _has_default)\n  {\n    has_default = _has_default;\n  }\n\n  void set_has_enum(bool _has_enum)\n  {\n    has_enum = _has_enum;\n  }\n\n  void set_long_long_arg(bool _long_long_arg)\n  {\n    long_long_arg = _long_long_arg;\n  }\n\n  void set_longtype(const string &_longtype)\n  {\n    longtype = _longtype;\n  }\n\n  void set_multiple(bool _multiple)\n  {\n    multiple = _multiple;\n  }\n\n  void set_name(const string &_name)\n  {\n    name = _name;\n  }\n\n  void set_origtype(const string &_origtype)\n  {\n    origtype = _origtype;\n  }\n\n  void set_type(const string &_type)\n  {\n    type = _type;\n  }\n\n  void generate_option_arg(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // OPTION_ARG_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/print_help_string.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"print_help_string.h\"\n\nvoid\nprint_help_string_gen_class::generate_print_help_string(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (shared)\n    {\n      generate_string (target, stream, indent + indent_str.length ());\n      stream << \"[\";\n      generate_string (index, stream, indent + indent_str.length ());\n      stream << \"] = \";\n      if (last)\n        {\n          stream << \"0; \";\n        }\n      else\n        {\n          generate_string (from, stream, indent + indent_str.length ());\n          stream << \"[\";\n          generate_string (full_index, stream, indent + indent_str.length ());\n          stream << \"];\";\n        }\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"\\\"\";\n      generate_string (helpstring, stream, indent + indent_str.length ());\n      stream << \"\\\",\";\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/print_help_string.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef PRINT_HELP_STRING_GEN_CLASS_H\n#define PRINT_HELP_STRING_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass print_help_string_gen_class\n{\n protected:\n  string from;\n  string full_index;\n  string helpstring;\n  string index;\n  bool last;\n  bool shared;\n  string target;\n\n public:\n  print_help_string_gen_class() :\n    last (false), shared (false)\n  {\n  }\n\n  print_help_string_gen_class(const string &_from, const string &_full_index, const string &_helpstring, const string &_index, bool _last, bool _shared, const string &_target) :\n    from (_from), full_index (_full_index), helpstring (_helpstring), index (_index), last (_last), shared (_shared), target (_target)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_from(const string &_from)\n  {\n    from = _from;\n  }\n\n  void set_full_index(const string &_full_index)\n  {\n    full_index = _full_index;\n  }\n\n  void set_helpstring(const string &_helpstring)\n  {\n    helpstring = _helpstring;\n  }\n\n  void set_index(const string &_index)\n  {\n    index = _index;\n  }\n\n  void set_last(bool _last)\n  {\n    last = _last;\n  }\n\n  void set_shared(bool _shared)\n  {\n    shared = _shared;\n  }\n\n  void set_target(const string &_target)\n  {\n    target = _target;\n  }\n\n  void generate_print_help_string(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // PRINT_HELP_STRING_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/required_option.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"required_option.h\"\n\nvoid\nrequired_option_gen_class::generate_required_option(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  if (checkrange)\n    {\n      stream << \"if (\";\n      generate_string (mode_condition, stream, indent + indent_str.length ());\n      stream << \"check_multiple_option_occurrences(\";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \", args_info->\";\n      generate_string (option_var_name, stream, indent + indent_str.length ());\n      stream << \"_given, args_info->\";\n      generate_string (option_var_name, stream, indent + indent_str.length ());\n      stream << \"_min, args_info->\";\n      generate_string (option_var_name, stream, indent + indent_str.length ());\n      stream << \"_max, \\\"\";\n      generate_string (option_descr, stream, indent + indent_str.length ());\n      stream << \"\\\"))\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"   error = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n  else\n    {\n      stream << \"if (\";\n      generate_string (mode_condition, stream, indent + indent_str.length ());\n      stream << \"! args_info->\";\n      generate_string (option_var_name, stream, indent + indent_str.length ());\n      stream << \"_given)\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  {\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    fprintf (stderr, \\\"%s: \";\n      generate_string (option_descr, stream, indent + indent_str.length ());\n      stream << \" option required%s\\\\n\\\", \";\n      generate_string (package_var_name, stream, indent + indent_str.length ());\n      stream << \", (additional_error ? additional_error : \\\"\\\"));\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"    error = 1;\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"  }\";\n      stream << \"\\n\";\n      stream << indent_str;\n      stream << \"\\n\";\n      stream << indent_str;\n    }\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/required_option.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef REQUIRED_OPTION_GEN_CLASS_H\n#define REQUIRED_OPTION_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass required_option_gen_class\n{\n protected:\n  bool checkrange;\n  string mode_condition;\n  string option_descr;\n  string option_var_name;\n  string package_var_name;\n\n public:\n  required_option_gen_class() :\n    checkrange (false)\n  {\n  }\n\n  required_option_gen_class(bool _checkrange, const string &_mode_condition, const string &_option_descr, const string &_option_var_name, const string &_package_var_name) :\n    checkrange (_checkrange), mode_condition (_mode_condition), option_descr (_option_descr), option_var_name (_option_var_name), package_var_name (_package_var_name)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_checkrange(bool _checkrange)\n  {\n    checkrange = _checkrange;\n  }\n\n  void set_mode_condition(const string &_mode_condition)\n  {\n    mode_condition = _mode_condition;\n  }\n\n  void set_option_descr(const string &_option_descr)\n  {\n    option_descr = _option_descr;\n  }\n\n  void set_option_var_name(const string &_option_var_name)\n  {\n    option_var_name = _option_var_name;\n  }\n\n  void set_package_var_name(const string &_package_var_name)\n  {\n    package_var_name = _package_var_name;\n  }\n\n  void generate_required_option(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // REQUIRED_OPTION_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/reset_group.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"reset_group.h\"\n\nvoid\nreset_group_gen_class::generate_reset_group(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"static void\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"reset_group_\";\n  generate_string (name, stream, indent + indent_str.length ());\n  stream << \"(struct \";\n  generate_string (args_info, stream, indent + indent_str.length ());\n  stream << \" *args_info)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"{\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  if (! args_info->\";\n  generate_string (name, stream, indent + indent_str.length ());\n  stream << \"_group_counter)\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"    return;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  indent = 2;\n  stream << \"  \";\n  generate_string (body, stream, indent + indent_str.length ());\n  indent = 0;\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"  args_info->\";\n  generate_string (name, stream, indent + indent_str.length ());\n  stream << \"_group_counter = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"}\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/reset_group.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef RESET_GROUP_GEN_CLASS_H\n#define RESET_GROUP_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass reset_group_gen_class\n{\n protected:\n  string args_info;\n  string body;\n  string name;\n\n public:\n  reset_group_gen_class()\n  {\n  }\n\n  reset_group_gen_class(const string &_args_info, const string &_body, const string &_name) :\n    args_info (_args_info), body (_body), name (_name)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_args_info(const string &_args_info)\n  {\n    args_info = _args_info;\n  }\n\n  void set_body(const string &_body)\n  {\n    body = _body;\n  }\n\n  void set_name(const string &_name)\n  {\n    name = _name;\n  }\n\n  void generate_reset_group(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // RESET_GROUP_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/skels/update_given.cc",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#include \"update_given.h\"\n\nvoid\nupdate_given_gen_class::generate_update_given(ostream &stream, unsigned int indent)\n{\n  string indent_str (indent, ' ');\n  indent = 0;\n\n  stream << \"args_info->\";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_given += local_args_info.\";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_given;\";\n  stream << \"\\n\";\n  stream << indent_str;\n  stream << \"local_args_info.\";\n  generate_string (option_var_name, stream, indent + indent_str.length ());\n  stream << \"_given = 0;\";\n  stream << \"\\n\";\n  stream << indent_str;\n}\n"
  },
  {
    "path": "utilities/gengetopt/skels/update_given.h",
    "content": "/*\n * File automatically generated by\n * gengen 1.2 by Lorenzo Bettini\n * https://www.gnu.org/software/gengen\n */\n\n#ifndef UPDATE_GIVEN_GEN_CLASS_H\n#define UPDATE_GIVEN_GEN_CLASS_H\n\n#include <string>\n#include <iostream>\n\nusing std::string;\nusing std::ostream;\n\nclass update_given_gen_class\n{\n protected:\n  string option_var_name;\n\n public:\n  update_given_gen_class()\n  {\n  }\n\n  update_given_gen_class(const string &_option_var_name) :\n    option_var_name (_option_var_name)\n  {\n  }\n\n  static void\n  generate_string(const string &s, ostream &stream, unsigned int indent)\n  {\n    if (!indent || s.find('\\n') == string::npos)\n      {\n        stream << s;\n        return;\n      }\n\n    string::size_type pos;\n    string::size_type start = 0;\n    string ind (indent, ' ');\n    while ( (pos=s.find('\\n', start)) != string::npos)\n      {\n        stream << s.substr (start, (pos+1)-start);\n        start = pos+1;\n        if (start+1 <= s.size ())\n          stream << ind;\n      }\n    if (start+1 <= s.size ())\n      stream << s.substr (start);\n  }\n\n  void set_option_var_name(const string &_option_var_name)\n  {\n    option_var_name = _option_var_name;\n  }\n\n  void generate_update_given(ostream &stream, unsigned int indent = 0);\n\n};\n\n#endif // UPDATE_GIVEN_GEN_CLASS_H\n"
  },
  {
    "path": "utilities/gengetopt/yyerror.cc",
    "content": "/*\nThis file is licensed to you under the license specified in the included file\n`LICENSE'. Look there for further details.\n*/\n\n\n/*\n  Called by yyparse on error.\n */\n\n#include \"yyerror.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <iostream>\n\nextern int gengetopt_count_line;\nextern char * gengetopt_input_filename;\n\nextern int tokenpos;\nextern char linebuf[];\nextern char *yytext;\n\nusing namespace std;\n\nvoid\nyyerror (const char *s)\n{\n  const char *source =\n    (gengetopt_input_filename ? gengetopt_input_filename : \"gengetopt\");\n\n  fprintf (stderr, \"%s:%d: %s %s\\n\", source, gengetopt_count_line, s, yytext);\n\n  if (/*!linebuf || */!strlen(linebuf))\n    return;\n\n  fprintf (stderr, \"%s:%d: %s\\n\", source, gengetopt_count_line, linebuf);\n  fprintf (stderr, \"%s:%d: %*s\\n\", source, gengetopt_count_line,\n           tokenpos + 1, \"^\");\n}\n\nvoid\nyyerror (gengetopt_option *opt, const char *s)\n{\n  const char *source =\n    (opt->filename ? opt->filename : \"gengetopt\");\n\n  cerr << source << \":\" << opt->linenum << \": \" << s << endl;\n}\n"
  },
  {
    "path": "utilities/gengetopt/yyerror.h",
    "content": "#ifndef YYERROR_H_\n#define YYERROR_H_\n\n#include \"ggos.h\"\n\nvoid\nyyerror (const char *s);\n\nvoid\nyyerror (gengetopt_option *opt, const char *s);\n\n#endif /*YYERROR_H_*/\n"
  },
  {
    "path": "utilities/gengetopt/yywrap.c",
    "content": "/*\nThis file is licensed to you under the license specified in the included file\n`LICENSE'. Look there for further details.\n*/\n\n\n/*\n  This function is called when found EOF.\n */\n#include <stdio.h>\n\nint\nyywrap ()\n{\n  /* fprintf (stderr, \"yywrap() called.\\n\"); */\n  return 1;\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/CMakeLists.txt",
    "content": "set(LPSOLVE_VERSION_MAJOR 5)\nset(LPSOLVE_VERSION_MINOR 5)\nset(LPSOLVE_VERSION_PATCH 2)\nset(LPSOLVE_VERSION ${LPSOLVE_VERSION_MAJOR}.${LPSOLVE_VERSION_MINOR}.${LPSOLVE_VERSION_PATCH})\n\nrtk_module_warnings_disable(C CXX)\n\n# Set up install directories\nadd_library(lpsolve55\n\tlp_MDO.c\n\tshared/commonlib.c\n\tshared/mmio.c\n\tshared/myblas.c\n\tini.c\n\tcolamd/colamd.c\n\tlp_rlp.c\n\tlp_crash.c\n\tbfp/bfp_LUSOL/lp_LUSOL.c\n\tbfp/bfp_LUSOL/LUSOL/lusol.c\n\tlp_Hash.c\n\tlp_lib.c\n\tlp_wlp.c\n\tlp_matrix.c\n\tlp_mipbb.c\n\tlp_MPS.c\n\tlp_params.c\n\tlp_presolve.c\n\tlp_price.c\n\tlp_pricePSE.c\n\tlp_report.c\n\tlp_scale.c\n\tlp_simplex.c\n\tlp_SOS.c\n\tlp_utils.c\n\tyacc_read.c\n)\n\ninclude_directories(\n\t\"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>\"\n\t\"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/shared>\"\n\t\"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/bfp>\"\n\t\"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/bfp/bfp_LUSOL>\"\n\t\"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/bfp/bfp_LUSOL/LUSOL>\"\n\t\"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/colamd>\"\n)\n\nset_property(TARGET lpsolve55 APPEND PROPERTY COMPILE_DEFINITIONS\n\tYY_NEVER_INTERACTIVE\n\tPARSER_LP\n\tINVERSE_ACTIVE=INVERSE_LUSOL\n\tRoleIsExternalInvEngine\n        LoadInverseLib=FALSE\n        LoadLanguageLib=FALSE\n        LoadableBlasLib=0\n)\n\nif(WIN32)\n    set_property(TARGET lpsolve55 APPEND PROPERTY COMPILE_DEFINITIONS\n                INLINE=static\n\t\t_USRDLL\n\t\tWIN32\n    )\nendif()\n\ninclude(CheckSymbolExists)\ncheck_symbol_exists(isnan math.h HAVE_ISNAN)\nif(NOT HAVE_ISNAN)\n\tset_property(TARGET lpsolve55 APPEND PROPERTY COMPILE_DEFINITIONS NOISNAN)\nendif()\n\n# Set version of library\nset_target_properties(lpsolve55 PROPERTIES VERSION ${LPSOLVE_VERSION}\n                                           SOVERSION ${LPSOLVE_VERSION_MAJOR})\n\nif (NOT ITK_SOURCE_DIR)\n  # Export to RTK build targets must be done after RTK has been loaded by ITK.\n  # When building externally we must do this after including ITKModuleExternal.\n  # See RTK/CMakeLists.txt.\nelse()\n  itk_module_target(lpsolve55)\nendif()\n"
  },
  {
    "path": "utilities/lp_solve/README.txt",
    "content": "Introduction\n------------\nWhat is lp_solve and what is it not?\nThe simple answer is, lp_solve is a Mixed Integer Linear Programming (MILP) solver.\n\nIt is a free (see LGPL for the GNU lesser general public license) linear (integer) programming solver\nbased on the revised simplex method and the Branch-and-bound method for the integers.\nIt contains full source, examples and manuals.\nlp_solve solves pure linear, (mixed) integer/binary, semi-continuous and\nspecial ordered sets (SOS) models.\n\nSee the reference guide for more information.\n\n\nlp_solve 5.5\n------------\n\nWhy a jump from version numbers 5.1 to 5.5 ?\nThis is done to indicate that this is more than just another update.\nThe solver engine was revised and optimised in such a way that performance has improved considerably.\nNumerical stability is also better resulting in more models that can be solved.\nThe LUSOL bfp is now also the default. In the past, the etaPFI bfp package was the default,\nbut for larger models this leads faster to numerical instabilities and performance problems.\n\nOverall, the v5.5 code is faster and more robust than v5.1.\nThis robustness is for example proven by the fact that many more models can now be solved even without scaling.\n\nThe API hasn't changed very much.\nThere are a couple of new routines and one routine has an extra argument.\nSome constants got new values.\n\n    * Fundamental internal change to the solver engine resulting in better performance and numerical stability.\n      Both the LP solver and the B&B solvers are enhanced.\n    * Optimised MILP branch truncation, with reduced cost fixing.\n    * LUSOL bfp is now the default.\n    * Presolve is improved in functionality and performance.\n    * Better handling of degeneracy, with more options.\n    * Store and read options from a file make it easier to set options.\n    * Partial pricing for the primal simplex now works.\n    * Full support for xli_ZIMPL v2.0.3.\n    * The objective function is no longer stored as part of the constraint matrix.\n    * Dual-long step code is in place, but not fully activated yet.\n    * General code cleanup.\n    * Added OBJSENSE and OBJNAME headers in the free MPS format (See MPS file format).\n    * The MathProg xli driver has now the ability to generate a model.\n    * New API routines\n\nStart by taking a look at 'Changes compared to version 4', 'Changes from version 5.1 to version 5.5'\nand 'lp_solve usage'\nThis gives a good starting point.\n\n\nBFP's\n-----\n\nBFP stands for Basis Factorization Package, which is a unique lp_solve feature.  Considerable\neffort has been put in this new feature and we have big expectations for this. BFP is a generic\ninterface model and users can develop their own implementations based on the provided templates.\nWe are very interested in providing as many different BFPs as possible to the community.\n\nlp_solve 5.5 has the LUSOL BFP built in as default engine.  In addition two other\nBFPs are included for both Windows and Linux: bfp_etaPFI.dll, bfp_GLPK.dll for Windows and\nlibbfp_etaPFI.so, libbfp_GLPK.so for Linux.  The bfp_etaPFI includes\nadvanced column ordering using the COLAMD library, as well as better pivot management for\nstability.  For complex models, however, the LU factorization approach is much better, and\nlp_solve now includes LUSOL as one of the most stable engines available anywhere.  LUSOL was\noriginally developed by Prof. Saunders at Stanford, and it has now been ported to C\nand enhanced by Kjell.\n\nIf you compile BFPs yourself, make sure that under Windows, you use __stdcall convention and\nuse 8 byte alignments.  This is needed for the BFPs to work correctly with the general\ndistribution of lp_solve and also to make sharing BFPs as uncomplicated as possible.\n\nSee the reference guide for more information.\n\n\nXLI's\n-----\n\nXLI stands for eXternal Language Interface, also a unique lp_solve feature. XLI's are stand-alone\nlibraries used as add-on to lp_solve to make it possible to read and write lp models in a format\nnot natively supported by lp_solve. Examples are CPLEX lp format, LINDO lp format, MathProg format,\nXML format...\n\nSee the reference guide for more information.\n\n\nlpsolve API\n-----------\n\nDon't forget that the API has changed compared to previous versions of lpsolve and that you just\ncan't use the version 5 lpsolve library with your version 4 or older code.  That is also the\nreason why the library is now called lpsolve55.dll/lpsolve55.a.  lpsolve55.dll or lpsolve55.a are\nonly needed when you call the lpsolve library via the API interface from your program.\nThe lp_solve program is still a stand-alone executable program.\n\nThere are examples interfaces for different language like C, VB, C#, VB.NET, Java,\nDelphi, and there is now also even a COM object to access the lpsolve library.  This means that\nthe door is wide-open for using lp_solve in many different situations.  Thus everything that is\navailable in version 4 is now also available in version 5 and already much more!\n\nSee the reference guide for more information.\n\n\nConversion between lp modeling formats\n--------------------------------------\n\nNote that lp2mps and mps2lp don't exist anymore. However this functionality is now implemented\nin lp_solve:\n\nlp2mps can be simulated as following:\nlp_solve -parse_only -lp infile -wmps outfile\n\nmps2lp can be simulated as following:\nlp_solve -parse_only -mps infile -wlp outfile\n\n\nvia the -rxli option, a model can be read via an XLI library and via the -wxli option, a model\ncan be written via an XLI library.\n\n\nHow to build the executables yourself.\n---------------------------------------\n\nAt this time, there are no Makefiles yet. However for the time being, there are batch files/scripts\nto build. For the Microsoft compiler under Windows, use cvc6.bat, for the gnu compiler under Windows,\nuse cgcc.bat and for Unix/Linux, use the ccc shell script (sh ccc).\n\nSee the reference guide for more information.\n\n\nIDE\n---\n\nUnder Windows, there is now also a very user friendly lpsolve IDE. Check out LPSolveIDE\n\nSee the reference guide for more information.\n\n\nDocumentation (reference guide)\n-------------------------------\n\nSee lp_solve55.chm for a Windows HTML help documentation file.\nThe html files are also in lp_solve_5.5_doc.tar.gz. Start with index.htm\nAlso see http://lpsolve.sourceforge.net/ for a on-line documentation\n\n\nChange history:\n---------------\n\n17/05/05 version 5.5.0.0\n- Beta release of version 5.5\n\n??/??/05 version 5.5.0.1\n- ?\n\n26/06/05 version 5.5.0.2\n- ?\n\n29/06/05 version 5.5.0.3\n- ?\n\n16/08/05 version 5.5.0.4\n- There are no API changes\n- The LUSOL message routine could generate a crash under some cicumstances. Fixed\n- A crash could occur when building the model in add_row_mode. Fixed.\n- write_params didn't write the PRESOLVE and PRESOLVELOOPS correctly. Fixed.\n- write_params didn't write constants with value 0. Fixed.\n- The library did not compile under msdev 2002 (VC 7.0 _MSC_VER 1300). Fixed.\n- There were some problems with printing long long variables which could generate a crash. Fixed.\n- An overflow error could occur because memory was sometimes overwritten. Fixed.\n- Presolve routines are revised. They are again improved and made faster.\n  Also some problems with it are fixed (possible crashes).\n- Solver revised. Again made faster and more stable.\n- get_row/get_column returned FALSE if the row/column is empty. Fixed.\n- get_rowex/get_columnex now returns -1 if and error is detected. This instead of 0.\n  This to know the distinction between an empty row/column and an error.\n- set_bounds had a possible problem when min and max are equal. Fixed.\n- A crash/damage error could occur when rows/columns are added after a solve. Fixed.\n- The my_chsign macro in lp_types.h gave warnings with some compilers. Fixed.\n- The lp_solve program now returns 255 if an unexpected error occurs. Before this was 1\n  But this interferes with the lpsolve library return codes.\n- With the lp_solve program, debug and print modes were not written correctly in a\n  specified parameter file. Fixed.\n- With the lp_solve program, presolveloops was not set correctly. Fixed.\n\n17/09/05 version 5.5.0.5\n- In some cases, SOS restrictions were not optimized till optimality. Fixed.\n- Presolve sometimes generated 'Column -xxx out of range during presolve' with a possible crash.\n- Presolve sometimes removed integer and/or semi-cont variables that should not be deleted. Fixed.\n- B&B sometimes didn't find the most optimal solution. Fixed.\n- Internal constant COMP_EQUAL renamed to COMP_PREFERNONE because this could interfere with a define\n  in the standard header files.\n- The lp parser had problems with variables starting with INF and there is a + or - sign just before it.\n  Fixed.\n- Added options -presolvem, -presolvefd, -presolvebnd, -presolved, -presolveslk\n- Updated documentation. put_bb_branchfunc, put_bb_nodefunc, set_epslevel, dualize_lp, set_basisvar\n\n16/11/05 version 5.5.0.6\n- set_add_rowmode should not be called after a solve. There is now a test in this routine when this is\n  done and it then returns FALSE.\n- When an empty string (\"\") as filename is provided to set_outputfile, then output is completely\n  ignored.\n- In some cases, SOS models did not solve to their most optimal solution.\n- There was as problem with get_sensitivity_objex. Calling it (sometimes only after multiple times)\n  resulted in protection errors/core dumps.\n- When a model has no constraints, it did not solve most of the times.\n- column_in_lp didn't work anymore.\n- Large upper bounds could make the model unstable. A change was made to fix this.\n- set_improve could let crash the model.\n- lp_params.c used the non-ANSI function unlink(). Changed to ANSI function remove().\n- Presolve is again revised considerably.\n- SOS handling is improved when there are a lot of SOS constraints.\n- Limited constraint-to-SOS1 presolve to constraints with at least 4 variables.\n- Limited bound tightening presolve loops.\n\n12/02/06 version 5.5.0.7\n- When SOS restrictions are added after a previous solve, a crash could occur.\n- Optimized renaming a variable when the new name is equal to the old name.\n- A possible crash could occur when presolve was enabled\n- The constant ANTIDEGEN_DEFAULT is changed. ANTIDEGEN_INFEASIBLE is removed from it.\n  This constant should not be used unless you have some very tight and hard to solve\n  models where the optimal solution numerically straddles infeasibility.\n- There was a possible problem with set_row(ex). It sometimes wrongfully changed the row.\n- When integer variables were scaled, it could happen that because of rounding errors,\n  a loop was created.\n- Sometimes integer models kept on looping in the B&B algorithm.\n- A memory overrun could occur when an initial basis is set. This when variable names\n  are in Rnnn format and constraint names in Cnnn format.\n- Some fixes are made in presolve.\n- On 64-bit systems, compiler warnings were given and some code worked wrong resulting in\n  wrong results.\n- lp_solve.c didn't compile with some compilers because if a very deep nested if statement.\n- The distributed files now have the version number include in the filename.\n  For example lp_solve_5.5.0.7_exe.zip\n  This for a possible move to SourceForge in the (near?) future.\n- When illegal bounds are specified in the MPS format (lower bound larger than upper bound)\n  then a warning was given but the illegal bound was just ignored and the model was solved.\n  This resulted in a solution that did not comply to the original model. Now the message is\n  seen as an error and solving is aborted.\n\n\n06/09/06 version 5.5.0.8\n- When presolve is active and columns are removed and there are SOS constraints, then presolve\n  had an error which could result in hanging while solve or maybe wrong solutions.\n- set_row(ex) set wrong values when used after a previous solve and scaling is active.\n- disabled PRESOLVE_REDUCEMIP since it is very rare that this is effective, and also that it adds\n  code complications and delayed presolve effects that are not captured properly.\n- made routine guess_basis available for all languages (now exported by the dll).\n  The routine is now also documented.\n- some bug corrections in guess_basis.\n- Corrected a problem with add_column(ex) when add_rowmode is enabled.\n- write_lp now wraps long lines over multiple lines to make it more readable.\n- A compilation warning/error sometimes occured on is_fixedvar in lp_lusol.c with some compilers.\n- Added options -wxlisol and -wxlisolopt to lp_solve program to write a solution file for those\n  XLIs that support it.\n- Updated CPLEX XLI to support constants in objective.\n- Added documentation on infeasible models, guess_basis, DIMACS models, CPLEX format, Zimpl, GNU Mathprog.\n  Corrected/updated documentation on get_col_name, get_row_name, get_nameindex, write_xli,\n  External Language Interfaces.\n- The mps reader was improved for the rarely cases where the same elements are provided multiple\n  times. These are now added.\n- Revised the java unittest example because it gave some errors that it shouldn't give.\n\n07/10/06 version 5.5.0.9\n- set_row(ex) could sometimes set wrong values in the model.\n- Sometimes models with semi-cont variables which are also integer and scaling is active, a solution\n  was returned that is not most optimal or it returns infeasible.\n- write_mps didn't write semi-cont variables with an infinite upper bound.\n- When presolve can solve the model on its own and objective direction is maximize then a wrong sign\n  was shown in the reported price on screen.\n- write_lp writes constraint and bounds in the same way if a constraint is not named. If a constraint\n  only has one variable then it looks like a bound. This can give problems because when a constraint\n  is interpreted as bound and it is negative then the problem definition changes.\n  Therefore a constraint which is not named and having only one variable in it is getting a name to\n  make sure it is interpreted as a constraint.\n- The lp_solve program didn't interprete the PRESOLVED solve return code very well. Fixed.\n- bfp_GLPK and xli_MathProg are now compiled against GLPK 4.11\n- When an integer model is aborted before the most optimal solution is found (timeout or\n  break at first, ...) solve returned OPTIMAL (0) instead of SUBOPTIMAL (1). This is now corrected.\n\n14/01/07 version 5.5.0.10\n- If a model has integer variables, but the model is already integer optimal in the simplex fase,\n  then it was reported as suboptimal feasible.\n- get_objective, get_variables, get_ptr_variables, get_constraints, get_ptr_constraints, get_primal_solution\n  reported 'not a valid basis' when presolve is active and the model is entirely solved by presolve.\n- presolve on a model with SOS variables sometimes went wrong.\n- presolve on a model with SOS variables where infeasibility is detected crashed.\n- read_bas could fail when not all constraints had names or had names like default variable names.\n- A crash could occur with set_row(ex) in rowmode.\n- The lp format has been extended with a free section to define free variables.\n- bfp_GLPK and xli_MathProg are now compiled against GLPK 4.13\n- fixed bug in the pseudocost logic that can blow up subsequent pseudocost values in that\n  branch and make them almost random.\n- In some rare cases a memory overrun could occur when constraints are added after a previous solve.\n- Made the copy_lp routine work. Note that information about the optimisation of the original model\n  is not copied (at this time). Only the model is.\n- Fixed a bug in the hashing routines that had only influence in some rare cases in the\n  MATLAB, O-Matrix, Scilab, Octave, Python drivers.\n- coldual sometimes worked on a uninitialised variable value with unpredictable results.\n\n27/12/07 version 5.5.0.11\n- Fixed a problem in presolve. Sometimes an array-index-out-of-bounds error occured.\n- Added a makefile for Linux.\n- When adding constraints, in some rare cases a memory overrun could occur resulting in a crash.\n- add_constraintex with count=0 and row=colno=NULL gave a protection error.\n  several XLIs didn't work anymore because of this.\n- set_constr_type sometimes set wrong signs for the coefficient matrix when add_rowmode is on.\n- presolve did an unnecessary extra loop. Also a test is added to stop presolve when very few\n  changes are done.\n- for very large models, a request of much more memory than is reasonable could occur. Fixed.\n- Modified LINDO XLI to read keywords also not at column 1 and to accept an empty objective function.\n  Previously this wat not possible.\n- In some rare cases, numbers very close to their integer values (for example 11276.999999999998)\n  were truncated to their ceiling value (for example 11276) instead of rounded\n  (for example 11277).\n- Solved a problem with presolve with an all-int constraint.\n- Solved a problem with presolve coldominate\n- Added stronger checking of the MPS format.\n  Fields that must be blank are now also tested accordingly so that if data is there that it is\n  not ignored as before.\n- FREE MPS format was not read ok if row/column name were all numbers\n  or a FR, MI, PL, BV bound was defined. Fixed.\n- The lp-format now also supports a bin(ary) section to define binary variables.\n- When an integer model is aborted before the most optimal solution is found\n  via break at first or break at value, solve returned OPTIMAL (0) instead of SUBOPTIMAL (1).\n  This is now corrected. Problem occured in version 5.5.0.10\n- Fixed a problem with del_constraint. Constraints names were not shifted and reported variable result was incorrect.\n- read_XLI failed with MathProg if datamodel was provided with \"\" when there is no datamodel.\n  NULL was expected in the past. \"\" is now also accepted.\n- Added an XLI to read Xpress lp files.\n- Added routines MPS_writefileex, write_lpex.\n- Added options -o0, -o1 to lp_solve command driven program to specify if objective is in basis or not.\n- Added new information in the reference guide:\n   - Linear programming basics\n   - Presolve\n   - Xpress lp files\n\n04/01/08 version 5.5.0.11\n- There was an error in the lp-parser resulting is misreading the model in many cases. This was fixed in the existing release and an update of following files is posted:\n    lp_solve_5.5.0.11_exe.tar.gz\n    lp_solve_5.5.0.11_dev.tar.gz\n    lp_solve_5.5.0.11_source.tar.gz\n    lp_solve_5.5.0.11_exe.zip\n    lp_solve_5.5.0.11_dev.zip\n\n13/03/08 version 5.5.0.12\n- When NODE_RCOSTFIXING (bound tightening during B&B) (enabled by default) was enabled some models were not solved\n  to optimality.\n- In following situation a (sub-optimal) solution was returned while no integer\n  solution isn't found yet at this time.\n   - The model contains integers\n   - A break at first is set\n   - A timeout is set\n   - The timeout occurs before a first integer solution is found\n   - When the timeout occurs, the simplex algorithm is in phase 2 and has a feasible (but non-integer) solution, but not optimal yet.\n- If an integer solution is found with the same objective value as the relaxed solution then\n  B&B is stopped. However this resulted in a report of a SUBOPTIMAL solution while this is not true.\n  The found solution is then optimal.\n- On 64-bit Linux systems crashes occured when information is printed via variable argument routines.\n- There was a warning about redefinition of MAXINT32, MAXUINT32, MAXINT64, MAXUINT64 when compiled\n  with MS Visual C 2008.\n- The reference guide now also contains the Java documentation.\n\n03/08/08 version 5.5.0.13\n- The code should now completely be reentrant and thread safe.\n  Especially the lp-parser, but also the solver code itself used static variables which made it\n  not reentrant.\n  The lp parser code has changed considerably for this. Also the lex and yacc code had to be made\n  reentrant. This is only tested with GNU flex and bison. Not with lex and yacc.\n  This should be no problem since the corresponding c files are included with the source so people\n  don't have to build these themselves.\n- commonlib.c/h were also under BFP/BFP_LUSOL/LUSOL while a more advanced version is also\n  under the shared directory. The one from LUSOL is removed.\n- If objective coefficients are all integer and the columns are integer or objective coefficients\n  are zero, then B&B can stop when the objective function equals ceil/floor(real objective)\n  which results in a faster solving process. This did not work anymore and is now fixed.\n- The lpsolve IDE is now also on sourceforge (previously it was a link to another site).\n  Also the sources are included.\n\n02/02/09 version 5.5.0.14\n- The lp format now allows spaces between the row label and the colon.\n- Added better error handling in the copy_lp API\n- Timeout in a MIP model sometimes resulted in an endless loop\n- Revised isnan call for gnu compilers\n- Removed some extra static variables for better reentrance support.\n- REPORT_Objective now reports large objective values (>1e-5) with better precision\n- On Windows the binaries are again compiled with compiler optimization /O2 for better performance.\n- Compiled and tested on Windows and Linux 64-bit. 64-bit binaries are now provided.\n  Changed project files and compile scripts for 64-bit compilation.\n  Binaries are now located in a subdirectory bin\\platform\n- Added PHP driver so that lpsolve can be called from PHP\n- When an MPS file is created, upper bounds were written before lower bounds.\n  Now it is the other way around. First lower bounds and then upper bounds.\n- The MPS reader could not handle negative lower bounds where the lower bound was specified after the upper bound.\n- The MPS write now writes the implicit lower bound of zero if the variable has no lower bound and it is integer.\n  This to make sure that other solvers (like CPLEX) interprete the variable as integer and not binary.\n- The LINDO XLI parser interpreted negative lower and upper bounds as positive\n- Added the option -stat to the lp_solve driver program. It prints statistics of the model like number of\n  rows/columns used and smalled and largest value in objective, RHS and coefficient matrix.\n- Added the option -plp to the lp_solve driver program. It prints the model via the print_lp API function.\n\n09/09/09 version 5.5.0.15\n- Improved guess_basis\n- set_row(ex) corrections. Actually completely revised the routine.\n  Sometimes the matrix was corrupted after the call.\n- When in set_add_row mode, all API calls can now be used. For example printing or writing the model,\n  retrieving data from the model and so on are now all possible in that mode.\n  Will help greatly when debugging your models.\n- Sometimes an integer model is reported infeasible while it isn't because the integer solution\n  is much different from the relaxed (real) model. Then API call set_bb_depthlimit can be used\n  to increase the default B&B depth. However its new value was not used for the depth limit of an\n  individual variabled which could result in still infeasible results.\n- modified the demo program not to use the str_ versions of API calls, because they are not\n  performant and not intended to be used in real programs.\n- Added an lpsolve driver to Sysquake.\n- Added an lpsolve driver to FreeMat.\n- Added an lpsolve driver to Euler.\n- Added an Access example.\n- Added documentation to use lpsolve from Sage via the existing Python driver.\n- Changed the second parameter to read_mps, read_MPS, read_freemps and read_freeMPS from verbose to options.\n  These routines now supports via this options parameter the native IBM interpretation of\n  integer variables and allows to negate the objective constant.\n  This is also supported by the lp_solve command line program via the -mps_ibm and -mps_negobjconst options.\n  This is also supported by the IDE in the options tab.\n- Removed read_LPhandle and read_MPShandle from the lprec structure.\n  On their place there is now read_LP and read_MPS.\n  The handle functions are not usable anyway under windows as dll because the FILE structure\n  is searched in the dll space and therefore not working.\n  read_LP and read_MPS work on the file name and always work.\n  Since these handle routines were not documented anyway and the lp structure should not be\n  accessed by applications (except XLI and BFP drivers) this change should not give any (compatibility) problem at all.\n- write_lp/write_LP write just a + or - if the factor to a variable is +1 or -1\n  However when the number was not exactly one, for example 1.0000000000001, then the test\n  on equal to one gave false, but the writing was a 1 because only 12 significant digits are written.\n  The result was that the 1 was written in that case. Not an error, but when lp files are compared,\n  this is enoying. Now this is solved. When a +1 or -1 would be written then alyways only + and -\n  is written and +1 or -1 will never occur again.\n- When a message function is set via put_msgfunc,\n  in message MSG_LPOPTIMAL it was not possible to get the solution. Now it is.\n  Also when messages MSG_MILPFEASIBLE, MSG_MILPBETTER, MSG_MILPEQUAL were catched the\n  returned solution was the one from the previous MIP solution. This is now also fixed.\n  With this fix, the IDE now also shows the relaxed solution (column LP Optimal).\n- Extended the MATLAB, O-Matrix, Scilab, Octave, Python, PHP and of course the new\n  Sysquake, FreeMat and Euler drivers to support string constants. See the reference guide.\n- Compiled and tested lpsolve on MAC OSX 10.4.8 (Intel). Compilation scripts for this platform\n  were added and revised and binaries are provided to download.\n- Revised the c# and vb.net lpsolve code to pass arrays back and forth to the dll to make it also work on 64 bit systems.\n- IDE enhancements:\n      - Can talk to the lpsolve55.dll large address aware version so access to 3.4G 32 bit memory.\n      - Can write and read lp_solve parameter files ( type .lpi) via Options, Solver params, so\n        it is easy to save a readable file of parameters for a particular problem class when it is found.\n        The file can then be collected by the -rpar exe param or the read_params() API.\n      - Added Options, Reset to solver defaults to go back to all lp_solve defaults.\n      - Added in Help a link to the online help files.\n      - Resized the help, main and statistics windows for Vista.\n      - Added the Xpress XLI to the setup.\n      - Use the latest dlls, especially lpsolve55.dll, in the setup.\n      - Added the two new MPS options for IBM integer variables and negate objective constant.\n      - Added the option to ignore integer restrictions.\n17/09/09 version 5.5.0.15b\n- objfrom values where not correct if scaling is active.\n  Routine to calculate these values and the objective from-till values is revised\n  and made a bit more performant.\n- write_lp did not write all column data. For objective function and constraints.\n\n28/10/09 version 5.5.1.0\n- In some cases with a model with integer variables lp_solve did not find the most optimal solution. Fixed.\n- The reported relative gap for the optimal solution was not always ok.\n- Sensitivity on a zero upper bounded variable was not calculated. Now it is.\n\n08/03/10 version 5.5.1.2\n- When there are integer variables in the model then sensitivity is not correct.\n\n12/08/10 version 5.5.2.0\n- add_SOS did a wrong test when SOS type is bigger than 2 if this SOS is allowed in lp_solve. Fixed\n- new and improved MIP_stepOF function to find integer solutions.\n- fixes in set_row.\n- replaces code\n   w *= 2*lp->is_lower[i] - 1;\n  by\n   w = my_chsign(!lp->is_lower[i], w);\n  because the old failed on AIX\n  Also changed the definition of my_chsign in lp_types.h in the same way.\n- Added the option -BR in the lp_solve driver program to select branch rule NODE_PSEUDORATIOSELECT\n- lpsolve.pas updated for Delphi 2009.\n- Python driver updated to allow also to provide numpy arrays to the lpsolve driver.\n- xli_MathProg is now compiled against glpk 4.44 meaning that it now supports the MathProg Tables feature\n  as described in https://www.cs.unb.ca/~bremner/docs/glpk/tables.pdf\n  csv, ODBC and MySQL are supported on all platforms.\n- Added MSF support. MSF (Microsoft Solver Foundation) is a microsoft .NET library to access solvers via an OO way\n  MSF has a default lpsolve driver, but the one on the sourceforge site is enhanced in functionality and performance.\n  There is also documentation in the lpsolve reference guide.\n\n../../.. version 5.5.2.1\n- fixed a small error in new and improved MIP_stepOF function to find integer solutions.\n\n../../.. version 5.5.2.2\n- For integer models with semi-cont variables it happened sometimes that a message\n  \"fillbranches_BB: Inconsistent equal-valued bounds for ...\" occured and that the semi-cont condition\n  was not respected.\n- New functions added: get_accuracy to get the numeric accuracy after solve.\n- New functions added: set_break_numeric_accuracy, get_break_numeric_accuracy to let lp_solve return ACCURACYERROR\n  instead of FEASIBLE when numerical accuracy if worse then the provided values.\n  In the past, lp_solve only returned a non-optimal status in case of very severe numerical instability.\n  Now it will return already ACCURACYERROR when it finds a relative inaccuracy of 5e-7\n- When reading a model from the lp-format and important issues are detected such as already bounds on variables being overruled\n  later with for example a bin keyword, this is now reported in the default verbose level such that this is seen easier.\n\n08/05/16 version 5.5.2.3\n- For some models with integer variables, lp_solve did not find the most optimal solution.\n\n15/09/16 version 5.5.2.4\n- When using set_lowbo and set_upbo to set bounds on a variable and the new low/up bounds are very close to each other\n  but not equal then they are set equal for numerical stability.\n\n18/09/16 version 5.5.2.5\n- When all variables in the model are integer, but not all binary (in fact difference between upper and lower bound 1),\n  then it could happen that not the most optimal integer solution was found.\n- Updated/added scaling options to the lp_solve command line program\n\nWe are thrilled to hear from you and your experiences with this new version. The good and the bad.\nAlso we would be pleased to hear about your experiences with the different BFPs on your models.\n\nPlease send reactions to:\nPeter Notebaert: lpsolve@peno.be\nKjell Eikland: kjell.eikland@broadpark.no\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/LUSOL_LGPL.txt",
    "content": "\t\t  GNU LESSER GENERAL PUBLIC LICENSE\n\t\t       Version 2.1, February 1999\n\n Copyright (C) 1991, 1999 Free Software Foundation, Inc.\n     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n[This is the first released version of the Lesser GPL.  It also counts\n as the successor of the GNU Library Public License, version 2, hence\n the version number 2.1.]\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicenses are intended to guarantee your freedom to share and change\nfree software--to make sure the software is free for all its users.\n\n  This license, the Lesser General Public License, applies to some\nspecially designated software packages--typically libraries--of the\nFree Software Foundation and other authors who decide to use it.  You\ncan use it too, but we suggest you first think carefully about whether\nthis license or the ordinary General Public License is the better\nstrategy to use in any particular case, based on the explanations below.\n\n  When we speak of free software, we are referring to freedom of use,\nnot price.  Our General Public Licenses are designed to make sure that\nyou have the freedom to distribute copies of free software (and charge\nfor this service if you wish); that you receive source code or can get\nit if you want it; that you can change the software and use pieces of\nit in new free programs; and that you are informed that you can do\nthese things.\n\n  To protect your rights, we need to make restrictions that forbid\ndistributors to deny you these rights or to ask you to surrender these\nrights.  These restrictions translate to certain responsibilities for\nyou if you distribute copies of the library or if you modify it.\n\n  For example, if you distribute copies of the library, whether gratis\nor for a fee, you must give the recipients all the rights that we gave\nyou.  You must make sure that they, too, receive or can get the source\ncode.  If you link other code with the library, you must provide\ncomplete object files to the recipients, so that they can relink them\nwith the library after making changes to the library and recompiling\nit.  And you must show them these terms so they know their rights.\n\n  We protect your rights with a two-step method: (1) we copyright the\nlibrary, and (2) we offer you this license, which gives you legal\npermission to copy, distribute and/or modify the library.\n\n  To protect each distributor, we want to make it very clear that\nthere is no warranty for the free library.  Also, if the library is\nmodified by someone else and passed on, the recipients should know\nthat what they have is not the original version, so that the original\nauthor's reputation will not be affected by problems that might be\nintroduced by others.\n\f\n  Finally, software patents pose a constant threat to the existence of\nany free program.  We wish to make sure that a company cannot\neffectively restrict the users of a free program by obtaining a\nrestrictive license from a patent holder.  Therefore, we insist that\nany patent license obtained for a version of the library must be\nconsistent with the full freedom of use specified in this license.\n\n  Most GNU software, including some libraries, is covered by the\nordinary GNU General Public License.  This license, the GNU Lesser\nGeneral Public License, applies to certain designated libraries, and\nis quite different from the ordinary General Public License.  We use\nthis license for certain libraries in order to permit linking those\nlibraries into non-free programs.\n\n  When a program is linked with a library, whether statically or using\na shared library, the combination of the two is legally speaking a\ncombined work, a derivative of the original library.  The ordinary\nGeneral Public License therefore permits such linking only if the\nentire combination fits its criteria of freedom.  The Lesser General\nPublic License permits more lax criteria for linking other code with\nthe library.\n\n  We call this license the \"Lesser\" General Public License because it\ndoes Less to protect the user's freedom than the ordinary General\nPublic License.  It also provides other free software developers Less\nof an advantage over competing non-free programs.  These disadvantages\nare the reason we use the ordinary General Public License for many\nlibraries.  However, the Lesser license provides advantages in certain\nspecial circumstances.\n\n  For example, on rare occasions, there may be a special need to\nencourage the widest possible use of a certain library, so that it becomes\na de-facto standard.  To achieve this, non-free programs must be\nallowed to use the library.  A more frequent case is that a free\nlibrary does the same job as widely used non-free libraries.  In this\ncase, there is little to gain by limiting the free library to free\nsoftware only, so we use the Lesser General Public License.\n\n  In other cases, permission to use a particular library in non-free\nprograms enables a greater number of people to use a large body of\nfree software.  For example, permission to use the GNU C Library in\nnon-free programs enables many more people to use the whole GNU\noperating system, as well as its variant, the GNU/Linux operating\nsystem.\n\n  Although the Lesser General Public License is Less protective of the\nusers' freedom, it does ensure that the user of a program that is\nlinked with the Library has the freedom and the wherewithal to run\nthat program using a modified version of the Library.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.  Pay close attention to the difference between a\n\"work based on the library\" and a \"work that uses the library\".  The\nformer contains code derived from the library, whereas the latter must\nbe combined with the library in order to run.\n\f\n\t\t  GNU LESSER GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License Agreement applies to any software library or other\nprogram which contains a notice placed by the copyright holder or\nother authorized party saying it may be distributed under the terms of\nthis Lesser General Public License (also called \"this License\").\nEach licensee is addressed as \"you\".\n\n  A \"library\" means a collection of software functions and/or data\nprepared so as to be conveniently linked with application programs\n(which use some of those functions and data) to form executables.\n\n  The \"Library\", below, refers to any such software library or work\nwhich has been distributed under these terms.  A \"work based on the\nLibrary\" means either the Library or any derivative work under\ncopyright law: that is to say, a work containing the Library or a\nportion of it, either verbatim or with modifications and/or translated\nstraightforwardly into another language.  (Hereinafter, translation is\nincluded without limitation in the term \"modification\".)\n\n  \"Source code\" for a work means the preferred form of the work for\nmaking modifications to it.  For a library, complete source code means\nall the source code for all modules it contains, plus any associated\ninterface definition files, plus the scripts used to control compilation\nand installation of the library.\n\n  Activities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning a program using the Library is not restricted, and output from\nsuch a program is covered only if its contents constitute a work based\non the Library (independent of the use of the Library in a tool for\nwriting it).  Whether that is true depends on what the Library does\nand what the program that uses the Library does.\n\n  1. You may copy and distribute verbatim copies of the Library's\ncomplete source code as you receive it, in any medium, provided that\nyou conspicuously and appropriately publish on each copy an\nappropriate copyright notice and disclaimer of warranty; keep intact\nall the notices that refer to this License and to the absence of any\nwarranty; and distribute a copy of this License along with the\nLibrary.\n\n  You may charge a fee for the physical act of transferring a copy,\nand you may at your option offer warranty protection in exchange for a\nfee.\n\f\n  2. You may modify your copy or copies of the Library or any portion\nof it, thus forming a work based on the Library, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) The modified work must itself be a software library.\n\n    b) You must cause the files modified to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    c) You must cause the whole of the work to be licensed at no\n    charge to all third parties under the terms of this License.\n\n    d) If a facility in the modified Library refers to a function or a\n    table of data to be supplied by an application program that uses\n    the facility, other than as an argument passed when the facility\n    is invoked, then you must make a good faith effort to ensure that,\n    in the event an application does not supply such function or\n    table, the facility still operates, and performs whatever part of\n    its purpose remains meaningful.\n\n    (For example, a function in a library to compute square roots has\n    a purpose that is entirely well-defined independent of the\n    application.  Therefore, Subsection 2d requires that any\n    application-supplied function or table used by this function must\n    be optional: if the application does not supply it, the square\n    root function must still compute square roots.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Library,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Library, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote\nit.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Library.\n\nIn addition, mere aggregation of another work not based on the Library\nwith the Library (or with a work based on the Library) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may opt to apply the terms of the ordinary GNU General Public\nLicense instead of this License to a given copy of the Library.  To do\nthis, you must alter all the notices that refer to this License, so\nthat they refer to the ordinary GNU General Public License, version 2,\ninstead of to this License.  (If a newer version than version 2 of the\nordinary GNU General Public License has appeared, then you can specify\nthat version instead if you wish.)  Do not make any other change in\nthese notices.\n\f\n  Once this change is made in a given copy, it is irreversible for\nthat copy, so the ordinary GNU General Public License applies to all\nsubsequent copies and derivative works made from that copy.\n\n  This option is useful when you wish to copy part of the code of\nthe Library into a program that is not a library.\n\n  4. You may copy and distribute the Library (or a portion or\nderivative of it, under Section 2) in object code or executable form\nunder the terms of Sections 1 and 2 above provided that you accompany\nit with the complete corresponding machine-readable source code, which\nmust be distributed under the terms of Sections 1 and 2 above on a\nmedium customarily used for software interchange.\n\n  If distribution of object code is made by offering access to copy\nfrom a designated place, then offering equivalent access to copy the\nsource code from the same place satisfies the requirement to\ndistribute the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  5. A program that contains no derivative of any portion of the\nLibrary, but is designed to work with the Library by being compiled or\nlinked with it, is called a \"work that uses the Library\".  Such a\nwork, in isolation, is not a derivative work of the Library, and\ntherefore falls outside the scope of this License.\n\n  However, linking a \"work that uses the Library\" with the Library\ncreates an executable that is a derivative of the Library (because it\ncontains portions of the Library), rather than a \"work that uses the\nlibrary\".  The executable is therefore covered by this License.\nSection 6 states terms for distribution of such executables.\n\n  When a \"work that uses the Library\" uses material from a header file\nthat is part of the Library, the object code for the work may be a\nderivative work of the Library even though the source code is not.\nWhether this is true is especially significant if the work can be\nlinked without the Library, or if the work is itself a library.  The\nthreshold for this to be true is not precisely defined by law.\n\n  If such an object file uses only numerical parameters, data\nstructure layouts and accessors, and small macros and small inline\nfunctions (ten lines or less in length), then the use of the object\nfile is unrestricted, regardless of whether it is legally a derivative\nwork.  (Executables containing this object code plus portions of the\nLibrary will still fall under Section 6.)\n\n  Otherwise, if the work is a derivative of the Library, you may\ndistribute the object code for the work under the terms of Section 6.\nAny executables containing that work also fall under Section 6,\nwhether or not they are linked directly with the Library itself.\n\f\n  6. As an exception to the Sections above, you may also combine or\nlink a \"work that uses the Library\" with the Library to produce a\nwork containing portions of the Library, and distribute that work\nunder terms of your choice, provided that the terms permit\nmodification of the work for the customer's own use and reverse\nengineering for debugging such modifications.\n\n  You must give prominent notice with each copy of the work that the\nLibrary is used in it and that the Library and its use are covered by\nthis License.  You must supply a copy of this License.  If the work\nduring execution displays copyright notices, you must include the\ncopyright notice for the Library among them, as well as a reference\ndirecting the user to the copy of this License.  Also, you must do one\nof these things:\n\n    a) Accompany the work with the complete corresponding\n    machine-readable source code for the Library including whatever\n    changes were used in the work (which must be distributed under\n    Sections 1 and 2 above); and, if the work is an executable linked\n    with the Library, with the complete machine-readable \"work that\n    uses the Library\", as object code and/or source code, so that the\n    user can modify the Library and then relink to produce a modified\n    executable containing the modified Library.  (It is understood\n    that the user who changes the contents of definitions files in the\n    Library will not necessarily be able to recompile the application\n    to use the modified definitions.)\n\n    b) Use a suitable shared library mechanism for linking with the\n    Library.  A suitable mechanism is one that (1) uses at run time a\n    copy of the library already present on the user's computer system,\n    rather than copying library functions into the executable, and (2)\n    will operate properly with a modified version of the library, if\n    the user installs one, as long as the modified version is\n    interface-compatible with the version that the work was made with.\n\n    c) Accompany the work with a written offer, valid for at\n    least three years, to give the same user the materials\n    specified in Subsection 6a, above, for a charge no more\n    than the cost of performing this distribution.\n\n    d) If distribution of the work is made by offering access to copy\n    from a designated place, offer equivalent access to copy the above\n    specified materials from the same place.\n\n    e) Verify that the user has already received a copy of these\n    materials or that you have already sent this user a copy.\n\n  For an executable, the required form of the \"work that uses the\nLibrary\" must include any data and utility programs needed for\nreproducing the executable from it.  However, as a special exception,\nthe materials to be distributed need not include anything that is\nnormally distributed (in either source or binary form) with the major\ncomponents (compiler, kernel, and so on) of the operating system on\nwhich the executable runs, unless that component itself accompanies\nthe executable.\n\n  It may happen that this requirement contradicts the license\nrestrictions of other proprietary libraries that do not normally\naccompany the operating system.  Such a contradiction means you cannot\nuse both them and the Library together in an executable that you\ndistribute.\n\f\n  7. You may place library facilities that are a work based on the\nLibrary side-by-side in a single library together with other library\nfacilities not covered by this License, and distribute such a combined\nlibrary, provided that the separate distribution of the work based on\nthe Library and of the other library facilities is otherwise\npermitted, and provided that you do these two things:\n\n    a) Accompany the combined library with a copy of the same work\n    based on the Library, uncombined with any other library\n    facilities.  This must be distributed under the terms of the\n    Sections above.\n\n    b) Give prominent notice with the combined library of the fact\n    that part of it is a work based on the Library, and explaining\n    where to find the accompanying uncombined form of the same work.\n\n  8. You may not copy, modify, sublicense, link with, or distribute\nthe Library except as expressly provided under this License.  Any\nattempt otherwise to copy, modify, sublicense, link with, or\ndistribute the Library is void, and will automatically terminate your\nrights under this License.  However, parties who have received copies,\nor rights, from you under this License will not have their licenses\nterminated so long as such parties remain in full compliance.\n\n  9. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Library or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Library (or any work based on the\nLibrary), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Library or works based on it.\n\n  10. Each time you redistribute the Library (or any work based on the\nLibrary), the recipient automatically receives a license from the\noriginal licensor to copy, distribute, link with or modify the Library\nsubject to these terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties with\nthis License.\n\f\n  11. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Library at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Library by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Library.\n\nIf any portion of this section is held invalid or unenforceable under any\nparticular circumstance, the balance of the section is intended to apply,\nand the section as a whole is intended to apply in other circumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  12. If the distribution and/or use of the Library is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Library under this License may add\nan explicit geographical distribution limitation excluding those countries,\nso that distribution is permitted only in or among countries not thus\nexcluded.  In such case, this License incorporates the limitation as if\nwritten in the body of this License.\n\n  13. The Free Software Foundation may publish revised and/or new\nversions of the Lesser General Public License from time to time.\nSuch new versions will be similar in spirit to the present version,\nbut may differ in detail to address new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Library\nspecifies a version number of this License which applies to it and\n\"any later version\", you have the option of following the terms and\nconditions either of that version or of any later version published by\nthe Free Software Foundation.  If the Library does not specify a\nlicense version number, you may choose any version ever published by\nthe Free Software Foundation.\n\f\n  14. If you wish to incorporate parts of the Library into other free\nprograms whose distribution conditions are incompatible with these,\nwrite to the author to ask for permission.  For software which is\ncopyrighted by the Free Software Foundation, write to the Free\nSoftware Foundation; we sometimes make exceptions for this.  Our\ndecision will be guided by the two goals of preserving the free status\nof all derivatives of our free software and of promoting the sharing\nand reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO\nWARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.\nEXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR\nOTHER PARTIES PROVIDE THE LIBRARY \"AS IS\" WITHOUT WARRANTY OF ANY\nKIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE\nLIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME\nTHE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN\nWRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY\nAND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU\nFOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR\nCONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE\nLIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING\nRENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A\nFAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF\nSUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\f\n           How to Apply These Terms to Your New Libraries\n\n  If you develop a new library, and you want it to be of the greatest\npossible use to the public, we recommend making it free software that\neveryone can redistribute and change.  You can do so by permitting\nredistribution under these terms (or, alternatively, under the terms of the\nordinary General Public License).\n\n  To apply these terms, attach the following notices to the library.  It is\nsafest to attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least the\n\"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the library's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public\n    License along with this library; if not, write to the Free Software\n    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n\nAlso add information on how to contact you by electronic and paper mail.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the library, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the\n  library `Frob' (a library for tweaking knobs) written by James Random Hacker.\n\n  <signature of Ty Coon>, 1 April 1990\n  Ty Coon, President of Vice\n\nThat's all there is to it!\n\n\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/LUSOL_Overview.txt",
    "content": "            Notes for Contribution of LUSOL to COIN-OR\n                            May 2004\n\nIntroduction\n============\n\nLUSOL maintains sparse LU factors of a square or rectangular sparse matrix.  It includes a Basis Factorization Package (BFP) suitable for implementing simplex and reduced-gradient methods for optimization.  It is a set of  routines written in ANSI C (adapted from the original Fortran 77 version).\n\nLUSOL includes the following features:\n\n-  A Markowitz-based sparse LU factorization for square,\n   rectangular and possibly singular matrices.\n\n-  Three options for balancing sparsity and stability:\n   Threshold Partial/Rook/Complete Pivoting (TPP, TRP, TCP).\n\n-  Rank-revealing properties.  TRP and TCP are intended for detecting singularities.\n\n-  Dynamic storage allocation (C version only).\n\n-  Stable column replacement as in the method of Bartels and Golub.\n\n-  Other stable updates: add, replace, or delete row or column\n   (currently F77 version only).\n\n-  Implementation into an easy-to-use BFP API (C version only).\n\n\nImplementation\n==============\n\nThe Factor routine is similar to the classical Markowitz routines MA28 and LA05 in the Harwell Subroutine Library. The source matrix nonzeros are stored column-wise with the largest entry at the top of each column.  Internally, the structure is also accessible row-wise.  All entries in a particular column or row are held in contiguous storage.  Fill is accommodated by moving a column or row to the beginning of free storage. Occasional compressions recover storage.  This scheme is effective for column-oriented TPP.  When the remaining matrix reaches a specified density, the factors are completed using dense processing.\n\nTRP uses an additional vector of storage to maintain the largest element in each remaining row.\n\nTCP uses a heap structure to hold the largest element in each column.  The largest element in the remaining matrix is then available at the top of the heap.\n\nThe final L is stored column-wise (and never changed).  The final U is stored row-wise as a triangular or trapezoidal sparse matrix.\n\nColumn replacements are implemented using a forward sweep of 2-by-2 stabilized elimination matrices.  L is updated in product form.  U is updated explicitly.\n\nThe other updates use either forward or backward sweeps. They tend to generate more nonzeros than column replacement.\n\nBoth the F77 and C versions contain extensive comments, method and implementational information as part of the code.\n\nThe C version contains a record-based wrapper for the data.  Function calls have been simplified by including references to this structure.  New maintenance routines enable dynamic instance creation and destruction, and  simplifies access to the most frequently used functions.  The LUSOL C library is multi-instance and fully re-entrant.  All control and output parameters have been given long descriptive names for usability.\n\n\nBenefits\n========\n\nRank-revealing properties and rectangular factors (and updates) have not previously been available in sparse LU software.  With sensible parameter settings and reasonably scaled data, all routines are numerically stable.  The updates may be called hundreds of times, and the decision to refactorize can be based on sparsity considerations alone.\n\nIn the Factor routine, rook pivoting (TRP) gives reliable rank determination without catastrophic degradation in sparsity or speed.  Complete pivoting (TCP) is included for moderate-sized matrices and for checking pathological cases (but the factors tend to be substantially more dense).\n\nTo conserve storage, one may request only the row and column pivot orders.  The factors are discarded as they are computed.  This is useful for basis repair, or for selecting a basis from a rectangular matrix.\n\n\nKnown Inefficiencies\n====================\n\nLUSOL is usually efficient on sparse matrices with dimensions up to about 100,000 (but not millions).\n\nIn the Factor routine, row and column lists must be updated each time a row and column is eliminated.  Deleting the pivot row and column is inefficient if the original matrix contains unusually dense rows or columns.  For TPP, dense columns could be kept aside and incorporated at the end via updates (but dense rows remain a difficulty).  For TRP and TCP, all rows and columns must be present to achieve the required numerical properties.\n\nFor TRP, the current bottleneck is updating the vector containing the largest element in each row.  One solution would be to include the matrix nonzeros in the row structure (but this carries its own cost).\n\nFor TCP, the heap structure is already efficient, but the dense factors (and the extended searching for acceptable pivots) are unavoidable expenses.\n\nThe triangular Solve routines do not take full of advantage of sparse right-hand sides.  Gilbert and Peierls have shown how to solve Lx = (sparse b) efficiently if L is stored column-wise.  Their approach could therefore be implemented in LUSOL for solves with L and U(transpose).  Solves with L(transpose) and U would need a second copy of L and U.\n\n\nOriginal Reference\n==================\n\nP. E. Gill, W. Murray, M. A. Saunders and M. H. Wright, Maintaining LU factors of a general sparse matrix, Linear Algebra and its Applications 88/89, 239-270 (1987).\n\n\nMaintainers\n===========\n\nF77 version: Michael Saunders (saunders@stanford.edu).\nC version: Kjell Eikland (kjell.eikland@broadpark.no).\n\n\nContributors\n============\n\nPhilip Gill, Walter Murray, Margaret Wright, Michael O'Sullivan.\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/LUSOL_README.txt",
    "content": "README.TXT for LUSOL - Advanced LU solver with enhanced numerical stability options\n-----------------------------------------------------------------------------------\n\nLUSOL - pronounced \"L-U-SOL\" - was developed by Prof. Michael Saunders at the\nStanford (University) Optimization Laboratory over a period of 2 decades of\nprogressive improvements.  It is a particularly capable matrix factorization system\nand includes sparsity-preserving column updates and equation solving.  It is\ntherefore particularly well suited to be part of a system to solve tough mathematical\nprogramming problems.  Further details can be found in the file \"LUSOL-overview.txt.\"\n\nA big step has been made in converting the original Fortran code into a much more\neasily accessible and modularized system based on ANSI C as part of the release of\nlp_solve v5.  LUSOL is fully implemented as a \"Basis Factorization Package\", BFP in\nlp_solve and is the BFP of choice for large and complex models, if not all.  As part\nof the conversion to C, processor optimized BLAS functionality has been enabled, and\nfuture enhancements to LUSOL may make increasing use of this, ensuring top performance.\n\nFor the lp_solve release of LUSOL, a stand-alone equation solving system has also been\ndeveloped.  A pre-compiled Windows command-line executable version is included in the\nstandard distribution of LUSOL. In addition, the program options illustrate several\nadvanced uses of LUSOL.  The equation solving utility features reading of standard\nmatrix files in the Harwell-Boeing, MatrixMarket and text formats.  Sample matrix\nmodels are provided for Harwell-Boeing (.RUA) and MatrixMarket (.mtx).\n\nThe LUSOL code is released under the GNU Lesser General Public Licence.  Confer the\nfile \"Licence_LGPL.txt\" for the full terms of this licence.  These terms make lp_solve\nand LUSOL available and distributable on equal licencing terms.  It is expected that\nLUSOL will have an official repository in the near future, but the LUSOL archive at\nthe Yahoo lp_solve group will be an official copy and the formal repository until\nfurther notice.\n\n\nKjell Eikland\n14 July 2004\nOslo, Norway\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol.c",
    "content": "\n/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   LUSOL routines from the Stanford Optimization Laboratory\n   The parts included are:\n    lusol1      Factor a given matrix A from scratch (lu1fac).\n    lusol2      Heap-management routines for lu1fac.\n    lusol6      Solve with the current LU factors.\n    lusol7      Utilities for all update routines.\n    lusol8      Replace a column (Bartels-Golub update).\n   ------------------------------------------------------------------\n   26 Apr 2002: TCP implemented using heap data structure.\n   01 May 2002: lu1DCP implemented.\n   07 May 2002: lu1mxc must put 0.0 at top of empty columns.\n   09 May 2002: lu1mCP implements Markowitz with cols searched\n                in heap order.\n                Often faster (searching 20 or 40 cols) but more dense.\n   11 Jun 2002: TRP implemented.\n                lu1mRP implements Markowitz with Threshold Rook\n                Pivoting.\n                lu1mxc maintains max col elements  (was lu1max.)\n                lu1mxr maintains max row elements.\n   12 Jun 2002: lu1mCP seems too slow on big problems (e.g. memplus).\n                Disabled it for the moment.  (Use lu1mar + TCP.)\n   14 Dec 2002: TSP implemented.\n                lu1mSP implements Markowitz with TSP.\n   07 Mar 2003: character*1, character*2 changed to f90 form.\n                Comments changed from * in column to ! in column 1.\n                Comments kept within column 72 to avoid compiler\n                warning.\n   06 Mar 2004: Translation to C by Kjell Eikland with the addition\n                of data wrappers, parametric constants, various\n                helper routines, and dynamic memory reallocation.\n   26 May 2004: Added LUSOL_IP_UPDATELIMIT parameter and provided\n                for dynamic memory expansion based on possible\n                forward requirements.\n   08 Jul 2004: Revised logic in lu6chk based on new code from\n                Michael Saunders.\n   01 Dec 2005: Add support for CMEX interface (disable by undef MATLAB)\n                Also include various bug fixes (disable by undef YZHANG)\n                Yin Zhang <yzhang@cs.utexas.edu>\n   01 Jan 2006: Added storage of singular indeces, not only the last.\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n#include <float.h>\n#include <math.h>\n#include \"lusol.h\"\n#include \"myblas.h\"\n#ifdef MATLAB\n  #include \"mex.h\"\n#endif\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n/* LUSOL Object creation and destruction */\n\nvoid *clean_realloc(void *oldptr, int width, int newsize, int oldsize)\n{\n  newsize *= width;\n  oldsize *= width;\n  oldptr = LUSOL_REALLOC(oldptr, newsize);\n  if(newsize > oldsize)\n/*    MEMCLEAR(oldptr+oldsize, newsize-oldsize); */\n    memset((char *)oldptr+oldsize, '\\0', newsize-oldsize);\n  return(oldptr);\n}\n\nMYBOOL LUSOL_realloc_a(LUSOLrec *LUSOL, int newsize)\n{\n  int oldsize;\n\n  if(newsize < 0)\n    newsize = LUSOL->lena + MAX(abs(newsize), LUSOL_MINDELTA_a);\n\n  oldsize = LUSOL->lena;\n  LUSOL->lena = newsize;\n  if(newsize > 0)\n    newsize++;\n  if(oldsize > 0)\n    oldsize++;\n\n  LUSOL->a    = (REAL *) clean_realloc(LUSOL->a,    sizeof(*(LUSOL->a)),\n                                                    newsize, oldsize);\n  LUSOL->indc = (int *)  clean_realloc(LUSOL->indc, sizeof(*(LUSOL->indc)),\n                                                    newsize, oldsize);\n  LUSOL->indr = (int *)  clean_realloc(LUSOL->indr, sizeof(*(LUSOL->indr)),\n                                                    newsize, oldsize);\n  if((newsize == 0) ||\n     ((LUSOL->a != NULL) && (LUSOL->indc != NULL) && (LUSOL->indr != NULL)))\n    return( TRUE );\n  else\n    return( FALSE );\n}\n\nMYBOOL LUSOL_expand_a(LUSOLrec *LUSOL, int *delta_lena, int *right_shift)\n{\n#ifdef StaticMemAlloc\n  return( FALSE );\n#else\n  int LENA, NFREE, LFREE;\n\n  /* Add expansion factor to avoid having to resize too often/too much;\n     (exponential formula suggested by Michael A. Saunders) */\n  LENA = LUSOL->lena;\n  *delta_lena = DELTA_SIZE(*delta_lena, LENA);\n\n  /* Expand it! */\n  if((*delta_lena <= 0) || !LUSOL_realloc_a(LUSOL, LENA+(*delta_lena)))\n    return( FALSE );\n\n  /* Make sure we return the actual memory increase of a */\n  *delta_lena = LUSOL->lena-LENA;\n\n  /* Shift the used memory area to the right */\n  LFREE = *right_shift;\n  NFREE = LFREE+*delta_lena;\n  LENA  -= LFREE-1;\n  MEMMOVE(LUSOL->a+NFREE,    LUSOL->a+LFREE,    LENA);\n  MEMMOVE(LUSOL->indr+NFREE, LUSOL->indr+LFREE, LENA);\n  MEMMOVE(LUSOL->indc+NFREE, LUSOL->indc+LFREE, LENA);\n\n  /* Also return the new starting position for the used memory area of a */\n  *right_shift  = NFREE;\n\n  LUSOL->expanded_a++;\n  return( TRUE );\n#endif\n}\n\nMYBOOL LUSOL_realloc_r(LUSOLrec *LUSOL, int newsize)\n{\n  int oldsize;\n\n  if(newsize < 0)\n    newsize = LUSOL->maxm + MAX(abs(newsize), LUSOL_MINDELTA_rc);\n\n  oldsize = LUSOL->maxm;\n  LUSOL->maxm = newsize;\n  if(newsize > 0)\n    newsize++;\n  if(oldsize > 0)\n    oldsize++;\n\n  LUSOL->lenr  = (int *) clean_realloc(LUSOL->lenr,  sizeof(*(LUSOL->lenr)),\n                                                     newsize, oldsize);\n  LUSOL->ip    = (int *) clean_realloc(LUSOL->ip,    sizeof(*(LUSOL->ip)),\n                                                     newsize, oldsize);\n  LUSOL->iqloc = (int *) clean_realloc(LUSOL->iqloc, sizeof(*(LUSOL->iqloc)),\n                                                     newsize, oldsize);\n  LUSOL->ipinv = (int *) clean_realloc(LUSOL->ipinv, sizeof(*(LUSOL->ipinv)),\n                                                     newsize, oldsize);\n  LUSOL->locr  = (int *) clean_realloc(LUSOL->locr,  sizeof(*(LUSOL->locr)),\n                                                     newsize, oldsize);\n\n  if((newsize == 0) ||\n     ((LUSOL->lenr != NULL) &&\n      (LUSOL->ip != NULL) && (LUSOL->iqloc != NULL) &&\n      (LUSOL->ipinv != NULL) && (LUSOL->locr != NULL))) {\n\n#ifndef ClassicHamaxR\n#ifdef AlwaysSeparateHamaxR\n    if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP)\n#endif\n    {\n      LUSOL->amaxr = (REAL *) clean_realloc(LUSOL->amaxr, sizeof(*(LUSOL->amaxr)),\n                                                          newsize, oldsize);\n      if((newsize > 0) && (LUSOL->amaxr == NULL))\n        return( FALSE );\n    }\n#endif\n    return( TRUE );\n  }\n  else\n    return( FALSE );\n}\n\nMYBOOL LUSOL_realloc_c(LUSOLrec *LUSOL, int newsize)\n{\n  int oldsize;\n\n  if(newsize < 0)\n    newsize = LUSOL->maxn + MAX(abs(newsize), LUSOL_MINDELTA_rc);\n\n  oldsize = LUSOL->maxn;\n  LUSOL->maxn = newsize;\n  if(newsize > 0)\n    newsize++;\n  if(oldsize > 0)\n    oldsize++;\n\n  LUSOL->lenc  = (int *)  clean_realloc(LUSOL->lenc,  sizeof(*(LUSOL->lenc)),\n                                                      newsize, oldsize);\n  LUSOL->iq    = (int *)  clean_realloc(LUSOL->iq,    sizeof(*(LUSOL->iq)),\n                                                      newsize, oldsize);\n  LUSOL->iploc = (int *)  clean_realloc(LUSOL->iploc, sizeof(*(LUSOL->iploc)),\n                                                      newsize, oldsize);\n  LUSOL->iqinv = (int *)  clean_realloc(LUSOL->iqinv, sizeof(*(LUSOL->iqinv)),\n                                                      newsize, oldsize);\n  LUSOL->locc  = (int *)  clean_realloc(LUSOL->locc,  sizeof(*(LUSOL->locc)),\n                                                      newsize, oldsize);\n  LUSOL->w     = (REAL *) clean_realloc(LUSOL->w,     sizeof(*(LUSOL->w)),\n                                                      newsize, oldsize);\n#ifdef LUSOLSafeFastUpdate\n  LUSOL->vLU6L = (REAL *) clean_realloc(LUSOL->vLU6L, sizeof(*(LUSOL->vLU6L)),\n                                                      newsize, oldsize);\n#else\n  LUSOL->vLU6L = LUSOL->w;\n#endif\n\n  if((newsize == 0) ||\n     ((LUSOL->w != NULL) && (LUSOL->lenc != NULL) &&\n      (LUSOL->iq != NULL) && (LUSOL->iploc != NULL) &&\n      (LUSOL->iqinv != NULL) && (LUSOL->locc != NULL))) {\n\n#ifndef ClassicHamaxR\n    if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TCP) {\n      LUSOL->Ha = (REAL *) clean_realloc(LUSOL->Ha,   sizeof(*(LUSOL->Ha)),\n                                                      newsize, oldsize);\n      LUSOL->Hj = (int *)  clean_realloc(LUSOL->Hj,   sizeof(*(LUSOL->Hj)),\n                                                      newsize, oldsize);\n      LUSOL->Hk = (int *)  clean_realloc(LUSOL->Hk,   sizeof(*(LUSOL->Hk)),\n                                                      newsize, oldsize);\n      if((newsize > 0) &&\n         ((LUSOL->Ha == NULL) || (LUSOL->Hj == NULL) || (LUSOL->Hk == NULL)))\n        return( FALSE );\n    }\n#endif\n#ifndef ClassicdiagU\n    if(LUSOL->luparm[LUSOL_IP_KEEPLU] == FALSE) {\n      LUSOL->diagU = (REAL *) clean_realloc(LUSOL->diagU, sizeof(*(LUSOL->diagU)),\n                                                          newsize, oldsize);\n      if((newsize > 0) && (LUSOL->diagU == NULL))\n        return( FALSE );\n    }\n#endif\n\n    return( TRUE );\n  }\n  else\n    return( FALSE );\n}\n\nLUSOLrec *LUSOL_create(FILE *outstream, int msgfil, int pivotmodel, int updatelimit)\n{\n  LUSOLrec *newLU;\n\n  newLU = (LUSOLrec *) LUSOL_CALLOC(1, sizeof(*newLU));\n  if(newLU == NULL)\n    return( newLU );\n\n  newLU->luparm[LUSOL_IP_SCALAR_NZA]       = LUSOL_MULT_nz_a;\n  newLU->outstream = outstream;\n  newLU->luparm[LUSOL_IP_PRINTUNIT]        = msgfil;\n  newLU->luparm[LUSOL_IP_PRINTLEVEL]       = LUSOL_MSG_SINGULARITY;\n\n  LUSOL_setpivotmodel(newLU, pivotmodel, LUSOL_PIVTOL_DEFAULT);\n\n  newLU->parmlu[LUSOL_RP_GAMMA]            = LUSOL_DEFAULT_GAMMA;\n\n  newLU->parmlu[LUSOL_RP_ZEROTOLERANCE]    = 3.0e-13;\n\n  newLU->parmlu[LUSOL_RP_SMALLDIAG_U]      = /*3.7e-11;*/\n  newLU->parmlu[LUSOL_RP_EPSDIAG_U]        = 3.7e-11;\n\n  newLU->parmlu[LUSOL_RP_COMPSPACE_U]      = 3.0e+0;\n\n  newLU->luparm[LUSOL_IP_MARKOWITZ_MAXCOL] = 5;\n  newLU->parmlu[LUSOL_RP_MARKOWITZ_CONLY]  = 0.3e+0;\n  newLU->parmlu[LUSOL_RP_MARKOWITZ_DENSE]  = 0.5e+0;\n\n  newLU->parmlu[LUSOL_RP_SMARTRATIO]       = LUSOL_DEFAULT_SMARTRATIO;\n#ifdef ForceRowBasedL0\n  newLU->luparm[LUSOL_IP_ACCELERATION]     = LUSOL_BASEORDER;\n#endif\n  newLU->luparm[LUSOL_IP_KEEPLU]           = TRUE;\n  newLU->luparm[LUSOL_IP_UPDATELIMIT]      = updatelimit;\n\n  init_BLAS();\n\n  return( newLU );\n}\n\nMYBOOL LUSOL_sizeto(LUSOLrec *LUSOL, int init_r, int init_c, int init_a)\n{\n  if(init_c == 0)\n    LUSOL_FREE(LUSOL->isingular);\n  if(LUSOL_realloc_a(LUSOL, init_a) &&\n     LUSOL_realloc_r(LUSOL, init_r) &&\n     LUSOL_realloc_c(LUSOL, init_c))\n    return( TRUE );\n  else\n    return( FALSE );\n}\n\nconst char *LUSOL_pivotLabel(LUSOLrec *LUSOL)\n{\n  static const char *pivotText[LUSOL_PIVMOD_MAX+1] =\n  {\"TPP\", \"TRP\", \"TCP\", \"TSP\"};\n  return(pivotText[LUSOL->luparm[LUSOL_IP_PIVOTTYPE]]);\n}\n\nvoid LUSOL_setpivotmodel(LUSOLrec *LUSOL, int pivotmodel, int initlevel)\n{\n  REAL newFM, newUM;\n\n  /* Set pivotmodel if specified */\n  if(pivotmodel > LUSOL_PIVMOD_NOCHANGE) {\n    if((pivotmodel <= LUSOL_PIVMOD_DEFAULT) || (pivotmodel > LUSOL_PIVMOD_MAX))\n      pivotmodel = LUSOL_PIVMOD_TPP;\n    LUSOL->luparm[LUSOL_IP_PIVOTTYPE]        = pivotmodel;\n  }\n\n  /* Check if we need bother about changing tolerances */\n  if((initlevel <= LUSOL_PIVTOL_NOCHANGE) || (initlevel > LUSOL_PIVTOL_MAX))\n    return;\n\n  /* Set default pivot tolerances\n     (note that UPDATEMAX should always be <= FACTORMAX) */\n  if(initlevel == LUSOL_PIVTOL_BAGGY) {        /* Extra-loose pivot thresholds */\n    newFM = 500.0;\n    newUM = newFM / 20;\n  }\n  else if(initlevel == LUSOL_PIVTOL_LOOSE) {  /* Moderately tight pivot tolerances */\n    newFM = 100.0;\n    newUM = newFM / 10;\n  }\n  else if(initlevel == LUSOL_PIVTOL_NORMAL) { /* Standard pivot tolerances */\n    newFM = 28.0;\n    newUM = newFM / 4;\n  }\n  else if(initlevel == LUSOL_PIVTOL_SLIM) {   /* Better accuracy pivot tolerances */\n    newFM = 10.0;\n    newUM = newFM / 2;\n  }\n  else if(initlevel == LUSOL_PIVTOL_TIGHT) {  /* Enhanced accuracy pivot tolerances */\n    newFM = 5.0;\n    newUM = newFM / 2;\n  }\n  else if(initlevel == LUSOL_PIVTOL_SUPER) {  /* Very tight pivot tolerances for extra accuracy */\n    newFM = 2.5;\n    newUM = 1.99;\n  }\n  else {                                      /* Extremely tight pivot tolerances for extra accuracy */\n    newFM = 1.99;\n    newUM = newFM / 1.49;\n  }\n\n  /* Set the tolerances */\n  LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = newFM;\n  LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij] = newUM;\n}\n\nMYBOOL LUSOL_tightenpivot(LUSOLrec *LUSOL)\n{\n#if 0\n  REAL newvalue;\n#endif\n\n  /* Give up tightening if we are already less than limit and we cannot change strategy */\n  if(MIN(LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij],\n         LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij]) < 1.1) {\n    if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] >= LUSOL_PIVMOD_TRP)\n      return( FALSE );\n    LUSOL_setpivotmodel(LUSOL, LUSOL->luparm[LUSOL_IP_PIVOTTYPE]+1, LUSOL_PIVTOL_DEFAULT+1);\n    return( 2 );\n  }\n\n  /* Otherwise tighten according to defined schedule */\n#if 0   /* This is Michael Saunder's proposed tightening procedure */\n  newvalue = sqrt(LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij]);\n  LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = newvalue;\n  SETMIN(LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij], newvalue);\n#elif 0 /* This is Kjell Eikland's schedule #1 */\n  newvalue = sqrt(LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij]);\n  LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = newvalue;\n  LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij] = 1.0 + (newvalue - 1.0) / 2;\n#else   /* This was Kjell Eikland's schedule #2 */\n  LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = 1.0 + LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij]/3.0;\n  LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij] = 1.0 + LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij]/3.0;\n#endif\n  return( TRUE );\n}\n\nMYBOOL LUSOL_addSingularity(LUSOLrec *LUSOL, int singcol, int *inform)\n{\n  int NSING = LUSOL->luparm[LUSOL_IP_SINGULARITIES],\n      ASING = LUSOL->luparm[LUSOL_IP_SINGULARLISTSIZE];\n\n  /* Check if we need to allocated list memory to store multiple singularities */\n  if((NSING > 0) && (NSING >= ASING)) {\n\n    /* Increase list in \"reasonable\" steps */\n    ASING += (int) (10.0 * (log10((REAL) LUSOL->m)+1.0));\n    LUSOL->isingular = (int *) LUSOL_REALLOC(LUSOL->isingular, sizeof(*LUSOL->isingular)*(ASING+1));\n    if(LUSOL->isingular == NULL) {\n      LUSOL->luparm[LUSOL_IP_SINGULARLISTSIZE] = 0;\n      *inform = LUSOL_INFORM_NOMEMLEFT;\n      return( FALSE );\n    }\n    LUSOL->luparm[LUSOL_IP_SINGULARLISTSIZE] = ASING;\n\n    /* Transfer the first singularity if the list was just created */\n    if(NSING == 1)\n      LUSOL->isingular[NSING] = LUSOL->luparm[LUSOL_IP_SINGULARINDEX];\n  }\n\n  /* Update singularity count and store its index */\n  NSING++;\n  if(NSING > 1) {\n    LUSOL->isingular[0] = NSING;\n    LUSOL->isingular[NSING] = singcol;\n  }\n  LUSOL->luparm[LUSOL_IP_SINGULARITIES] = NSING;\n\n  /* Mimic old logic by keeping the last singularity stored */\n  LUSOL->luparm[LUSOL_IP_SINGULARINDEX] = singcol;\n\n  return( TRUE );\n}\n\nint LUSOL_getSingularity(LUSOLrec *LUSOL, int singitem)\n{\n  if((singitem > LUSOL->luparm[LUSOL_IP_SINGULARITIES]) || (singitem < 0))\n    singitem = -1;\n  else if(singitem == 0)\n    singitem = LUSOL->luparm[LUSOL_IP_SINGULARITIES];\n  else if(singitem > 1)\n    singitem = LUSOL->isingular[singitem];\n  else\n    singitem = LUSOL->luparm[LUSOL_IP_SINGULARINDEX];\n  return( singitem );\n}\n\nint LUSOL_findSingularityPosition(LUSOLrec *LUSOL, int singcol)\n/* The purpose of this routine is to find the slack row/column in\n   user-index that was singular in the last unsuccessful column\n   update; zero is returned if the search was unsuccessful.\n   By adding a slack at this position this particular singularity\n   should disappear.\n   (Source: Michael A. Saunders; private communication to KE) */\n{\n#if 0 /* Michael Saunders version */\n  int j;\n  for(j = LUSOL->m; j > 0; j--)\n    if(LUSOL->iq[j] == singcol)\n      break;\n  singcol = j;\n#else /* Kjell Eikland version (note that iqinv could be invalid in early versions of LUSOL) */\n  singcol = LUSOL->iqinv[singcol];\n#endif\n  return( LUSOL->ip[singcol] );\n}\n\nconst char *LUSOL_informstr(LUSOLrec *LUSOL, int inform)\n{\n  static const char *informText[LUSOL_INFORM_MAX-LUSOL_INFORM_MIN+1] =\n  {\"LUSOL_RANKLOSS: Lost rank\",\n   \"LUSOL_LUSUCCESS: Success\",\n   \"LUSOL_LUSINGULAR: Singular A\",\n   \"LUSOL_LUUNSTABLE: Unstable factorization\",\n   \"LUSOL_ADIMERR: Row or column count exceeded\",\n   \"LUSOL_ADUPLICATE: Duplicate A matrix entry found\",\n   \"(Undefined message)\",\n   \"(Undefined message)\",\n   \"LUSOL_ANEEDMEM: Insufficient memory for factorization\",\n   \"LUSOL_FATALERR: Fatal internal error\",\n   \"LUSOL_NOPIVOT: Found no suitable pivot\",\n   \"LUSOL_NOMEMLEFT: Could not obtain more memory\"};\n  if((inform < LUSOL_INFORM_MIN) || (inform > LUSOL_INFORM_MAX))\n    inform = LUSOL->luparm[LUSOL_IP_INFORM];\n  return(informText[inform-LUSOL_INFORM_MIN]);\n}\n\nvoid LUSOL_clear(LUSOLrec *LUSOL, MYBOOL nzonly)\n{\n  int len;\n\n  LUSOL->nelem = 0;\n  if(!nzonly) {\n\n   /* lena arrays */\n    len = LUSOL->lena + LUSOL_ARRAYOFFSET;\n    MEMCLEAR(LUSOL->a,    len);\n    MEMCLEAR(LUSOL->indc, len);\n    MEMCLEAR(LUSOL->indr, len);\n\n   /* maxm arrays */\n    len = LUSOL->maxm + LUSOL_ARRAYOFFSET;\n    MEMCLEAR(LUSOL->lenr,  len);\n    MEMCLEAR(LUSOL->ip,    len);\n    MEMCLEAR(LUSOL->iqloc, len);\n    MEMCLEAR(LUSOL->ipinv, len);\n    MEMCLEAR(LUSOL->locr,  len);\n\n#ifndef ClassicHamaxR\n    if((LUSOL->amaxr != NULL)\n#ifdef AlwaysSeparateHamaxR\n       && (LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP)\n#endif\n      )\n      MEMCLEAR(LUSOL->amaxr, len);\n#endif\n\n   /* maxn arrays */\n    len = LUSOL->maxn + LUSOL_ARRAYOFFSET;\n    MEMCLEAR(LUSOL->lenc,  len);\n    MEMCLEAR(LUSOL->iq,    len);\n    MEMCLEAR(LUSOL->iploc, len);\n    MEMCLEAR(LUSOL->iqinv, len);\n    MEMCLEAR(LUSOL->locc,  len);\n    MEMCLEAR(LUSOL->w,     len);\n\n    if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TCP) {\n      MEMCLEAR(LUSOL->Ha,  len);\n      MEMCLEAR(LUSOL->Hj,  len);\n      MEMCLEAR(LUSOL->Hk,  len);\n    }\n#ifndef ClassicdiagU\n    if(LUSOL->luparm[LUSOL_IP_KEEPLU] == FALSE) {\n      MEMCLEAR(LUSOL->diagU, len);\n    }\n#endif\n\n  }\n}\n\nMYBOOL LUSOL_assign(LUSOLrec *LUSOL, int iA[], int jA[], REAL Aij[], int nzcount, MYBOOL istriplet)\n{\n  int k, m, n, ij, kol;\n\n  /* Adjust the size of the a structure */\n  if(nzcount > (LUSOL->lena/LUSOL->luparm[LUSOL_IP_SCALAR_NZA]) &&\n     !LUSOL_realloc_a(LUSOL, nzcount*LUSOL->luparm[LUSOL_IP_SCALAR_NZA]))\n    return( FALSE );\n\n  m = 0;\n  n = 0;\n  kol = 1;\n  for(k = 1; k <= nzcount; k++) {\n    /* First the row indicator */\n    ij = iA[k];\n    if(ij > m) {\n      m = ij;\n      if(m > LUSOL->maxm &&\n         !LUSOL_realloc_r(LUSOL, -(m / LUSOL_MINDELTA_FACTOR + 1)))\n        return( FALSE );\n    }\n    LUSOL->indc[k] = ij;\n\n    /* Then the column indicator;\n       Handle both triplet and column count formats */\n    if(istriplet)\n      ij = jA[k];\n    else {\n      if(k >= jA[kol])\n        kol++;\n      ij = kol;\n    }\n    if(ij > n) {\n      n = ij;\n      if(n > LUSOL->maxn &&\n         !LUSOL_realloc_c(LUSOL, -(n / LUSOL_MINDELTA_FACTOR + 1)))\n        return( FALSE );\n    }\n    LUSOL->indr[k] = ij;\n\n    /* Lastly the matrix value itself */\n    LUSOL->a[k] = Aij[k];\n  }\n  LUSOL->m = m;\n  LUSOL->n = n;\n  LUSOL->nelem = nzcount;\n  return( TRUE );\n}\n\nint LUSOL_loadColumn(LUSOLrec *LUSOL, int iA[], int jA, REAL Aij[], int nzcount, int offset1)\n{\n  int i, ii, nz, k;\n\n  nz = LUSOL->nelem;\n  i = nz + nzcount;\n  if(i > (LUSOL->lena/LUSOL->luparm[LUSOL_IP_SCALAR_NZA]) &&\n     !LUSOL_realloc_a(LUSOL, i*LUSOL->luparm[LUSOL_IP_SCALAR_NZA]))\n  return( -1 );\n\n  k = 0;\n  for(ii = 1; ii <= nzcount; ii++) {\n    i = ii + offset1;\n    if(Aij[i] == 0)\n      continue;\n    if(iA[i] <= 0 || iA[i] > LUSOL->m ||\n       jA <= 0 || jA > LUSOL->n) {\n      LUSOL_report(LUSOL, 0, \"Variable index outside of set bounds (r:%d/%d, c:%d/%d)\\n\",\n                             iA[i], LUSOL->m, jA, LUSOL->n);\n      continue;\n    }\n    k++;\n    nz++;\n    LUSOL->a[nz]    = Aij[i];\n    LUSOL->indc[nz] = iA[i];\n    LUSOL->indr[nz] = jA;\n  }\n  LUSOL->nelem = nz;\n  return( k );\n}\n\nvoid LUSOL_free(LUSOLrec *LUSOL)\n{\n  LUSOL_realloc_a(LUSOL, 0);\n  LUSOL_realloc_r(LUSOL, 0);\n  LUSOL_realloc_c(LUSOL, 0);\n  if(LUSOL->L0 != NULL)\n    LUSOL_matfree(&(LUSOL->L0));\n  if(LUSOL->U != NULL)\n    LUSOL_matfree(&(LUSOL->U));\n  if(!is_nativeBLAS())\n    unload_BLAS();\n  LUSOL_FREE(LUSOL);\n}\n\nvoid LUSOL_report(LUSOLrec *LUSOL, int msglevel, const char *format, ...)\n{\n  va_list ap;\n\n  if(LUSOL == NULL) {\n    va_start(ap, format);\n    vfprintf(stderr, format, ap);\n    va_end(ap);\n  }\n  else if(msglevel >= 0  /*LUSOL->luparm[2]*/) {\n    if(LUSOL->writelog != NULL) {\n      char buff[255];\n\n      va_start(ap, format);\n      vsprintf(buff, format, ap);\n      va_end(ap);\n      LUSOL->writelog(LUSOL, LUSOL->loghandle, buff);\n    }\n    if(LUSOL->outstream != NULL) {\n      va_start(ap, format);\n      vfprintf(LUSOL->outstream, format, ap);\n      va_end(ap);\n      fflush(LUSOL->outstream);\n    }\n  }\n}\n\nvoid LUSOL_timer(LUSOLrec *LUSOL, int timerid, const char *text)\n{\n  LUSOL_report(LUSOL, -1, \"TimerID %d at %s - %s\\n\",\n                          timerid, \"\", text);\n}\n\nint LUSOL_factorize(LUSOLrec *LUSOL)\n{\n  int inform;\n\n  LU1FAC( LUSOL, &inform );\n  return( inform );\n}\n\nint LUSOL_ftran(LUSOLrec *LUSOL, REAL b[], int NZidx[], MYBOOL prepareupdate)\n{\n  int  inform;\n  REAL *vector;\n\n  if(prepareupdate)\n    vector = LUSOL->vLU6L;\n  else\n    vector = LUSOL->w;\n\n  /* Copy RHS vector, but make adjustment for offset since this\n     can create a memory error when the calling program uses\n     a 0-base vector offset back to comply with LUSOL. */\n  MEMCOPY(vector+1, b+1, LUSOL->n);\n  if (vector != NULL)\n    vector[0] = 0;\n\n  LU6SOL(LUSOL, LUSOL_SOLVE_Aw_v, vector, b, NZidx, &inform);\n  LUSOL->luparm[LUSOL_IP_FTRANCOUNT]++;\n\n  return(inform);\n}\n\n\nint LUSOL_btran(LUSOLrec *LUSOL, REAL b[], int NZidx[])\n{\n  int inform;\n\n  /* Copy RHS vector, but make adjustment for offset since this\n     can create a memory error when the calling program uses\n     a 0-base vector offset back to comply with LUSOL. */\n  MEMCOPY(LUSOL->w+1, b+1, LUSOL->m);\n  if (LUSOL->w != NULL)\n    LUSOL->w[0] = 0;\n\n  LU6SOL(LUSOL, LUSOL_SOLVE_Atv_w, b, LUSOL->w, NZidx, &inform);\n  LUSOL->luparm[LUSOL_IP_BTRANCOUNT]++;\n\n  return(inform);\n}\n\n\nint LUSOL_replaceColumn(LUSOLrec *LUSOL, int jcol, REAL v[])\n{\n  int  inform;\n  REAL DIAG, VNORM;\n\n  LU8RPC(LUSOL, LUSOL_UPDATE_OLDNONEMPTY, LUSOL_UPDATE_NEWNONEMPTY,\n                jcol, v, NULL,\n                &inform, &DIAG, &VNORM);\n\n  LUSOL->replaced_c++;\n  return( inform );\n}\n\nREAL LUSOL_vecdensity(LUSOLrec *LUSOL, REAL V[])\n{\n  int I, N = 0;\n\n  for(I = 1; I <= LUSOL->m; I++)\n    if(fabs(V[I]) > 0)\n      N++;\n  return( (REAL) N / (REAL) LUSOL->m );\n}\n\nchar relationChar(REAL left, REAL right)\n{\n  if(left > right)\n    return('>');\n  else if(left == right)\n    return('=');\n  else\n    return('<');\n}\n\n/* Retrieve the core modules ordered by order of dependency */\n\n#include \"lusol2.c\"      /* Heap management */\n#include \"lusol6a.c\"     /* Singularity checking and equation solving */\n#include \"lusol1.c\"      /* Factorization and core components */\n#include \"lusol7a.c\"     /* Utility routines for updates */\n#include \"lusol8a.c\"     /* Column update */\n\n\nvoid LUSOL_dump(FILE *output, LUSOLrec *LUSOL)\n{\n  MYBOOL userfile = (MYBOOL) (output != NULL);\n\n  if(!userfile)\n    output = fopen(\"LUSOL.dbg\", \"w\");\n\n  blockWriteREAL(output, \"a\", LUSOL->a, 1, LUSOL->lena);\n  blockWriteINT(output, \"indc\", LUSOL->indc, 1, LUSOL->lena);\n  blockWriteINT(output, \"indr\", LUSOL->indr, 1, LUSOL->lena);\n\n  blockWriteINT(output, \"ip\", LUSOL->ip, 1, LUSOL->m);\n  blockWriteINT(output, \"iq\", LUSOL->iq, 1, LUSOL->n);\n  blockWriteINT(output, \"lenc\", LUSOL->lenc, 1, LUSOL->n);\n  blockWriteINT(output, \"lenr\", LUSOL->lenr, 1, LUSOL->m);\n\n  blockWriteINT(output, \"locc\", LUSOL->locc, 1, LUSOL->n);\n  blockWriteINT(output, \"locr\", LUSOL->locr, 1, LUSOL->m);\n  blockWriteINT(output, \"iploc\", LUSOL->iploc, 1, LUSOL->n);\n  blockWriteINT(output, \"iqloc\", LUSOL->iqloc, 1, LUSOL->m);\n\n  blockWriteINT(output, \"ipinv\", LUSOL->ipinv, 1, LUSOL->m);\n  blockWriteINT(output, \"iqinv\", LUSOL->iqinv, 1, LUSOL->n);\n\n  if(!userfile)\n    fclose(output);\n}\n\nLUSOLmat *LUSOL_matcreate(int dim, int nz)\n{\n  LUSOLmat *newm;\n\n  newm = (LUSOLmat *) LUSOL_CALLOC(1, sizeof(*newm));\n  if(newm != NULL) {\n    newm->a    = (REAL *) LUSOL_MALLOC((nz+1)*sizeof(REAL));\n    newm->lenx = (int *)  LUSOL_MALLOC((dim+1)*sizeof(int));\n    newm->indx = (int *)  LUSOL_MALLOC((dim+1)*sizeof(int));\n    newm->indr = (int *)  LUSOL_MALLOC((nz+1)*sizeof(int));\n    newm->indc = (int *)  LUSOL_MALLOC((nz+1)*sizeof(int));\n    if((newm->a == NULL) ||\n       (newm->lenx == NULL) || (newm->indx == NULL) ||\n       (newm->indr == NULL) || (newm->indc == NULL))\n      LUSOL_matfree(&newm);\n  }\n  return(newm);\n}\nvoid LUSOL_matfree(LUSOLmat **mat)\n{\n  if((mat == NULL) || (*mat == NULL))\n    return;\n  LUSOL_FREE((*mat)->a);\n  LUSOL_FREE((*mat)->indc);\n  LUSOL_FREE((*mat)->indr);\n  LUSOL_FREE((*mat)->lenx);\n  LUSOL_FREE((*mat)->indx);\n  LUSOL_FREE(*mat);\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol.h",
    "content": "#ifndef HEADER_LUSOL\n#define HEADER_LUSOL\n\n/* Include necessary libraries                                               */\n/* ------------------------------------------------------------------------- */\n#include <stdio.h>\n#include \"commonlib.h\"\n\n/* Version information                                                       */\n/* ------------------------------------------------------------------------- */\n#define LUSOL_VERMAJOR   2\n#define LUSOL_VERMINOR   2\n#define LUSOL_RELEASE    2\n#define LUSOL_BUILD      0\n\n/* Dynamic memory management macros                                          */\n/* ------------------------------------------------------------------------- */\n#ifdef MATLAB\n  #define LUSOL_MALLOC(bytesize)        mxMalloc(bytesize)\n  #define LUSOL_CALLOC(count, recsize)  mxCalloc(count, recsize)\n  #define LUSOL_REALLOC(ptr, bytesize)  mxRealloc((void *) ptr, bytesize)\n  #define LUSOL_FREE(ptr)               {mxFree(ptr); ptr=NULL;}\n#else\n  #define LUSOL_MALLOC(bytesize)        malloc(bytesize)\n  #define LUSOL_CALLOC(count, recsize)  calloc(count, recsize)\n  #define LUSOL_REALLOC(ptr, bytesize)  realloc((void *) ptr, bytesize)\n  #define LUSOL_FREE(ptr)               {free(ptr); ptr=NULL;}\n#endif\n\n/* Performance compiler options                                              */\n/* ------------------------------------------------------------------------- */\n#if 1\n  #define ForceInitialization      /* Satisfy compilers, check during debugging! */\n  #define LUSOLFastDenseIndex           /* Increment the linearized dense address */\n  #define LUSOLFastClear           /* Use intrinsic functions for memory zeroing */\n  #define LUSOLFastMove              /* Use intrinsic functions for memory moves */\n  #define LUSOLFastCopy               /* Use intrinsic functions for memory copy */\n  #define LUSOLFastSolve           /* Use pointer operations in equation solving */\n  #define LUSOLSafeFastUpdate      /* Use separate array for LU6L result storage */\n/*#define UseOld_LU6CHK_20040510 */\n/*#define AlwaysSeparateHamaxR */       /* Enabled when the pivot model is fixed */\n  #if 0\n    #define ForceRowBasedL0                  /* Create a row-sorted version of L0 */\n  #endif\n/*  #define SetSmallToZero*/\n/*  #define DoTraceL0 */\n#endif\n/*#define UseTimer */\n\n\n/* Legacy compatibility and testing options (Fortran-LUSOL)                  */\n/* ------------------------------------------------------------------------- */\n#if 0\n  #define LegacyTesting\n  #define StaticMemAlloc           /* Preallocated vs. dynamic memory allocation */\n  #define ClassicdiagU                                  /* Store diagU at end of a */\n  #define ClassicHamaxR                    /* Store H+AmaxR at end of a/indc/indr */\n#endif\n\n\n/* General constants and data type definitions                               */\n/* ------------------------------------------------------------------------- */\n#define LUSOL_ARRAYOFFSET            1\n#ifndef ZERO\n  #define ZERO                       0\n#endif\n#ifndef ONE\n  #define ONE                        1\n#endif\n#ifndef FALSE\n  #define FALSE                      0\n#endif\n#ifndef TRUE\n  #define TRUE                       1\n#endif\n#ifndef NULL\n  #define NULL                       0\n#endif\n#ifndef REAL\n  #define REAL double\n#endif\n#ifndef REALXP\n  #define REALXP long double\n#endif\n#ifndef MYBOOL\n  #define MYBOOL unsigned char\n#endif\n\n\n/* User-settable default parameter values                                    */\n/* ------------------------------------------------------------------------- */\n#define LUSOL_DEFAULT_GAMMA        2.0\n#define LUSOL_SMALLNUM         1.0e-20  /* IAEE doubles have precision 2.22e-16 */\n#define LUSOL_BIGNUM           1.0e+20\n#define LUSOL_MINDELTA_FACTOR        4\n#define LUSOL_MINDELTA_a         10000\n#if 1\n  #define LUSOL_MULT_nz_a            2  /* Suggested by Yin Zhang */\n#else\n  #define LUSOL_MULT_nz_a            5  /* Could consider 6 or 7 */\n#endif\n#define LUSOL_MINDELTA_rc         1000\n#define LUSOL_DEFAULT_SMARTRATIO 0.667\n\n/* Fixed system parameters (changeable only by developers)                   */\n/* ------------------------------------------------------------------------- */\n\n/* parmlu INPUT parameters: */\n#define LUSOL_RP_SMARTRATIO          0\n#define LUSOL_RP_FACTORMAX_Lij       1\n#define LUSOL_RP_UPDATEMAX_Lij       2\n#define LUSOL_RP_ZEROTOLERANCE       3\n#define LUSOL_RP_SMALLDIAG_U         4\n#define LUSOL_RP_EPSDIAG_U           5\n#define LUSOL_RP_COMPSPACE_U         6\n#define LUSOL_RP_MARKOWITZ_CONLY     7\n#define LUSOL_RP_MARKOWITZ_DENSE     8\n#define LUSOL_RP_GAMMA               9\n\n/* parmlu OUPUT parameters: */\n#define LUSOL_RP_MAXELEM_A          10\n#define LUSOL_RP_MAXMULT_L          11\n#define LUSOL_RP_MAXELEM_U          12\n#define LUSOL_RP_MAXELEM_DIAGU      13\n#define LUSOL_RP_MINELEM_DIAGU      14\n#define LUSOL_RP_MAXELEM_TCP        15\n#define LUSOL_RP_GROWTHRATE         16\n#define LUSOL_RP_USERDATA_1         17\n#define LUSOL_RP_USERDATA_2         18\n#define LUSOL_RP_USERDATA_3         19\n#define LUSOL_RP_RESIDUAL_U         20\n#define LUSOL_RP_LASTITEM            LUSOL_RP_RESIDUAL_U\n\n/* luparm INPUT parameters: */\n#define LUSOL_IP_USERDATA_0          0\n#define LUSOL_IP_PRINTUNIT           1\n#define LUSOL_IP_PRINTLEVEL          2\n#define LUSOL_IP_MARKOWITZ_MAXCOL    3\n#define LUSOL_IP_SCALAR_NZA          4\n#define LUSOL_IP_UPDATELIMIT         5\n#define LUSOL_IP_PIVOTTYPE           6\n#define LUSOL_IP_ACCELERATION        7\n#define LUSOL_IP_KEEPLU              8\n#define LUSOL_IP_SINGULARLISTSIZE    9\n\n/* luparm OUTPUT parameters: */\n#define LUSOL_IP_INFORM             10\n#define LUSOL_IP_SINGULARITIES      11\n#define LUSOL_IP_SINGULARINDEX      12\n#define LUSOL_IP_MINIMUMLENA        13\n#define LUSOL_IP_MAXLEN             14\n#define LUSOL_IP_UPDATECOUNT        15\n#define LUSOL_IP_RANK_U             16\n#define LUSOL_IP_COLCOUNT_DENSE1    17\n#define LUSOL_IP_COLCOUNT_DENSE2    18\n#define LUSOL_IP_COLINDEX_DUMIN     19\n#define LUSOL_IP_COLCOUNT_L0        20\n#define LUSOL_IP_NONZEROS_L0        21\n#define LUSOL_IP_NONZEROS_U0        22\n#define LUSOL_IP_NONZEROS_L         23\n#define LUSOL_IP_NONZEROS_U         24\n#define LUSOL_IP_NONZEROS_ROW       25\n#define LUSOL_IP_COMPRESSIONS_LU    26\n#define LUSOL_IP_MARKOWITZ_MERIT    27\n#define LUSOL_IP_TRIANGROWS_U       28\n#define LUSOL_IP_TRIANGROWS_L       29\n#define LUSOL_IP_FTRANCOUNT         30\n#define LUSOL_IP_BTRANCOUNT         31\n#define LUSOL_IP_ROWCOUNT_L0        32\n#define LUSOL_IP_LASTITEM            LUSOL_IP_ROWCOUNT_L0\n\n\n/* Macros for matrix-based access for dense part of A and timer mapping      */\n/* ------------------------------------------------------------------------- */\n#define DAPOS(row, col)   (row + (col-1)*LDA)\n#define timer(text, id)   LUSOL_timer(LUSOL, id, text)\n\n\n/* Parameter/option defines                                                  */\n/* ------------------------------------------------------------------------- */\n#define LUSOL_MSG_NONE              -1\n#define LUSOL_MSG_SINGULARITY        0\n#define LUSOL_MSG_STATISTICS        10\n#define LUSOL_MSG_PIVOT             50\n\n#define LUSOL_BASEORDER              0\n#define LUSOL_OTHERORDER             1\n#define LUSOL_AUTOORDER              2\n#define LUSOL_ACCELERATE_L0          4\n#define LUSOL_ACCELERATE_U           8\n\n#define LUSOL_PIVMOD_NOCHANGE       -2  /* Don't change active pivoting model */\n#define LUSOL_PIVMOD_DEFAULT        -1  /* Set pivoting model to default */\n#define LUSOL_PIVMOD_TPP             0  /* Threshold Partial   pivoting (normal) */\n#define LUSOL_PIVMOD_TRP             1  /* Threshold Rook      pivoting */\n#define LUSOL_PIVMOD_TCP             2  /* Threshold Complete  pivoting */\n#define LUSOL_PIVMOD_TSP             3  /* Threshold Symmetric pivoting */\n#define LUSOL_PIVMOD_MAX             LUSOL_PIVMOD_TSP\n\n#define LUSOL_PIVTOL_NOCHANGE        0\n#define LUSOL_PIVTOL_BAGGY           1\n#define LUSOL_PIVTOL_LOOSE           2\n#define LUSOL_PIVTOL_NORMAL          3\n#define LUSOL_PIVTOL_SLIM            4\n#define LUSOL_PIVTOL_TIGHT           5\n#define LUSOL_PIVTOL_SUPER           6\n#define LUSOL_PIVTOL_CORSET          7\n#define LUSOL_PIVTOL_DEFAULT         LUSOL_PIVTOL_SLIM\n#define LUSOL_PIVTOL_MAX             LUSOL_PIVTOL_CORSET\n\n#define LUSOL_UPDATE_OLDEMPTY        0  /* No/empty current column. */\n#define LUSOL_UPDATE_OLDNONEMPTY     1  /* Current column need not have been empty. */\n#define LUSOL_UPDATE_NEWEMPTY        0  /* New column is taken to be zero. */\n#define LUSOL_UPDATE_NEWNONEMPTY     1  /* v(*) contains the new column;\n                                           on exit,  v(*)  satisfies  L*v = a(new). */\n#define LUSOL_UPDATE_USEPREPARED     2  /* v(*)  must satisfy  L*v = a(new). */\n\n#define LUSOL_SOLVE_Lv_v             1  /* v  solves   L v = v(input). w  is not touched. */\n#define LUSOL_SOLVE_Ltv_v            2  /* v  solves   L'v = v(input). w  is not touched. */\n#define LUSOL_SOLVE_Uw_v             3  /* w  solves   U w = v.        v  is not altered. */\n#define LUSOL_SOLVE_Utv_w            4  /* v  solves   U'v = w.        w  is destroyed. */\n#define LUSOL_SOLVE_Aw_v             5  /* w  solves   A w = v.        v  is altered as in 1. */\n#define LUSOL_FTRAN   LUSOL_SOLVE_Aw_v\n#define LUSOL_SOLVE_Atv_w            6  /* v  solves   A'v = w.        w  is destroyed. */\n#define LUSOL_BTRAN  LUSOL_SOLVE_Atv_w\n\n/* If mode = 3,4,5,6, v and w must not be the same arrays.\n   If lu1fac has just been used to factorize a symmetric matrix A\n   (which must be definite or quasi-definite), the factors A = L U\n   may be regarded as A = LDL', where D = diag(U).  In such cases,\n   the following (faster) solve codes may be used:                  */\n#define LUSOL_SOLVE_Av_v             7  /* v  solves   A v = L D L'v = v(input). w  is not touched. */\n#define LUSOL_SOLVE_LDLtv_v          8  /* v  solves       L |D| L'v = v(input). w  is not touched. */\n\n#define LUSOL_INFORM_RANKLOSS       -1\n#define LUSOL_INFORM_LUSUCCESS       0\n#define LUSOL_INFORM_LUSINGULAR      1\n#define LUSOL_INFORM_LUUNSTABLE      2\n#define LUSOL_INFORM_ADIMERR         3\n#define LUSOL_INFORM_ADUPLICATE      4\n#define LUSOL_INFORM_ANEEDMEM        7  /* Set lena >= luparm[LUSOL_IP_MINIMUMLENA] */\n#define LUSOL_INFORM_FATALERR        8\n#define LUSOL_INFORM_NOPIVOT         9  /* No diagonal pivot found with TSP or TDP. */\n#define LUSOL_INFORM_NOMEMLEFT      10\n\n#define LUSOL_INFORM_MIN             LUSOL_INFORM_RANKLOSS\n#define LUSOL_INFORM_MAX             LUSOL_INFORM_NOMEMLEFT\n\n#define LUSOL_INFORM_GETLAST        10  /* Code for LUSOL_informstr. */\n#define LUSOL_INFORM_SERIOUS         LUSOL_INFORM_LUUNSTABLE\n\n\n/* Prototypes for call-back functions                                        */\n/* ------------------------------------------------------------------------- */\ntypedef void LUSOLlogfunc(void *lp, void *userhandle, char *buf);\n\n\n/* Sparse matrix data */\ntypedef struct _LUSOLmat {\n  REAL *a;\n  int  *lenx, *indr, *indc, *indx;\n} LUSOLmat;\n\n\n/* The main LUSOL data record */\n/* ------------------------------------------------------------------------- */\ntypedef struct _LUSOLrec {\n\n  /* General data */\n  FILE         *outstream;           /* Output stream, initialized to STDOUT */\n  LUSOLlogfunc *writelog;\n    void       *loghandle;\n  LUSOLlogfunc *debuginfo;\n\n  /* Parameter storage arrays */\n  int    luparm[LUSOL_IP_LASTITEM + 1];\n  REAL   parmlu[LUSOL_RP_LASTITEM + 1];\n\n  /* Arrays of length lena+1 */\n  int    lena, nelem;\n  int    *indc, *indr;\n  REAL   *a;\n\n  /* Arrays of length maxm+1 (row storage) */\n  int    maxm, m;\n  int    *lenr, *ip, *iqloc, *ipinv, *locr;\n\n  /* Arrays of length maxn+1 (column storage) */\n  int    maxn, n;\n  int    *lenc, *iq, *iploc, *iqinv, *locc;\n  REAL   *w, *vLU6L;\n\n  /* List of singular columns, with dynamic size allocation */\n  int    *isingular;\n\n  /* Extra arrays of length n for TCP and keepLU == FALSE */\n  REAL   *Ha, *diagU;\n  int    *Hj, *Hk;\n\n  /* Extra arrays of length m for TRP*/\n  REAL   *amaxr;\n\n  /* Extra array for L0 and U stored by row/column for faster btran/ftran */\n  LUSOLmat *L0;\n  LUSOLmat *U;\n\n  /* Miscellaneous data */\n  int    expanded_a;\n  int    replaced_c;\n  int    replaced_r;\n\n} LUSOLrec;\n\n\nLUSOLrec *LUSOL_create(FILE *outstream, int msgfil, int pivotmodel, int updatelimit);\nMYBOOL LUSOL_sizeto(LUSOLrec *LUSOL, int init_r, int init_c, int init_a);\nMYBOOL LUSOL_assign(LUSOLrec *LUSOL, int iA[], int jA[], REAL Aij[],\n                                     int nzcount, MYBOOL istriplet);\nvoid LUSOL_clear(LUSOLrec *LUSOL, MYBOOL nzonly);\nvoid LUSOL_free(LUSOLrec *LUSOL);\n\nLUSOLmat *LUSOL_matcreate(int dim, int nz);\nvoid LUSOL_matfree(LUSOLmat **mat);\n\nint LUSOL_loadColumn(LUSOLrec *LUSOL, int iA[], int jA, REAL Aij[], int nzcount, int offset1);\nvoid LUSOL_setpivotmodel(LUSOLrec *LUSOL, int pivotmodel, int initlevel);\nint LUSOL_factorize(LUSOLrec *LUSOL);\nint LUSOL_replaceColumn(LUSOLrec *LUSOL, int jcol, REAL v[]);\n\nMYBOOL LUSOL_tightenpivot(LUSOLrec *LUSOL);\nMYBOOL LUSOL_addSingularity(LUSOLrec *LUSOL, int singcol, int *inform);\nint LUSOL_getSingularity(LUSOLrec *LUSOL, int singitem);\nint LUSOL_findSingularityPosition(LUSOLrec *LUSOL, int singcol);\n\nconst char *LUSOL_pivotLabel(LUSOLrec *LUSOL);\nconst char *LUSOL_informstr(LUSOLrec *LUSOL, int inform);\nREAL LUSOL_vecdensity(LUSOLrec *LUSOL, REAL V[]);\nvoid LUSOL_report(LUSOLrec *LUSOL, int msglevel, const char *format, ...);\nvoid LUSOL_timer(LUSOLrec *LUSOL, int timerid, const char *text);\n\nint LUSOL_ftran(LUSOLrec *LUSOL, REAL b[], int NZidx[], MYBOOL prepareupdate);\nint LUSOL_btran(LUSOLrec *LUSOL, REAL b[], int NZidx[]);\n\nvoid LU1FAC(LUSOLrec *LUSOL, int *INFORM);\nMYBOOL LU1L0(LUSOLrec *LUSOL, LUSOLmat **mat, int *inform);\nvoid LU6SOL(LUSOLrec *LUSOL, int MODE, REAL V[], REAL W[], int NZidx[], int *INFORM);\nvoid LU8RPC(LUSOLrec *LUSOL, int MODE1, int MODE2,\n            int JREP, REAL V[], REAL W[],\n            int *INFORM, REAL *DIAG, REAL *VNORM);\n\nvoid LUSOL_dump(FILE *output, LUSOLrec *LUSOL);\n\n\nvoid print_L0(LUSOLrec *LUSOL);\n\n\n#endif /* HEADER_LUSOL */\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol1.c",
    "content": "\n/* ==================================================================\n   lu1DCP factors a dense m x n matrix A by Gaussian elimination,\n   using Complete Pivoting (row and column interchanges) for stability.\n   This version also uses column interchanges if all elements in a\n   pivot column are smaller than (or equal to) \"small\".  Such columns\n   are changed to zero and permuted to the right-hand end.\n   As in LINPACK's dgefa, ipvt(!) keeps track of pivot rows.\n   Rows of U are interchanged, but we don't have to physically\n   permute rows of L.  In contrast, column interchanges are applied\n   directly to the columns of both L and U, and to the column\n   permutation vector iq(*).\n   ------------------------------------------------------------------\n   On entry:\n      a       Array holding the matrix A to be factored.\n      lda     The leading dimension of the array  a.\n      m       The number of rows    in  A.\n      n       The number of columns in  A.\n      small   A drop tolerance.  Must be zero or positive.\n\n   On exit:\n      a       An upper triangular matrix and the multipliers\n              which were used to obtain it.\n              The factorization can be written  A = L*U  where\n              L  is a product of permutation and unit lower\n              triangular matrices and  U  is upper triangular.\n      nsing   Number of singularities detected.\n      ipvt    Records the pivot rows.\n      iq      A vector to which column interchanges are applied.\n   ------------------------------------------------------------------\n   01 May 2002: First dense Complete Pivoting, derived from lu1DPP.\n   07 May 2002: Another break needed at end of first loop.\n   07 May 2002: Current version of lu1DCP.\n   ================================================================== */\nvoid LU1DCP(LUSOLrec *LUSOL, REAL DA[], int LDA, int M, int N, REAL SMALL,\n            int *NSING, int IPVT[], int IX[])\n{\n  int       I, J, K, KP1, L, LAST, LENCOL, IMAX, JMAX, JLAST, JNEW;\n  REAL      AIJMAX, AJMAX;\n  REAL T;\n#ifdef LUSOLFastDenseIndex\n  REAL *DA1, *DA2;\n  int IDA1, IDA2;\n#else\n  int IDA1, IDA2;\n#endif\n  (void)LUSOL;\n\n  *NSING = 0;\n  LENCOL = M+1;\n  LAST = N;\n/*     -----------------------------------------------------------------\n        Start of elimination loop.\n       ----------------------------------------------------------------- */\n  for(K = 1; K <= N; K++) {\n    KP1 = K+1;\n    LENCOL--;\n/*      Find the biggest aij in row imax and column jmax. */\n    AIJMAX = ZERO;\n    IMAX = K;\n    JMAX = K;\n    JLAST = LAST;\n    for(J = K; J <= JLAST; J++) {\nx10:\n      L = idamax(LENCOL,DA+DAPOS(K,J)-LUSOL_ARRAYOFFSET,1)+K-1;\n      AJMAX = fabs(DA[DAPOS(L,J)]);\n      if(AJMAX<=SMALL) {\n/*     ========================================================\n        Do column interchange, changing old column to zero.\n        Reduce  \"last\"  and try again with same j.\n       ======================================================== */\n        (*NSING)++;\n        JNEW = IX[LAST];\n        IX[LAST] = IX[J];\n        IX[J] = JNEW;\n#ifdef LUSOLFastDenseIndex\n        DA1 = DA+DAPOS(0,LAST);\n        DA2 = DA+DAPOS(0,J);\n        for(I = 1; I <= K-1; I++) {\n          DA1++;\n          DA2++;\n          T = *DA1;\n          *DA1 = *DA2;\n          *DA2 = T;\n#else\n        for(I = 1; I <= K-1; I++) {\n          IDA1 = DAPOS(I,LAST);\n          IDA2 = DAPOS(I,J);\n          T = DA[IDA1];\n          DA[IDA1] = DA[IDA2];\n          DA[IDA2] = T;\n#endif\n        }\n#ifdef LUSOLFastDenseIndex\n        for(I = K; I <= M; I++) {\n          DA1++;\n          DA2++;\n          T = *DA1;\n          *DA1 = ZERO;\n          *DA2 = T;\n#else\n        for(I = K; I <= M; I++) {\n          IDA1 = DAPOS(I,LAST);\n          IDA2 = DAPOS(I,J);\n          T = DA[IDA1];\n          DA[IDA1] = ZERO;\n          DA[IDA2] = T;\n#endif\n        }\n        LAST--;\n        if(J<=LAST)\n          goto x10;\n        break;\n      }\n/*      Check if this column has biggest aij so far. */\n      if(AIJMAX<AJMAX) {\n        AIJMAX = AJMAX;\n        IMAX = L;\n        JMAX = J;\n      }\n      if(J>=LAST)\n        break;\n    }\n    IPVT[K] = IMAX;\n    if(JMAX!=K) {\n/*     ==========================================================\n        Do column interchange (k and jmax).\n       ========================================================== */\n      JNEW = IX[JMAX];\n      IX[JMAX] = IX[K];\n      IX[K] = JNEW;\n#ifdef LUSOLFastDenseIndex\n      DA1 = DA+DAPOS(0,JMAX);\n      DA2 = DA+DAPOS(0,K);\n      for(I = 1; I <= M; I++) {\n        DA1++;\n        DA2++;\n        T = *DA1;\n        *DA1 = *DA2;\n        *DA2 = T;\n#else\n      for(I = 1; I <= M; I++) {\n        IDA1 = DAPOS(I,JMAX);\n        IDA2 = DAPOS(I,K);\n        T = DA[IDA1];\n        DA[IDA1] = DA[IDA2];\n        DA[IDA2] = T;\n#endif\n      }\n    }\n    if(M>K) {\n/*     ===========================================================\n        Do row interchange if necessary.\n       =========================================================== */\n      if(IMAX!=K) {\n        IDA1 = DAPOS(IMAX,K);\n        IDA2 = DAPOS(K,K);\n        T = DA[IDA1];\n        DA[IDA1] = DA[IDA2];\n        DA[IDA2] = T;\n      }\n/*     ===========================================================\n        Compute multipliers.\n        Do row elimination with column indexing.\n       =========================================================== */\n      T = -ONE/DA[DAPOS(K,K)];\n      dscal(M-K,T,DA+DAPOS(KP1,K)-LUSOL_ARRAYOFFSET,1);\n      for(J = KP1; J <= LAST; J++) {\n        IDA1 = DAPOS(IMAX,J);\n        T = DA[IDA1];\n        if(IMAX!=K) {\n          IDA2 = DAPOS(K,J);\n          DA[IDA1] = DA[IDA2];\n          DA[IDA2] = T;\n        }\n        daxpy(M-K,T,DA+DAPOS(KP1,K)-LUSOL_ARRAYOFFSET,1,\n                    DA+DAPOS(KP1,J)-LUSOL_ARRAYOFFSET,1);\n      }\n    }\n    else\n      break;\n    if(K>=LAST)\n      break;\n  }\n/*      Set ipvt(*) for singular rows. */\n  for(K = LAST+1; K <= M; K++)\n    IPVT[K] = K;\n\n}\n\n/* ==================================================================\n   lu1DPP factors a dense m x n matrix A by Gaussian elimination,\n   using row interchanges for stability, as in dgefa from LINPACK.\n   This version also uses column interchanges if all elements in a\n   pivot column are smaller than (or equal to) \"small\".  Such columns\n   are changed to zero and permuted to the right-hand end.\n   As in LINPACK, ipvt(*) keeps track of pivot rows.\n   Rows of U are interchanged, but we don't have to physically\n   permute rows of L.  In contrast, column interchanges are applied\n   directly to the columns of both L and U, and to the column\n   permutation vector iq(*).\n   ------------------------------------------------------------------\n   On entry:\n        a       Array holding the matrix A to be factored.\n        lda     The leading dimension of the array  a.\n        m       The number of rows    in  A.\n        n       The number of columns in  A.\n        small   A drop tolerance.  Must be zero or positive.\n\n   On exit:\n        a       An upper triangular matrix and the multipliers\n                which were used to obtain it.\n                The factorization can be written  A = L*U  where\n                L  is a product of permutation and unit lower\n                triangular matrices and  U  is upper triangular.\n        nsing   Number of singularities detected.\n        ipvt    Records the pivot rows.\n        iq      A vector to which column interchanges are applied.\n   ------------------------------------------------------------------\n   02 May 1989: First version derived from dgefa\n                in LINPACK (version dated 08/14/78).\n   05 Feb 1994: Generalized to treat rectangular matrices\n                and use column interchanges when necessary.\n                ipvt is retained, but column permutations are applied\n                directly to iq(*).\n   21 Dec 1994: Bug found via example from Steve Dirkse.\n                Loop 100 added to set ipvt(*) for singular rows.\n   ================================================================== */\nvoid LU1DPP(LUSOLrec *LUSOL, REAL DA[], int LDA, int M, int N, REAL SMALL,\n            int *NSING, int IPVT[], int IX[])\n{\n  int            I, J, K, KP1, L, LAST, LENCOL;\n  REAL T;\n#ifdef LUSOLFastDenseIndex\n  REAL *DA1, *DA2;\n  int IDA1, IDA2;\n#else\n  int IDA1, IDA2;\n#endif\n  (void)LUSOL;\n\n  *NSING = 0;\n  K = 1;\n  LAST = N;\n/*      ------------------------------------------------------------------\n        Start of elimination loop.\n        ------------------------------------------------------------------ */\nx10:\n  KP1 = K+1;\n  LENCOL = (M-K)+1;\n/*      Find l, the pivot row. */\n  L = (idamax(LENCOL,DA+DAPOS(K,K)-LUSOL_ARRAYOFFSET,1)+K)-1;\n  IPVT[K] = L;\n  if(fabs(DA[DAPOS(L,K)])<=SMALL) {\n/*         ===============================================================\n           Do column interchange, changing old pivot column to zero.\n           Reduce  \"last\"  and try again with same k.\n           =============================================================== */\n    (*NSING)++;\n    J = IX[LAST];\n    IX[LAST] = IX[K];\n    IX[K] = J;\n#ifdef LUSOLFastDenseIndex\n    DA1 = DA+DAPOS(0,LAST);\n    DA2 = DA+DAPOS(0,K);\n    for(I = 1; I <= K-1; I++) {\n      DA1++;\n      DA2++;\n      T = *DA1;\n      *DA1 = *DA2;\n      *DA2 = T;\n#else\n    for(I = 1; I <= K-1; I++) {\n      IDA1 = DAPOS(I,LAST);\n      IDA2 = DAPOS(I,K);\n      T = DA[IDA1];\n      DA[IDA1] = DA[IDA2];\n      DA[IDA2] = T;\n#endif\n    }\n#ifdef LUSOLFastDenseIndex\n    for(I = K; I <= M; I++) {\n      DA1++;\n      DA2++;\n      T = *DA1;\n      *DA1 = ZERO;\n      *DA2 = T;\n#else\n    for(I = K; I <= M; I++) {\n      IDA1 = DAPOS(I,LAST);\n      IDA2 = DAPOS(I,K);\n      T = DA[IDA1];\n      DA[IDA1] = ZERO;\n      DA[IDA2] = T;\n#endif\n    }\n    LAST = LAST-1;\n    if(K<=LAST)\n      goto x10;\n  }\n  else if(M>K) {\n/*         ===============================================================\n           Do row interchange if necessary.\n           =============================================================== */\n    if(L!=K) {\n      IDA1 = DAPOS(L,K);\n      IDA2 = DAPOS(K,K);\n      T = DA[IDA1];\n      DA[IDA1] = DA[IDA2];\n      DA[IDA2] = T;\n    }\n/*         ===============================================================\n           Compute multipliers.\n           Do row elimination with column indexing.\n           =============================================================== */\n    T = -ONE/DA[DAPOS(K,K)];\n    dscal(M-K,T,DA+DAPOS(KP1,K)-LUSOL_ARRAYOFFSET,1);\n    for(J = KP1; J <= LAST; J++) {\n      IDA1 = DAPOS(L,J);\n      T = DA[IDA1];\n      if(L!=K) {\n        IDA2 = DAPOS(K,J);\n        DA[IDA1] = DA[IDA2];\n        DA[IDA2] = T;\n      }\n      daxpy(M-K,T,DA+DAPOS(KP1,K)-LUSOL_ARRAYOFFSET,1,\n                  DA+DAPOS(KP1,J)-LUSOL_ARRAYOFFSET,1);\n    }\n    K++;\n    if(K<=LAST)\n      goto x10;\n  }\n/*      Set ipvt(*) for singular rows. */\n  for(K = LAST+1; K <= M; K++)\n    IPVT[K] = K;\n\n}\n\n\n/* ==================================================================\n   lu1pq1  constructs a permutation  iperm  from the array  len.\n   ------------------------------------------------------------------\n   On entry:\n   len(i)  holds the number of nonzeros in the i-th row (say)\n           of an m by n matrix.\n   num(*)  can be anything (workspace).\n\n   On exit:\n   iperm   contains a list of row numbers in the order\n           rows of length 0,  rows of length 1,..., rows of length n.\n   loc(nz) points to the first row containing  nz  nonzeros,\n           nz = 1, n.\n   inv(i)  points to the position of row i within iperm(*).\n   ================================================================== */\nvoid LU1PQ1(LUSOLrec *LUSOL, int M, int N, int LEN[],\n            int IPERM[], int LOC[], int INV[], int NUM[])\n{\n  int NZEROS, NZ, I, L;\n  (void)LUSOL;\n\n/*      Count the number of rows of each length. */\n  NZEROS = 0;\n  for(NZ = 1; NZ <= N; NZ++) {\n    NUM[NZ] = 0;\n    LOC[NZ] = 0;\n  }\n  for(I = 1; I <= M; I++) {\n    NZ = LEN[I];\n    if(NZ==0)\n      NZEROS++;\n    else\n      NUM[NZ]++;\n  }\n/*      Set starting locations for each length. */\n  L = NZEROS+1;\n  for(NZ = 1; NZ <= N; NZ++) {\n    LOC[NZ] = L;\n    L += NUM[NZ];\n    NUM[NZ] = 0;\n  }\n/*      Form the list. */\n  NZEROS = 0;\n  for(I = 1; I <= M; I++) {\n    NZ = LEN[I];\n    if(NZ==0) {\n      NZEROS++;\n      IPERM[NZEROS] = I;\n    }\n    else {\n      L = LOC[NZ]+NUM[NZ];\n      IPERM[L] = I;\n      NUM[NZ]++;\n    }\n  }\n/*      Define the inverse of iperm. */\n  for(L = 1; L <= M; L++) {\n    I = IPERM[L];\n    INV[I] = L;\n  }\n}\n\n/* ==================================================================\n   lu1pq2 frees the space occupied by the pivot row,\n   and updates the column permutation iq.\n   Also used to free the pivot column and update the row perm ip.\n   ------------------------------------------------------------------\n   nzpiv   (input)    is the length of the pivot row (or column).\n   nzchng  (output)   is the net change in total nonzeros.\n   ------------------------------------------------------------------\n   14 Apr 1989  First version.\n   ================================================================== */\nvoid LU1PQ2(LUSOLrec *LUSOL, int NZPIV, int *NZCHNG,\n            int IND[], int LENOLD[], int LENNEW[], int IXLOC[], int IX[], int IXINV[])\n{\n  int LR, J, NZ, NZNEW, L, NEXT, LNEW, JNEW;\n  (void)LUSOL;\n\n  *NZCHNG = 0;\n  for(LR = 1; LR <= NZPIV; LR++) {\n    J = IND[LR];\n    IND[LR] = 0;\n    NZ = LENOLD[LR];\n    NZNEW = LENNEW[J];\n    if(NZ!=NZNEW) {\n      L = IXINV[J];\n      *NZCHNG = (*NZCHNG+NZNEW)-NZ;\n/*            l above is the position of column j in iq  (so j = iq(l)). */\n      if(NZ<NZNEW) {\n/*               Column  j  has to move towards the end of  iq. */\nx110:\n        NEXT = NZ+1;\n        LNEW = IXLOC[NEXT]-1;\n        if(LNEW!=L) {\n          JNEW = IX[LNEW];\n          IX[L] = JNEW;\n          IXINV[JNEW] = L;\n        }\n        L = LNEW;\n        IXLOC[NEXT] = LNEW;\n        NZ = NEXT;\n        if(NZ<NZNEW)\n          goto x110;\n      }\n      else {\n/*               Column  j  has to move towards the front of  iq. */\nx120:\n        LNEW = IXLOC[NZ];\n        if(LNEW!=L) {\n          JNEW = IX[LNEW];\n          IX[L] = JNEW;\n          IXINV[JNEW] = L;\n        }\n        L = LNEW;\n        IXLOC[NZ] = LNEW+1;\n        NZ = NZ-1;\n        if(NZ>NZNEW)\n          goto x120;\n      }\n      IX[LNEW] = J;\n      IXINV[J] = LNEW;\n    }\n  }\n}\n\n/* ==================================================================\n   lu1pq3  looks at the permutation  iperm(*)  and moves any entries\n   to the end whose corresponding length  len(*)  is zero.\n   ------------------------------------------------------------------\n   09 Feb 1994: Added work array iw(*) to improve efficiency.\n   ================================================================== */\nvoid LU1PQ3(LUSOLrec *LUSOL, int MN, int LEN[], int IPERM[], int IW[], int *NRANK)\n{\n  int NZEROS, K, I;\n  (void)LUSOL;\n\n  *NRANK = 0;\n  NZEROS = 0;\n  for(K = 1; K <= MN; K++) {\n    I = IPERM[K];\n    if(LEN[I]==0) {\n      NZEROS++;\n      IW[NZEROS] = I;\n    }\n    else {\n      (*NRANK)++;\n      IPERM[*NRANK] = I;\n    }\n  }\n  for(K = 1; K <= NZEROS; K++)\n    IPERM[(*NRANK)+K] = IW[K];\n}\n\n/* ==================================================================\n   lu1rec\n   ------------------------------------------------------------------\n   On exit:\n   ltop         is the length of useful entries in ind(*), a(*).\n   ind(ltop+1)  is \"i\" such that len(i), loc(i) belong to the last\n                item in ind(*), a(*).\n   ------------------------------------------------------------------\n   00 Jun 1983: Original version of lu1rec followed John Reid's\n                compression routine in LA05.  It recovered\n                space in ind(*) and optionally a(*)\n                by eliminating entries with ind(l) = 0.\n                The elements of ind(*) could not be negative.\n                If len(i) was positive, entry i contained\n                that many elements, starting at  loc(i).\n                Otherwise, entry i was eliminated.\n   23 Mar 2001: Realised we could have len(i) = 0 in rare cases!\n                (Mostly during TCP when the pivot row contains\n                a column of length 1 that couldn't be a pivot.)\n                Revised storage scheme to\n                   keep        entries with       ind(l) >  0,\n                   squeeze out entries with -n <= ind(l) <= 0,\n                and to allow len(i) = 0.\n                Empty items are moved to the end of the compressed\n                ind(*) and/or a(*) arrays are given one empty space.\n                Items with len(i) < 0 are still eliminated.\n   27 Mar 2001: Decided to use only ind(l) > 0 and = 0 in lu1fad.\n                Still have to keep entries with len(i) = 0.\n   ================================================================== */\nvoid LU1REC(LUSOLrec *LUSOL, int N, MYBOOL REALS, int *LTOP,\n                             int IND[], int LEN[], int LOC[])\n{\n  int  NEMPTY, I, LENI, L, LEND, K, KLAST, ILAST, LPRINT;\n\n  NEMPTY = 0;\n  for(I = 1; I <= N; I++) {\n    LENI = LEN[I];\n    if(LENI>0) {\n      L = (LOC[I]+LENI)-1;\n      LEN[I] = IND[L];\n      IND[L] = -(N+I);\n    }\n    else if(LENI==0)\n      NEMPTY++;\n  }\n  K = 0;\n/*      Previous k */\n  KLAST = 0;\n/*      Last entry moved. */\n  ILAST = 0;\n  LEND = *LTOP;\n  for(L = 1; L <= LEND; L++) {\n    I = IND[L];\n    if(I>0) {\n      K++;\n      IND[K] = I;\n      if(REALS)\n        LUSOL->a[K] = LUSOL->a[L];\n    }\n    else if(I<-N) {\n/*            This is the end of entry  i. */\n      I = -(N+I);\n      ILAST = I;\n      K++;\n      IND[K] = LEN[I];\n      if(REALS)\n        LUSOL->a[K] = LUSOL->a[L];\n      LOC[I] = KLAST+1;\n      LEN[I] = K-KLAST;\n      KLAST = K;\n    }\n  }\n/*      Move any empty items to the end, adding 1 free entry for each. */\n  if(NEMPTY>0) {\n    for(I = 1; I <= N; I++) {\n      if(LEN[I]==0) {\n        K++;\n        LOC[I] = K;\n        IND[K] = 0;\n        ILAST = I;\n      }\n    }\n  }\n  LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL];\n  if(LPRINT>=LUSOL_MSG_PIVOT)\n    LUSOL_report(LUSOL, 0, \"lu1rec.  File compressed from %d to %d\\n\",\n                        *LTOP,K,REALS,NEMPTY);\n/*      ncp */\n  LUSOL->luparm[LUSOL_IP_COMPRESSIONS_LU]++;\n/*      Return ilast in ind(ltop + 1). */\n  *LTOP = K;\n  IND[(*LTOP)+1] = ILAST;\n}\n\n/* ==================================================================\n   lu1slk  sets w(j) > 0 if column j is a unit vector.\n   ------------------------------------------------------------------\n   21 Nov 2000: First version.  lu1fad needs it for TCP.\n                Note that w(*) is nominally an integer array,\n                but the only spare space is the double array w(*).\n   ================================================================== */\nvoid LU1SLK(LUSOLrec *LUSOL)\n{\n  int J, LC1, LQ, LQ1, LQ2;\n\n  for(J = 1; J <= LUSOL->n; J++) {\n    LUSOL->w[J] = 0;\n  }\n  LQ1 = (LUSOL->iqloc ? LUSOL->iqloc[1] : LUSOL->n+1);\n/*  LQ1 = LUSOL->iqloc[1];   This is the original version; correction above by Yin Zhang */\n  LQ2 = LUSOL->n;\n  if(LUSOL->m>1)\n    LQ2 = LUSOL->iqloc[2]-1;\n  for(LQ = LQ1; LQ <= LQ2; LQ++) {\n    J = LUSOL->iq[LQ];\n    LC1 = LUSOL->locc[J];\n    if(fabs(LUSOL->a[LC1])==1) {\n      LUSOL->w[J] = 1;\n    }\n  }\n}\n\n/* ==================================================================\n   lu1gau does most of the work for each step of Gaussian elimination.\n   A multiple of the pivot column is added to each other column j\n   in the pivot row.  The column list is fully updated.\n   The row list is updated if there is room, but some fill-ins may\n   remain, as indicated by ifill and jfill.\n   ------------------------------------------------------------------\n   Input:\n      ilast    is the row    at the end of the row    list.\n      jlast    is the column at the end of the column list.\n      lfirst   is the first column to be processed.\n      lu + 1   is the corresponding element of U in au(*).\n      nfill    keeps track of pending fill-in.\n      a(*)     contains the nonzeros for each column j.\n      indc(*)  contains the row indices for each column j.\n      al(*)    contains the new column of L.  A multiple of it is\n               used to modify each column.\n      mark(*)  has been set to -1, -2, -3, ... in the rows\n               corresponding to nonzero 1, 2, 3, ... of the col of L.\n      au(*)    contains the new row of U.  Each nonzero gives the\n               required multiple of the column of L.\n\n   Workspace:\n      markl(*) marks the nonzeros of L actually used.\n               (A different mark, namely j, is used for each column.)\n\n   Output:\n      ilast     New last row    in the row    list.\n      jlast     New last column in the column list.\n      lfirst    = 0 if all columns were completed,\n                > 0 otherwise.\n      lu        returns the position of the last nonzero of U\n                actually used, in case we come back in again.\n      nfill     keeps track of the total extra space needed in the\n                row file.\n      ifill(ll) counts pending fill-in for rows involved in the new\n                column of L.\n      jfill(lu) marks the first pending fill-in stored in columns\n                involved in the new row of U.\n   ------------------------------------------------------------------\n   16 Apr 1989: First version of lu1gau.\n   23 Apr 1989: lfirst, lu, nfill are now input and output\n                to allow re-entry if elimination is interrupted.\n   23 Mar 2001: Introduced ilast, jlast.\n   27 Mar 2001: Allow fill-in \"in situ\" if there is already room\n                up to but NOT INCLUDING the end of the\n                row or column file.\n                Seems safe way to avoid overwriting empty rows/cols\n                at the end.  (May not be needed though, now that we\n                have ilast and jlast.)\n   ================================================================== */\nvoid LU1GAU(LUSOLrec *LUSOL, int MELIM, int NSPARE,\n            REAL SMALL, int LPIVC1, int LPIVC2, int *LFIRST, int LPIVR2,\n            int LFREE, int MINFRE, int ILAST, int *JLAST, int *LROW, int *LCOL,\n            int *LU, int *NFILL,\n            int MARK[],  REAL AL[], int MARKL[], REAL AU[], int IFILL[], int JFILL[])\n{\n  MYBOOL ATEND;\n  int    LR, J, LENJ, NFREE, LC1, LC2, NDONE, NDROP, L, I, LL, K,\n         LR1, LAST, LREP, L1, L2, LC, LENI;\n  REAL UJ;\n  REAL   AIJ;\n\n  for(LR = *LFIRST; LR <= LPIVR2; LR++) {\n    J = LUSOL->indr[LR];\n    LENJ = LUSOL->lenc[J];\n    NFREE = LFREE - *LCOL;\n    if(NFREE<MINFRE)\n      goto x900;\n/*         ---------------------------------------------------------------\n           Inner loop to modify existing nonzeros in column  j.\n           Loop 440 performs most of the arithmetic involved in the\n           whole LU factorization.\n           ndone counts how many multipliers were used.\n           ndrop counts how many modified nonzeros are negligibly small.\n           --------------------------------------------------------------- */\n    (*LU)++;\n    UJ = AU[*LU];\n    LC1 = LUSOL->locc[J];\n    LC2 = (LC1+LENJ)-1;\n    ATEND = (MYBOOL) (J==*JLAST);\n    NDONE = 0;\n    if(LENJ==0)\n      goto x500;\n    NDROP = 0;\n    for(L = LC1; L <= LC2; L++) {\n      I = LUSOL->indc[L];\n      LL = -MARK[I];\n      if(LL>0) {\n        NDONE++;\n        MARKL[LL] = J;\n        LUSOL->a[L] += AL[LL]*UJ;\n        if(fabs(LUSOL->a[L])<=SMALL) {\n          NDROP++;\n        }\n      }\n    }\n/*         ---------------------------------------------------------------\n           Remove any negligible modified nonzeros from both\n           the column file and the row file.\n           --------------------------------------------------------------- */\n    if(NDROP==0)\n      goto x500;\n    K = LC1;\n    for(L = LC1; L <= LC2; L++) {\n      I = LUSOL->indc[L];\n      if(fabs(LUSOL->a[L])<=SMALL)\n        goto x460;\n      LUSOL->a[K] = LUSOL->a[L];\n      LUSOL->indc[K] = I;\n      K++;\n      continue;\n/*            Delete the nonzero from the row file. */\nx460:\n      LENJ--;\n      LUSOL->lenr[I]--;\n      LR1 = LUSOL->locr[I];\n      LAST = LR1+LUSOL->lenr[I];\n      for(LREP = LR1; LREP <= LAST; LREP++) {\n        if(LUSOL->indr[LREP]==J)\n          break;\n      }\n      LUSOL->indr[LREP] = LUSOL->indr[LAST];\n      LUSOL->indr[LAST] = 0;\n      if(I==ILAST)\n        (*LROW)--;\n    }\n/*         Free the deleted elements from the column file. */\n#ifdef LUSOLFastClear\n    MEMCLEAR(LUSOL->indc+K, LC2-K+1);\n#else\n    for(L = K; L <= LC2; L++)\n      LUSOL->indc[L] = ZERO;\n#endif\n    if(ATEND)\n      *LCOL = K-1;\n/*         ---------------------------------------------------------------\n           Deal with the fill-in in column j.\n           --------------------------------------------------------------- */\nx500:\n    if(NDONE==MELIM)\n      goto x590;\n/*         See if column j already has room for the fill-in. */\n    if(ATEND)\n      goto x540;\n    LAST = (LC1+LENJ)-1;\n    L1 = LAST+1;\n    L2 = (LAST+MELIM)-NDONE;\n/*      27 Mar 2001: Be sure it's not at or past end of the col file. */\n    if(L2>=*LCOL)\n      goto x520;\n    for(L = L1; L <= L2; L++) {\n      if(LUSOL->indc[L]!=0)\n        goto x520;\n    }\n    goto x540;\n/*         We must move column j to the end of the column file.\n           First, leave some spare room at the end of the\n           current last column. */\nx520:\n#if 1\n    L1 = (*LCOL)+1;\n    L2 = (*LCOL)+NSPARE;\n    *LCOL = L2;\n    for(L = L1; L <= L2; L++) {\n#else\n    for(L = (*LCOL)+1; L <= (*LCOL)+NSPARE; L++) {\n      *LCOL = L;  /* ****** ERROR ???? */\n#endif\n/*      Spare space is free. */\n      LUSOL->indc[L] = 0;\n    }\n    ATEND = TRUE;\n    *JLAST = J;\n    L1 = LC1;\n    L2 = *LCOL;\n    LC1 = L2+1;\n    LUSOL->locc[J] = LC1;\n    for(L = L1; L <= LAST; L++) {\n      L2++;\n      LUSOL->a[L2] = LUSOL->a[L];\n      LUSOL->indc[L2] = LUSOL->indc[L];\n/*      Free space. */\n      LUSOL->indc[L] = 0;\n    }\n    *LCOL = L2;\n/*         ---------------------------------------------------------------\n           Inner loop for the fill-in in column j.\n           This is usually not very expensive.\n           --------------------------------------------------------------- */\nx540:\n    LAST = (LC1+LENJ)-1;\n    LL = 0;\n    for(LC = LPIVC1; LC <= LPIVC2; LC++) {\n      LL++;\n      if(MARKL[LL]==J)\n        continue;\n      AIJ = AL[LL]*UJ;\n      if(fabs(AIJ)<=SMALL)\n        continue;\n      LENJ++;\n      LAST++;\n      LUSOL->a[LAST] = AIJ;\n      I = LUSOL->indc[LC];\n      LUSOL->indc[LAST] = I;\n      LENI = LUSOL->lenr[I];\n/*            Add 1 fill-in to row i if there is already room.\n              27 Mar 2001: Be sure it's not at or past the }\n                           of the row file. */\n      L = LUSOL->locr[I]+LENI;\n      if(L>=*LROW)\n        goto x550;\n      if(LUSOL->indr[L]>0)\n        goto x550;\n      LUSOL->indr[L] = J;\n      LUSOL->lenr[I] = LENI+1;\n      continue;\n/*            Row i does not have room for the fill-in.\n              Increment ifill(ll) to count how often this has\n              happened to row i.  Also, add m to the row index\n              indc(last) in column j to mark it as a fill-in that is\n              still pending.\n              If this is the first pending fill-in for row i,\n              nfill includes the current length of row i\n              (since the whole row has to be moved later).\n              If this is the first pending fill-in for column j,\n              jfill(lu) records the current length of column j\n              (to shorten the search for pending fill-ins later). */\nx550:\n      if(IFILL[LL]==0)\n        (*NFILL) += LENI+NSPARE;\n      if(JFILL[*LU]==0)\n        JFILL[*LU] = LENJ;\n      (*NFILL)++;\n      IFILL[LL]++;\n      LUSOL->indc[LAST] = LUSOL->m+I;\n    }\n    if(ATEND)\n      *LCOL = LAST;\n/*         End loop for column  j.  Store its final length. */\nx590:\n    LUSOL->lenc[J] = LENJ;\n  }\n/*      Successful completion. */\n  *LFIRST = 0;\n  return;\n/*      Interruption.  We have to come back in after the\n        column file is compressed.  Give lfirst a new value.\n        lu and nfill will retain their current values. */\nx900:\n  *LFIRST = LR;\n}\n\n/* ==================================================================\n   lu1mar  uses a Markowitz criterion to select a pivot element\n   for the next stage of a sparse LU factorization,\n   subject to a Threshold Partial Pivoting stability criterion (TPP)\n   that bounds the elements of L.\n   ------------------------------------------------------------------\n   gamma  is \"gamma\" in the tie-breaking rule TB4 in the LUSOL paper.\n   ------------------------------------------------------------------\n   Search cols of length nz = 1, then rows of length nz = 1,\n   then   cols of length nz = 2, then rows of length nz = 2, etc.\n   ------------------------------------------------------------------\n   00 Jan 1986  Version documented in LUSOL paper:\n                Gill, Murray, Saunders and Wright (1987),\n                Maintaining LU factors of a general sparse matrix,\n                Linear algebra and its applications 88/89, 239-270.\n   02 Feb 1989  Following Suhl and Aittoniemi (1987), the largest\n                element in each column is now kept at the start of\n                the column, i.e. in position locc(j) of a and indc.\n                This should speed up the Markowitz searches.\n   26 Apr 1989  Both columns and rows searched during spars1 phase.\n                Only columns searched during spars2 phase.\n                maxtie replaced by maxcol and maxrow.\n   05 Nov 1993  Initializing  \"mbest = m * n\"  wasn't big enough when\n                m = 10, n = 3, and last column had 7 nonzeros.\n   09 Feb 1994  Realised that \"mbest = maxmn * maxmn\" might overflow.\n                Changed to    \"mbest = maxmn * 1000\".\n   27 Apr 2000  On large example from Todd Munson,\n                that allowed  \"if (mbest .le. nz1**2) go to 900\"\n                to exit before any pivot had been found.\n                Introduced kbest = mbest / nz1.\n                Most pivots can be rejected with no integer multiply.\n                TRUE merit is evaluated only if it's as good as the\n                best so far (or better).  There should be no danger\n                of integer overflow unless A is incredibly\n                large and dense.\n   10 Sep 2000  TCP, aijtol added for Threshold Complete Pivoting.\n   ================================================================== */\nvoid LU1MAR(LUSOLrec *LUSOL, int MAXMN, MYBOOL TCP, REAL AIJTOL, REAL LTOL,\n            int MAXCOL, int MAXROW, int *IBEST, int *JBEST, int *MBEST)\n{\n  int  KBEST, NCOL, NROW, NZ1, NZ, LQ1, LQ2, LQ, J, LC1, LC2, LC, I, LEN1, MERIT, LP1,\n       LP2, LP, LR1, LR2, LR;\n  REAL ABEST, LBEST, AMAX, AIJ, CMAX;\n\n  ABEST = ZERO;\n  LBEST = ZERO;\n  *IBEST = 0;\n  *MBEST = -1;\n  KBEST = MAXMN+1;\n  NCOL = 0;\n  NROW = 0;\n  NZ1 = 0;\n  for(NZ = 1; NZ <= MAXMN; NZ++) {\n/*         nz1    = nz - 1\n           if (mbest .le. nz1**2) go to 900 */\n    if(KBEST<=NZ1)\n      goto x900;\n    if(*IBEST>0) {\n      if(NCOL>=MAXCOL)\n        goto x200;\n    }\n    if(NZ>LUSOL->m)\n      goto x200;\n/*         ---------------------------------------------------------------\n           Search the set of columns of length  nz.\n           --------------------------------------------------------------- */\n    LQ1 = LUSOL->iqloc[NZ];\n    LQ2 = LUSOL->n;\n    if(NZ<LUSOL->m)\n      LQ2 = LUSOL->iqloc[NZ+1]-1;\n    for(LQ = LQ1; LQ <= LQ2; LQ++) {\n      NCOL = NCOL+1;\n      J = LUSOL->iq[LQ];\n      LC1 = LUSOL->locc[J];\n      LC2 = LC1+NZ1;\n      AMAX = fabs(LUSOL->a[LC1]);\n/*            Test all aijs in this column.\n              amax is the largest element (the first in the column).\n              cmax is the largest multiplier if aij becomes pivot. */\n      if(TCP) {\n/*      Nothing in whole column */\n        if(AMAX<AIJTOL)\n          continue;\n      }\n      for(LC = LC1; LC <= LC2; LC++) {\n        I = LUSOL->indc[LC];\n        LEN1 = LUSOL->lenr[I]-1;\n/*               merit  = nz1 * len1\n                 if (merit > mbest) continue; */\n        if(LEN1>KBEST)\n          continue;\n/*               aij  has a promising merit.\n                 Apply the stability test.\n                 We require  aij  to be sufficiently large compared to\n                 all other nonzeros in column  j.  This is equivalent\n                 to requiring cmax to be bounded by Ltol. */\n        if(LC==LC1) {\n/*                  This is the maximum element, amax.\n                    Find the biggest element in the rest of the column\n                    and hence get cmax.  We know cmax .le. 1, but\n                    we still want it exactly in order to break ties.\n                    27 Apr 2002: Settle for cmax = 1. */\n          AIJ = AMAX;\n          CMAX = ONE;\n/*                  cmax   = zero\n                    for (l = lc1 + 1; l <= lc2; l++)\n                       cmax  = max( cmax, abs( a(l) ) );\n                    cmax   = cmax / amax; */\n        }\n        else {\n/*                  aij is not the biggest element, so cmax .ge. 1.\n                    Bail out if cmax will be too big. */\n          AIJ = fabs(LUSOL->a[LC]);\n/*      Absolute test for Complete Pivoting */\n          if(TCP) {\n            if(AIJ<AIJTOL)\n              continue;\n/*      TPP */\n          }\n          else {\n            if(AIJ*LTOL<AMAX)\n              continue;\n          }\n          CMAX = AMAX/AIJ;\n        }\n/*               aij  is big enough.  Its maximum multiplier is cmax. */\n        MERIT = NZ1*LEN1;\n        if(MERIT==*MBEST) {\n/*                  Break ties.\n                    (Initializing mbest < 0 prevents getting here if\n                    nothing has been found yet.)\n                    In this version we minimize cmax\n                    but if it is already small we maximize the pivot. */\n          if(LBEST<=LUSOL->parmlu[LUSOL_RP_GAMMA] &&\n             CMAX<=LUSOL->parmlu[LUSOL_RP_GAMMA]) {\n            if(ABEST>=AIJ)\n              continue;\n          }\n          else {\n            if(LBEST<=CMAX)\n              continue;\n          }\n        }\n/*               aij  is the best pivot so far. */\n        *IBEST = I;\n        *JBEST = J;\n        KBEST = LEN1;\n        *MBEST = MERIT;\n        ABEST = AIJ;\n        LBEST = CMAX;\n        if(NZ==1)\n          goto x900;\n      }\n/*            Finished with that column. */\n      if(*IBEST>0) {\n        if(NCOL>=MAXCOL)\n          goto x200;\n      }\n    }\n/*         ---------------------------------------------------------------\n           Search the set of rows of length  nz.\n           --------------------------------------------------------------- */\nx200:\n/*    if (mbest .le. nz*nz1) go to 900 */\n    if(KBEST<=NZ)\n      goto x900;\n    if(*IBEST>0) {\n      if(NROW>=MAXROW)\n        goto x290;\n    }\n    if(NZ>LUSOL->n)\n      goto x290;\n    LP1 = LUSOL->iploc[NZ];\n    LP2 = LUSOL->m;\n    if(NZ<LUSOL->n)\n      LP2 = LUSOL->iploc[NZ+1]-1;\n    for(LP = LP1; LP <= LP2; LP++) {\n      NROW++;\n      I = LUSOL->ip[LP];\n      LR1 = LUSOL->locr[I];\n      LR2 = LR1+NZ1;\n      for(LR = LR1; LR <= LR2; LR++) {\n        J = LUSOL->indr[LR];\n        LEN1 = LUSOL->lenc[J]-1;\n/*               merit  = nz1 * len1\n                 if (merit .gt. mbest) continue */\n        if(LEN1>KBEST)\n          continue;\n/*               aij  has a promising merit.\n                 Find where  aij  is in column  j. */\n        LC1 = LUSOL->locc[J];\n        LC2 = LC1+LEN1;\n        AMAX = fabs(LUSOL->a[LC1]);\n        for(LC = LC1; LC <= LC2; LC++) {\n          if(LUSOL->indc[LC]==I)\n            break;\n        }\n/*               Apply the same stability test as above. */\n        AIJ = fabs(LUSOL->a[LC]);\n/*      Absolute test for Complete Pivoting */\n        if(TCP) {\n          if(AIJ<AIJTOL)\n            continue;\n        }\n        if(LC==LC1) {\n/*                  This is the maximum element, amax.\n                    Find the biggest element in the rest of the column\n                    and hence get cmax.  We know cmax .le. 1, but\n                    we still want it exactly in order to break ties.\n                    27 Apr 2002: Settle for cmax = 1. */\n          CMAX = ONE;\n/*                  cmax   = zero\n                    for(l = lc1 + 1; l <= lc2; l++)\n                       cmax  = max( cmax, fabs( a(l) ) )\n                    cmax   = cmax / amax */\n        }\n        else {\n/*                  aij is not the biggest element, so cmax .ge. 1.\n                    Bail out if cmax will be too big. */\n          if(TCP) {\n/*      relax */\n          }\n          else {\n            if(AIJ*LTOL<AMAX)\n              continue;\n          }\n          CMAX = AMAX/AIJ;\n        }\n/*               aij  is big enough.  Its maximum multiplier is cmax. */\n        MERIT = NZ1*LEN1;\n        if(MERIT==*MBEST) {\n/*                  Break ties as before.\n                    (Initializing mbest < 0 prevents getting here if\n                    nothing has been found yet.) */\n          if(LBEST<=LUSOL->parmlu[LUSOL_RP_GAMMA] &&\n             CMAX<=LUSOL->parmlu[LUSOL_RP_GAMMA]) {\n            if(ABEST>=AIJ)\n              continue;\n          }\n          else {\n            if(LBEST<=CMAX)\n              continue;\n          }\n        }\n/*               aij  is the best pivot so far. */\n        *IBEST = I;\n        *JBEST = J;\n        *MBEST = MERIT;\n        KBEST = LEN1;\n        ABEST = AIJ;\n        LBEST = CMAX;\n        if(NZ==1)\n          goto x900;\n      }\n/*            Finished with that row. */\n      if(*IBEST>0) {\n        if(NROW>=MAXROW)\n          goto x290;\n      }\n    }\n/*         See if it's time to quit. */\nx290:\n    if(*IBEST>0) {\n      if(NROW>=MAXROW && NCOL>=MAXCOL)\n        goto x900;\n    }\n/*         Press on with next nz. */\n    NZ1 = NZ;\n    if(*IBEST>0)\n      KBEST = *MBEST/NZ1;\n  }\nx900:\n;\n}\n\n/* ==================================================================\n   lu1mCP  uses a Markowitz criterion to select a pivot element\n   for the next stage of a sparse LU factorization,\n   subject to a Threshold Complete Pivoting stability criterion (TCP)\n   that bounds the elements of L and U.\n   ------------------------------------------------------------------\n   gamma  is \"gamma\" in the tie-breaking rule TB4 in the LUSOL paper.\n   ------------------------------------------------------------------\n   09 May 2002: First version of lu1mCP.\n                It searches columns only, using the heap that\n                holds the largest element in each column.\n   09 May 2002: Current version of lu1mCP.\n   ================================================================== */\nvoid LU1MCP(LUSOLrec *LUSOL, REAL AIJTOL, int *IBEST, int *JBEST, int *MBEST,\n            int HLEN, REAL HA[], int HJ[])\n{\n  int  J, KHEAP, LC, LC1, LC2, LENJ, MAXCOL, NCOL, NZ1, I, LEN1, MERIT;\n  REAL ABEST, AIJ, AMAX, CMAX, LBEST;\n\n/*      ------------------------------------------------------------------\n        Search up to maxcol columns stored at the top of the heap.\n        The very top column helps initialize mbest.\n        ------------------------------------------------------------------ */\n  ABEST = ZERO;\n  LBEST = ZERO;\n  *IBEST = 0;\n/*      Column at the top of the heap */\n  *JBEST = HJ[1];\n  LENJ = LUSOL->lenc[*JBEST];\n/*      Bigger than any possible merit */\n  *MBEST = LENJ*HLEN;\n/*      ??? Big question */\n  MAXCOL = 40;\n/*      No. of columns searched */\n  NCOL = 0;\n  for(KHEAP = 1; KHEAP <= HLEN; KHEAP++) {\n    AMAX = HA[KHEAP];\n    if(AMAX<AIJTOL)\n      continue;\n    NCOL++;\n    J = HJ[KHEAP];\n/*         ---------------------------------------------------------------\n           This column has at least one entry big enough (the top one).\n           Search the column for other possibilities.\n           --------------------------------------------------------------- */\n    LENJ = LUSOL->lenc[J];\n    NZ1 = LENJ-1;\n    LC1 = LUSOL->locc[J];\n    LC2 = LC1+NZ1;\n/* --      amax   = abs( a(lc1) )\n           Test all aijs in this column.\n           amax is the largest element (the first in the column).\n           cmax is the largest multiplier if aij becomes pivot. */\n    for(LC = LC1; LC <= LC2; LC++) {\n      I = LUSOL->indc[LC];\n      LEN1 = LUSOL->lenr[I]-1;\n      MERIT = NZ1*LEN1;\n      if(MERIT>*MBEST)\n        continue;\n/*            aij  has a promising merit. */\n      if(LC==LC1) {\n/*               This is the maximum element, amax.\n                 Find the biggest element in the rest of the column\n                 and hence get cmax.  We know cmax .le. 1, but\n                 we still want it exactly in order to break ties.\n                 27 Apr 2002: Settle for cmax = 1. */\n        AIJ = AMAX;\n        CMAX = ONE;\n/*               cmax   = ZERO;\n                 for(l = lc1 + 1; l <= lc2; l++)\n                    cmax  = max( cmax, abs( a(l) ) )\n                 cmax   = cmax / amax; */\n      }\n      else {\n/*               aij is not the biggest element, so cmax .ge. 1.\n                 Bail out if cmax will be too big. */\n        AIJ = fabs(LUSOL->a[LC]);\n        if(AIJ<AIJTOL)\n          continue;\n        CMAX = AMAX/AIJ;\n      }\n/*            aij  is big enough.  Its maximum multiplier is cmax. */\n      if(MERIT==*MBEST) {\n/*               Break ties.\n                 (Initializing mbest \"too big\" prevents getting here if\n                 nothing has been found yet.)\n                 In this version we minimize cmax\n                 but if it is already small we maximize the pivot. */\n        if(LBEST<=LUSOL->parmlu[LUSOL_RP_GAMMA] &&\n           CMAX<=LUSOL->parmlu[LUSOL_RP_GAMMA]) {\n          if(ABEST>=AIJ)\n            continue;\n        }\n        else {\n          if(LBEST<=CMAX)\n            continue;\n        }\n      }\n/*            aij  is the best pivot so far. */\n      *IBEST = I;\n      *JBEST = J;\n      *MBEST = MERIT;\n      ABEST = AIJ;\n      LBEST = CMAX;\n/*      Col or row of length 1 */\n      if(MERIT==0)\n        goto x900;\n    }\n    if(NCOL>=MAXCOL)\n      goto x900;\n  }\nx900:\n;\n}\n\n/* ==================================================================\n   lu1mRP  uses a Markowitz criterion to select a pivot element\n   for the next stage of a sparse LU factorization,\n   subject to a Threshold Rook Pivoting stability criterion (TRP)\n   that bounds the elements of L and U.\n   ------------------------------------------------------------------\n   11 Jun 2002: First version of lu1mRP derived from lu1mar.\n   11 Jun 2002: Current version of lu1mRP.\n   ================================================================== */\nvoid LU1MRP(LUSOLrec *LUSOL, int MAXMN, REAL LTOL, int MAXCOL, int MAXROW,\n  int *IBEST, int *JBEST, int *MBEST, REAL AMAXR[])\n{\n  int  I, J, KBEST, LC, LC1, LC2, LEN1, LP, LP1, LP2, LQ, LQ1,\n       LQ2, LR, LR1, LR2, MERIT, NCOL, NROW, NZ, NZ1;\n  REAL ABEST, AIJ, AMAX, ATOLI, ATOLJ;\n\n/*      ------------------------------------------------------------------\n        Search cols of length nz = 1, then rows of length nz = 1,\n        then   cols of length nz = 2, then rows of length nz = 2, etc.\n        ------------------------------------------------------------------ */\n  ABEST = ZERO;\n  *IBEST = 0;\n  KBEST = MAXMN+1;\n  *MBEST = -1;\n  NCOL = 0;\n  NROW = 0;\n  NZ1 = 0;\n  for(NZ = 1; NZ <= MAXMN; NZ++) {\n/*         nz1    = nz - 1\n           if (mbest .le. nz1**2) go to 900 */\n    if(KBEST<=NZ1)\n      goto x900;\n    if(*IBEST>0) {\n      if(NCOL>=MAXCOL)\n        goto x200;\n    }\n    if(NZ>LUSOL->m)\n      goto x200;\n/*         ---------------------------------------------------------------\n           Search the set of columns of length  nz.\n           --------------------------------------------------------------- */\n    LQ1 = LUSOL->iqloc[NZ];\n    LQ2 = LUSOL->n;\n    if(NZ<LUSOL->m)\n      LQ2 = LUSOL->iqloc[NZ+1]-1;\n    for(LQ = LQ1; LQ <= LQ2; LQ++) {\n      NCOL = NCOL+1;\n      J = LUSOL->iq[LQ];\n      LC1 = LUSOL->locc[J];\n      LC2 = LC1+NZ1;\n      AMAX = fabs(LUSOL->a[LC1]);\n/*      Min size of pivots in col j */\n      ATOLJ = AMAX/LTOL;\n/*            Test all aijs in this column. */\n      for(LC = LC1; LC <= LC2; LC++) {\n        I = LUSOL->indc[LC];\n        LEN1 = LUSOL->lenr[I]-1;\n/*               merit  = nz1 * len1\n                 if (merit .gt. mbest) continue; */\n        if(LEN1>KBEST)\n          continue;\n/*               aij  has a promising merit.\n                 Apply the Threshold Rook Pivoting stability test.\n                 First we require aij to be sufficiently large\n                 compared to other nonzeros in column j.\n                 Then  we require aij to be sufficiently large\n                 compared to other nonzeros in row    i. */\n        AIJ = fabs(LUSOL->a[LC]);\n        if(AIJ<ATOLJ)\n          continue;\n        if(AIJ*LTOL<AMAXR[I])\n          continue;\n/*               aij  is big enough. */\n        MERIT = NZ1*LEN1;\n        if(MERIT==*MBEST) {\n/*                  Break ties.\n                    (Initializing mbest < 0 prevents getting here if\n                    nothing has been found yet.) */\n          if(ABEST>=AIJ)\n            continue;\n        }\n/*               aij  is the best pivot so far. */\n        *IBEST = I;\n        *JBEST = J;\n        KBEST = LEN1;\n        *MBEST = MERIT;\n        ABEST = AIJ;\n        if(NZ==1)\n          goto x900;\n      }\n/*            Finished with that column. */\n      if(*IBEST>0) {\n        if(NCOL>=MAXCOL)\n          goto x200;\n      }\n    }\n/*         ---------------------------------------------------------------\n           Search the set of rows of length  nz.\n           --------------------------------------------------------------- */\nx200:\n/*    if (mbest .le. nz*nz1) go to 900 */\n    if(KBEST<=NZ)\n      goto x900;\n    if(*IBEST>0) {\n      if(NROW>=MAXROW)\n        goto x290;\n    }\n    if(NZ>LUSOL->n)\n      goto x290;\n    LP1 = LUSOL->iploc[NZ];\n    LP2 = LUSOL->m;\n    if(NZ<LUSOL->n)\n      LP2 = LUSOL->iploc[NZ+1]-1;\n    for(LP = LP1; LP <= LP2; LP++) {\n      NROW = NROW+1;\n      I = LUSOL->ip[LP];\n      LR1 = LUSOL->locr[I];\n      LR2 = LR1+NZ1;\n/*      Min size of pivots in row i */\n      ATOLI = AMAXR[I]/LTOL;\n      for(LR = LR1; LR <= LR2; LR++) {\n        J = LUSOL->indr[LR];\n        LEN1 = LUSOL->lenc[J]-1;\n/*               merit  = nz1 * len1\n                 if (merit .gt. mbest) continue; */\n        if(LEN1>KBEST)\n          continue;\n/*               aij  has a promising merit.\n                 Find where  aij  is in column j. */\n        LC1 = LUSOL->locc[J];\n        LC2 = LC1+LEN1;\n        AMAX = fabs(LUSOL->a[LC1]);\n        for(LC = LC1; LC <= LC2; LC++) {\n          if(LUSOL->indc[LC]==I)\n            break;\n        }\n/*               Apply the Threshold Rook Pivoting stability test.\n                 First we require aij to be sufficiently large\n                 compared to other nonzeros in row    i.\n                 Then  we require aij to be sufficiently large\n                 compared to other nonzeros in column j. */\n        AIJ = fabs(LUSOL->a[LC]);\n        if(AIJ<ATOLI)\n          continue;\n        if(AIJ*LTOL<AMAX)\n          continue;\n/*               aij  is big enough. */\n        MERIT = NZ1*LEN1;\n        if(MERIT==*MBEST) {\n/*                  Break ties as before.\n                    (Initializing mbest < 0 prevents getting here if\n                    nothing has been found yet.) */\n          if(ABEST>=AIJ)\n            continue;\n        }\n/*               aij  is the best pivot so far. */\n        *IBEST = I;\n        *JBEST = J;\n        KBEST = LEN1;\n        *MBEST = MERIT;\n        ABEST = AIJ;\n        if(NZ==1)\n          goto x900;\n      }\n/*            Finished with that row. */\n      if(*IBEST>0) {\n        if(NROW>=MAXROW)\n          goto x290;\n      }\n    }\n/*         See if it's time to quit. */\nx290:\n    if(*IBEST>0) {\n      if(NROW>=MAXROW && NCOL>=MAXCOL)\n        goto x900;\n    }\n/*         Press on with next nz. */\n    NZ1 = NZ;\n    if(*IBEST>0)\n      KBEST = *MBEST/NZ1;\n  }\nx900:\n;\n}\n\n/* ==================================================================\n   lu1mSP  is intended for symmetric matrices that are either\n   definite or quasi-definite.\n   lu1mSP  uses a Markowitz criterion to select a pivot element for\n   the next stage of a sparse LU factorization of a symmetric matrix,\n   subject to a Threshold Symmetric Pivoting stability criterion\n   (TSP) restricted to diagonal elements to preserve symmetry.\n   This bounds the elements of L and U and should have rank-revealing\n   properties analogous to Threshold Rook Pivoting for unsymmetric\n   matrices.\n   ------------------------------------------------------------------\n   14 Dec 2002: First version of lu1mSP derived from lu1mRP.\n                There is no safeguard to ensure that A is symmetric.\n   14 Dec 2002: Current version of lu1mSP.\n   ================================================================== */\nvoid LU1MSP(LUSOLrec *LUSOL, int MAXMN, REAL LTOL, int MAXCOL,\n            int *IBEST, int *JBEST, int *MBEST)\n{\n  int  I, J, KBEST, LC, LC1, LC2, LQ, LQ1, LQ2, MERIT, NCOL, NZ, NZ1;\n  REAL ABEST, AIJ, AMAX, ATOLJ;\n\n/*      ------------------------------------------------------------------\n        Search cols of length nz = 1, then cols of length nz = 2, etc.\n        ------------------------------------------------------------------ */\n  ABEST = ZERO;\n  *IBEST = 0;\n  *MBEST = -1;\n  KBEST = MAXMN+1;\n  NCOL = 0;\n  NZ1 = 0;\n  for(NZ = 1; NZ <= MAXMN; NZ++) {\n/*         nz1    = nz - 1\n           if (mbest .le. nz1**2) go to 900 */\n    if(KBEST<=NZ1)\n      goto x900;\n    if(*IBEST>0) {\n      if(NCOL>=MAXCOL)\n        goto x200;\n    }\n    if(NZ>LUSOL->m)\n      goto x200;\n/*         ---------------------------------------------------------------\n           Search the set of columns of length  nz.\n           --------------------------------------------------------------- */\n    LQ1 = LUSOL->iqloc[NZ];\n    LQ2 = LUSOL->n;\n    if(NZ<LUSOL->m)\n      LQ2 = LUSOL->iqloc[NZ+1]-1;\n    for(LQ = LQ1; LQ <= LQ2; LQ++) {\n      NCOL++;\n      J = LUSOL->iq[LQ];\n      LC1 = LUSOL->locc[J];\n      LC2 = LC1+NZ1;\n      AMAX = fabs(LUSOL->a[LC1]);\n/*      Min size of pivots in col j */\n      ATOLJ = AMAX/LTOL;\n/*            Test all aijs in this column.\n              Ignore everything except the diagonal. */\n      for(LC = LC1; LC <= LC2; LC++) {\n        I = LUSOL->indc[LC];\n/*      Skip off-diagonals. */\n        if(I!=J)\n          continue;\n/*               merit  = nz1 * nz1\n                 if (merit .gt. mbest) continue; */\n        if(NZ1>KBEST)\n          continue;\n/*               aij  has a promising merit.\n                 Apply the Threshold Partial Pivoting stability test\n                 (which is equivalent to Threshold Rook Pivoting for\n                 symmetric matrices).\n                 We require aij to be sufficiently large\n                 compared to other nonzeros in column j. */\n        AIJ = fabs(LUSOL->a[LC]);\n        if(AIJ<ATOLJ)\n          continue;\n/*               aij  is big enough. */\n        MERIT = NZ1*NZ1;\n        if(MERIT==*MBEST) {\n/*                  Break ties.\n                    (Initializing mbest < 0 prevents getting here if\n                    nothing has been found yet.) */\n          if(ABEST>=AIJ)\n            continue;\n        }\n/*               aij  is the best pivot so far. */\n        *IBEST = I;\n        *JBEST = J;\n        KBEST = NZ1;\n        *MBEST = MERIT;\n        ABEST = AIJ;\n        if(NZ==1)\n          goto x900;\n      }\n/*            Finished with that column. */\n      if(*IBEST>0) {\n        if(NCOL>=MAXCOL)\n          goto x200;\n      }\n    }\n/*         See if it's time to quit. */\nx200:\n    if(*IBEST>0) {\n      if(NCOL>=MAXCOL)\n        goto x900;\n    }\n/*         Press on with next nz. */\n    NZ1 = NZ;\n    if(*IBEST>0)\n      KBEST = *MBEST/NZ1;\n  }\nx900:\n;\n}\n\n/* ==================================================================\n   lu1mxc  moves the largest element in each of columns iq(k1:k2)\n   to the top of its column.\n   If k1 > k2, nothing happens.\n   ------------------------------------------------------------------\n   06 May 2002: (and earlier)\n                All columns k1:k2 must have one or more elements.\n   07 May 2002: Allow for empty columns.  The heap routines need to\n                find 0.0 as the \"largest element\".\n   29 Nov 2005: Bug fix - avoiding overwriting the next column when\n                the current column is empty (i.e. LENJ==0)\n                Yin Zhang <yzhang@cs.utexas.edu>\n   ================================================================== */\nvoid LU1MXC(LUSOLrec *LUSOL, int K1, int K2, int IX[])\n{\n  int  I, J, K, L, LC, LENJ;\n  REAL AMAX;\n\n  for(K = K1; K <= K2; K++) {\n    J = IX[K];\n    LC = LUSOL->locc[J];\n    LENJ = LUSOL->lenc[J];\n    if(LENJ==0)\n/*      LUSOL->a[LC] = ZERO;  Removal suggested by Yin Zhang to avoid overwriting next column when current is empty */\n      ;\n    else {\n      L = idamax(LUSOL->lenc[J], LUSOL->a + LC - LUSOL_ARRAYOFFSET,1) + LC - 1;\n      if(L>LC) {\n        AMAX = LUSOL->a[L];\n        LUSOL->a[L] = LUSOL->a[LC];\n        LUSOL->a[LC] = AMAX;\n        I = LUSOL->indc[L];\n        LUSOL->indc[L] = LUSOL->indc[LC];\n        LUSOL->indc[LC] = I;\n      }\n    }\n  }\n}\n\n/* ==================================================================\n   lu1mxr  finds the largest element in each of row ip(k1:k2)\n   and stores it in Amaxr(*).  The nonzeros are stored column-wise\n   in (a,indc,lenc,locc) and their structure is row-wise\n   in (  indr,lenr,locr).\n   If k1 > k2, nothing happens.\n   ------------------------------------------------------------------\n   11 Jun 2002: First version of lu1mxr.\n                Allow for empty columns.\n   ================================================================== */\nvoid LU1MXR(LUSOLrec *LUSOL, int K1, int K2, int IX[], REAL AMAXR[])\n{\n#define FastMXR\n#ifdef FastMXR\n  static int  I, *J, *IC, K, LC, LC1, LC2, LR, LR1, LR2;\n  static REAL AMAX;\n#else\n  int  I, J, K, LC, LC1, LC2, LR, LR1, LR2;\n  REAL AMAX;\n#endif\n\n  for(K = K1; K <= K2; K++) {\n    AMAX = ZERO;\n    I = IX[K];\n/*      Find largest element in row i. */\n    LR1 = LUSOL->locr[I];\n    LR2 = (LR1+LUSOL->lenr[I])-1;\n#ifdef FastMXR\n    for(LR = LR1, J = LUSOL->indr + LR1;\n        LR <= LR2; LR++, J++) {\n/*      Find where  aij  is in column  j. */\n      LC1 = LUSOL->locc[*J];\n      LC2 = LC1+LUSOL->lenc[*J];\n      for(LC = LC1, IC = LUSOL->indc + LC1;\n          LC < LC2; LC++, IC++) {\n        if(*IC==I)\n          break;\n      }\n      SETMAX(AMAX,fabs(LUSOL->a[LC]));\n    }\n#else\n    for(LR = LR1; LR <= LR2; LR++) {\n      J = LUSOL->indr[LR];\n/*      Find where  aij  is in column  j. */\n      LC1 = LUSOL->locc[J];\n      LC2 = (LC1+LUSOL->lenc[J])-1;\n      for(LC = LC1; LC <= LC2; LC++) {\n        if(LUSOL->indc[LC]==I)\n          break;\n      }\n      SETMAX(AMAX,fabs(LUSOL->a[LC]));\n    }\n#endif\n    AMAXR[I] = AMAX;\n  }\n}\n\n\n/* ==================================================================\n   lu1ful computes a dense (full) LU factorization of the\n   mleft by nleft matrix that remains to be factored at the\n   beginning of the nrowu-th pass through the main loop of lu1fad.\n   ------------------------------------------------------------------\n   02 May 1989: First version.\n   05 Feb 1994: Column interchanges added to lu1DPP.\n   08 Feb 1994: ipinv reconstructed, since lu1pq3 may alter ip.\n   ================================================================== */\nvoid LU1FUL(LUSOLrec *LUSOL, int LEND, int LU1, MYBOOL TPP,\n            int MLEFT, int NLEFT, int NRANK, int NROWU,\n            int *LENL, int *LENU, int *NSING,\n            MYBOOL KEEPLU, REAL SMALL, REAL D[], int IPVT[])\n{\n  int  L, I, J, IPBASE, LDBASE, LQ, LC1, LC2, LC, LD, LKK, LKN, LU, K, L1,\n       L2, IBEST, JBEST, LA, LL, NROWD, NCOLD;\n  REAL AI, AJ;\n\n/*      ------------------------------------------------------------------\n        If lu1pq3 moved any empty rows, reset ipinv = inverse of ip.\n        ------------------------------------------------------------------ */\n  if(NRANK<LUSOL->m) {\n    for(L = 1; L <= LUSOL->m; L++) {\n      I = LUSOL->ip[L];\n      LUSOL->ipinv[I] = L;\n    }\n  }\n/*      ------------------------------------------------------------------\n        Copy the remaining matrix into the dense matrix D.\n         ------------------------------------------------------------------ */\n#ifdef LUSOLFastClear\n  MEMCLEAR((D+1), LEND);\n#else\n/*   dload(LEND, ZERO, D, 1); */\n  for(J = 1; J <= LEND; J++)\n    D[J] = ZERO;\n#endif\n\n  IPBASE = NROWU-1;\n  LDBASE = 1-NROWU;\n  for(LQ = NROWU; LQ <= LUSOL->n; LQ++) {\n    J = LUSOL->iq[LQ];\n    LC1 = LUSOL->locc[J];\n    LC2 = (LC1+LUSOL->lenc[J])-1;\n    for(LC = LC1; LC <= LC2; LC++) {\n      I = LUSOL->indc[LC];\n      LD = LDBASE+LUSOL->ipinv[I];\n      D[LD] = LUSOL->a[LC];\n    }\n    LDBASE += MLEFT;\n  }\n/*      ------------------------------------------------------------------\n        Call our favorite dense LU factorizer.\n        ------------------------------------------------------------------ */\n  if(TPP)\n    LU1DPP(LUSOL, D,MLEFT,MLEFT,NLEFT,SMALL,NSING,IPVT,LUSOL->iq+NROWU-LUSOL_ARRAYOFFSET);\n  else\n    LU1DCP(LUSOL, D,MLEFT,MLEFT,NLEFT,SMALL,NSING,IPVT,LUSOL->iq+NROWU-LUSOL_ARRAYOFFSET);\n\n/*      ------------------------------------------------------------------\n        Move D to the beginning of A,\n        and pack L and U at the top of a, indc, indr.\n        In the process, apply the row permutation to ip.\n        lkk points to the diagonal of U.\n        ------------------------------------------------------------------ */\n#ifdef LUSOLFastCopy\n  MEMCOPY(LUSOL->a+1,D+1,LEND);\n#else\n  dcopy(LEND,D,1,LUSOL->a,1);\n#endif\n#ifdef ClassicdiagU\n  LUSOL->diagU = LUSOL->a + (LUSOL->lena-LUSOL->n);\n#endif\n  LKK = 1;\n  LKN = (LEND-MLEFT)+1;\n  LU = LU1;\n  for(K = 1; K <= MIN(MLEFT,NLEFT); K++) {\n    L1 = IPBASE+K;\n    L2 = IPBASE+IPVT[K];\n    if(L1!=L2) {\n      I = LUSOL->ip[L1];\n      LUSOL->ip[L1] = LUSOL->ip[L2];\n      LUSOL->ip[L2] = I;\n    }\n    IBEST = LUSOL->ip[L1];\n    JBEST = LUSOL->iq[L1];\n    if(KEEPLU) {\n/*            ===========================================================\n              Pack the next column of L.\n              =========================================================== */\n      LA = LKK;\n      LL = LU;\n      NROWD = 1;\n      for(I = K+1; I <= MLEFT; I++) {\n        LA++;\n        AI = LUSOL->a[LA];\n        if(fabs(AI)>SMALL) {\n          NROWD = NROWD+1;\n          LL--;\n          LUSOL->a[LL] = AI;\n          LUSOL->indc[LL] = LUSOL->ip[IPBASE+I];\n          LUSOL->indr[LL] = IBEST;\n        }\n      }\n/*            ===========================================================\n              Pack the next row of U.\n              We go backwards through the row of D\n              so the diagonal ends up at the front of the row of  U.\n              Beware -- the diagonal may be zero.\n              =========================================================== */\n      LA = LKN+MLEFT;\n      LU = LL;\n      NCOLD = 0;\n      for(J = NLEFT; J >= K; J--) {\n        LA = LA-MLEFT;\n        AJ = LUSOL->a[LA];\n        if(fabs(AJ)>SMALL || J==K) {\n          NCOLD++;\n          LU--;\n          LUSOL->a[LU] = AJ;\n          LUSOL->indr[LU] = LUSOL->iq[IPBASE+J];\n        }\n      }\n      LUSOL->lenr[IBEST] = -NCOLD;\n      LUSOL->lenc[JBEST] = -NROWD;\n      *LENL = ((*LENL)+NROWD)-1;\n      *LENU = (*LENU)+NCOLD;\n      LKN++;\n    }\n    else {\n/*            ===========================================================\n              Store just the diagonal of U, in natural order.\n              =========================================================== */\n      LUSOL->diagU[JBEST] = LUSOL->a[LKK];\n    }\n    LKK += MLEFT+1;\n  }\n}\n\n\n/* ==================================================================\n   lu1or1  organizes the elements of an  m by n  matrix  A  as\n   follows.  On entry, the parallel arrays   a, indc, indr,\n   contain  nelem  entries of the form     aij,    i,    j,\n   in any order.  nelem  must be positive.\n   Entries not larger than the input parameter  small  are treated as\n   zero and removed from   a, indc, indr.  The remaining entries are\n   defined to be nonzero.  numnz  returns the number of such nonzeros\n   and  Amax  returns the magnitude of the largest nonzero.\n   The arrays  lenc, lenr  return the number of nonzeros in each\n   column and row of  A.\n   inform = 0  on exit, except  inform = 1  if any of the indices in\n   indc, indr  imply that the element  aij  lies outside the  m by n\n   dimensions of  A.\n   ------------------------------------------------------------------\n   xx Feb 1985: Original version.\n   17 Oct 2000: a, indc, indr now have size lena to allow nelem = 0.\n   ================================================================== */\nvoid LU1OR1(LUSOLrec *LUSOL, REAL SMALL,\n            REAL *AMAX, int *NUMNZ, int *LERR, int *INFORM)\n{\n  int I, J, L, LDUMMY;\n\n#ifdef LUSOLFastClear\n  MEMCLEAR((LUSOL->lenr+1), LUSOL->m);\n  MEMCLEAR((LUSOL->lenc+1), LUSOL->n);\n#else\n  for(I = 1; I <= LUSOL->m; I++)\n    LUSOL->lenr[I] = ZERO;\n  for(I = 1; I <= LUSOL->n; I++)\n    LUSOL->lenc[I] = ZERO;\n#endif\n\n  *AMAX = 0;\n  *NUMNZ = LUSOL->nelem;\n  L = LUSOL->nelem+1;\n  for(LDUMMY = 1; LDUMMY <= LUSOL->nelem; LDUMMY++) {\n    L--;\n    if(fabs(LUSOL->a[L])>SMALL) {\n      I = LUSOL->indc[L];\n      J = LUSOL->indr[L];\n      SETMAX(*AMAX,fabs(LUSOL->a[L]));\n      if(I<1 || I>LUSOL->m)\n        goto x910;\n      if(J<1 || J>LUSOL->n)\n        goto x910;\n      LUSOL->lenr[I]++;\n      LUSOL->lenc[J]++;\n    }\n    else {\n/*            Replace a negligible element by last element.  Since\n              we are going backwards, we know the last element is ok. */\n      LUSOL->a[L] = LUSOL->a[*NUMNZ];\n      LUSOL->indc[L] = LUSOL->indc[*NUMNZ];\n      LUSOL->indr[L] = LUSOL->indr[*NUMNZ];\n      (*NUMNZ)--;\n    }\n  }\n  *LERR = 0;\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  return;\n\nx910:\n  *LERR = L;\n  *INFORM = LUSOL_INFORM_LUSINGULAR;\n}\n\n/* ==================================================================\n   lu1or2  sorts a list of matrix elements  a(i,j)  into column\n   order, given  numa  entries  a(i,j),  i,  j  in the parallel\n   arrays  a, inum, jnum  respectively.  The matrix is assumed\n   to have  n  columns and an arbitrary number of rows.\n   On entry,  len(*)  must contain the length of each column.\n   On exit,  a(*) and inum(*)  are sorted,  jnum(*) = 0,  and\n   loc(j)  points to the start of column j.\n   lu1or2  is derived from  mc20ad,  a routine in the Harwell\n   Subroutine Library, author J. K. Reid.\n   ------------------------------------------------------------------\n   xx Feb 1985: Original version.\n   17 Oct 2000: a, inum, jnum now have size lena to allow nelem = 0.\n   ================================================================== */\nvoid LU1OR2(LUSOLrec *LUSOL)\n{\n  REAL ACE, ACEP;\n  int  L, J, I, JCE, ICE, ICEP, JCEP, JA, JB;\n\n/*      Set  loc(j)  to point to the beginning of column  j. */\n  L = 1;\n  for(J = 1; J <= LUSOL->n; J++) {\n    LUSOL->locc[J] = L;\n    L += LUSOL->lenc[J];\n  }\n/*      Sort the elements into column order.\n        The algorithm is an in-place sort and is of order  numa. */\n  for(I = 1; I <= LUSOL->nelem; I++) {\n/*         Establish the current entry. */\n    JCE = LUSOL->indr[I];\n    if(JCE==0)\n      continue;\n    ACE = LUSOL->a[I];\n    ICE = LUSOL->indc[I];\n    LUSOL->indr[I] = 0;\n/*         Chain from current entry. */\n    for(J = 1; J <= LUSOL->nelem; J++) {\n/*            The current entry is not in the correct position.\n              Determine where to store it. */\n      L = LUSOL->locc[JCE];\n      LUSOL->locc[JCE]++;\n/*            Save the contents of that location. */\n      ACEP = LUSOL->a[L];\n      ICEP = LUSOL->indc[L];\n      JCEP = LUSOL->indr[L];\n/*            Store current entry. */\n      LUSOL->a[L] = ACE;\n      LUSOL->indc[L] = ICE;\n      LUSOL->indr[L] = 0;\n/*            If next current entry needs to be processed,\n              copy it into current entry. */\n      if(JCEP==0)\n        break;\n      ACE = ACEP;\n      ICE = ICEP;\n      JCE = JCEP;\n    }\n  }\n/*      Reset loc(j) to point to the start of column j. */\n  JA = 1;\n  for(J = 1; J <= LUSOL->n; J++) {\n    JB = LUSOL->locc[J];\n    LUSOL->locc[J] = JA;\n    JA = JB;\n  }\n}\n\n/* ==================================================================\n   lu1or3  looks for duplicate elements in an  m by n  matrix  A\n   defined by the column list  indc, lenc, locc.\n   iw  is used as a work vector of length  m.\n   ------------------------------------------------------------------\n   xx Feb 1985: Original version.\n   17 Oct 2000: indc, indr now have size lena to allow nelem = 0.\n   ================================================================== */\nvoid LU1OR3(LUSOLrec *LUSOL, int *LERR, int *INFORM)\n{\n  int I, J, L1, L2, L;\n\n#ifdef LUSOLFastClear\n  MEMCLEAR((LUSOL->ip+1), LUSOL->m);\n#else\n  for(I = 1; I <= LUSOL->m; I++)\n    LUSOL->ip[I] = ZERO;\n#endif\n\n  for(J = 1; J <= LUSOL->n; J++) {\n    if(LUSOL->lenc[J]>0) {\n      L1 = LUSOL->locc[J];\n      L2 = (L1+LUSOL->lenc[J])-1;\n      for(L = L1; L <= L2; L++) {\n        I = LUSOL->indc[L];\n        if(LUSOL->ip[I]==J)\n          goto x910;\n        LUSOL->ip[I] = J;\n      }\n    }\n  }\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  return;\nx910:\n  *LERR = L;\n  *INFORM = LUSOL_INFORM_LUSINGULAR;\n}\n\n/* ==================================================================\n   lu1or4 constructs a row list  indr, locr\n   from a corresponding column list  indc, locc,\n   given the lengths of both columns and rows in  lenc, lenr.\n   ------------------------------------------------------------------\n   xx Feb 1985: Original version.\n   17 Oct 2000: indc, indr now have size lena to allow nelem = 0.\n   ================================================================== */\nvoid LU1OR4(LUSOLrec *LUSOL)\n{\n  int L, I, L2, J, JDUMMY, L1, LR;\n\n/*      Initialize  locr(i)  to point just beyond where the\n        last component of row  i  will be stored. */\n  L = 1;\n  for(I = 1; I <= LUSOL->m; I++) {\n    L += LUSOL->lenr[I];\n    LUSOL->locr[I] = L;\n  }\n/*      By processing the columns backwards and decreasing  locr(i)\n        each time it is accessed, it will end up pointing to the\n        beginning of row  i  as required. */\n  L2 = LUSOL->nelem;\n  J = LUSOL->n+1;\n  for(JDUMMY = 1; JDUMMY <= LUSOL->n; JDUMMY++) {\n    J = J-1;\n    if(LUSOL->lenc[J]>0) {\n      L1 = LUSOL->locc[J];\n      for(L = L1; L <= L2; L++) {\n        I = LUSOL->indc[L];\n        LR = LUSOL->locr[I]-1;\n        LUSOL->locr[I] = LR;\n        LUSOL->indr[LR] = J;\n      }\n      L2 = L1-1;\n    }\n  }\n}\n\n/* ==================================================================\n   lu1pen deals with pending fill-in in the row file.\n   ------------------------------------------------------------------\n   ifill(ll) says if a row involved in the new column of L\n             has to be updated.  If positive, it is the total\n             length of the final updated row.\n   jfill(lu) says if a column involved in the new row of U\n             contains any pending fill-ins.  If positive, it points\n             to the first fill-in in the column that has yet to be\n             added to the row file.\n   ------------------------------------------------------------------\n   16 Apr 1989: First version of lu1pen.\n   23 Mar 2001: ilast used and updated.\n   ================================================================== */\nvoid LU1PEN(LUSOLrec *LUSOL, int NSPARE, int *ILAST,\n            int LPIVC1, int LPIVC2, int LPIVR1, int LPIVR2,\n            int *LROW, int IFILL[], int JFILL[])\n{\n  int  LL, LC, L, I, LR1, LR2, LR, LU, J, LC1, LC2, LAST;\n\n  LL = 0;\n  for(LC = LPIVC1; LC <= LPIVC2; LC++) {\n    LL++;\n    if(IFILL[LL]==0)\n      continue;\n/*      Another row has pending fill.\n        First, add some spare space at the }\n        of the current last row. */\n#if 1\n    LC1 = (*LROW)+1;\n    LC2 = (*LROW)+NSPARE;\n    *LROW = LC2;\n    for(L = LC1; L <= LC2; L++) {\n#else\n    for(L = (*LROW)+1; L <= (*LROW)+NSPARE; L++) {\n      *LROW = L;  /* ******* ERROR ???? */\n#endif\n      LUSOL->indr[L] = 0;\n    }\n/*      Now move row i to the end of the row file. */\n    I = LUSOL->indc[LC];\n    *ILAST = I;\n    LR1 = LUSOL->locr[I];\n    LR2 = (LR1+LUSOL->lenr[I])-1;\n    LUSOL->locr[I] = (*LROW)+1;\n    for(LR = LR1; LR <= LR2; LR++) {\n      (*LROW)++;\n      LUSOL->indr[*LROW] = LUSOL->indr[LR];\n      LUSOL->indr[LR] = 0;\n    }\n    (*LROW) += IFILL[LL];\n  }\n/*         Scan all columns of  D  and insert the pending fill-in\n           into the row file. */\n  LU = 1;\n  for(LR = LPIVR1; LR <= LPIVR2; LR++) {\n    LU++;\n    if(JFILL[LU]==0)\n      continue;\n    J = LUSOL->indr[LR];\n    LC1 = (LUSOL->locc[J]+JFILL[LU])-1;\n    LC2 = (LUSOL->locc[J]+LUSOL->lenc[J])-1;\n    for(LC = LC1; LC <= LC2; LC++) {\n      I = LUSOL->indc[LC]-LUSOL->m;\n      if(I>0) {\n        LUSOL->indc[LC] = I;\n        LAST = LUSOL->locr[I]+LUSOL->lenr[I];\n        LUSOL->indr[LAST] = J;\n        LUSOL->lenr[I]++;\n      }\n    }\n  }\n}\n\n\n/* ==================================================================\n   lu1fad  is a driver for the numerical phase of lu1fac.\n   At each stage it computes a column of  L  and a row of  U,\n   using a Markowitz criterion to select the pivot element,\n   subject to a stability criterion that bounds the elements of  L.\n   ------------------------------------------------------------------\n   Local variables\n   ---------------\n   lcol   is the length of the column file.  It points to the last\n          nonzero in the column list.\n   lrow   is the analogous quantity for the row file.\n   lfile  is the file length (lcol or lrow) after the most recent\n          compression of the column list or row list.\n   nrowd  and  ncold  are the number of rows and columns in the\n          matrix defined by the pivot column and row.  They are the\n          dimensions of the submatrix D being altered at this stage.\n   melim  and  nelim  are the number of rows and columns in the\n          same matrix D, excluding the pivot column and row.\n   mleft  and  nleft  are the number of rows and columns\n          still left to be factored.\n   nzchng is the increase in nonzeros in the matrix that remains\n          to be factored after the current elimination\n          (usually negative).\n   nzleft is the number of nonzeros still left to be factored.\n   nspare is the space we leave at the end of the last row or\n          column whenever a row or column is being moved to the }\n          of its file.  nspare = 1 or 2 might help reduce the\n          number of file compressions when storage is tight.\n   The row and column ordering permutes A into the form\n                      ------------------------\n                       \\                     |\n                        \\         U1         |\n                         \\                   |\n                          --------------------\n                          |\\\n                          | \\\n                          |  \\\n          P A Q   =       |   \\\n                          |    \\\n                          |     --------------\n                          |     |            |\n                          |     |            |\n                          | L1  |     A2     |\n                          |     |            |\n                          |     |            |\n                          --------------------\n   where the block A2 is factored as  A2 = L2 U2.\n   The phases of the factorization are as follows.\n   Utri   is true when U1 is being determined.\n          Any column of length 1 is accepted immediately (if TPP).\n   Ltri   is true when L1 is being determined.\n          lu1mar exits as soon as an acceptable pivot is found\n          in a row of length 1.\n   spars1 is true while the density of the (modified) A2 is less\n          than the parameter dens1 = parmlu(7) = 0.3 say.\n          lu1mar searches maxcol columns and maxrow rows,\n          where  maxcol = luparm(3),  maxrow = maxcol - 1.\n          lu1mxc is used to keep the biggest element at the top\n          of all remaining columns.\n   spars2 is true while the density of the modified A2 is less\n          than the parameter dens2 = parmlu(8) = 0.6 say.\n          lu1mar searches maxcol columns and no rows.\n          lu1mxc could fix up only the first maxcol cols (with TPP).\n          22 Sep 2000:  For simplicity, lu1mxc fixes all\n                        modified cols.\n   dense  is true once the density of A2 reaches dens2.\n          lu1mar searches only 1 column (the shortest).\n          lu1mxc could fix up only the first column (with TPP).\n   ------------------------------------------------------------------\n   00 Jan 1986  Version documented in LUSOL paper:\n                Gill, Murray, Saunders and Wright (1987),\n                Maintaining LU factors of a general sparse matrix,\n                Linear algebra and its applications 88/89, 239-270.\n   02 Feb 1989  Following Suhl and Aittoniemi (1987), the largest\n                element in each column is now kept at the start of\n                the column, i.e. in position locc(j) of a and indc.\n                This should speed up the Markowitz searches.\n                To save time on highly triangular matrices, we wait\n                until there are no further columns of length 1\n                before setting and maintaining that property.\n   12 Apr 1989  ipinv and iqinv added (inverses of ip and iq)\n                to save searching ip and iq for rows and columns\n                altered in each elimination step.  (Used in lu1pq2)\n   19 Apr 1989  Code segmented to reduce its size.\n                lu1gau does most of the Gaussian elimination work.\n                lu1mar does just the Markowitz search.\n                lu1mxc moves biggest elements to top of columns.\n                lu1pen deals with pending fill-in in the row list.\n                lu1pq2 updates the row and column permutations.\n   26 Apr 1989  maxtie replaced by maxcol, maxrow in the Markowitz\n                search.  maxcol, maxrow change as density increases.\n   25 Oct 1993  keepLU implemented.\n   07 Feb 1994  Exit main loop early to finish off with a dense LU.\n                densLU tells lu1fad whether to do it.\n   21 Dec 1994  Bug fixed.  nrank was wrong after the call to lu1ful.\n   12 Nov 1999  A parallel version of dcopy gave trouble in lu1ful\n                during left-shift of dense matrix D within a(*).\n                Fixed this unexpected problem here in lu1fad\n                by making sure the first and second D don't overlap.\n   13 Sep 2000  TCP (Threshold Complete Pivoting) implemented.\n                lu2max added\n                (finds aijmax from biggest elems in each col).\n                Utri, Ltri and Spars1 phases apply.\n                No switch to Dense CP yet.  (Only TPP switches.)\n   14 Sep 2000  imax needed to remember row containing aijmax.\n   22 Sep 2000  For simplicity, lu1mxc always fixes all modified cols.\n                (TPP spars2 used to fix just the first maxcol cols.)\n   08 Nov 2000: Speed up search for aijmax.\n                Don't need to search all columns if the elimination\n                didn't alter the col containing the current aijmax.\n   21 Nov 2000: lu1slk implemented for Utri phase with TCP\n                to guard against deceptive triangular matrices.\n                (Utri used to have aijtol >= 0.9999 to include\n                slacks, but this allows other 1s to be accepted.)\n                Utri now accepts slacks, but applies normal aijtol\n                test to other pivots.\n   28 Nov 2000: TCP with empty cols must call lu1mxc and lu2max\n                with ( lq1, n, ... ), not just ( 1, n, ... ).\n   23 Mar 2001: lu1fad bug with TCP.\n                A col of length 1 might not be accepted as a pivot.\n                Later it appears in a pivot row and temporarily\n                has length 0 (when pivot row is removed\n                but before the column is filled in).  If it is the\n                last column in storage, the preceding col also thinks\n                it is \"last\".  Trouble arises when the preceding col\n                needs fill-in -- it overlaps the real \"last\" column.\n                (Very rarely, same trouble might have happened if\n                the drop tolerance caused columns to have length 0.)\n                Introduced ilast to record the last row in row file,\n                           jlast to record the last col in col file.\n                lu1rec returns ilast = indr(lrow + 1)\n                            or jlast = indc(lcol + 1).\n                (Should be an output parameter, but didn't want to\n                alter lu1rec's parameter list.)\n                lu1rec also treats empty rows or cols safely.\n                (Doesn't eliminate them!)\n   26 Apr 2002: Heap routines added for TCP.\n                lu2max no longer needed.\n                imax, jmax used only for printing.\n   01 May 2002: lu1DCP implemented (dense complete pivoting).\n                Both TPP and TCP now switch to dense LU\n                when density exceeds dens2.\n   06 May 2002: In dense mode, store diag(U) in natural order.\n   09 May 2002: lu1mCP implemented (Markowitz TCP via heap).\n   11 Jun 2002: lu1mRP implemented (Markowitz TRP).\n   28 Jun 2002: Fixed call to lu1mxr.\n   14 Dec 2002: lu1mSP implemented (Markowitz TSP).\n   15 Dec 2002: Both TPP and TSP can grab cols of length 1\n                during Utri.\n   ================================================================== */\nvoid LU1FAD(LUSOLrec *LUSOL,\n#ifdef ClassicHamaxR\n            int LENA2, int LENH, REAL HA[], int HJ[], int HK[], REAL AMAXR[],\n#endif\n            int *INFORM, int *LENL, int *LENU, int *MINLEN,\n            int *MERSUM, int *NUTRI, int *NLTRI,\n            int *NDENS1, int *NDENS2, int *NRANK,\n            REAL *LMAX, REAL *UMAX, REAL *DUMAX, REAL *DUMIN, REAL *AKMAX)\n{\n  MYBOOL UTRI, LTRI, SPARS1, SPARS2, DENSE, DENSLU, KEEPLU, TCP, TPP, TRP,TSP;\n  int    HLEN, HOPS, H, LPIV, LPRINT, MAXCOL, MAXROW, ILAST, JLAST, LFILE, LROW, LCOL,\n         MINMN, MAXMN, NZLEFT, NSPARE, LU1, KK, J, LC, MLEFT, NLEFT, NROWU,\n         LQ1, LQ2, JBEST, LQ, I, IBEST, MBEST, LEND, NFREE, LD, NCOLD, NROWD,\n         MELIM, NELIM, JMAX, IMAX, LL1, LSAVE, LFREE, LIMIT, MINFRE, LPIVR, LPIVR1, LPIVR2,\n         L, LPIVC, LPIVC1, LPIVC2, KBEST, LU, LR, LENJ, LC1, LAST, LL, LS,\n         LENI, LR1, LFIRST, NFILL, NZCHNG, K, MRANK, NSING;\n  REAL   LIJ, LTOL, SMALL, USPACE, DENS1, DENS2, AIJMAX, AIJTOL, AMAX, ABEST, DIAG, V;\n#ifdef ClassicHamaxR\n  int    LDIAGU;\n#else\n  int    LENA2 = LUSOL->lena;\n#endif\n\n#ifdef UseTimer\n  int    eltime, mktime, ntime;\n  timer ( \"start\", 3 );\n  ntime = LUSOL->n / 4;\n#endif\n\n#ifdef ForceInitialization\n  AIJMAX = 0;\n  AIJTOL = 0;\n  HLEN   = 0;\n  JBEST  = 0;\n  IBEST  = 0;\n  MBEST  = 0;\n  LEND   = 0;\n  LD     = 0;\n#endif\n\n  LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL];\n  MAXCOL = LUSOL->luparm[LUSOL_IP_MARKOWITZ_MAXCOL];\n  LPIV   = LUSOL->luparm[LUSOL_IP_PIVOTTYPE];\n  KEEPLU = (MYBOOL) (LUSOL->luparm[LUSOL_IP_KEEPLU]!=FALSE);\n/*      Threshold Partial   Pivoting (normal). */\n  TPP = (MYBOOL) (LPIV==LUSOL_PIVMOD_TPP);\n/*      Threshold Rook      Pivoting */\n  TRP = (MYBOOL) (LPIV==LUSOL_PIVMOD_TRP);\n/*      Threshold Complete  Pivoting. */\n  TCP = (MYBOOL) (LPIV==LUSOL_PIVMOD_TCP);\n/*      Threshold Symmetric Pivoting. */\n  TSP = (MYBOOL) (LPIV==LUSOL_PIVMOD_TSP);\n  DENSLU = FALSE;\n  MAXROW = MAXCOL-1;\n/*      Assume row m is last in the row file. */\n  ILAST = LUSOL->m;\n/*      Assume col n is last in the col file. */\n  JLAST = LUSOL->n;\n  LFILE = LUSOL->nelem;\n  LROW = LUSOL->nelem;\n  LCOL = LUSOL->nelem;\n  MINMN = MIN(LUSOL->m,LUSOL->n);\n  MAXMN = MAX(LUSOL->m,LUSOL->n);\n  NZLEFT = LUSOL->nelem;\n  NSPARE = 1;\n\n  if(KEEPLU)\n    LU1 = LENA2+1;\n  else {\n/*         Store only the diagonals of U in the top of memory. */\n#ifdef ClassicdiagU\n    LDIAGU = LENA2-LUSOL->n;\n    LU1 = LDIAGU+1;\n    LUSOL->diagU = LUSOL->a+LDIAGU;\n#else\n    LU1 = LENA2+1;\n#endif\n  }\n\n  LTOL = LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij];\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  USPACE = LUSOL->parmlu[LUSOL_RP_COMPSPACE_U];\n  DENS1 = LUSOL->parmlu[LUSOL_RP_MARKOWITZ_CONLY];\n  DENS2 = LUSOL->parmlu[LUSOL_RP_MARKOWITZ_DENSE];\n  UTRI = TRUE;\n  LTRI = FALSE;\n  SPARS1 = FALSE;\n  SPARS2 = FALSE;\n  DENSE = FALSE;\n/*      Check parameters. */\n  SETMAX(LTOL,1.0001E+0);\n  SETMIN(DENS1,DENS2);\n/*      Initialize output parameters.\n        lenL, lenU, minlen, mersum, nUtri, nLtri, ndens1, ndens2, nrank\n        are already initialized by lu1fac. */\n  *LMAX  = ZERO;\n  *UMAX  = ZERO;\n  *DUMAX = ZERO;\n  *DUMIN = LUSOL_BIGNUM;\n  if(LUSOL->nelem==0)\n    *DUMIN = ZERO;\n  *AKMAX = ZERO;\n  HOPS = 0;\n/*      More initialization.\n        Don't worry yet about lu1mxc. */\n  if(TPP || TSP) {\n    AIJMAX = ZERO;\n    AIJTOL = ZERO;\n    HLEN = 1;\n/*      TRP or TCP */\n  }\n  else {\n/*      Move biggest element to top of each column.\n        Set w(*) to mark slack columns (unit vectors). */\n    LU1MXC(LUSOL, 1,LUSOL->n,LUSOL->iq);\n    LU1SLK(LUSOL);\n  }\n  if(TRP)\n/*      Find biggest element in each row. */\n#ifdef ClassicHamaxR\n    LU1MXR(LUSOL, 1,LUSOL->m,LUSOL->ip,AMAXR);\n#else\n    LU1MXR(LUSOL, 1,LUSOL->m,LUSOL->ip,LUSOL->amaxr);\n#endif\n\n  if(TCP) {\n/*      Set Ha(1:Hlen) = biggest element in each column,\n            Hj(1:Hlen) = corresponding column indices. */\n    HLEN = 0;\n    for(KK = 1; KK <= LUSOL->n; KK++) {\n      HLEN++;\n      J = LUSOL->iq[KK];\n      LC = LUSOL->locc[J];\n#ifdef ClassicHamaxR\n      HA[HLEN] = fabs(LUSOL->a[LC]);\n      HJ[HLEN] = J;\n      HK[J] = HLEN;\n#else\n      LUSOL->Ha[HLEN] = fabs(LUSOL->a[LC]);\n      LUSOL->Hj[HLEN] = J;\n      LUSOL->Hk[J] = HLEN;\n#endif\n    }\n/*      Build the heap, creating new Ha, Hj and setting Hk(1:Hlen). */\n#ifdef ClassicHamaxR\n    HBUILD(HA,HJ,HK,HLEN,&HOPS);\n#else\n    HBUILD(LUSOL->Ha,LUSOL->Hj,LUSOL->Hk,HLEN,&HOPS);\n#endif\n  }\n/*      ------------------------------------------------------------------\n        Start of main loop.\n        ------------------------------------------------------------------ */\n  MLEFT = LUSOL->m+1;\n  NLEFT = LUSOL->n+1;\n  for(NROWU = 1; NROWU <= MINMN; NROWU++) {\n#ifdef UseTimer\n    mktime = (nrowu / ntime) + 4;\n    eltime = (nrowu / ntime) + 9;\n#endif\n    MLEFT--;\n    NLEFT--;\n/*         Bail out if there are no nonzero rows left. */\n    if(LUSOL->iploc[1]>LUSOL->m)\n      goto x900;\n/*      For TCP, the largest Aij is at the top of the heap. */\n   if(TCP) {\n/*\n              Marvelously easy */\n#ifdef ClassicHamaxR\n      AIJMAX = HA[1];\n#else\n      AIJMAX = LUSOL->Ha[1];\n#endif\n      SETMAX(*AKMAX,AIJMAX);\n      AIJTOL = AIJMAX/LTOL;\n    }\n/*         ===============================================================\n           Find a suitable pivot element.\n           =============================================================== */\n    if(UTRI) {\n/*            ------------------------------------------------------------\n              So far all columns have had length 1.\n              We are still looking for the (backward) triangular part of A\n              that forms the first rows and columns of U.\n              ------------------------------------------------------------ */\n      LQ1 = LUSOL->iqloc[1];\n      LQ2 = LUSOL->n;\n      if(LUSOL->m>1)\n        LQ2 = LUSOL->iqloc[2]-1;\n/*      There are more cols of length 1. */\n      if(LQ1<=LQ2) {\n        if(TPP || TSP) {\n/*      Grab the first one. */\n          JBEST = LUSOL->iq[LQ1];\n/*      Scan all columns of length 1 ... TRP or TCP */\n        }\n        else {\n          JBEST = 0;\n          for(LQ = LQ1; LQ <= LQ2; LQ++) {\n            J = LUSOL->iq[LQ];\n/*      Accept a slack */\n            if(LUSOL->w[J]>ZERO) {\n              JBEST = J;\n              goto x250;\n            }\n            LC = LUSOL->locc[J];\n            AMAX = fabs(LUSOL->a[LC]);\n            if(TRP) {\n              I = LUSOL->indc[LC];\n#ifdef ClassicHamaxR\n              AIJTOL = AMAXR[I]/LTOL;\n#else\n              AIJTOL = LUSOL->amaxr[I]/LTOL;\n#endif\n            }\n            if(AMAX>=AIJTOL) {\n              JBEST = J;\n              goto x250;\n            }\n          }\n        }\nx250:\n        if(JBEST>0) {\n          LC = LUSOL->locc[JBEST];\n          IBEST = LUSOL->indc[LC];\n          MBEST = 0;\n          goto x300;\n        }\n      }\n/*            This is the end of the U triangle.\n              We will not return to this part of the code.\n              TPP and TSP call lu1mxc for the first time\n              (to move biggest element to top of each column). */\n      if(LPRINT>=LUSOL_MSG_PIVOT)\n        LUSOL_report(LUSOL, 0, \"Utri ended.  spars1 = TRUE\\n\");\n      UTRI = FALSE;\n      LTRI = TRUE;\n      SPARS1 = TRUE;\n      *NUTRI = NROWU-1;\n      if(TPP || TSP)\n        LU1MXC(LUSOL, LQ1,LUSOL->n,LUSOL->iq);\n    }\n    if(SPARS1) {\n/*            ------------------------------------------------------------\n              Perform a Markowitz search.\n              Search cols of length 1, then rows of length 1,\n              then   cols of length 2, then rows of length 2, etc.\n              ------------------------------------------------------------ */\n#ifdef UseTimer\n        timer ( \"start\", mktime );\n#endif\n/*      12 Jun 2002: Next line disables lu1mCP below\n              if (TPP) then */\n      if(TPP || TCP) {\n        LU1MAR(LUSOL, MAXMN,TCP,AIJTOL,LTOL,MAXCOL,MAXROW,&IBEST,&JBEST,&MBEST);\n      }\n      else if(TRP) {\n#ifdef ClassicHamaxR\n        LU1MRP(LUSOL, MAXMN,LTOL,MAXCOL,MAXROW,&IBEST,&JBEST,&MBEST,AMAXR);\n#else\n        LU1MRP(LUSOL, MAXMN,LTOL,MAXCOL,MAXROW,&IBEST,&JBEST,&MBEST,LUSOL->amaxr);\n#endif\n/*      else if (TCP) {\n        lu1mCP( m    , n     , lena  , aijtol,\n                      ibest, jbest , mbest ,\n                      a    , indc  , indr  ,\n                      lenc , lenr  , locc  ,\n                      Hlen , Ha    , Hj    ) */\n      }\n      else if(TSP) {\n        LU1MSP(LUSOL, MAXMN,LTOL,MAXCOL,&IBEST,&JBEST,&MBEST);\n        if(IBEST==0)\n          goto x990;\n      }\n#ifdef UseTimer\n      timer ( \"finish\", mktime );\n#endif\n      if(LTRI) {\n/*               So far all rows have had length 1.\n                 We are still looking for the (forward) triangle of A\n                 that forms the first rows and columns of L. */\n        if(MBEST>0) {\n          LTRI = FALSE;\n          *NLTRI = NROWU-1-*NUTRI;\n          if(LPRINT>=LUSOL_MSG_PIVOT)\n            LUSOL_report(LUSOL, 0, \"Ltri ended.\\n\");\n        }\n      }\n      else {\n/*               See if what's left is as dense as dens1. */\n        if(NZLEFT>=(DENS1*MLEFT)*NLEFT) {\n          SPARS1 = FALSE;\n          SPARS2 = TRUE;\n          *NDENS1 = NLEFT;\n          MAXROW = 0;\n          if(LPRINT>=LUSOL_MSG_PIVOT)\n            LUSOL_report(LUSOL, 0, \"spars1 ended.  spars2 = TRUE\\n\");\n        }\n      }\n    }\n    else if(SPARS2 || DENSE) {\n/*            ------------------------------------------------------------\n              Perform a restricted Markowitz search,\n              looking at only the first maxcol columns.  (maxrow = 0.)\n              ------------------------------------------------------------ */\n#ifdef UseTimer\n      timer ( \"start\", mktime );\n#endif\n/*      12 Jun 2002: Next line disables lu1mCP below\n              if (TPP) then */\n      if(TPP || TCP) {\n        LU1MAR(LUSOL, MAXMN,TCP,AIJTOL,LTOL,MAXCOL,MAXROW,&IBEST,&JBEST,&MBEST);\n      }\n      else if(TRP) {\n#ifdef ClassicHamaxR\n        LU1MRP(LUSOL, MAXMN,LTOL,MAXCOL,MAXROW,&IBEST,&JBEST,&MBEST,AMAXR);\n#else\n        LU1MRP(LUSOL, MAXMN,LTOL,MAXCOL,MAXROW,&IBEST,&JBEST,&MBEST,LUSOL->amaxr);\n#endif\n/*      else if (TCP) {\n        lu1mCP( m    , n     , lena  , aijtol,\n                      ibest, jbest , mbest ,\n                      a    , indc  , indr  ,\n                      lenc , lenr  , locc  ,\n                      Hlen , Ha    , Hj    ) */\n      }\n      else if(TSP) {\n        LU1MSP(LUSOL, MAXMN,LTOL,MAXCOL,&IBEST,&JBEST,&MBEST);\n        if(IBEST==0)\n          goto x985;\n      }\n#ifdef UseTimer\n      timer ( \"finish\", mktime );\n#endif\n/*            See if what's left is as dense as dens2. */\n      if(SPARS2) {\n        if(NZLEFT>=(DENS2*MLEFT)*NLEFT) {\n          SPARS2 = FALSE;\n          DENSE = TRUE;\n          *NDENS2 = NLEFT;\n          MAXCOL = 1;\n          if(LPRINT>=LUSOL_MSG_PIVOT)\n            LUSOL_report(LUSOL, 0, \"spars2 ended.  dense = TRUE\\n\");\n        }\n      }\n    }\n/*         ---------------------------------------------------------------\n           See if we can finish quickly.\n           --------------------------------------------------------------- */\n    if(DENSE) {\n      LEND = MLEFT*NLEFT;\n      NFREE = LU1-1;\n      if(NFREE>=2*LEND) {\n/*               There is room to treat the remaining matrix as\n                 a dense matrix D.\n                 We may have to compress the column file first.\n                 12 Nov 1999: D used to be put at the\n                              beginning of free storage (lD = lcol + 1).\n                              Now put it at the end     (lD = lu1 - lenD)\n                              so the left-shift in lu1ful will not\n                              involve overlapping storage\n                              (fatal with parallel dcopy).\n   */\n        DENSLU = TRUE;\n        *NDENS2 = NLEFT;\n        LD = LU1-LEND;\n        if(LCOL>=LD) {\n          LU1REC(LUSOL, LUSOL->n,TRUE,&LCOL,\n                        LUSOL->indc,LUSOL->lenc,LUSOL->locc);\n          LFILE = LCOL;\n          JLAST = LUSOL->indc[LCOL+1];\n        }\n        goto x900;\n      }\n    }\n/*         ===============================================================\n           The best  aij  has been found.\n           The pivot row  ibest  and the pivot column  jbest\n           Define a dense matrix  D  of size  nrowd  by  ncold.\n           =============================================================== */\nx300:\n    NCOLD = LUSOL->lenr[IBEST];\n    NROWD = LUSOL->lenc[JBEST];\n    MELIM = NROWD-1;\n    NELIM = NCOLD-1;\n    (*MERSUM) += MBEST;\n    (*LENL) += MELIM;\n    (*LENU) += NCOLD;\n    if(LPRINT>=LUSOL_MSG_PIVOT) {\n      if(NROWU==1)\n        LUSOL_report(LUSOL, 0, \"lu1fad debug:\\n\");\n      if(TPP || TRP || TSP) {\n        LUSOL_report(LUSOL, 0, \"nrowu:%7d   i,jbest:%7d,%7d   nrowd,ncold:%6d,%6d\\n\",\n                            NROWU, IBEST,JBEST, NROWD,NCOLD);\n/*      TCP */\n      }\n      else {\n#ifdef ClassicHamaxR\n        JMAX = HJ[1];\n#else\n        JMAX = LUSOL->Hj[1];\n#endif\n        IMAX = LUSOL->indc[LUSOL->locc[JMAX]];\n        LUSOL_report(LUSOL, 0, \"nrowu:%7d   i,jbest:%7d,%7d   nrowd,ncold:%6d,%6d   i,jmax:%7d,%7d   aijmax:%g\\n\",\n                            NROWU, IBEST,JBEST, NROWD,NCOLD, IMAX,JMAX, AIJMAX);\n      }\n    }\n/*         ===============================================================\n           Allocate storage for the next column of  L  and next row of  U.\n           Initially the top of a, indc, indr are used as follows:\n                      ncold       melim       ncold        melim\n           a      |...........|...........|ujbest..ujn|li1......lim|\n           indc   |...........|  lenr(i)  |  lenc(j)  |  markl(i)  |\n           indr   |...........| iqloc(i)  |  jfill(j) |  ifill(i)  |\n                 ^           ^             ^           ^            ^\n                 lfree   lsave             lu1         ll1          oldlu1\n           Later the correct indices are inserted:\n           indc   |           |           |           |i1........im|\n           indr   |           |           |jbest....jn|ibest..ibest|\n           =============================================================== */\n    if(!KEEPLU) {\n/*            Always point to the top spot.\n              Only the current column of L and row of U will\n              take up space, overwriting the previous ones. */\n#ifdef ClassicHamaxR\n      LU1 = LDIAGU+1;\n#else\n      LU1 = LENA2+1;\n#endif\n    }\n    /* Update (left-shift) pointers to make room for the new data */\n    LL1 = LU1-MELIM;\n    LU1 = LL1-NCOLD;\n    LSAVE = LU1-NROWD;\n    LFREE = LSAVE-NCOLD;\n\n    /* Check if we need to allocate more memory, and allocate if necessary */\n#if 0  /* Proposal by Michael A. Saunders (logic based on Markowitz' rule) */\n    L = NROWD*NCOLD;\n\n    /* Try to avoid future expansions by anticipating further updates - KE extension */\n    if(LUSOL->luparm[LUSOL_IP_UPDATELIMIT] > 0)\n#if 1\n      L *= (int) (log(LUSOL->luparm[LUSOL_IP_UPDATELIMIT]-LUSOL->luparm[LUSOL_IP_UPDATECOUNT]+2.0) + 1);\n#else\n      L *= (LUSOL->luparm[LUSOL_IP_UPDATELIMIT]-LUSOL->luparm[LUSOL_IP_UPDATECOUNT]) / 2 + 1;\n#endif\n\n#else  /* Version by Kjell Eikland (from luparm[LUSOL_IP_MINIMUMLENA] and safety margin) */\n    L  = (KEEPLU ? MAX(LROW, LCOL) + 2*(LUSOL->m+LUSOL->n) : 0);\n    L *= LUSOL_MULT_nz_a;\n    SETMAX(L, NROWD*NCOLD);\n#endif\n\n    /* Do the memory expansion */\n    if((L > LFREE-LCOL) && LUSOL_expand_a(LUSOL, &L, &LFREE)) {\n      LL1   += L;\n      LU1   += L;\n      LSAVE += L;\n#ifdef ClassicdiagU\n      LUSOL->diagU += L;\n#endif\n#ifdef ClassicHamaxR\n      HA    += L;\n      HJ    += L;\n      HK    += L;\n      AMAXR += L;\n#endif\n    }\n    LIMIT = (int) (USPACE*LFILE)+LUSOL->m+LUSOL->n+1000;\n\n/*         Make sure the column file has room.\n           Also force a compression if its length exceeds a certain limit. */\n#ifdef StaticMemAlloc\n    MINFRE = NCOLD+MELIM;\n#else\n    MINFRE = NROWD*NCOLD;\n#endif\n    NFREE = LFREE-LCOL;\n    if(NFREE<MINFRE || LCOL>LIMIT) {\n      LU1REC(LUSOL, LUSOL->n,TRUE,&LCOL,\n                    LUSOL->indc,LUSOL->lenc,LUSOL->locc);\n      LFILE = LCOL;\n      JLAST = LUSOL->indc[LCOL+1];\n      NFREE = LFREE-LCOL;\n      if(NFREE<MINFRE)\n        goto x970;\n    }\n/*         Make sure the row file has room. */\n#ifdef StaticMemAlloc\n    MINFRE = NCOLD+MELIM;\n#else\n    MINFRE = NROWD*NCOLD;\n#endif\n    NFREE = LFREE-LROW;\n    if(NFREE<MINFRE || LROW>LIMIT) {\n      LU1REC(LUSOL, LUSOL->m,FALSE,&LROW,\n                    LUSOL->indr,LUSOL->lenr,LUSOL->locr);\n      LFILE = LROW;\n      ILAST = LUSOL->indr[LROW+1];\n      NFREE = LFREE-LROW;\n      if(NFREE<MINFRE)\n        goto x970;\n    }\n/*         ===============================================================\n           Move the pivot element to the front of its row\n           and to the top of its column.\n           =============================================================== */\n    LPIVR = LUSOL->locr[IBEST];\n    LPIVR1 = LPIVR+1;\n    LPIVR2 = LPIVR+NELIM;\n    for(L = LPIVR; L <= LPIVR2; L++) {\n      if(LUSOL->indr[L]==JBEST)\n        break;\n    }\n\n    LUSOL->indr[L] = LUSOL->indr[LPIVR];\n    LUSOL->indr[LPIVR] = JBEST;\n    LPIVC = LUSOL->locc[JBEST];\n    LPIVC1 = LPIVC+1;\n    LPIVC2 = LPIVC+MELIM;\n    for(L = LPIVC; L <= LPIVC2; L++) {\n      if(LUSOL->indc[L]==IBEST)\n        break;\n    }\n    LUSOL->indc[L] = LUSOL->indc[LPIVC];\n    LUSOL->indc[LPIVC] = IBEST;\n    ABEST = LUSOL->a[L];\n    LUSOL->a[L] = LUSOL->a[LPIVC];\n    LUSOL->a[LPIVC] = ABEST;\n    if(!KEEPLU)\n/*            Store just the diagonal of U, in natural order.\n   !!         a[ldiagU + nrowu] = abest ! This was in pivot order. */\n      LUSOL->diagU[JBEST] = ABEST;\n\n/*     ==============================================================\n        Delete pivot col from heap.\n        Hk tells us where it is in the heap.\n       ============================================================== */\n    if(TCP) {\n#ifdef ClassicHamaxR\n      KBEST = HK[JBEST];\n      HDELETE(HA,HJ,HK,&HLEN,KBEST,&H);\n#else\n      KBEST = LUSOL->Hk[JBEST];\n      HDELETE(LUSOL->Ha,LUSOL->Hj,LUSOL->Hk,&HLEN,KBEST,&H);\n#endif\n      HOPS += H;\n    }\n/*         ===============================================================\n           Delete the pivot row from the column file\n           and store it as the next row of  U.\n           set  indr(lu) = 0     to initialize jfill ptrs on columns of D,\n                indc(lu) = lenj  to save the original column lengths.\n           =============================================================== */\n    LUSOL->a[LU1] = ABEST;\n    LUSOL->indr[LU1] = JBEST;\n    LUSOL->indc[LU1] = NROWD;\n    LU = LU1;\n    DIAG = fabs(ABEST);\n    SETMAX(*UMAX,DIAG);\n    SETMAX(*DUMAX,DIAG);\n    SETMIN(*DUMIN,DIAG);\n    for(LR = LPIVR1; LR <= LPIVR2; LR++) {\n      LU++;\n      J = LUSOL->indr[LR];\n      LENJ = LUSOL->lenc[J];\n      LUSOL->lenc[J] = LENJ-1;\n      LC1 = LUSOL->locc[J];\n      LAST = LC1+LUSOL->lenc[J];\n      for(L = LC1; L <= LAST; L++) {\n        if(LUSOL->indc[L]==IBEST)\n          break;\n      }\n      LUSOL->a[LU] = LUSOL->a[L];\n      LUSOL->indr[LU] = 0;\n      LUSOL->indc[LU] = LENJ;\n      SETMAX(*UMAX,fabs(LUSOL->a[LU]));\n      LUSOL->a[L] = LUSOL->a[LAST];\n      LUSOL->indc[L] = LUSOL->indc[LAST];\n/*      Free entry */\n      LUSOL->indc[LAST] = 0;\n/* ???        if (j .eq. jlast) lcol = lcol - 1 */\n    }\n/*         ===============================================================\n           Delete the pivot column from the row file\n           and store the nonzeros of the next column of  L.\n           Set  indc(ll) = 0     to initialize markl(*) markers,\n                indr(ll) = 0     to initialize ifill(*) row fill-in cntrs,\n                indc(ls) = leni  to save the original row lengths,\n                indr(ls) = iqloc(i)    to save parts of  iqloc(*),\n                iqloc(i) = lsave - ls  to point to the nonzeros of  L\n                         = -1, -2, -3, ... in mark(*).\n           =============================================================== */\n    LUSOL->indc[LSAVE] = NCOLD;\n    if(MELIM==0)\n      goto x700;\n    LL = LL1-1;\n    LS = LSAVE;\n    ABEST = ONE/ABEST;\n    for(LC = LPIVC1; LC <= LPIVC2; LC++) {\n      LL++;\n      LS++;\n      I = LUSOL->indc[LC];\n      LENI = LUSOL->lenr[I];\n      LUSOL->lenr[I] = LENI-1;\n      LR1 = LUSOL->locr[I];\n      LAST = LR1+LUSOL->lenr[I];\n      for(L = LR1; L <= LAST; L++) {\n        if(LUSOL->indr[L]==JBEST)\n          break;\n      }\n      LUSOL->indr[L] = LUSOL->indr[LAST];\n/*      Free entry */\n      LUSOL->indr[LAST] = 0;\n      LUSOL->a[LL] = -LUSOL->a[LC]*ABEST;\n      LIJ = fabs(LUSOL->a[LL]);\n      SETMAX(*LMAX,LIJ);\n      LUSOL->indc[LL] = 0;\n      LUSOL->indr[LL] = 0;\n      LUSOL->indc[LS] = LENI;\n      LUSOL->indr[LS] = LUSOL->iqloc[I];\n      LUSOL->iqloc[I] = LSAVE-LS;\n    }\n/*         ===============================================================\n           Do the Gaussian elimination.\n           This involves adding a multiple of the pivot column\n           to all other columns in the pivot row.\n           Sometimes more than one call to lu1gau is needed to allow\n           compression of the column file.\n           lfirst  says which column the elimination should start with.\n           minfre  is a bound on the storage needed for any one column.\n           lu      points to off-diagonals of u.\n           nfill   keeps track of pending fill-in in the row file.\n           =============================================================== */\n    if(NELIM==0)\n      goto x700;\n    LFIRST = LPIVR1;\n    MINFRE = MLEFT+NSPARE;\n    LU = 1;\n    NFILL = 0;\n\nx400:\n#ifdef UseTimer\n    timer ( \"start\", eltime );\n#endif\n    LU1GAU(LUSOL, MELIM,NSPARE,SMALL,LPIVC1,LPIVC2,&LFIRST,LPIVR2,\n           LFREE,MINFRE,ILAST,&JLAST,&LROW,&LCOL,&LU,&NFILL,\n           LUSOL->iqloc, LUSOL->a+LL1-LUSOL_ARRAYOFFSET,\n           LUSOL->indc+LL1-LUSOL_ARRAYOFFSET, LUSOL->a+LU1-LUSOL_ARRAYOFFSET,\n           LUSOL->indr+LL1-LUSOL_ARRAYOFFSET, LUSOL->indr+LU1-LUSOL_ARRAYOFFSET);\n#ifdef UseTimer\n    timer ( \"finish\", eltime );\n#endif\n    if(LFIRST>0) {\n/*            The elimination was interrupted.\n              Compress the column file and try again.\n              lfirst, lu and nfill have appropriate new values. */\n      LU1REC(LUSOL, LUSOL->n,TRUE,&LCOL,\n                    LUSOL->indc,LUSOL->lenc,LUSOL->locc);\n      LFILE = LCOL;\n      JLAST = LUSOL->indc[LCOL+1];\n      LPIVC = LUSOL->locc[JBEST];\n      LPIVC1 = LPIVC+1;\n      LPIVC2 = LPIVC+MELIM;\n      NFREE = LFREE-LCOL;\n      if(NFREE<MINFRE) {\n          goto x970;\n      }\n      goto x400;\n    }\n/*         ===============================================================\n           The column file has been fully updated.\n           Deal with any pending fill-in in the row file.\n           =============================================================== */\n    if(NFILL>0) {\n/*            Compress the row file if necessary.\n              lu1gau has set nfill to be the number of pending fill-ins\n              plus the current length of any rows that need to be moved. */\n      MINFRE = NFILL;\n      NFREE = LFREE-LROW;\n      if(NFREE<MINFRE) {\n        LU1REC(LUSOL, LUSOL->m,FALSE,&LROW,\n                      LUSOL->indr,LUSOL->lenr,LUSOL->locr);\n        LFILE = LROW;\n        ILAST = LUSOL->indr[LROW+1];\n        LPIVR = LUSOL->locr[IBEST];\n        LPIVR1 = LPIVR+1;\n        LPIVR2 = LPIVR+NELIM;\n        NFREE = LFREE-LROW;\n        if(NFREE<MINFRE) {\n            goto x970;\n        }\n      }\n/*            Move rows that have pending fill-in to end of the row file.\n              Then insert the fill-in. */\n      LU1PEN(LUSOL, NSPARE,&ILAST,\n             LPIVC1,LPIVC2,LPIVR1,LPIVR2,\n             &LROW,LUSOL->indr+LL1-LUSOL_ARRAYOFFSET,LUSOL->indr+LU1-LUSOL_ARRAYOFFSET);\n    }\n/*         ===============================================================\n           Restore the saved values of  iqloc.\n           Insert the correct indices for the col of L and the row of U.\n           =============================================================== */\nx700:\n    LUSOL->lenr[IBEST] = 0;\n    LUSOL->lenc[JBEST] = 0;\n    LL = LL1-1;\n    LS = LSAVE;\n    for(LC = LPIVC1; LC <= LPIVC2; LC++) {\n      LL++;\n      LS++;\n      I = LUSOL->indc[LC];\n      LUSOL->iqloc[I] = LUSOL->indr[LS];\n      LUSOL->indc[LL] = I;\n      LUSOL->indr[LL] = IBEST;\n    }\n    LU = LU1-1;\n    for(LR = LPIVR; LR <= LPIVR2; LR++) {\n      LU++;\n      LUSOL->indr[LU] = LUSOL->indr[LR];\n    }\n/*         ===============================================================\n           Free the space occupied by the pivot row\n           and update the column permutation.\n           Then free the space occupied by the pivot column\n           and update the row permutation.\n           nzchng is found in both calls to lu1pq2, but we use it only\n           after the second.\n           =============================================================== */\n    LU1PQ2(LUSOL, NCOLD, &NZCHNG,\n           LUSOL->indr+LPIVR-LUSOL_ARRAYOFFSET,\n           LUSOL->indc+LU1-LUSOL_ARRAYOFFSET, LUSOL->lenc,\n           LUSOL->iqloc, LUSOL->iq, LUSOL->iqinv);\n    LU1PQ2(LUSOL, NROWD, &NZCHNG,\n           LUSOL->indc+LPIVC-LUSOL_ARRAYOFFSET,\n           LUSOL->indc+LSAVE-LUSOL_ARRAYOFFSET, LUSOL->lenr,\n           LUSOL->iploc, LUSOL->ip, LUSOL->ipinv);\n    NZLEFT += NZCHNG;\n\n/*         ===============================================================\n           lu1mxr resets Amaxr(i) in each modified row i.\n           lu1mxc moves the largest aij to the top of each modified col j.\n           28 Jun 2002: Note that cols of L have an implicit diag of 1.0,\n                        so lu1mxr is called with ll1, not ll1+1, whereas\n                           lu1mxc is called with          lu1+1.\n           =============================================================== */\n    if(UTRI && TPP) {\n/*      Relax -- we're not keeping big elements at the top yet. */\n    }\n    else {\n      if(TRP && MELIM>0)\n#ifdef ClassicHamaxR\n        LU1MXR(LUSOL, LL1,LL,LUSOL->indc,AMAXR);\n#else\n        LU1MXR(LUSOL, LL1,LL,LUSOL->indc,LUSOL->amaxr);\n#endif\n\n      if(NELIM>0) {\n        LU1MXC(LUSOL, LU1+1,LU,LUSOL->indr);\n/*      Update modified columns in heap */\n        if(TCP) {\n          for(KK = LU1+1; KK <= LU; KK++) {\n            J = LUSOL->indr[KK];\n#ifdef ClassicHamaxR\n            K = HK[J];\n#else\n            K = LUSOL->Hk[J];\n#endif\n/*      Biggest aij in column j */\n            V = fabs(LUSOL->a[LUSOL->locc[J]]);\n#ifdef ClassicHamaxR\n            HCHANGE(HA,HJ,HK,HLEN,K,V,J,&H);\n#else\n            HCHANGE(LUSOL->Ha,LUSOL->Hj,LUSOL->Hk,HLEN,K,V,J,&H);\n#endif\n            HOPS += H;\n          }\n        }\n      }\n    }\n/*         ===============================================================\n           Negate lengths of pivot row and column so they will be\n           eliminated during compressions.\n           =============================================================== */\n    LUSOL->lenr[IBEST] = -NCOLD;\n    LUSOL->lenc[JBEST] = -NROWD;\n\n/*         Test for fatal bug: row or column lists overwriting L and U. */\n    if(LROW>LSAVE || LCOL>LSAVE)\n      goto x980;\n\n/*         Reset the file lengths if pivot row or col was at the end. */\n    if(IBEST==ILAST)\n      LROW = LUSOL->locr[IBEST];\n\n    if(JBEST==JLAST)\n      LCOL = LUSOL->locc[JBEST];\n\n  }\n/*      ------------------------------------------------------------------\n        End of main loop.\n        ------------------------------------------------------------------\n        ------------------------------------------------------------------\n        Normal exit.\n        Move empty rows and cols to the end of ip, iq.\n        Then finish with a dense LU if necessary.\n        ------------------------------------------------------------------ */\nx900:\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  LU1PQ3(LUSOL, LUSOL->m,LUSOL->lenr,LUSOL->ip,LUSOL->ipinv,&MRANK);\n  LU1PQ3(LUSOL, LUSOL->n,LUSOL->lenc,LUSOL->iq,LUSOL->iqinv,NRANK);\n  SETMIN(*NRANK, MRANK);\n  if(DENSLU) {\n#ifdef UseTimer\n    timer ( \"start\", 17 );\n#endif\n    LU1FUL(LUSOL, LEND,LU1,TPP,MLEFT,NLEFT,*NRANK,NROWU,LENL,LENU,\n           &NSING,KEEPLU,SMALL,LUSOL->a+LD-LUSOL_ARRAYOFFSET,LUSOL->locr);\n/* ***     21 Dec 1994: Bug in next line.\n   ***     nrank  = nrank - nsing */\n    *NRANK = MINMN-NSING;\n#ifdef UseTimer\n    timer ( \"finish\", 17 );\n#endif\n  }\n  *MINLEN = (*LENL)+(*LENU)+2*(LUSOL->m+LUSOL->n);\n  goto x990;\n/*      Not enough space free after a compress.\n        Set  minlen  to an estimate of the necessary value of  lena. */\nx970:\n  *INFORM = LUSOL_INFORM_ANEEDMEM;\n  *MINLEN = LENA2+LFILE+2*(LUSOL->m+LUSOL->n);\n  goto x990;\n/*      Fatal error.  This will never happen!\n       (Famous last words.) */\nx980:\n  *INFORM = LUSOL_INFORM_FATALERR;\n  goto x990;\n/*      Fatal error with TSP.  Diagonal pivot not found. */\nx985:\n  *INFORM = LUSOL_INFORM_NOPIVOT;\n/*      Exit. */\nx990:\n#ifdef UseTimer\n  timer ( \"finish\", 3 );\n#endif\n;\n}\n\n\n/* ==================================================================\n   lu1fac computes a factorization A = L*U, where A is a sparse\n   matrix with m rows and n columns, P*L*P' is lower triangular\n   and P*U*Q is upper triangular for certain permutations P, Q\n   (which are returned in the arrays ip, iq).\n   Stability is ensured by limiting the size of the elements of L.\n   The nonzeros of A are input via the parallel arrays a, indc, indr,\n   which should contain nelem entries of the form    aij,    i,    j\n   in any order.  There should be no duplicate pairs         i,    j.\n\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   +        Beware !!!   The row indices i must be in indc,         +\n   +              and the column indices j must be in indr.         +\n   +              (Not the other way round!)                        +\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n   It does not matter if some of the entries in a(*) are zero.\n   Entries satisfying  abs( a(i) ) .le. parmlu(3)  are ignored.\n   Other parameters in luparm and parmlu are described below.\n   The matrix A may be singular.  On exit, nsing = luparm(11) gives\n   the number of apparent singularities.  This is the number of\n   \"small\" diagonals of the permuted factor U, as judged by\n   the input tolerances Utol1 = parmlu(4) and  Utol2 = parmlu(5).\n   The diagonal element diagj associated with column j of A is\n   \"small\" if\n               abs( diagj ) .le. Utol1\n   or\n               abs( diagj ) .le. Utol2 * max( uj ),\n   where max( uj ) is the maximum element in the j-th column of U.\n   The position of such elements is returned in w(*).  In general,\n   w(j) = + max( uj ),  but if column j is a singularity,\n   w(j) = - max( uj ).  Thus, w(j) .le. 0 if column j appears to be\n   dependent on the other columns of A.\n   NOTE: lu1fac (like certain other sparse LU packages) does not\n   treat dense columns efficiently.  This means it will be slow\n   on \"arrow matrices\" of the form\n                A = (x       a)\n                    (  x     b)\n                    (    x   c)\n                    (      x d)\n                    (x x x x e)\n   if the numerical values in the dense column allow it to be\n   chosen LATE in the pivot order.\n   With TPP (Threshold Partial Pivoting), the dense column is\n   likely to be chosen late.\n   With TCP (Threshold Complete Pivoting), if any of a,b,c,d\n   is significantly larger than other elements of A, it will\n   be chosen as the first pivot and the dense column will be\n   eliminated, giving reasonably sparse factors.\n   However, if element e is so big that TCP chooses it, the factors\n   will become dense.  (It's hard to win on these examples!)\n   ------------------------------------------------------------------\n\n   Notes on the array names\n   ------------------------\n   During the LU factorization, the sparsity pattern of the matrix\n   being factored is stored twice: in a column list and a row list.\n   The column list is ( a, indc, locc, lenc )\n   where\n         a(*)    holds the nonzeros,\n         indc(*) holds the indices for the column list,\n         locc(j) points to the start of column j in a(*) and indc(*),\n         lenc(j) is the number of nonzeros in column j.\n   The row list is    (    indr, locr, lenr )\n   where\n         indr(*) holds the indices for the row list,\n         locr(i) points to the start of row i in indr(*),\n         lenr(i) is the number of nonzeros in row i.\n   At all stages of the LU factorization, ip contains a complete\n   row permutation.  At the start of stage k,  ip(1), ..., ip(k-1)\n   are the first k-1 rows of the final row permutation P.\n   The remaining rows are stored in an ordered list\n                        ( ip, iploc, ipinv )\n   where\n         iploc(nz) points to the start in ip(*) of the set of rows\n                   that currently contain nz nonzeros,\n         ipinv(i)  points to the position of row i in ip(*).\n   For example,\n         iploc(1) = k   (and this is where rows of length 1 {),\n         iploc(2) = k+p  if there are p rows of length 1\n                        (and this is where rows of length 2 {).\n   Similarly for iq, iqloc, iqinv.\n   ---------------------------------------------------------------------\n   INPUT PARAMETERS\n   m      (not altered) is the number of rows in A.\n   n      (not altered) is the number of columns in A.\n   nelem  (not altered) is the number of matrix entries given in\n          the arrays a, indc, indr.\n   lena   (not altered) is the dimension of  a, indc, indr.\n          This should be significantly larger than nelem.\n          Typically one should have\n             lena > max( 2*nelem, 10*m, 10*n, 10000 )\n          but some applications may need more.\n          On machines with virtual memory it is safe to have\n          lena \"far bigger than necessary\", since not all of the\n          arrays will be used.\n   a      (overwritten) contains entries   Aij  in   a(1:nelem).\n   indc   (overwritten) contains the indices i in indc(1:nelem).\n   indr   (overwritten) contains the indices j in indr(1:nelem).\n   luparm input parameters:                                Typical value\n   luparm( 1) = nout     File number for printed messages.         6\n   luparm( 2) = lprint   Print level.                              0\n                    <  0 suppresses output.\n                    =  0 gives error messages.\n                   >= 10 gives statistics about the LU factors.\n                   >= 50 gives debug output from lu1fac\n                         (the pivot row and column and the\n                         no. of rows and columns involved at\n                         each elimination step).\n   luparm( 3) = maxcol   lu1fac: maximum number of columns         5\n                         searched allowed in a Markowitz-type\n                         search for the next pivot element.\n                         For some of the factorization, the\n                         number of rows searched is\n                         maxrow = maxcol - 1.\n   luparm( 6) = 0    =>  TPP: Threshold Partial   Pivoting.        0\n              = 1    =>  TRP: Threshold Rook      Pivoting.\n              = 2    =>  TCP: Threshold Complete  Pivoting.\n              = 3    =>  TSP: Threshold Symmetric Pivoting.\n              = 4    =>  TDP: Threshold Diagonal  Pivoting.\n                              (TDP not yet implemented).\n                         TRP and TCP are more expensive than TPP but\n                         more stable and better at revealing rank.\n                         Take care with setting parmlu(1), especially\n                         with TCP.\n                         NOTE: TSP and TDP are for symmetric matrices\n                         that are either definite or quasi-definite.\n                         TSP is effectively TRP for symmetric matrices.\n                         TDP is effectively TCP for symmetric matrices.\n   luparm( 8) = keepLU   lu1fac: keepLU = 1 means the numerical    1\n                         factors will be computed if possible.\n                         keepLU = 0 means L and U will be discarded\n                         but other information such as the row and\n                         column permutations will be returned.\n                         The latter option requires less storage.\n   parmlu input parameters:                                Typical value\n   parmlu( 1) = Ltol1    Max Lij allowed during Factor.\n                                                   TPP     10.0 or 100.0\n                                                   TRP      4.0 or  10.0\n                                                   TCP      5.0 or  10.0\n                                                   TSP      4.0 or  10.0\n                         With TRP and TCP (Rook and Complete Pivoting),\n                         values less than 25.0 may be expensive\n                         on badly scaled data.  However,\n                         values less than 10.0 may be needed\n                         to obtain a reliable rank-revealing\n                         factorization.\n   parmlu( 2) = Ltol2    Max Lij allowed during Updates.            10.0\n                         during updates.\n   parmlu( 3) = small    Absolute tolerance for       eps**0.8 = 3.0d-13\n                         treating reals as zero.\n   parmlu( 4) = Utol1    Absolute tol for flagging    eps**0.67= 3.7d-11\n                         small diagonals of U.\n   parmlu( 5) = Utol2    Relative tol for flagging    eps**0.67= 3.7d-11\n                         small diagonals of U.\n                         (eps = machine precision)\n   parmlu( 6) = Uspace   Factor limiting waste space in  U.      3.0\n                         In lu1fac, the row or column lists\n                         are compressed if their length\n                         exceeds Uspace times the length of\n                         either file after the last compression.\n   parmlu( 7) = dens1    The density at which the Markowitz      0.3\n                         pivot strategy should search maxcol\n                         columns and no rows.\n                         (Use 0.3 unless you are experimenting\n                         with the pivot strategy.)\n   parmlu( 8) = dens2    the density at which the Markowitz      0.5\n                         strategy should search only 1 column,\n                         or (if storage is available)\n                         the density at which all remaining\n                         rows and columns will be processed\n                         by a dense LU code.\n                         For example, if dens2 = 0.1 and lena is\n                         large enough, a dense LU will be used\n                         once more than 10 per cent of the\n                         remaining matrix is nonzero.\n\n   OUTPUT PARAMETERS\n   a, indc, indr     contain the nonzero entries in the LU factors of A.\n          If keepLU = 1, they are in a form suitable for use\n          by other parts of the LUSOL package, such as lu6sol.\n          U is stored by rows at the start of a, indr.\n          L is stored by cols at the end   of a, indc.\n          If keepLU = 0, only the diagonals of U are stored, at the\n          end of a.\n   ip, iq    are the row and column permutations defining the\n          pivot order.  For example, row ip(1) and column iq(1)\n          defines the first diagonal of U.\n   lenc(1:numl0) contains the number of entries in nontrivial\n          columns of L (in pivot order).\n   lenr(1:m) contains the number of entries in each row of U\n          (in original order).\n   locc(1:n) = 0 (ready for the LU update routines).\n   locr(1:m) points to the beginning of the rows of U in a, indr.\n   iploc, iqloc, ipinv, iqinv  are undefined.\n   w      indicates singularity as described above.\n   inform = 0 if the LU factors were obtained successfully.\n          = 1 if U appears to be singular, as judged by lu6chk.\n          = 3 if some index pair indc(l), indr(l) lies outside\n              the matrix dimensions 1:m , 1:n.\n          = 4 if some index pair indc(l), indr(l) duplicates\n              another such pair.\n          = 7 if the arrays a, indc, indr were not large enough.\n              Their length \"lena\" should be increase to at least\n              the value \"minlen\" given in luparm(13).\n          = 8 if there was some other fatal error.  (Shouldn't happen!)\n          = 9 if no diagonal pivot could be found with TSP or TDP.\n              The matrix must not be sufficiently definite\n              or quasi-definite.\n   luparm output parameters:\n   luparm(10) = inform   Return code from last call to any LU routine.\n   luparm(11) = nsing    No. of singularities marked in the\n                         output array w(*).\n   luparm(12) = jsing    Column index of last singularity.\n   luparm(13) = minlen   Minimum recommended value for  lena.\n   luparm(14) = maxlen   ?\n   luparm(15) = nupdat   No. of updates performed by the lu8 routines.\n   luparm(16) = nrank    No. of nonempty rows of U.\n   luparm(17) = ndens1   No. of columns remaining when the density of\n                         the matrix being factorized reached dens1.\n   luparm(18) = ndens2   No. of columns remaining when the density of\n                         the matrix being factorized reached dens2.\n   luparm(19) = jumin    The column index associated with DUmin.\n   luparm(20) = numL0    No. of columns in initial  L.\n   luparm(21) = lenL0    Size of initial  L  (no. of nonzeros).\n   luparm(22) = lenU0    Size of initial  U.\n   luparm(23) = lenL     Size of current  L.\n   luparm(24) = lenU     Size of current  U.\n   luparm(25) = lrow     Length of row file.\n   luparm(26) = ncp      No. of compressions of LU data structures.\n   luparm(27) = mersum   lu1fac: sum of Markowitz merit counts.\n   luparm(28) = nUtri    lu1fac: triangular rows in U.\n   luparm(29) = nLtri    lu1fac: triangular rows in L.\n   luparm(30) =\n   parmlu output parameters:\n   parmlu(10) = Amax     Maximum element in  A.\n   parmlu(11) = Lmax     Maximum multiplier in current  L.\n   parmlu(12) = Umax     Maximum element in current  U.\n   parmlu(13) = DUmax    Maximum diagonal in  U.\n   parmlu(14) = DUmin    Minimum diagonal in  U.\n   parmlu(15) = Akmax    Maximum element generated at any stage\n                         during TCP factorization.\n   parmlu(16) = growth   TPP: Umax/Amax    TRP, TCP, TSP: Akmax/Amax\n   parmlu(17) =\n   parmlu(18) =\n   parmlu(19) =\n   parmlu(20) = resid    lu6sol: residual after solve with U or U'.\n   ...\n   parmlu(30) =\n   ------------------------------------------------------------------\n   00 Jun 1983  Original version.\n   00 Jul 1987  nrank  saved in luparm(16).\n   12 Apr 1989  ipinv, iqinv added as workspace.\n   26 Apr 1989  maxtie replaced by maxcol in Markowitz search.\n   16 Mar 1992  jumin  saved in luparm(19).\n   10 Jun 1992  lu1fad has to move empty rows and cols to the bottom\n                (via lu1pq3) before doing the dense LU.\n   12 Jun 1992  Deleted dense LU (lu1ful, lu1vlu).\n   25 Oct 1993  keepLU implemented.\n   07 Feb 1994  Added new dense LU (lu1ful, lu1den).\n   21 Dec 1994  Bugs fixed in lu1fad (nrank) and lu1ful (ipvt).\n   08 Aug 1995  Use ip instead of w as parameter to lu1or3 (for F90).\n   13 Sep 2000  TPP and TCP options implemented.\n   17 Oct 2000  Fixed troubles due to A = empty matrix (Todd Munson).\n   01 Dec 2000  Save Lmax, Umax, etc. after both lu1fad and lu6chk.\n                lu1fad sets them when keepLU = false.\n                lu6chk sets them otherwise, and includes items\n                from the dense LU.\n   11 Mar 2001  lu6chk now looks at diag(U) when keepLU = false.\n   26 Apr 2002  New TCP implementation using heap routines to\n                store largest element in each column.\n                New workspace arrays Ha, Hj, Hk required.\n                For compatibility, borrow space from a, indc, indr\n                rather than adding new input parameters.\n   01 May 2002  lu1den changed to lu1DPP (dense partial  pivoting).\n                lu1DCP implemented       (dense complete pivoting).\n                Both TPP and TCP now switch to dense mode and end.\n   ================================================================== */\nvoid LU1FAC(LUSOLrec *LUSOL, int *INFORM)\n{\n  MYBOOL  KEEPLU, TCP, TPP, TRP, TSP;\n  int     LPIV, NELEM0, LPRINT, MINLEN, NUML0, LENL, LENU, LROW, MERSUM,\n          NUTRI, NLTRI, NDENS1, NDENS2, NRANK, NSING, JSING, JUMIN, NUMNZ, LERR,\n          LU, LL, LM, LTOPL, K, I, LENUK, J, LENLK, IDUMMY, LLSAVE, NMOVE, L2, L, NCP, NBUMP;\n#ifdef ClassicHamaxR\n  int     LENH, LENA2, LOCH, LMAXR;\n#endif\n\n  REAL    LMAX, LTOL, SMALL, AMAX, UMAX, DUMAX, DUMIN, AKMAX, DM, DN, DELEM, DENSTY,\n          AGRWTH, UGRWTH, GROWTH, CONDU, DINCR, AVGMER;\n\n/*      Free row-based version of L0 (regenerated by LUSOL_btran). */\n  if(LUSOL->L0 != NULL)\n    LUSOL_matfree(&(LUSOL->L0));\n\n/*      Grab relevant input parameters. */\n  NELEM0 = LUSOL->nelem;\n  LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL];\n  LPIV   = LUSOL->luparm[LUSOL_IP_PIVOTTYPE];\n  KEEPLU = (MYBOOL) (LUSOL->luparm[LUSOL_IP_KEEPLU]!=FALSE);\n/*      Limit on size of Lij */\n  LTOL   = LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij];\n/*      Drop tolerance */\n  SMALL  = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  TPP = (MYBOOL) (LPIV==LUSOL_PIVMOD_TPP);\n  TRP = (MYBOOL) (LPIV==LUSOL_PIVMOD_TRP);\n  TCP = (MYBOOL) (LPIV==LUSOL_PIVMOD_TCP);\n  TSP = (MYBOOL) (LPIV==LUSOL_PIVMOD_TSP);\n/*      Initialize output parameters. */\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  LERR   = 0;\n  MINLEN = LUSOL->nelem + 2*(LUSOL->m+LUSOL->n);\n  NUML0  = 0;\n  LENL   = 0;\n  LENU   = 0;\n  LROW   = 0;\n  MERSUM = 0;\n  NUTRI  = LUSOL->m;\n  NLTRI  = 0;\n  NDENS1 = 0;\n  NDENS2 = 0;\n  NRANK  = 0;\n  NSING  = 0;\n  JSING  = 0;\n  JUMIN  = 0;\n  AMAX   = ZERO;\n  LMAX   = ZERO;\n  UMAX   = ZERO;\n  DUMAX  = ZERO;\n  DUMIN  = ZERO;\n  AKMAX  = ZERO;\n\n/*      Float version of dimensions. */\n  DM = LUSOL->m;\n  DN = LUSOL->n;\n  DELEM = LUSOL->nelem;\n\n/*      Initialize workspace parameters. */\n  LUSOL->luparm[LUSOL_IP_COMPRESSIONS_LU] = 0;\n  if(LUSOL->lena < MINLEN) {\n    if(!LUSOL_realloc_a(LUSOL, MINLEN))\n      goto x970;\n  }\n\n/*      ------------------------------------------------------------------\n        Organize the  aij's  in  a, indc, indr.\n        lu1or1  deletes small entries, tests for illegal  i,j's,\n                and counts the nonzeros in each row and column.\n        lu1or2  reorders the elements of  A  by columns.\n        lu1or3  uses the column list to test for duplicate entries\n                (same indices  i,j).\n        lu1or4  constructs a row list from the column list.\n        ------------------------------------------------------------------ */\n  LU1OR1(LUSOL, SMALL,&AMAX,&NUMNZ,&LERR,INFORM);\n  if(LPRINT>=LUSOL_MSG_STATISTICS) {\n    DENSTY = (100*DELEM)/(DM*DN);\n    LUSOL_report(LUSOL, 0, \"m:%6d %c n:%6d  nzcount:%9d  Amax:%g  Density:%g\\n\",\n                           LUSOL->m, relationChar(LUSOL->m, LUSOL->n), LUSOL->n,\n                           LUSOL->nelem, AMAX, DENSTY);\n  }\n  if(*INFORM!=LUSOL_INFORM_LUSUCCESS)\n    goto x930;\n  LUSOL->nelem = NUMNZ;\n  LU1OR2(LUSOL);\n  LU1OR3(LUSOL, &LERR,INFORM);\n  if(*INFORM!=LUSOL_INFORM_LUSUCCESS)\n    goto x940;\n  LU1OR4(LUSOL);\n/*      ------------------------------------------------------------------\n        Set up lists of rows and columns with equal numbers of nonzeros,\n        using  indc(*)  as workspace.\n        ------------------------------------------------------------------ */\n  LU1PQ1(LUSOL, LUSOL->m,LUSOL->n,LUSOL->lenr,\n         LUSOL->ip,LUSOL->iploc,LUSOL->ipinv,\n         LUSOL->indc+LUSOL->nelem); /* LUSOL_ARRAYOFFSET implied */\n  LU1PQ1(LUSOL, LUSOL->n,LUSOL->m,LUSOL->lenc,\n         LUSOL->iq,LUSOL->iqloc,LUSOL->iqinv,\n         LUSOL->indc+LUSOL->nelem); /* LUSOL_ARRAYOFFSET implied */\n/*      ------------------------------------------------------------------\n        For TCP, Ha, Hj, Hk are allocated separately, similarly amaxr\n        for TRP. Then compute the factorization  A = L*U.\n        ------------------------------------------------------------------ */\n#ifdef ClassicHamaxR\n  if(TPP || TSP) {\n    LENH  = 1;\n    LENA2 = LUSOL->lena;\n    LOCH  = LUSOL->lena;\n    LMAXR = 1;\n  }\n  else if(TRP) {\n    LENH  = 1;                     /* Dummy                                */\n    LENA2 = LUSOL->lena-LUSOL->m;  /* Reduced length of      a             */\n    LOCH  = LUSOL->lena;           /* Dummy                                */\n    LMAXR = LENA2+1;               /* Start of Amaxr      in a             */\n  }\n  else if(TCP) {\n    LENH  = LUSOL->n;              /* Length of heap                       */\n    LENA2 = LUSOL->lena-LENH;      /* Reduced length of      a, indc, indr */\n    LOCH  = LENA2+1;               /* Start of Ha, Hj, Hk in a, indc, indr */\n    LMAXR = 1;                     /* Dummy                                */\n  }\n  LU1FAD(LUSOL,\n         LENA2,LENH,\n         LUSOL->a+LOCH-LUSOL_ARRAYOFFSET,\n         LUSOL->indc+LOCH-LUSOL_ARRAYOFFSET,\n         LUSOL->indr+LOCH-LUSOL_ARRAYOFFSET,\n         LUSOL->a+LMAXR-LUSOL_ARRAYOFFSET,\n         INFORM,&LENL,&LENU,\n         &MINLEN,&MERSUM,&NUTRI,&NLTRI,&NDENS1,&NDENS2,\n         &NRANK,&LMAX,&UMAX,&DUMAX,&DUMIN,&AKMAX);\n#else\n  LU1FAD(LUSOL,\n         INFORM,&LENL,&LENU,\n         &MINLEN,&MERSUM,&NUTRI,&NLTRI,&NDENS1,&NDENS2,\n         &NRANK,&LMAX,&UMAX,&DUMAX,&DUMIN,&AKMAX);\n#endif\n  LUSOL->luparm[LUSOL_IP_RANK_U]     = NRANK;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_L] = LENL;\n  if(*INFORM==LUSOL_INFORM_ANEEDMEM)\n    goto x970;\n  if(*INFORM==LUSOL_INFORM_NOPIVOT)\n    goto x985;\n  if(*INFORM>LUSOL_INFORM_LUSUCCESS)\n    goto x980;\n  if(KEEPLU) {\n/*         ---------------------------------------------------------------\n           The LU factors are at the top of  a, indc, indr,\n           with the columns of  L  and the rows of  U  in the order\n           ( free )   ... ( u3 ) ( l3 ) ( u2 ) ( l2 ) ( u1 ) ( l1 ).\n           Starting with ( l1 ) and ( u1 ), move the rows of  U  to the\n           left and the columns of  L  to the right, giving\n           ( u1 ) ( u2 ) ( u3 ) ...   ( free )   ... ( l3 ) ( l2 ) ( l1 ).\n           Also, set  numl0 = the number of nonempty columns of  U.\n           --------------------------------------------------------------- */\n    LU = 0;\n    LL = LUSOL->lena+1;\n#ifdef ClassicHamaxR\n    LM = LENA2+1;\n#else\n    LM = LL;\n#endif\n    LTOPL = LL-LENL-LENU;\n    LROW = LENU;\n    for(K = 1; K <= NRANK; K++) {\n      I = LUSOL->ip[K];\n      LENUK = -LUSOL->lenr[I];\n      LUSOL->lenr[I] = LENUK;\n      J = LUSOL->iq[K];\n      LENLK = -LUSOL->lenc[J]-1;\n      if(LENLK>0) {\n        NUML0++;\n        LUSOL->iqloc[NUML0] = LENLK;\n      }\n      if(LU+LENUK<LTOPL) {\n/*               =========================================================\n                 There is room to move ( uk ).  Just right-shift ( lk ).\n                 ========================================================= */\n        for(IDUMMY = 1; IDUMMY <= LENLK; IDUMMY++) {\n          LL--;\n          LM--;\n          LUSOL->a[LL] = LUSOL->a[LM];\n          LUSOL->indc[LL] = LUSOL->indc[LM];\n          LUSOL->indr[LL] = LUSOL->indr[LM];\n        }\n      }\n      else {\n/*               =========================================================\n                 There is no room for ( uk ) yet.  We have to\n                 right-shift the whole of the remaining LU file.\n                 Note that ( lk ) ends up in the correct place.\n                 ========================================================= */\n        LLSAVE = LL-LENLK;\n        NMOVE = LM-LTOPL;\n        for(IDUMMY = 1; IDUMMY <= NMOVE; IDUMMY++) {\n          LL--;\n          LM--;\n          LUSOL->a[LL] = LUSOL->a[LM];\n          LUSOL->indc[LL] = LUSOL->indc[LM];\n          LUSOL->indr[LL] = LUSOL->indr[LM];\n        }\n        LTOPL = LL;\n        LL = LLSAVE;\n        LM = LL;\n      }\n/*            ======================================================\n              Left-shift ( uk ).\n              ====================================================== */\n      LUSOL->locr[I] = LU+1;\n      L2 = LM-1;\n      LM = LM-LENUK;\n      for(L = LM; L <= L2; L++) {\n        LU = LU+1;\n        LUSOL->a[LU] = LUSOL->a[L];\n        LUSOL->indr[LU] = LUSOL->indr[L];\n      }\n    }\n/*         ---------------------------------------------------------------\n           Save the lengths of the nonempty columns of  L,\n           and initialize  locc(j)  for the LU update routines.\n           --------------------------------------------------------------- */\n    for(K = 1; K <= NUML0; K++) {\n      LUSOL->lenc[K] = LUSOL->iqloc[K];\n    }\n    for(J = 1; J <= LUSOL->n; J++) {\n      LUSOL->locc[J] = 0;\n    }\n/*         ---------------------------------------------------------------\n           Test for singularity.\n           lu6chk  sets  nsing, jsing, jumin, Lmax, Umax, DUmax, DUmin\n           (including entries from the dense LU).\n           inform = 1  if there are singularities (nsing gt 0).\n           --------------------------------------------------------------- */\n    LU6CHK(LUSOL, 1,LUSOL->lena,INFORM);\n    NSING = LUSOL->luparm[LUSOL_IP_SINGULARITIES];\n    JSING = LUSOL->luparm[LUSOL_IP_SINGULARINDEX];\n    JUMIN = LUSOL->luparm[LUSOL_IP_COLINDEX_DUMIN];\n    LMAX  = LUSOL->parmlu[LUSOL_RP_MAXMULT_L];\n    UMAX  = LUSOL->parmlu[LUSOL_RP_MAXELEM_U];\n    DUMAX = LUSOL->parmlu[LUSOL_RP_MAXELEM_DIAGU];\n    DUMIN = LUSOL->parmlu[LUSOL_RP_MINELEM_DIAGU];\n  }\n  else {\n/*         ---------------------------------------------------------------\n           keepLU = 0.  L and U were not kept, just the diagonals of U.\n           lu1fac will probably be called again soon with keepLU = .true.\n           11 Mar 2001: lu6chk revised.  We can call it with keepLU = 0,\n                        but we want to keep Lmax, Umax from lu1fad.\n           05 May 2002: Allow for TCP with new lu1DCP.  Diag(U) starts\n                        below lena2, not lena.  Need lena2 in next line.\n           --------------------------------------------------------------- */\n#ifdef ClassicHamaxR\n    LU6CHK(LUSOL, 1,LENA2,INFORM);\n#else\n    LU6CHK(LUSOL, 1,LUSOL->lena,INFORM);\n#endif\n    NSING = LUSOL->luparm[LUSOL_IP_SINGULARITIES];\n    JSING = LUSOL->luparm[LUSOL_IP_SINGULARINDEX];\n    JUMIN = LUSOL->luparm[LUSOL_IP_COLINDEX_DUMIN];\n    DUMAX = LUSOL->parmlu[LUSOL_RP_MAXELEM_DIAGU];\n    DUMIN = LUSOL->parmlu[LUSOL_RP_MINELEM_DIAGU];\n  }\n  goto x990;\n/*      ------------\n        Error exits.\n        ------------ */\nx930:\n  *INFORM = LUSOL_INFORM_ADIMERR;\n  if(LPRINT>=LUSOL_MSG_SINGULARITY)\n    LUSOL_report(LUSOL, 0, \"lu1fac  error...\\nentry  a[%d]  has an illegal row (%d) or column (%d) index\\n\",\n                        LERR,LUSOL->indc[LERR],LUSOL->indr[LERR]);\n  goto x990;\nx940:\n  *INFORM = LUSOL_INFORM_ADUPLICATE;\n  if(LPRINT>=LUSOL_MSG_SINGULARITY)\n    LUSOL_report(LUSOL, 0, \"lu1fac  error...\\nentry  a[%d]  is a duplicate with indeces indc=%d, indr=%d\\n\",\n                        LERR,LUSOL->indc[LERR],LUSOL->indr[LERR]);\n  goto x990;\nx970:\n  *INFORM = LUSOL_INFORM_ANEEDMEM;\n  if(LPRINT>=LUSOL_MSG_SINGULARITY)\n    LUSOL_report(LUSOL, 0, \"lu1fac  error...\\ninsufficient storage; increase  lena  from %d to at least %d\\n\",\n                        LUSOL->lena, MINLEN);\n  goto x990;\nx980:\n  *INFORM = LUSOL_INFORM_FATALERR;\n  if(LPRINT>=LUSOL_MSG_SINGULARITY)\n    LUSOL_report(LUSOL, 0, \"lu1fac  error...\\nfatal bug   (sorry --- this should never happen)\\n\");\n  goto x990;\nx985:\n  *INFORM = LUSOL_INFORM_NOPIVOT;\n  if(LPRINT>=LUSOL_MSG_SINGULARITY)\n    LUSOL_report(LUSOL, 0, \"lu1fac  error...\\nTSP used but diagonal pivot could not be found\\n\");\n\n/*      Finalize and store output parameters. */\nx990:\n  LUSOL->nelem = NELEM0;\n  LUSOL->luparm[LUSOL_IP_SINGULARITIES]   = NSING;\n  LUSOL->luparm[LUSOL_IP_SINGULARINDEX]   = JSING;\n  LUSOL->luparm[LUSOL_IP_MINIMUMLENA]     = MINLEN;\n  LUSOL->luparm[LUSOL_IP_UPDATECOUNT]     = 0;\n  LUSOL->luparm[LUSOL_IP_RANK_U]          = NRANK;\n  LUSOL->luparm[LUSOL_IP_COLCOUNT_DENSE1] = NDENS1;\n  LUSOL->luparm[LUSOL_IP_COLCOUNT_DENSE2] = NDENS2;\n  LUSOL->luparm[LUSOL_IP_COLINDEX_DUMIN]  = JUMIN;\n  LUSOL->luparm[LUSOL_IP_COLCOUNT_L0]     = NUML0;\n  LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0]     = 0;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_L0]     = LENL;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_U0]     = LENU;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_L]      = LENL;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_U]      = LENU;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_ROW]    = LROW;\n  LUSOL->luparm[LUSOL_IP_MARKOWITZ_MERIT] = MERSUM;\n  LUSOL->luparm[LUSOL_IP_TRIANGROWS_U]    = NUTRI;\n  LUSOL->luparm[LUSOL_IP_TRIANGROWS_L]    = NLTRI;\n  LUSOL->parmlu[LUSOL_RP_MAXELEM_A]       = AMAX;\n  LUSOL->parmlu[LUSOL_RP_MAXMULT_L]       = LMAX;\n  LUSOL->parmlu[LUSOL_RP_MAXELEM_U]       = UMAX;\n  LUSOL->parmlu[LUSOL_RP_MAXELEM_DIAGU]   = DUMAX;\n  LUSOL->parmlu[LUSOL_RP_MINELEM_DIAGU]   = DUMIN;\n  LUSOL->parmlu[LUSOL_RP_MAXELEM_TCP]     = AKMAX;\n  AGRWTH = AKMAX/(AMAX+LUSOL_SMALLNUM);\n  UGRWTH = UMAX/(AMAX+LUSOL_SMALLNUM);\n  if(TPP)\n    GROWTH = UGRWTH;\n/*      TRP or TCP or TSP */\n  else\n    GROWTH = AGRWTH;\n  LUSOL->parmlu[LUSOL_RP_GROWTHRATE]      = GROWTH;\n\n  LUSOL->luparm[LUSOL_IP_FTRANCOUNT]      = 0;\n  LUSOL->luparm[LUSOL_IP_BTRANCOUNT]      = 0;\n\n/*      ------------------------------------------------------------------\n        Set overall status variable.\n        ------------------------------------------------------------------ */\n  LUSOL->luparm[LUSOL_IP_INFORM]          = *INFORM;\n  if(*INFORM == LUSOL_INFORM_NOMEMLEFT)\n    LUSOL_report(LUSOL, 0, \"lu1fac  error...\\ninsufficient memory available\\n\");\n\n/*      ------------------------------------------------------------------\n        Print statistics for the LU factors.\n        ------------------------------------------------------------------ */\n  NCP   = LUSOL->luparm[LUSOL_IP_COMPRESSIONS_LU];\n  CONDU = DUMAX/MAX(DUMIN,LUSOL_SMALLNUM);\n  DINCR = (LENL+LENU)-LUSOL->nelem;\n  DINCR = (DINCR*100)/MAX(DELEM,ONE);\n  AVGMER = MERSUM;\n  AVGMER = AVGMER/DM;\n  NBUMP = LUSOL->m-NUTRI-NLTRI;\n  if(LPRINT>=LUSOL_MSG_STATISTICS) {\n    if(TPP) {\n      LUSOL_report(LUSOL, 0, \"Merit %g %d %d %d %g %d %d %g %g %d %d %d\\n\",\n                          AVGMER,LENL,LENL+LENU,NCP,DINCR,NUTRI,LENU,\n                          LTOL,UMAX,UGRWTH,NLTRI,NDENS1,LMAX);\n    }\n    else {\n      LUSOL_report(LUSOL, 0, \"Merit %s %g %d %d %d %g %d %d %g %g %d %d %d %g %g\\n\",\n                          LUSOL_pivotLabel(LUSOL),\n                          AVGMER,LENL,LENL+LENU,NCP,DINCR,NUTRI,LENU,\n                          LTOL,UMAX,UGRWTH,NLTRI,NDENS1,LMAX,AKMAX,AGRWTH);\n    }\n    LUSOL_report(LUSOL, 0, \"bump%9d  dense2%7d  DUmax%g DUmin%g  conDU%g\\n\",\n                          NBUMP,NDENS2,DUMAX,DUMIN,CONDU);\n  }\n}\n\n\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol2.c",
    "content": "\n/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   File  lusol2 LUSOL heap management routines\n   Hbuild   Hchange  Hdelete  Hdown    Hinsert  Hup\n   Heap-management routines for LUSOL's lu1fac.\n   May be useful for other applications.\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   For LUSOL, the heap structure involves three arrays of length N.\n   N        is the current number of entries in the heap.\n   Ha(1:N)  contains the values that the heap is partially sorting.\n            For LUSOL they are double precision values -- the largest\n            element in each remaining column of the updated matrix.\n            The biggest entry is in Ha(1), the top of the heap.\n   Hj(1:N)  contains column numbers j.\n            Ha(k) is the biggest entry in column j = Hj(k).\n   Hk(1:N)  contains indices within the heap.  It is the\n            inverse of Hj(1:N), so  k = Hk(j)  <=>  j = Hj(k).\n            Column j is entry k in the heap.\n   hops     is the number of heap operations,\n            i.e., the number of times an entry is moved\n            (the number of \"hops\" up or down the heap).\n   Together, Hj and Hk let us find values inside the heap\n   whenever we want to change one of the values in Ha.\n   For other applications, Ha may need to be some other data type,\n   like the keys that sort routines operate on.\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   11 Feb 2002: MATLAB  version derived from \"Algorithms\" by\n                R. Sedgewick\n   03 Mar 2002: F77     version derived from MATLAB version.\n   07 May 2002: Safeguard input parameters k, N, Nk.\n                We don't want them to be output!\n   07 May 2002: Current version of lusol2.f.\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */\n\n/* ==================================================================\n   Hdown  updates heap by moving down tree from node k.\n   ------------------------------------------------------------------\n   01 May 2002: Need Nk for length of Hk.\n   05 May 2002: Change input paramter k to kk to stop k being output.\n   05 May 2002: Current version of Hdown.\n   ================================================================== */\nvoid HDOWN(REAL HA[], int HJ[], int HK[], int N, int K, int *HOPS)\n{\n  int  J, JJ, JV, N2;\n  REAL V;\n\n  *HOPS = 0;\n  V = HA[K];\n  JV = HJ[K];\n N2 = N/2;\n/*      while 1\n        break */\nx100:\n  if(K>N2)\n    goto x200;\n  (*HOPS)++;\n  J = K+K;\n  if(J<N) {\n    if(HA[J]<HA[J+1])\n      J++;\n  }\n/*      break */\n  if(V>=HA[J])\n    goto x200;\n  HA[K] = HA[J];\n  JJ = HJ[J];\n  HJ[K] = JJ;\n  HK[JJ] = K;\n  K = J;\n  goto x100;\n/*      end while */\nx200:\n  HA[K] = V;\n  HJ[K] = JV;\n  HK[JV] = K;\n}\n\n/* ==================================================================\n   Hup updates heap by moving up tree from node k.\n   ------------------------------------------------------------------\n   01 May 2002: Need Nk for length of Hk.\n   05 May 2002: Change input paramter k to kk to stop k being output.\n   05 May 2002: Current version of Hup.\n   ================================================================== */\nvoid HUP(REAL HA[], int HJ[], int HK[], int K, int *HOPS)\n{\n  int  J, JV, K2;\n  REAL V;\n\n  *HOPS = 0;\n  V = HA[K];\n JV = HJ[K];\n/*      while 1\n        break */\nx100:\n  if(K<2)\n    goto x200;\n  K2 = K/2;\n/*      break */\n  if(V<HA[K2])\n    goto x200;\n  (*HOPS)++;\n  HA[K] = HA[K2];\n  J = HJ[K2];\n  HJ[K] = J;\n  HK[J] = K;\n  K = K2;\n  goto x100;\n/*      end while */\nx200:\n  HA[K] = V;\n  HJ[K] = JV;\n  HK[JV] = K;\n}\n\n/* ==================================================================\n   Hinsert inserts (v,jv) into heap of length N-1\n   to make heap of length N.\n   ------------------------------------------------------------------\n   03 Apr 2002: First version of Hinsert.\n   01 May 2002: Require N to be final length, not old length.\n                Need Nk for length of Hk.\n   07 May 2002: Protect input parameters N, Nk.\n   07 May 2002: Current version of Hinsert.\n   ================================================================== */\nvoid HINSERT(REAL HA[], int HJ[], int HK[], int N,\n             REAL V, int JV, int *HOPS)\n{\n  HA[N] = V;\n  HJ[N] = JV;\n  HK[JV] = N;\n  HUP(HA,HJ,HK,N,HOPS);\n}\n\n/* ==================================================================\n   Hchange changes Ha(k) to v in heap of length N.\n   ------------------------------------------------------------------\n   01 May 2002: Need Nk for length of Hk.\n   07 May 2002: Protect input parameters N, Nk, k.\n   07 May 2002: Current version of Hchange.\n   ================================================================== */\nvoid HCHANGE(REAL HA[], int HJ[], int HK[], int N, int K,\n             REAL V, int JV, int *HOPS)\n{\n  REAL V1;\n\n  V1 = HA[K];\n  HA[K] = V;\n  HJ[K] = JV;\n  HK[JV] = K;\n  if(V1<V)\n    HUP  (HA,HJ,HK,  K,HOPS);\n  else\n    HDOWN(HA,HJ,HK,N,K,HOPS);\n}\n\n/* ==================================================================\n   Hdelete deletes Ha(k) from heap of length N.\n   ------------------------------------------------------------------\n   03 Apr 2002: Current version of Hdelete.\n   01 May 2002: Need Nk for length of Hk.\n   07 May 2002: Protect input parameters N, Nk, k.\n   07 May 2002: Current version of Hdelete.\n   ================================================================== */\nvoid HDELETE(REAL HA[], int HJ[], int HK[], int *N, int K, int *HOPS)\n{\n\n  int  JV, NX;\n  REAL V;\n\n  NX = *N;\n  V = HA[NX];\n  JV = HJ[NX];\n  (*N)--;\n  *HOPS = 0;\n  if(K<NX)\n    HCHANGE(HA,HJ,HK,NX,K,V,JV,HOPS);\n}\n\n/* ==================================================================\n   Hbuild initializes the heap by inserting each element of Ha.\n   Input:  Ha, Hj.\n   Output: Ha, Hj, Hk, hops.\n   ------------------------------------------------------------------\n   01 May 2002: Use k for new length of heap, not k-1 for old length.\n   05 May 2002: Use kk in call to stop loop variable k being altered.\n                (Actually Hinsert no longer alters that parameter.)\n   07 May 2002: ftnchek wants us to protect Nk, Ha(k), Hj(k) too.\n   07 May 2002: Current version of Hbuild.\n   ================================================================== */\nvoid HBUILD(REAL HA[], int HJ[], int HK[], int N, int *HOPS)\n{\n  int  H, JV, K, KK;\n  REAL V;\n\n  *HOPS = 0;\n  for(K = 1; K <= N; K++) {\n    KK = K;\n    V = HA[K];\n    JV = HJ[K];\n    HINSERT(HA,HJ,HK,KK,V,JV,&H);\n    (*HOPS) += H;\n  }\n}\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol6a.c",
    "content": "\n/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   File  lusol6a\n      lu6sol   lu6L     lu6Lt     lu6U     Lu6Ut   lu6LD   lu6chk\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   26 Apr 2002: lu6 routines put into a separate file.\n   15 Dec 2002: lu6sol modularized via lu6L, lu6Lt, lu6U, lu6Ut.\n                lu6LD implemented to allow solves with LDL' or L|D|L'.\n   15 Dec 2002: Current version of lusol6a.f.\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */\n\n/* ==================================================================\n   lu6chk  looks at the LU factorization  A = L*U.\n   If mode = 1, lu6chk is being called by lu1fac.\n   (Other modes not yet implemented.)\n   ------------------------------------------------------------------\n   The important input parameters are\n\n                  lprint = luparm(2)\n                  keepLU = luparm(8)\n                  Utol1  = parmlu(4)\n                  Utol2  = parmlu(5)\n\n   and the significant output parameters are\n\n                  inform = luparm(10)\n                  nsing  = luparm(11)\n                  jsing  = luparm(12)\n                  jumin  = luparm(19)\n                  Lmax   = parmlu(11)\n                  Umax   = parmlu(12)\n                  DUmax  = parmlu(13)\n                  DUmin  = parmlu(14)\n                  and      w(*).\n\n   Lmax  and Umax  return the largest elements in L and U.\n   DUmax and DUmin return the largest and smallest diagonals of U\n                   (excluding diagonals that are exactly zero).\n   In general, w(j) is set to the maximum absolute element in\n   the j-th column of U.  However, if the corresponding diagonal\n   of U is small in absolute terms or relative to w(j)\n   (as judged by the parameters Utol1, Utol2 respectively),\n   then w(j) is changed to - w(j).\n   Thus, if w(j) is not positive, the j-th column of A\n   appears to be dependent on the other columns of A.\n   The number of such columns, and the position of the last one,\n   are returned as nsing and jsing.\n   Note that nrank is assumed to be set already, and is not altered.\n   Typically, nsing will satisfy      nrank + nsing = n,  but if\n   Utol1 and Utol2 are rather large,  nsing > n - nrank   may occur.\n   If keepLU = 0,\n   Lmax  and Umax  are already set by lu1fac.\n   The diagonals of U are in the top of A.\n   Only Utol1 is used in the singularity test to set w(*).\n   inform = 0  if  A  appears to have full column rank  (nsing = 0).\n   inform = 1  otherwise  (nsing .gt. 0).\n   ------------------------------------------------------------------\n   00 Jul 1987: Early version.\n   09 May 1988: f77 version.\n   11 Mar 2001: Allow for keepLU = 0.\n   17 Nov 2001: Briefer output for singular factors.\n   05 May 2002: Comma needed in format 1100 (via Kenneth Holmstrom).\n   06 May 2002: With keepLU = 0, diags of U are in natural order.\n                They were not being extracted correctly.\n   23 Apr 2004: TRP can judge singularity better by comparing\n                all diagonals to DUmax.\n   27 Jun 2004: (PEG) Allow write only if nout .gt. 0.\n   ================================================================== */\n#ifdef UseOld_LU6CHK_20040510\nvoid LU6CHK(LUSOLrec *LUSOL, int MODE, int LENA2, int *INFORM)\n{\n  MYBOOL KEEPLU;\n  int    I, J, JUMIN, K, L, L1, L2, LENL, LPRINT, NDEFIC, NRANK;\n  REAL   AIJ, DIAG, DUMAX, DUMIN, LMAX, UMAX, UTOL1, UTOL2;\n\n  LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL];\n  KEEPLU = (MYBOOL) (LUSOL->luparm[LUSOL_IP_KEEPLU]!=0);\n  NRANK = LUSOL->luparm[LUSOL_IP_RANK_U];\n  LENL  = LUSOL->luparm[LUSOL_IP_NONZEROS_L];\n  UTOL1 = LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U];\n  UTOL2 = LUSOL->parmlu[LUSOL_RP_EPSDIAG_U];\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  LMAX  = ZERO;\n  UMAX  = ZERO;\n  LUSOL->luparm[LUSOL_IP_SINGULARITIES]  = 0;\n  LUSOL->luparm[LUSOL_IP_SINGULARINDEX]  = 0;\n  JUMIN = 0;\n  DUMAX = ZERO;\n  DUMIN = LUSOL_BIGNUM;\n\n#ifdef LUSOLFastClear\n  MEMCLEAR(LUSOL->w+1, LUSOL->n);\n#else\n  for(I = 1; I <= LUSOL->n; I++)\n    LUSOL->w[I] = ZERO;\n#endif\n\n  if(KEEPLU) {\n/*     --------------------------------------------------------------\n        Find  Lmax.\n       -------------------------------------------------------------- */\n    for(L = (LENA2+1)-LENL; L <= LENA2; L++) {\n      SETMAX(LMAX,fabs(LUSOL->a[L]));\n    }\n/*     --------------------------------------------------------------\n        Find Umax and set w(j) = maximum element in j-th column of U.\n       -------------------------------------------------------------- */\n    for(K = 1; K <= NRANK; K++) {\n      I = LUSOL->ip[K];\n      L1 = LUSOL->locr[I];\n      L2 = (L1+LUSOL->lenr[I])-1;\n      for(L = L1; L <= L2; L++) {\n        J = LUSOL->indr[L];\n        AIJ = fabs(LUSOL->a[L]);\n        SETMAX(LUSOL->w[J],AIJ);\n        SETMAX(UMAX,AIJ);\n      }\n    }\n/*     --------------------------------------------------------------\n        Negate w(j) if the corresponding diagonal of U is\n        too small in absolute terms or relative to the other elements\n        in the same column of  U.\n        Also find DUmax and DUmin, the extreme diagonals of U.\n       -------------------------------------------------------------- */\n    for(K = 1; K <= LUSOL->n; K++) {\n      J = LUSOL->iq[K];\n      if(K>NRANK)\n        DIAG = ZERO;\n      else {\n        I = LUSOL->ip[K];\n        L1 = LUSOL->locr[I];\n        DIAG = fabs(LUSOL->a[L1]);\n        SETMAX(DUMAX,DIAG);\n        if(DUMIN>DIAG) {\n          DUMIN = DIAG;\n          JUMIN = J;\n        }\n      }\n      if((DIAG<=UTOL1) || (DIAG<=UTOL2*LUSOL->w[J])) {\n        LUSOL_addSingularity(LUSOL, J, INFORM);\n        LUSOL->w[J] = -LUSOL->w[J];\n      }\n    }\n    LUSOL->parmlu[LUSOL_RP_MAXMULT_L] = LMAX;\n    LUSOL->parmlu[LUSOL_RP_MAXELEM_U] = UMAX;\n  }\n   else {\n/*     --------------------------------------------------------------\n        keepLU = 0.\n        Only diag(U) is stored.  Set w(*) accordingly.\n       -------------------------------------------------------------- */\n    for(K = 1; K <= LUSOL->n; K++) {\n      J = LUSOL->iq[K];\n      if(K>NRANK)\n        DIAG = ZERO;\n      else {\n/* !             diag   = abs( diagU(k) ) ! 06 May 2002: Diags are in natural order */\n        DIAG = fabs(LUSOL->diagU[J]);\n        LUSOL->w[J] = DIAG;\n        SETMAX(DUMAX,DIAG);\n        if(DUMIN>DIAG) {\n          DUMIN = DIAG;\n          JUMIN = J;\n        }\n      }\n      if(DIAG<=UTOL1) {\n        LUSOL_addSingularity(LUSOL, J, INFORM);\n        LUSOL->w[J] = -LUSOL->w[J];\n      }\n    }\n  }\n/*     -----------------------------------------------------------------\n        Set output parameters.\n       ----------------------------------------------------------------- */\n  if(JUMIN==0)\n    DUMIN = ZERO;\n  LUSOL->luparm[LUSOL_IP_COLINDEX_DUMIN] = JUMIN;\n  LUSOL->parmlu[LUSOL_RP_MAXELEM_DIAGU]  = DUMAX;\n  LUSOL->parmlu[LUSOL_RP_MINELEM_DIAGU]  = DUMIN;\n/*      The matrix has been judged singular. */\n  if(LUSOL->luparm[LUSOL_IP_SINGULARITIES]>0) {\n    *INFORM = LUSOL_INFORM_LUSINGULAR;\n    NDEFIC = LUSOL->n-NRANK;\n    if(LPRINT>=LUSOL_MSG_SINGULARITY) {\n      LUSOL_report(LUSOL, 0, \"Singular(m%cn)  rank:%9d  n-rank:%8d  nsing:%9d\\n\",\n                             relationChar(LUSOL->m, LUSOL->n),NRANK,NDEFIC,\n                             LUSOL->luparm[LUSOL_IP_SINGULARITIES]);\n    }\n  }\n/*      Exit. */\n  LUSOL->luparm[LUSOL_IP_INFORM] = *INFORM;\n}\n#else\nvoid LU6CHK(LUSOLrec *LUSOL, int MODE, int LENA2, int *INFORM)\n{\n  MYBOOL KEEPLU, TRP;\n  int    I, J, JUMIN, K, L, L1, L2, LENL, LDIAGU, LPRINT, NDEFIC, NRANK;\n  REAL   AIJ, DIAG, DUMAX, DUMIN, LMAX, UMAX, UTOL1, UTOL2;\n\n  LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL];\n  KEEPLU = (MYBOOL) (LUSOL->luparm[LUSOL_IP_KEEPLU] != 0);\n  TRP    = (MYBOOL) (LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP);\n  NRANK  = LUSOL->luparm[LUSOL_IP_RANK_U];\n  LENL   = LUSOL->luparm[LUSOL_IP_NONZEROS_L];\n  UTOL1  = LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U];\n  UTOL2  = LUSOL->parmlu[LUSOL_RP_EPSDIAG_U];\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  LMAX   = ZERO;\n  UMAX   = ZERO;\n  LUSOL->luparm[LUSOL_IP_SINGULARITIES] = 0;\n  LUSOL->luparm[LUSOL_IP_SINGULARINDEX] = 0;\n  JUMIN  = 0;\n  DUMAX  = ZERO;\n  DUMIN  = LUSOL_BIGNUM;\n\n#ifdef LUSOLFastClear\n  MEMCLEAR(LUSOL->w+1, LUSOL->n);\n#else\n  for(I = 1; I <= LUSOL->n; I++)\n    LUSOL->w[I] = ZERO;\n#endif\n\n  if(KEEPLU) {\n/*     --------------------------------------------------------------\n        Find  Lmax.\n       -------------------------------------------------------------- */\n    for(L = (LENA2+1)-LENL; L <= LENA2; L++) {\n      SETMAX(LMAX,fabs(LUSOL->a[L]));\n     }\n/*     --------------------------------------------------------------\n        Find Umax and set w(j) = maximum element in j-th column of U.\n       -------------------------------------------------------------- */\n    for(K = 1; K <= NRANK; K++) {\n      I = LUSOL->ip[K];\n      L1 = LUSOL->locr[I];\n      L2 = (L1+LUSOL->lenr[I])-1;\n      for(L = L1; L <= L2; L++) {\n        J = LUSOL->indr[L];\n        AIJ = fabs(LUSOL->a[L]);\n        SETMAX(LUSOL->w[J],AIJ);\n        SETMAX(UMAX,AIJ);\n      }\n    }\n    LUSOL->parmlu[LUSOL_RP_MAXMULT_L] = LMAX;\n    LUSOL->parmlu[LUSOL_RP_MAXELEM_U] = UMAX;\n/*     --------------------------------------------------------------\n       Find DUmax and DUmin, the extreme diagonals of U.\n       -------------------------------------------------------------- */\n    for(K = 1; K <= NRANK; K++) {\n      J     = LUSOL->iq[K];\n      I     = LUSOL->ip[K];\n      L1    = LUSOL->locr[I];\n      DIAG  = fabs(LUSOL->a[L1]);\n      SETMAX( DUMAX, DIAG );\n      if(DUMIN > DIAG) {\n        DUMIN  = DIAG;\n        JUMIN  = J;\n      }\n    }\n  }\n  else {\n/*     --------------------------------------------------------------\n       keepLU = 0.\n       Only diag(U) is stored.  Set w(*) accordingly.\n       Find DUmax and DUmin, the extreme diagonals of U.\n       -------------------------------------------------------------- */\n    LDIAGU = LENA2 - LUSOL->n;\n    for(K = 1; K <= NRANK; K++) {\n      J           = LUSOL->iq[K];\n      DIAG        = fabs( LUSOL->a[LDIAGU + J] ); /* are in natural order */\n      LUSOL->w[J] = DIAG;\n      SETMAX( DUMAX, DIAG );\n      if(DUMIN > DIAG) {\n        DUMIN = DIAG;\n        JUMIN = J;\n      }\n    }\n  }\n/*     --------------------------------------------------------------\n       Negate w(j) if the corresponding diagonal of U is\n       too small in absolute terms or relative to the other elements\n       in the same column of  U.\n\n       23 Apr 2004: TRP ensures that diags are NOT small relative to\n                    other elements in their own column.\n                    Much better, we can compare all diags to DUmax.\n      -------------------------------------------------------------- */\n  if((MODE == 1) && TRP) {\n    SETMAX( UTOL1, UTOL2*DUMAX );\n  }\n\n  if(KEEPLU) {\n    for(K = 1; K <= LUSOL->n; K++) {\n      J = LUSOL->iq[K];\n      if(K>NRANK)\n        DIAG = ZERO;\n      else {\n        I = LUSOL->ip[K];\n        L1 = LUSOL->locr[I];\n        DIAG = fabs(LUSOL->a[L1]);\n      }\n      if((DIAG<=UTOL1) || (DIAG<=UTOL2*LUSOL->w[J])) {\n        LUSOL_addSingularity(LUSOL, J, INFORM);\n        LUSOL->w[J] = -LUSOL->w[J];\n      }\n    }\n  }\n  else { /* keepLU = FALSE */\n    for(K = 1; K <= LUSOL->n; K++) {\n      J = LUSOL->iq[K];\n      DIAG = LUSOL->w[J];\n      if(DIAG<=UTOL1) {\n        LUSOL_addSingularity(LUSOL, J, INFORM);\n        LUSOL->w[J] = -LUSOL->w[J];\n      }\n    }\n  }\n/*     -----------------------------------------------------------------\n        Set output parameters.\n       ----------------------------------------------------------------- */\n  if(JUMIN==0)\n    DUMIN = ZERO;\n  LUSOL->luparm[LUSOL_IP_COLINDEX_DUMIN] = JUMIN;\n  LUSOL->parmlu[LUSOL_RP_MAXELEM_DIAGU]  = DUMAX;\n  LUSOL->parmlu[LUSOL_RP_MINELEM_DIAGU]  = DUMIN;\n/*      The matrix has been judged singular. */\n  if(LUSOL->luparm[LUSOL_IP_SINGULARITIES]>0) {\n    *INFORM = LUSOL_INFORM_LUSINGULAR;\n    NDEFIC = LUSOL->n-NRANK;\n    if((LUSOL->outstream!=NULL) && (LPRINT>=LUSOL_MSG_SINGULARITY)) {\n      LUSOL_report(LUSOL, 0, \"Singular(m%cn)  rank:%9d  n-rank:%8d  nsing:%9d\\n\",\n                             relationChar(LUSOL->m, LUSOL->n),NRANK,NDEFIC,\n                             LUSOL->luparm[LUSOL_IP_SINGULARITIES]);\n    }\n  }\n/*      Exit. */\n  LUSOL->luparm[LUSOL_IP_INFORM] = *INFORM;\n}\n#endif\n\n\n/* ------------------------------------------------------------------\n   Include routines for row-based L0.\n   20 Apr 2005 Current version - KE.\n   ------------------------------------------------------------------ */\n#include \"lusol6l0.c\"\n\n\n/* ------------------------------------------------------------------\n   lu6L   solves   L v = v(input).\n   ------------------------------------------------------------------\n   15 Dec 2002: First version derived from lu6sol.\n   15 Dec 2002: Current version.\n   ------------------------------------------------------------------ */\nvoid LU6L(LUSOLrec *LUSOL, int *INFORM, REAL V[], int NZidx[])\n{\n  (void)NZidx;\n  int  JPIV, K, L, L1, LEN, LENL, LENL0, NUML, NUML0;\n  REAL SMALL;\n  REAL VPIV;\n#ifdef LUSOLFastSolve\n  REAL *aptr;\n  int  *iptr, *jptr;\n#else\n  int  I, J;\n#endif\n  (void)NZidx;\n\n  NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0];\n  LENL0 = LUSOL->luparm[LUSOL_IP_NONZEROS_L0];\n  LENL  = LUSOL->luparm[LUSOL_IP_NONZEROS_L];\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  L1 = LUSOL->lena+1;\n  for(K = 1; K <= NUML0; K++) {\n    LEN = LUSOL->lenc[K];\n    L = L1;\n    L1 -= LEN;\n    JPIV = LUSOL->indr[L1];\n    VPIV = V[JPIV];\n    if(fabs(VPIV)>SMALL) {\n/*     ***** This loop could be coded specially. */\n#ifdef LUSOLFastSolve\n      L--;\n      for(aptr = LUSOL->a+L, iptr = LUSOL->indc+L;\n          LEN > 0; LEN--, aptr--, iptr--)\n        V[*iptr] += (*aptr) * VPIV;\n#else\n      for(; LEN > 0; LEN--) {\n        L--;\n        I = LUSOL->indc[L];\n        V[I] += LUSOL->a[L]*VPIV;\n      }\n#endif\n    }\n#ifdef SetSmallToZero\n    else\n      V[JPIV] = 0;\n#endif\n  }\n  L = (LUSOL->lena-LENL0)+1;\n  NUML = LENL-LENL0;\n/*     ***** This loop could be coded specially. */\n#ifdef LUSOLFastSolve\n  L--;\n  for(aptr = LUSOL->a+L, jptr = LUSOL->indr+L, iptr = LUSOL->indc+L;\n      NUML > 0; NUML--, aptr--, jptr--, iptr--) {\n    if(fabs(V[*jptr])>SMALL)\n      V[*iptr] += (*aptr) * V[*jptr];\n#ifdef SetSmallToZero\n    else\n      V[*jptr] = 0;\n#endif\n  }\n#else\n  for(; NUML > 0; NUML--) {\n    L--;\n    J = LUSOL->indr[L];\n    if(fabs(V[J])>SMALL) {\n      I = LUSOL->indc[L];\n      V[I] += LUSOL->a[L]*V[J];\n    }\n#ifdef SetSmallToZero\n    else\n      V[J] = 0;\n#endif\n  }\n#endif\n/*      Exit. */\n  LUSOL->luparm[LUSOL_IP_INFORM] = *INFORM;\n}\n\n/* ==================================================================\n   lu6LD  assumes lu1fac has computed factors A = LU of a\n   symmetric definite or quasi-definite matrix A,\n   using Threshold Symmetric Pivoting (TSP),   luparm(6) = 3,\n   or    Threshold Diagonal  Pivoting (TDP),   luparm(6) = 4.\n   It also assumes that no updates have been performed.\n   In such cases,  U = D L', where D = diag(U).\n   lu6LDL returns v as follows:\n\n   mode\n    1    v  solves   L D v = v(input).\n    2    v  solves   L|D|v = v(input).\n   ------------------------------------------------------------------\n   15 Dec 2002: First version of lu6LD.\n   15 Dec 2002: Current version.\n   ================================================================== */\nvoid LU6LD(LUSOLrec *LUSOL, int *INFORM, int MODE, REAL V[], int NZidx[])\n{\n  (void)NZidx;\n  int  IPIV, K, L, L1, LEN, NUML0;\n  REAL DIAG, SMALL;\n  REAL VPIV;\n#ifdef LUSOLFastSolve\n  REAL *aptr;\n  int  *jptr;\n#else\n  int  J;\n#endif\n  (void)NZidx;\n\n/*      Solve L D v(new) = v  or  L|D|v(new) = v, depending on mode.\n        The code for L is the same as in lu6L,\n        but when a nonzero entry of v arises, we divide by\n        the corresponding entry of D or |D|. */\n  NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0];\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  L1 = LUSOL->lena+1;\n  for(K = 1; K <= NUML0; K++) {\n    LEN = LUSOL->lenc[K];\n    L = L1;\n    L1 -= LEN;\n    IPIV = LUSOL->indr[L1];\n    VPIV = V[IPIV];\n    if(fabs(VPIV)>SMALL) {\n/*     ***** This loop could be coded specially. */\n#ifdef LUSOLFastSolve\n      L--;\n      for(aptr = LUSOL->a+L, jptr = LUSOL->indc+L;\n          LEN > 0; LEN--, aptr--, jptr--)\n        V[*jptr] += (*aptr)*VPIV;\n#else\n      for(; LEN > 0; LEN--) {\n        L--;\n        J = LUSOL->indc[L];\n        V[J] += LUSOL->a[L]*VPIV;\n      }\n#endif\n/*      Find diag = U(ipiv,ipiv) and divide by diag or |diag|. */\n      L = LUSOL->locr[IPIV];\n      DIAG = LUSOL->a[L];\n      if(MODE==2)\n        DIAG = fabs(DIAG);\n      V[IPIV] = VPIV/DIAG;\n    }\n#ifdef SetSmallToZero\n    else\n      V[IPIV] = 0;\n#endif\n  }\n}\n\n\n/* ==================================================================\n   lu6Lt  solves   L'v = v(input).\n   ------------------------------------------------------------------\n   15 Dec 2002: First version derived from lu6sol.\n   15 Dec 2002: Current version.\n   ================================================================== */\nvoid LU6LT(LUSOLrec *LUSOL, int *INFORM, REAL V[], int NZidx[])\n{\n#ifdef DoTraceL0\n  REAL    TEMP;\n#endif\n  int     K, L, L1, L2, LEN, LENL, LENL0, NUML0;\n  REAL    SMALL;\n  REALXP SUM;\n  REAL HOLD;\n#if (defined LUSOLFastSolve) && !(defined DoTraceL0)\n  REAL    *aptr;\n  int     *iptr, *jptr;\n#else\n  int     I, J;\n#endif\n\n  NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0];\n  LENL0 = LUSOL->luparm[LUSOL_IP_NONZEROS_L0];\n  LENL  = LUSOL->luparm[LUSOL_IP_NONZEROS_L];\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  L1 = (LUSOL->lena-LENL)+1;\n  L2 = LUSOL->lena-LENL0;\n\n/*     ***** This loop could be coded specially. */\n#if (defined LUSOLFastSolve) && !(defined DoTraceL0)\n  for(L = L1, aptr = LUSOL->a+L1, iptr = LUSOL->indr+L1, jptr = LUSOL->indc+L1;\n      L <= L2; L++, aptr++, iptr++, jptr++) {\n    HOLD = V[*jptr];\n    if(fabs(HOLD)>SMALL)\n      V[*iptr] += (*aptr)*HOLD;\n#ifdef SetSmallToZero\n    else\n      V[*jptr] = 0;\n#endif\n  }\n#else\n  for(L = L1; L <= L2; L++) {\n    J = LUSOL->indc[L];\n    HOLD = V[J];\n    if(fabs(HOLD)>SMALL) {\n      I = LUSOL->indr[L];\n      V[I] += LUSOL->a[L]*HOLD;\n    }\n#ifdef SetSmallToZero\n    else\n      V[J] = 0;\n#endif\n  }\n#endif\n\n  /* Do row-based L0 version, if available */\n  if((LUSOL->L0 != NULL) ||\n     ((LUSOL->luparm[LUSOL_IP_BTRANCOUNT] == 0) && LU1L0(LUSOL, &(LUSOL->L0), INFORM))) {\n    LU6L0T_v(LUSOL, LUSOL->L0, V, NZidx, INFORM);\n  }\n\n  /* Alternatively, do the standard column-based L0 version */\n  else  {\n    /* Perform loop over columns */\n    for(K = NUML0; K >= 1; K--) {\n      SUM = ZERO;\n      LEN = LUSOL->lenc[K];\n      L1 = L2+1;\n      L2 += LEN;\n/*     ***** This loop could be coded specially. */\n#if (defined LUSOLFastSolve) && !(defined DoTraceL0)\n      for(L = L1, aptr = LUSOL->a+L1, jptr = LUSOL->indc+L1;\n          L <= L2; L++, aptr++, jptr++)\n        SUM += (*aptr) * V[*jptr];\n#else\n      for(L = L1; L <= L2; L++) {\n        J = LUSOL->indc[L];\n#ifndef DoTraceL0\n        SUM += LUSOL->a[L]*V[J];\n#else\n        TEMP = V[LUSOL->indr[L1]] + SUM;\n        SUM += LUSOL->a[L]*V[J];\n        printf(\"V[%3d] = V[%3d] + L[%d,%d]*V[%3d]\\n\", LUSOL->indr[L1], LUSOL->indr[L1], J,LUSOL->indr[L1], J);\n        printf(\"%6g = %6g + %6g*%6g\\n\", V[LUSOL->indr[L1]] + SUM, TEMP, LUSOL->a[L], V[J]);\n#endif\n      }\n#endif\n      V[LUSOL->indr[L1]] += (REAL) SUM;\n    }\n  }\n\n/*      Exit. */\n  LUSOL->luparm[LUSOL_IP_INFORM] = *INFORM;\n}\n\nvoid print_L0(LUSOLrec *LUSOL)\n{\n  int  I, J, K, L, L1, L2, LEN, LENL0, NUML0;\n  REAL *denseL0 = (REAL*) calloc(LUSOL->m+1, (LUSOL->n+1)*sizeof(*denseL0));\n\n  NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0];\n  LENL0 = LUSOL->luparm[LUSOL_IP_NONZEROS_L0];\n\n  L2 = LUSOL->lena-LENL0;\n  for(K = NUML0; K >= 1; K--) {\n    LEN = LUSOL->lenc[K];\n    L1 = L2+1;\n    L2 += LEN;\n    for(L = L1; L <= L2; L++) {\n      I = LUSOL->indc[L];\n      I = LUSOL->ipinv[I]; /* Undo row mapping */\n      J = LUSOL->indr[L];\n      denseL0[(LUSOL->n+1)*(J-1) + I] = LUSOL->a[L];\n    }\n  }\n\n  for(I = 1; I <= LUSOL->n; I++) {\n    for(J = 1; J <= LUSOL->m; J++)\n      fprintf(stdout, \"%10g\", denseL0[(LUSOL->n+1)*(J-1) + I]);\n    fprintf(stdout, \"\\n\");\n  }\n  LUSOL_FREE(denseL0);\n}\n\n\n/* ------------------------------------------------------------------\n   Include routines for column-based U.\n   5 Feb 2006 Current version - KE.\n   ------------------------------------------------------------------ */\n#include \"lusol6u.c\"\n\n\n/* ==================================================================\n   lu6U   solves   U w = v.          v  is not altered.\n   ------------------------------------------------------------------\n   15 Dec 2002: First version derived from lu6sol.\n   15 Dec 2002: Current version.\n   ================================================================== */\nvoid LU6U(LUSOLrec *LUSOL, int *INFORM, REAL V[], REAL W[], int NZidx[])\n{\n  /* Do column-based U version, if available */\n  if((LUSOL->U != NULL) ||\n     ((LUSOL->luparm[LUSOL_IP_FTRANCOUNT] == 0) && LU1U0(LUSOL, &(LUSOL->U), INFORM))) {\n    LU6U0_v(LUSOL, LUSOL->U, V, W, NZidx, INFORM);\n  }\n  /* Alternatively, do the standard column-based L0 version */\n  else {\n    int  I, J, K, KLAST, L, L1, L2, L3, NRANK, NRANK1;\n    REAL SMALL;\n    REALXP T;\n#ifdef LUSOLFastSolve\n    REAL *aptr;\n    int  *jptr;\n#endif\n    NRANK = LUSOL->luparm[LUSOL_IP_RANK_U];\n    SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n    *INFORM = LUSOL_INFORM_LUSUCCESS;\n    NRANK1 = NRANK+1;\n/*      Find the first nonzero in v(1:nrank), counting backwards. */\n    for(KLAST = NRANK; KLAST >= 1; KLAST--) {\n      I = LUSOL->ip[KLAST];\n      if(fabs(V[I])>SMALL)\n        break;\n    }\n    L = LUSOL->n;\n#ifdef LUSOLFastSolve\n    for(K = KLAST+1, jptr = LUSOL->iq+K; K <= L; K++, jptr++)\n      W[*jptr] = ZERO;\n#else\n    for(K = KLAST+1; K <= L; K++) {\n      J = LUSOL->iq[K];\n      W[J] = ZERO;\n    }\n#endif\n/*      Do the back-substitution, using rows 1:klast of U. */\n    for(K = KLAST; K >= 1; K--) {\n      I = LUSOL->ip[K];\n      T = V[I];\n      L1 = LUSOL->locr[I];\n      L2 = L1+1;\n      L3 = (L1+LUSOL->lenr[I])-1;\n/*     ***** This loop could be coded specially. */\n#ifdef LUSOLFastSolve\n      for(L = L2, aptr = LUSOL->a+L2, jptr = LUSOL->indr+L2;\n          L <= L3; L++, aptr++, jptr++)\n        T -= (*aptr) * W[*jptr];\n#else\n      for(L = L2; L <= L3; L++) {\n        J = LUSOL->indr[L];\n        T -= LUSOL->a[L]*W[J];\n      }\n#endif\n      J = LUSOL->iq[K];\n      if(fabs((REAL) T)<=SMALL)\n        T = ZERO;\n      else\n        T /= LUSOL->a[L1];\n      W[J] = (REAL) T;\n    }\n/*      Compute residual for overdetermined systems. */\n    T = ZERO;\n    for(K = NRANK1; K <= LUSOL->m; K++) {\n      I = LUSOL->ip[K];\n      T += fabs(V[I]);\n    }\n/*      Exit. */\n    if(T>ZERO)\n      *INFORM = LUSOL_INFORM_LUSINGULAR;\n    LUSOL->luparm[LUSOL_IP_INFORM]     = *INFORM;\n    LUSOL->parmlu[LUSOL_RP_RESIDUAL_U] = (REAL) T;\n  }\n}\n\n/* ==================================================================\n   lu6Ut  solves   U'v = w.          w  is destroyed.\n   ------------------------------------------------------------------\n   15 Dec 2002: First version derived from lu6sol.\n   15 Dec 2002: Current version.\n   ================================================================== */\nvoid LU6UT(LUSOLrec *LUSOL, int *INFORM, REAL V[], REAL W[], int NZidx[])\n{\n  (void)NZidx;\n  int  I, J, K, L, L1, L2, NRANK, NRANK1,\n       *ip = LUSOL->ip + 1, *iq = LUSOL->iq + 1;\n  REAL SMALL;\n  REAL T;\n#ifdef LUSOLFastSolve\n  REAL *aptr;\n  int  *jptr;\n#endif\n  (void)NZidx;\n\n  NRANK = LUSOL->luparm[LUSOL_IP_RANK_U];\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  NRANK1 = NRANK+1;\n  L = LUSOL->m;\n#ifdef LUSOLFastSolve\n  for(K = NRANK1, jptr = LUSOL->ip+K; K <= L; K++, jptr++)\n    V[*jptr] = ZERO;\n#else\n  for(K = NRANK1; K <= L; K++) {\n    I = LUSOL->ip[K];\n    V[I] = ZERO;\n  }\n#endif\n/*      Do the forward-substitution, skipping columns of U(transpose)\n        when the associated element of w(*) is negligible. */\n#if 0\n  for(K = 1; K <= NRANK; K++) {\n    I = LUSOL->ip[K];\n    J = LUSOL->iq[K];\n#else\n  for(K = 1; K <= NRANK; K++, ip++, iq++) {\n    I = *ip;\n    J = *iq;\n#endif\n    T = W[J];\n    if(fabs(T)<=SMALL) {\n      V[I] = ZERO;\n      continue;\n    }\n    L1 = LUSOL->locr[I];\n    T /= LUSOL->a[L1];\n    V[I] = T;\n    L2 = (L1+LUSOL->lenr[I])-1;\n    L1++;\n/*     ***** This loop could be coded specially. */\n#ifdef LUSOLFastSolve\n    for(L = L1, aptr = LUSOL->a+L1, jptr = LUSOL->indr+L1;\n        L <= L2; L++, aptr++, jptr++)\n      W[*jptr] -= T * (*aptr);\n#else\n    for(L = L1; L <= L2; L++) {\n      J = LUSOL->indr[L];\n      W[J] -= T*LUSOL->a[L];\n    }\n#endif\n  }\n/*      Compute residual for overdetermined systems. */\n  T = ZERO;\n  for(K = NRANK1; K <= LUSOL->n; K++) {\n    J = LUSOL->iq[K];\n    T += fabs(W[J]);\n  }\n/*      Exit. */\n  if(T>ZERO)\n    *INFORM = LUSOL_INFORM_LUSINGULAR;\n  LUSOL->luparm[LUSOL_IP_INFORM]     = *INFORM;\n  LUSOL->parmlu[LUSOL_RP_RESIDUAL_U] = T;\n}\n\n/* ==================================================================\n   lu6sol  uses the factorization  A = L U  as follows:\n   ------------------------------------------------------------------\n   mode\n    1    v  solves   L v = v(input).   w  is not touched.\n    2    v  solves   L'v = v(input).   w  is not touched.\n    3    w  solves   U w = v.          v  is not altered.\n    4    v  solves   U'v = w.          w  is destroyed.\n    5    w  solves   A w = v.          v  is altered as in 1.\n    6    v  solves   A'v = w.          w  is destroyed.\n\n   If mode = 3,4,5,6, v and w must not be the same arrays.\n   If lu1fac has just been used to factorize a symmetric matrix A\n   (which must be definite or quasi-definite), the factors A = L U\n   may be regarded as A = LDL', where D = diag(U).  In such cases,\n\n   mode\n    7    v  solves   A v = L D L'v = v(input).   w  is not touched.\n    8    v  solves       L |D| L'v = v(input).   w  is not touched.\n\n   ip(*), iq(*)      hold row and column numbers in pivotal order.\n   lenc(k)           is the length of the k-th column of initial L.\n   lenr(i)           is the length of the i-th row of U.\n   locc(*)           is not used.\n   locr(i)           is the start  of the i-th row of U.\n\n   U is assumed to be in upper-trapezoidal form (nrank by n).\n   The first entry for each row is the diagonal element\n   (according to the permutations  ip, iq).  It is stored at\n   location locr(i) in a(*), indr(*).\n\n   On exit, inform = 0 except as follows.\n     if(mode = 3,4,5,6 and if U (and hence A) is singular,)\n     inform = 1 if there is a nonzero residual in solving the system\n     involving U.  parmlu(20) returns the norm of the residual.\n   ------------------------------------------------------------------\n     July 1987: Early version.\n   09 May 1988: f77 version.\n   27 Apr 2000: Abolished the dreaded \"computed go to\".\n                But hard to change other \"go to\"s to \"if then else\".\n   15 Dec 2002: lu6L, lu6Lt, lu6U, lu6Ut added to modularize lu6sol.\n   ================================================================== */\nvoid LU6SOL(LUSOLrec *LUSOL, int MODE, REAL V[], REAL W[], int NZidx[], int *INFORM)\n{\n  if(MODE==LUSOL_SOLVE_Lv_v) {          /* Solve  L v(new) = v. */\n    LU6L(LUSOL, INFORM,V, NZidx);\n  }\n  else if(MODE==LUSOL_SOLVE_Ltv_v) {    /* Solve  L'v(new) = v. */\n    LU6LT(LUSOL, INFORM,V, NZidx);\n  }\n  else if(MODE==LUSOL_SOLVE_Uw_v) {     /* Solve  U w = v. */\n    LU6U(LUSOL, INFORM,V,W, NZidx);\n  }\n  else if(MODE==LUSOL_SOLVE_Utv_w) {    /* Solve  U'v = w. */\n    LU6UT(LUSOL, INFORM,V,W, NZidx);\n  }\n  else if(MODE==LUSOL_SOLVE_Aw_v) {     /* Solve  A w      = v (i.e. FTRAN) */\n    LU6L(LUSOL, INFORM,V, NZidx);        /* via     L v(new) = v */\n    LU6U(LUSOL, INFORM,V,W, NULL);       /* ... and U w = v(new). */\n  }\n  else if(MODE==LUSOL_SOLVE_Atv_w) {    /* Solve  A'v = w (i.e. BTRAN) */\n    LU6UT(LUSOL, INFORM,V,W, NZidx);     /* via      U'v = w */\n    LU6LT(LUSOL, INFORM,V, NULL);        /* ... and  L'v(new) = v. */\n  }\n  else if(MODE==LUSOL_SOLVE_Av_v) {     /* Solve  LDv(bar) = v */\n    LU6LD(LUSOL, INFORM,1,V, NZidx);     /* and    L'v(new) = v(bar). */\n    LU6LT(LUSOL, INFORM,V, NULL);\n  }\n  else if(MODE==LUSOL_SOLVE_LDLtv_v) {  /* Solve  L|D|v(bar) = v */\n    LU6LD(LUSOL, INFORM,2,V, NZidx);     /* and    L'v(new) = v(bar). */\n    LU6LT(LUSOL, INFORM,V, NULL);\n  }\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol6l0.c",
    "content": "\n/* Create a row-based version of L0.\n   This makes it possible to solve L0'x=h (btran) faster for sparse h,\n   since we only run down the columns of L0' (rows of LO) for which\n   the corresponding entry in h is non-zero. */\nMYBOOL LU1L0(LUSOLrec *LUSOL, LUSOLmat **mat, int *inform)\n{\n  MYBOOL status = FALSE;\n  int    K, L, LL, L1, L2, LENL0, NUML0, I;\n  int    *lsumr;\n\n  /* Assume success */\n  *inform = LUSOL_INFORM_LUSUCCESS;\n\n  /* Check if there is anything worth doing */\n  if(mat == NULL)\n    return( status );\n  if(*mat != NULL)\n    LUSOL_matfree(mat);\n  NUML0 = LUSOL->luparm[LUSOL_IP_COLCOUNT_L0];\n  LENL0 = LUSOL->luparm[LUSOL_IP_NONZEROS_L0];\n  if((NUML0 == 0) || (LENL0 == 0) ||\n     (LUSOL->luparm[LUSOL_IP_ACCELERATION] == LUSOL_BASEORDER) ||\n     ((LUSOL->luparm[LUSOL_IP_ACCELERATION] & LUSOL_ACCELERATE_L0) == 0))\n    return( status );\n\n  /* Allocate temporary array */\n  lsumr = (int *) LUSOL_CALLOC((LUSOL->m+1), sizeof(*lsumr));\n  if(lsumr == NULL) {\n    *inform = LUSOL_INFORM_NOMEMLEFT;\n    return( status );\n  }\n\n  /* Compute non-zero counts by permuted row index (order is unimportant) */\n  K = 0;\n  L2 = LUSOL->lena;\n  L1 = L2-LENL0+1;\n  for(L = L1; L <= L2; L++) {\n    I = LUSOL->indc[L];\n    lsumr[I]++;\n    if(lsumr[I] == 1)\n      K++;\n  }\n  LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0] = K;\n\n  /* Check if we should apply \"smarts\" before proceeding to the row matrix creation */\n  if((LUSOL->luparm[LUSOL_IP_ACCELERATION] & LUSOL_AUTOORDER) &&\n     ((REAL) LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0] /\n#if 0\n             LUSOL->luparm[LUSOL_IP_COLCOUNT_L0]\n#else\n             LUSOL->m\n#endif\n      > LUSOL->parmlu[LUSOL_RP_SMARTRATIO]))\n    goto Finish;\n\n  /* We are Ok to create the new matrix object */\n  *mat = LUSOL_matcreate(LUSOL->m, LENL0);\n  if(*mat == NULL) {\n    *inform = LUSOL_INFORM_NOMEMLEFT;\n    goto Finish;\n  }\n\n  /* Cumulate row counts to get vector offsets; first row is leftmost\n     (stick with Fortran array offset for consistency) */\n  (*mat)->lenx[0] = 1;\n  for(K = 1; K <= LUSOL->m; K++) {\n    (*mat)->lenx[K] = (*mat)->lenx[K-1] + lsumr[K];\n    lsumr[K] = (*mat)->lenx[K-1];\n  }\n\n  /* Map the matrix into row order by permuted index;\n     Note: The first permuted row is located leftmost in the array.\n           The column order is irrelevant, since the indeces will\n           refer to constant / resolved values of V[] during solve. */\n  L2 = LUSOL->lena;\n  L1 = L2-LENL0+1;\n  for(L = L1; L <= L2; L++) {\n    I = LUSOL->indc[L];\n    LL = lsumr[I]++;\n    (*mat)->a[LL] = LUSOL->a[L];\n    (*mat)->indr[LL] = LUSOL->indr[L];\n    (*mat)->indc[LL] = I;\n  }\n\n  /* Pack row starting positions, and set mapper from original index to packed */\n  I = 0;\n  for(L = 1; L <= LUSOL->m; L++) {\n    K = LUSOL->ip[L];\n    if((*mat)->lenx[K] > (*mat)->lenx[K-1]) {\n      I++;\n      (*mat)->indx[I] = K;\n    }\n  }\n\n  /* Confirm that everything went well */\n  status = TRUE;\n\n  /* Clean up */\nFinish:\n  FREE(lsumr);\n  return( status );\n}\n\n/* Solve L0' v = v based on row-based version of L0, constructed by LU1L0 */\nvoid LU6L0T_v(LUSOLrec *LUSOL, LUSOLmat *mat, REAL V[], int NZidx[], int *INFORM)\n{\n  int  LEN, K, KK, L, L1, NUML0;\n#ifdef DoTraceL0\n  REAL TEMP;\n#endif\n  REAL SMALL;\n  REAL VPIV;\n#if (defined LUSOLFastSolve) && !(defined DoTraceL0)\n  REAL *aptr;\n  int  *jptr;\n#else\n  int  J;\n#endif\n  (void)NZidx;\n  (void)INFORM;\n\n  NUML0 = LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0];\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n\n  /* Loop over the nz columns of L0' - from the end, going forward. */\n  for(K = NUML0; K > 0; K--) {\n    KK = mat->indx[K];\n    L  = mat->lenx[KK];\n    L1 = mat->lenx[KK-1];\n    LEN = L - L1;\n    if(LEN == 0)\n      continue;\n    /* Get value of the corresponding active entry of V[] */\n    VPIV = V[KK];\n    /* Only process the column of L0' if the value of V[] is non-zero */\n    if(fabs(VPIV)>SMALL) {\n/*     ***** This loop could be coded specially. */\n#if (defined LUSOLFastSolve) && !(defined DoTraceL0)\n      L--;\n      for(aptr = mat->a+L, jptr = mat->indr+L;\n          LEN > 0; LEN--, aptr--, jptr--)\n        V[*jptr] += VPIV * (*aptr);\n#else\n      for(; LEN > 0; LEN--) {\n        L--;\n        J = mat->indr[L];\n#ifndef DoTraceL0\n        V[J] += VPIV * mat->a[L];\n#else\n        TEMP = V[J];\n        V[J] += VPIV * mat->a[L];\n        printf(\"V[%3d] = V[%3d] + L[%d,%d]*V[%3d]\\n\", J, J, KK,J, KK);\n        printf(\"%6g = %6g + %6g*%6g\\n\", V[J], TEMP, mat->a[L], VPIV);\n#endif\n      }\n#endif\n    }\n#ifdef SetSmallToZero\n    else\n      V[KK] = 0;\n#endif\n  }\n\n}\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol6u.c",
    "content": "\n/* Create a column-based version of U.\n   This makes it possible to solve Ux=h (ftran) faster for sparse h,\n   since we only run down the rows of U (columns of U') for which\n   the corresponding entry in h is non-zero. */\nMYBOOL LU1U0(LUSOLrec *LUSOL, LUSOLmat **mat, int *inform)\n{\n  MYBOOL status = FALSE;\n  int    K, L, LL, LENU, NUMU, J;\n  int    *lsumc;\n\n  /* Assume success */\n  *inform = LUSOL_INFORM_LUSUCCESS;\n\n  /* Check if there is anything worth doing */\n  if(mat == NULL)\n    return( status );\n  if(*mat != NULL)\n    LUSOL_matfree(mat);\n  NUMU = LUSOL->luparm[LUSOL_IP_RANK_U];\n  LENU = LUSOL->luparm[LUSOL_IP_NONZEROS_U];\n  if((NUMU == 0) || (LENU == 0) ||\n     (LUSOL->luparm[LUSOL_IP_ACCELERATION] == LUSOL_BASEORDER) ||\n     ((LUSOL->luparm[LUSOL_IP_ACCELERATION] & LUSOL_ACCELERATE_U) == 0))\n    return( status );\n\n  /* Allocate temporary array */\n  lsumc = (int *) LUSOL_CALLOC((LUSOL->n+1), sizeof(*lsumc));\n  if(lsumc == NULL) {\n    *inform = LUSOL_INFORM_NOMEMLEFT;\n    return( status );\n  }\n\n  /* Compute non-zero counts by permuted column index (order is unimportant) */\n  for(L = 1; L <= LENU; L++) {\n    J = LUSOL->indr[L];\n    lsumc[J]++;\n  }\n\n  /* Check if we should apply \"smarts\" before proceeding to the column matrix creation */\n  if((LUSOL->luparm[LUSOL_IP_ACCELERATION] & LUSOL_AUTOORDER) &&\n     ((REAL) sqrt((REAL) NUMU/LENU) > LUSOL->parmlu[LUSOL_RP_SMARTRATIO]))\n    goto Finish;\n\n  /* We are Ok to create the new matrix object */\n  *mat = LUSOL_matcreate(LUSOL->n, LENU);\n  if(*mat == NULL) {\n    *inform = LUSOL_INFORM_NOMEMLEFT;\n    goto Finish;\n  }\n\n  /* Cumulate row counts to get vector offsets; first column is leftmost\n     (stick with Fortran array offset for consistency) */\n  (*mat)->lenx[0] = 1;\n  for(K = 1; K <= LUSOL->n; K++) {\n    (*mat)->lenx[K] = (*mat)->lenx[K-1] + lsumc[K];\n    lsumc[K] = (*mat)->lenx[K-1];\n  }\n\n  /* Map the matrix into column order by permuted index;\n     Note: The first permuted column is located leftmost in the array.\n           The row order is irrelevant, since the indeces will\n           refer to constant / resolved values of V[] during solve. */\n  for(L = 1; L <= LENU; L++) {\n    J = LUSOL->indr[L];\n    LL = lsumc[J]++;\n    (*mat)->a[LL] = LUSOL->a[L];\n    (*mat)->indr[LL] = J;\n    (*mat)->indc[LL] = LUSOL->indc[L];\n  }\n\n  /* Pack column starting positions, and set mapper from original index to packed */\n  J = 0;\n  for(L = 1; L <= LUSOL->n; L++) {\n    K = LUSOL->iq[L];\n#if 1  /* Deactivate to produce a full-rank version (implicit unit diagonals) */\n    if((*mat)->lenx[K] > (*mat)->lenx[K-1])\n#endif\n    {\n      J++;\n     (*mat)->indx[J] = K;\n    }\n  }\n\n  /* Confirm that everything went well */\n  status = TRUE;\n\n  /* Clean up */\nFinish:\n  FREE(lsumc);\n  return( status );\n}\n\n/* Solve U w = v based on column-based version of U, constructed by LU1U0 */\nvoid LU6U0_v(LUSOLrec *LUSOL, LUSOLmat *mat, REAL V[], REAL W[], int NZidx[], int *INFORM)\n{\n  (void)NZidx;\n#ifdef DoTraceU0\n  REAL TEMP;\n#endif\n  int  LEN, I, K, L, L1, NRANK, NRANK1, KLAST;\n  REAL SMALL;\n  REAL T;\n#if (defined xxLUSOLFastSolve) && !(defined DoTraceU0)\n  REAL *aptr;\n  int  *jptr;\n#else\n  int  J;\n#endif\n  (void)NZidx;\n\n  NRANK = LUSOL->luparm[LUSOL_IP_RANK_U];\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  NRANK1 = NRANK+1;\n/*      Find the first nonzero in v(1:nrank), counting backwards. */\n  for(KLAST = NRANK; KLAST >= 1; KLAST--) {\n    I = LUSOL->ip[KLAST];\n    if(fabs(V[I])>SMALL)\n      break;\n  }\n  L = LUSOL->n;\n#ifdef xxLUSOLFastSolve\n  for(K = KLAST+1, jptr = LUSOL->iq+K; K <= L; K++, jptr++)\n    W[*jptr] = ZERO;\n#else\n  for(K = KLAST+1; K <= L; K++) {\n    J = LUSOL->iq[K];\n    W[J] = ZERO;\n  }\n#endif\n  /* Loop over the nz columns of U - from the right, going left. */\n  for(K = NRANK; K > 0; K--) {\n    I = mat->indx[K];\n    L = mat->lenx[I];\n    L1 = mat->lenx[I-1];\n    LEN = L - L1;\n    T = V[I];\n    if(fabs(T)<=SMALL) {\n      W[K] = ZERO;\n      continue;\n    }\n    T /= mat->a[L1];  /* Should it be L or L1 ? */\n    W[K] = T;\n    LEN--;\n/*     ***** This loop could be coded specially. */\n#ifdef xxLUSOLFastSolve\n    L--;\n    for(aptr = mat->a+L, jptr = mat->indc+L;\n        LEN > 0; LEN--, aptr--, jptr--)\n      V[*jptr] -= T * (*aptr);\n#else\n    for(; LEN > 0; LEN--) {\n      L--;\n      J = mat->indc[L];\n#ifndef DoTraceL0\n      V[J] -= T * mat->a[L];\n#else\n      TEMP = V[J];\n      V[J] += T * mat->a[L];\n      printf(\"V[%3d] = V[%3d] + L[%d,%d]*V[%3d]\\n\", J, J, I,J, I);\n      printf(\"%6g = %6g + %6g*%6g\\n\", V[J], TEMP, mat->a[L], T);\n#endif\n    }\n#endif\n  }\n/*      Compute residual for overdetermined systems. */\n  T = ZERO;\n  for(K = NRANK1; K <= LUSOL->m; K++) {\n    I = LUSOL->ip[K];\n    T += fabs(V[I]);\n  }\n/*      Exit. */\n  if(T>ZERO)\n    *INFORM = LUSOL_INFORM_LUSINGULAR;\n  LUSOL->luparm[LUSOL_IP_INFORM]     = *INFORM;\n  LUSOL->parmlu[LUSOL_RP_RESIDUAL_U] = (REAL) T;\n}\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol7a.c",
    "content": "\n/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   File  lusol7a\n      lu7add   lu7cyc   lu7elm   lu7for   lu7rnk   lu7zap\n      Utilities for LUSOL's update routines.\n      lu7for is the most important -- the forward sweep.\n  01 May 2002: Derived from LUSOL's original lu7a.f file.\n  01 May 2002: Current version of lusol7a.f.\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */\n\n/* ==================================================================\n   lu7add  inserts the first nrank elements of the vector v(*)\n   as column  jadd  of  U.  We assume that  U  does not yet have any\n   entries in this column.\n   Elements no larger than  parmlu(3)  are treated as zero.\n   klast  will be set so that the last row to be affected\n   (in pivotal order) is row  ip(klast).\n   ------------------------------------------------------------------\n   09 May 1988: First f77 version.\n   ================================================================== */\nvoid LU7ADD(LUSOLrec *LUSOL, int JADD, REAL V[], int LENL, int *LENU,\n  int *LROW, int NRANK, int *INFORM, int *KLAST, REAL *VNORM)\n{\n  REAL SMALL;\n  int  K, I, LENI, MINFRE, NFREE, LR1, LR2, L;\n#ifndef LUSOLFastMove\n  int J;\n#endif\n\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  *VNORM = ZERO;\n  *KLAST = 0;\n  for(K = 1; K <= NRANK; K++) {\n    I = LUSOL->ip[K];\n    if(fabs(V[I])<=SMALL)\n      continue;\n    *KLAST = K;\n    (*VNORM) += fabs(V[I]);\n    LENI = LUSOL->lenr[I];\n/*         Compress row file if necessary. */\n    MINFRE = LENI+1;\n    NFREE = LUSOL->lena - LENL - *LROW;\n    if(NFREE<MINFRE) {\n      LU1REC(LUSOL, LUSOL->m, TRUE,LROW,LUSOL->indr,LUSOL->lenr,LUSOL->locr);\n      NFREE = LUSOL->lena - LENL - *LROW;\n      if(NFREE<MINFRE)\n        goto x970;\n    }\n/*         Move row  i  to the end of the row file,\n           unless it is already there.\n           No need to move if there is a gap already. */\n    if(LENI==0)\n      LUSOL->locr[I] = (*LROW) + 1;\n    LR1 = LUSOL->locr[I];\n    LR2 = (LR1+LENI)-1;\n    if(LR2==*LROW)\n      goto x150;\n    if(LUSOL->indr[LR2+1]==0)\n      goto x180;\n    LUSOL->locr[I] = (*LROW) + 1;\n#ifdef LUSOLFastMove\n    L = LR2-LR1+1;\n    if(L > 0) {\n      LR2 = (*LROW)+1;\n      MEMMOVE(LUSOL->a+LR2,    LUSOL->a+LR1, L);\n      MEMMOVE(LUSOL->indr+LR2, LUSOL->indr+LR1, L);\n      MEMCLEAR(LUSOL->indr+LR1, L);\n      *LROW += L;\n    }\n#else\n    for(L = LR1; L <= LR2; L++) {\n      (*LROW)++;\n      LUSOL->a[*LROW] = LUSOL->a[L];\n      J = LUSOL->indr[L];\n      LUSOL->indr[L] = 0;\n      LUSOL->indr[*LROW] = J;\n    }\n#endif\nx150:\n    LR2 = *LROW;\n    (*LROW)++;\n/*         Add the element of  v. */\nx180:\n    LR2++;\n    LUSOL->a[LR2] = V[I];\n    LUSOL->indr[LR2] = JADD;\n    LUSOL->lenr[I] = LENI+1;\n    (*LENU)++;\n  }\n/*      Normal exit. */\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  goto x990;\n/*      Not enough storage. */\nx970:\n  *INFORM = LUSOL_INFORM_ANEEDMEM;\nx990:\n;\n}\n\n/* ==================================================================\n   lu7cyc performs a cyclic permutation on the row or column ordering\n   stored in ip, moving entry kfirst down to klast.\n   If kfirst .ge. klast, lu7cyc should not be called.\n   Sometimes klast = 0 and nothing should happen.\n   ------------------------------------------------------------------\n   09 May 1988: First f77 version.\n   ================================================================== */\nvoid LU7CYC(LUSOLrec *LUSOL, int KFIRST, int KLAST, int IX[])\n{\n  (void)LUSOL;\n  if(KFIRST<KLAST) {\n    int IFIRST, K;\n#ifdef LUSOLFastMove\n#if 1\n    IFIRST = IX[KFIRST];\n    K = KLAST-KFIRST;\n    MEMMOVE(IX+KFIRST, IX+KFIRST+1, K);\n    IX[KLAST] = IFIRST;\n#else\n    int *IXK, *IXK1;\n    IXK = IX+KFIRST;\n    IFIRST = *IXK;\n    for(K = KFIRST, IXK1 = IXK+1; K <= KLAST-1; K++, IXK++, IXK1++) {\n      *IXK = *IXK1;\n    }\n    *IXK = IFIRST;\n#endif\n#else\n    IFIRST = IX[KFIRST];\n    for(K = KFIRST; K <= KLAST-1; K++) {\n      IX[K] = IX[K+1];\n    }\n    IX[KLAST] = IFIRST;\n#endif\n  }\n}\n\n/* ==================================================================\n   lu7elm  eliminates the subdiagonal elements of a vector  v(*),\n   where  L*v = y  for some vector y.\n   If  jelm > 0,  y  has just become column  jelm  of the matrix  A.\n   lu7elm  should not be called unless  m  is greater than  nrank.\n   inform = 0 if y contained no subdiagonal nonzeros to eliminate.\n   inform = 1 if y contained at least one nontrivial subdiagonal.\n   inform = 7 if there is insufficient storage.\n   ------------------------------------------------------------------\n   09 May 1988: First f77 version.\n                No longer calls lu7for at end.  lu8rpc, lu8mod do so.\n   ================================================================== */\nvoid LU7ELM(LUSOLrec *LUSOL, int JELM, REAL V[], int *LENL,\n            int *LROW, int NRANK, int *INFORM, REAL *DIAG)\n{\n  REAL VI, VMAX, SMALL;\n  int  NRANK1, MINFRE, NFREE, KMAX, L, K, I, LMAX, IMAX, L1, L2;\n\n#ifdef ForceInitialization\n  LMAX = 0;\n#endif\n\n  SMALL = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  NRANK1 = NRANK+1;\n  *DIAG = ZERO;\n/*      Compress row file if necessary. */\n  MINFRE = LUSOL->m-NRANK;\n  NFREE = LUSOL->lena-(*LENL)-(*LROW);\n  if(NFREE>=MINFRE)\n    goto x100;\n  LU1REC(LUSOL, LUSOL->m,TRUE,LROW,LUSOL->indr,LUSOL->lenr,LUSOL->locr);\n  NFREE = LUSOL->lena-(*LENL)-(*LROW);\n  if(NFREE<MINFRE)\n    goto x970;\n\n/*      Pack the subdiagonals of  v  into  L,  and find the largest. */\nx100:\n  VMAX = ZERO;\n  KMAX = 0;\n  L = (LUSOL->lena-(*LENL))+1;\n  for(K = NRANK1; K <= LUSOL->m; K++) {\n    I = LUSOL->ip[K];\n    VI = fabs(V[I]);\n    if(VI<=SMALL)\n      continue;\n    L--;\n    LUSOL->a[L] = V[I];\n    LUSOL->indc[L] = I;\n    if(VMAX>=VI)\n      continue;\n    VMAX = VI;\n    KMAX = K;\n    LMAX = L;\n  }\n  if(KMAX==0)\n    goto x900;\n/*      ------------------------------------------------------------------\n        Remove  vmax  by overwriting it with the last packed  v(i).\n        Then set the multipliers in  L  for the other elements.\n        ------------------------------------------------------------------ */\n  IMAX = LUSOL->ip[KMAX];\n  VMAX = LUSOL->a[LMAX];\n  LUSOL->a[LMAX] = LUSOL->a[L];\n  LUSOL->indc[LMAX] = LUSOL->indc[L];\n  L1 = L+1;\n  L2 = LUSOL->lena-(*LENL);\n  *LENL = ((*LENL)+L2)-L;\n  for(L = L1; L <= L2; L++) {\n    LUSOL->a[L] /= -VMAX;\n    LUSOL->indr[L] = IMAX;\n  }\n/*      Move the row containing vmax to pivotal position nrank + 1. */\n  LUSOL->ip[KMAX] = LUSOL->ip[NRANK1];\n  LUSOL->ip[NRANK1] = IMAX;\n  *DIAG = VMAX;\n/*      ------------------------------------------------------------------\n        If jelm is positive, insert  vmax  into a new row of  U.\n        This is now the only subdiagonal element.\n        ------------------------------------------------------------------ */\n  if(JELM>0) {\n    (*LROW)++;\n    LUSOL->locr[IMAX] = *LROW;\n    LUSOL->lenr[IMAX] = 1;\n    LUSOL->a[*LROW] = VMAX;\n    LUSOL->indr[*LROW] = JELM;\n  }\n  *INFORM = LUSOL_INFORM_LUSINGULAR;\n  goto x990;\n/*      No elements to eliminate. */\nx900:\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  goto x990;\n/*      Not enough storage. */\nx970:\n  *INFORM = LUSOL_INFORM_ANEEDMEM;\nx990:\n;\n}\n\n/* ==================================================================\n   lu7for  (forward sweep) updates the LU factorization  A = L*U\n   when row  iw = ip(klast)  of  U  is eliminated by a forward\n   sweep of stabilized row operations, leaving  ip * U * iq  upper\n   triangular.\n   The row permutation  ip  is updated to preserve stability and/or\n   sparsity.  The column permutation  iq  is not altered.\n   kfirst  is such that row  ip(kfirst)  is the first row involved\n   in eliminating row  iw.  (Hence,  kfirst  marks the first nonzero\n   in row  iw  in pivotal order.)  If  kfirst  is unknown it may be\n   input as  1.\n   klast   is such that row  ip(klast)  is the row being eliminated.\n   klast   is not altered.\n   lu7for  should be called only if  kfirst .le. klast.\n   If  kfirst = klast,  there are no nonzeros to eliminate, but the\n   diagonal element of row  ip(klast)  may need to be moved to the\n   front of the row.\n   ------------------------------------------------------------------\n   On entry,  locc(*)  must be zero.\n\n   On exit:\n   inform = 0  if row iw has a nonzero diagonal (could be small).\n   inform = 1  if row iw has no diagonal.\n   inform = 7  if there is not enough storage to finish the update.\n\n   On a successful exit (inform le 1),  locc(*)  will again be zero.\n   ------------------------------------------------------------------\n      Jan 1985: Final f66 version.\n   09 May 1988: First f77 version.\n   ================================================================== */\nvoid LU7FOR(LUSOLrec *LUSOL, int KFIRST, int KLAST, int *LENL, int *LENU,\n                     int *LROW, int *INFORM, REAL *DIAG)\n{\n  MYBOOL SWAPPD;\n  int    KBEGIN, IW, LENW, LW1, LW2, JFIRST, MINFRE, NFREE, L, J, KSTART, KSTOP, K,\n         LFIRST, IV, LENV, LV1, JLAST, LV2, LV3, LV, JV, LW, LDIAG, LIMIT;\n  REAL   AMULT, LTOL, USPACE, SMALL, VJ, WJ;\n\n  LTOL   = LUSOL->parmlu[LUSOL_RP_UPDATEMAX_Lij];\n  SMALL  = LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE];\n  USPACE = LUSOL->parmlu[LUSOL_RP_COMPSPACE_U];\n  KBEGIN = KFIRST;\n  SWAPPD = FALSE;\n\n/*      We come back here from below if a row interchange is performed. */\nx100:\n  IW = LUSOL->ip[KLAST];\n  LENW = LUSOL->lenr[IW];\n  if(LENW==0)\n    goto x910;\n  LW1 = LUSOL->locr[IW];\n  LW2 = (LW1+LENW)-1;\n  JFIRST = LUSOL->iq[KBEGIN];\n  if(KBEGIN>=KLAST)\n    goto x700;\n/*      Make sure there is room at the end of the row file\n        in case row  iw  is moved there and fills in completely. */\n  MINFRE = LUSOL->n+1;\n  NFREE = LUSOL->lena-(*LENL)-(*LROW);\n  if(NFREE<MINFRE) {\n    LU1REC(LUSOL, LUSOL->m,TRUE,LROW,LUSOL->indr,LUSOL->lenr,LUSOL->locr);\n    LW1 = LUSOL->locr[IW];\n    LW2 = (LW1+LENW)-1;\n    NFREE = LUSOL->lena-(*LENL)-(*LROW);\n    if(NFREE<MINFRE)\n      goto x970;\n\n  }\n/*      Set markers on row  iw. */\n  for(L = LW1; L <= LW2; L++) {\n    J = LUSOL->indr[L];\n    LUSOL->locc[J] = L;\n  }\n/*      ==================================================================\n        Main elimination loop.\n        ================================================================== */\n  KSTART = KBEGIN;\n  KSTOP = MIN(KLAST,LUSOL->n);\n  for(K = KSTART; K <= KSTOP; K++) {\n    JFIRST = LUSOL->iq[K];\n    LFIRST = LUSOL->locc[JFIRST];\n    if(LFIRST==0)\n      goto x490;\n/*         Row  iw  has its first element in column  jfirst. */\n    WJ = LUSOL->a[LFIRST];\n    if(K==KLAST)\n      goto x490;\n/*         ---------------------------------------------------------------\n           We are about to use the first element of row  iv\n                  to eliminate the first element of row  iw.\n           However, we may wish to interchange the rows instead,\n           to preserve stability and/or sparsity.\n           --------------------------------------------------------------- */\n    IV = LUSOL->ip[K];\n    LENV = LUSOL->lenr[IV];\n    LV1 = LUSOL->locr[IV];\n    VJ = ZERO;\n    if(LENV==0)\n      goto x150;\n    if(LUSOL->indr[LV1]!=JFIRST)\n      goto x150;\n    VJ = LUSOL->a[LV1];\n    if(SWAPPD)\n      goto x200;\n    if(LTOL*fabs(WJ)<fabs(VJ))\n      goto x200;\n    if(LTOL*fabs(VJ)<fabs(WJ))\n      goto x150;\n    if(LENV<=LENW)\n      goto x200;\n/*         ---------------------------------------------------------------\n           Interchange rows  iv  and  iw.\n           --------------------------------------------------------------- */\nx150:\n    LUSOL->ip[KLAST] = IV;\n    LUSOL->ip[K] = IW;\n    KBEGIN = K;\n    SWAPPD = TRUE;\n    goto x600;\n/*         ---------------------------------------------------------------\n           Delete the eliminated element from row  iw\n           by overwriting it with the last element.\n           --------------------------------------------------------------- */\nx200:\n    LUSOL->a[LFIRST] = LUSOL->a[LW2];\n    JLAST = LUSOL->indr[LW2];\n    LUSOL->indr[LFIRST] = JLAST;\n    LUSOL->indr[LW2] = 0;\n    LUSOL->locc[JLAST] = LFIRST;\n    LUSOL->locc[JFIRST] = 0;\n    LENW--;\n    (*LENU)--;\n    if(*LROW==LW2)\n      (*LROW)--;\n    LW2 = LW2-1;\n/*         ---------------------------------------------------------------\n           Form the multiplier and store it in the  L  file.\n           --------------------------------------------------------------- */\n    if(fabs(WJ)<=SMALL)\n      goto x490;\n    AMULT = -WJ/VJ;\n    L = LUSOL->lena-(*LENL);\n    LUSOL->a[L] = AMULT;\n    LUSOL->indr[L] = IV;\n    LUSOL->indc[L] = IW;\n    (*LENL)++;\n/*         ---------------------------------------------------------------\n           Add the appropriate multiple of row  iv  to row  iw.\n           We use two different inner loops.  The first one is for the\n           case where row  iw  is not at the end of storage.\n           --------------------------------------------------------------- */\n    if(LENV==1)\n      goto x490;\n    LV2 = LV1+1;\n    LV3 = (LV1+LENV)-1;\n    if(LW2==*LROW)\n      goto x400;\n/*         ...............................................................\n           This inner loop will be interrupted only if\n           fill-in occurs enough to bump into the next row.\n           ............................................................... */\n    for(LV = LV2; LV <= LV3; LV++) {\n      JV = LUSOL->indr[LV];\n      LW = LUSOL->locc[JV];\n      if(LW>0) {\n/*               No fill-in. */\n        LUSOL->a[LW] += AMULT*LUSOL->a[LV];\n        if(fabs(LUSOL->a[LW])<=SMALL) {\n/*                  Delete small computed element. */\n          LUSOL->a[LW] = LUSOL->a[LW2];\n          J = LUSOL->indr[LW2];\n          LUSOL->indr[LW] = J;\n          LUSOL->indr[LW2] = 0;\n          LUSOL->locc[J] = LW;\n          LUSOL->locc[JV] = 0;\n          (*LENU)--;\n          LENW--;\n          LW2--;\n        }\n      }\n      else {\n/*               Row  iw  doesn't have an element in column  jv  yet\n                 so there is a fill-in. */\n        if(LUSOL->indr[LW2+1]!=0)\n          goto x360;\n        (*LENU)++;\n        LENW++;\n        LW2++;\n        LUSOL->a[LW2] = AMULT*LUSOL->a[LV];\n        LUSOL->indr[LW2] = JV;\n        LUSOL->locc[JV] = LW2;\n      }\n    }\n    goto x490;\n/*         Fill-in interrupted the previous loop.\n           Move row  iw  to the end of the row file. */\nx360:\n    LV2 = LV;\n    LUSOL->locr[IW] = (*LROW)+1;\n\n#ifdef LUSOLFastMove\n    L = LW2-LW1+1;\n    if(L > 0) {\n      int loci, *locp;\n      for(loci = LW1, locp = LUSOL->indr+LW1;\n          loci <= LW2; loci++, locp++) {\n        (*LROW)++;\n        LUSOL->locc[*locp] = *LROW;\n      }\n      LW2 = (*LROW)-L+1;\n      MEMMOVE(LUSOL->a+LW2,    LUSOL->a+LW1, L);\n      MEMMOVE(LUSOL->indr+LW2, LUSOL->indr+LW1, L);\n      MEMCLEAR(LUSOL->indr+LW1, L);\n    }\n#else\n    for(L = LW1; L <= LW2; L++) {\n      (*LROW)++;\n      LUSOL->a[*LROW] = LUSOL->a[L];\n      J = LUSOL->indr[L];\n      LUSOL->indr[L] = 0;\n      LUSOL->indr[*LROW] = J;\n      LUSOL->locc[J] = *LROW;\n    }\n#endif\n    LW1 = LUSOL->locr[IW];\n    LW2 = *LROW;\n/*         ...............................................................\n           Inner loop with row  iw  at the end of storage.\n           ............................................................... */\nx400:\n    for(LV = LV2; LV <= LV3; LV++) {\n      JV = LUSOL->indr[LV];\n      LW = LUSOL->locc[JV];\n      if(LW>0) {\n/*               No fill-in. */\n        LUSOL->a[LW] += AMULT*LUSOL->a[LV];\n        if(fabs(LUSOL->a[LW])<=SMALL) {\n/*                  Delete small computed element. */\n          LUSOL->a[LW] = LUSOL->a[LW2];\n          J = LUSOL->indr[LW2];\n          LUSOL->indr[LW] = J;\n          LUSOL->indr[LW2] = 0;\n          LUSOL->locc[J] = LW;\n          LUSOL->locc[JV] = 0;\n          (*LENU)--;\n          LENW--;\n          LW2--;\n        }\n      }\n      else {\n/*               Row  iw  doesn't have an element in column  jv  yet\n                 so there is a fill-in. */\n        (*LENU)++;\n        LENW++;\n        LW2++;\n        LUSOL->a[LW2] = AMULT*LUSOL->a[LV];\n        LUSOL->indr[LW2] = JV;\n        LUSOL->locc[JV] = LW2;\n      }\n    }\n    *LROW = LW2;\n/*         The  k-th  element of row  iw  has been processed.\n           Reset  swappd  before looking at the next element. */\nx490:\n    SWAPPD = FALSE;\n  }\n/*      ==================================================================\n        End of main elimination loop.\n        ==================================================================\n\n        Cancel markers on row  iw. */\nx600:\n  LUSOL->lenr[IW] = LENW;\n  if(LENW==0)\n    goto x910;\n  for(L = LW1; L <= LW2; L++) {\n    J = LUSOL->indr[L];\n    LUSOL->locc[J] = 0;\n  }\n/*      Move the diagonal element to the front of row  iw.\n        At this stage,  lenw gt 0  and  klast le n. */\nx700:\n  for(L = LW1; L <= LW2; L++) {\n    LDIAG = L;\n    if(LUSOL->indr[L]==JFIRST)\n      goto x730;\n  }\n  goto x910;\n\nx730:\n  *DIAG = LUSOL->a[LDIAG];\n  LUSOL->a[LDIAG] = LUSOL->a[LW1];\n  LUSOL->a[LW1] = *DIAG;\n  LUSOL->indr[LDIAG] = LUSOL->indr[LW1];\n  LUSOL->indr[LW1] = JFIRST;\n/*      If an interchange is needed, repeat from the beginning with the\n        new row  iw,  knowing that the opposite interchange cannot occur. */\n  if(SWAPPD)\n    goto x100;\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  goto x950;\n/*      Singular. */\nx910:\n  *DIAG = ZERO;\n  *INFORM = LUSOL_INFORM_LUSINGULAR;\n/*      Force a compression if the file for  U  is much longer than the\n        no. of nonzeros in  U  (i.e. if  lrow  is much bigger than  lenU).\n        This should prevent memory fragmentation when there is far more\n        memory than necessary  (i.e. when  lena  is huge). */\nx950:\n  LIMIT = (int) (USPACE*(*LENU))+LUSOL->m+LUSOL->n+1000;\n  if(*LROW>LIMIT)\n    LU1REC(LUSOL, LUSOL->m,TRUE,LROW,LUSOL->indr,LUSOL->lenr,LUSOL->locr);\n  goto x990;\n/*      Not enough storage. */\nx970:\n  *INFORM = LUSOL_INFORM_ANEEDMEM;\n/*      Exit. */\nx990:\n;\n}\n\n/* ==================================================================\n   lu7rnk (check rank) assumes U is currently nrank by n\n   and determines if row nrank contains an acceptable pivot.\n   If not, the row is deleted and nrank is decreased by 1.\n   jsing is an input parameter (not altered).  If jsing is positive,\n   column jsing has already been judged dependent.  A substitute\n   (if any) must be some other column.\n   ------------------------------------------------------------------\n   -- Jul 1987: First version.\n   09 May 1988: First f77 version.\n   ================================================================== */\nvoid LU7RNK(LUSOLrec *LUSOL, int JSING, int *LENU,\n            int *LROW, int *NRANK, int *INFORM, REAL *DIAG)\n{\n  REAL UTOL1, UMAX;\n  int  IW, LENW, L1, L2, LMAX, L, JMAX, KMAX;\n\n#ifdef ForceInitialization\n  L1 = 0;\n  L2 = 0;\n#endif\n\n  UTOL1 = LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U];\n  *DIAG = ZERO;\n/*      Find Umax, the largest element in row nrank. */\n  IW = LUSOL->ip[*NRANK];\n  LENW = LUSOL->lenr[IW];\n  if(LENW==0)\n    goto x400;\n  L1 = LUSOL->locr[IW];\n  L2 = (L1+LENW)-1;\n  UMAX = ZERO;\n  LMAX = L1;\n  for(L = L1; L <= L2; L++) {\n    if(UMAX<fabs(LUSOL->a[L])) {\n      UMAX = fabs(LUSOL->a[L]);\n      LMAX = L;\n    }\n  }\n/*      Find which column that guy is in (in pivotal order).\n        Interchange him with column nrank, then move him to be\n        the new diagonal at the front of row nrank. */\n  *DIAG = LUSOL->a[LMAX];\n  JMAX = LUSOL->indr[LMAX];\n  for(KMAX = *NRANK; KMAX <= LUSOL->n; KMAX++) {\n    if(LUSOL->iq[KMAX]==JMAX)\n      break;\n  }\n  LUSOL->iq[KMAX] = LUSOL->iq[*NRANK];\n  LUSOL->iq[*NRANK] = JMAX;\n  LUSOL->a[LMAX] = LUSOL->a[L1];\n  LUSOL->a[L1] = *DIAG;\n  LUSOL->indr[LMAX] = LUSOL->indr[L1];\n  LUSOL->indr[L1] = JMAX;\n/*      See if the new diagonal is big enough. */\n  if(UMAX<=UTOL1)\n    goto x400;\n  if(JMAX==JSING)\n    goto x400;\n/*      ------------------------------------------------------------------\n        The rank stays the same.\n        ------------------------------------------------------------------ */\n  *INFORM = LUSOL_INFORM_LUSUCCESS;\n  return;\n/*      ------------------------------------------------------------------\n        The rank decreases by one.\n        ------------------------------------------------------------------ */\nx400:\n  *INFORM = LUSOL_INFORM_RANKLOSS;\n  (*NRANK)--;\n  if(LENW>0) {\n/*         Delete row nrank from U. */\n    LENU = LENU-LENW;\n    LUSOL->lenr[IW] = 0;\n    for(L = L1; L <= L2; L++) {\n      LUSOL->indr[L] = 0;\n    }\n    if(L2==*LROW) {\n/*            This row was at the end of the data structure.\n              We have to reset lrow.\n              Preceding rows might already have been deleted, so we\n              have to be prepared to go all the way back to 1. */\n      for(L = 1; L <= L2; L++) {\n        if(LUSOL->indr[*LROW]>0)\n          goto x900;\n        (*LROW)--;\n      }\n    }\n  }\nx900:\n;\n}\n\n/* ==================================================================\n   lu7zap  eliminates all nonzeros in column  jzap  of  U.\n   It also sets  kzap  to the position of  jzap  in pivotal order.\n   Thus, on exit we have  iq(kzap) = jzap.\n   ------------------------------------------------------------------\n   -- Jul 1987: nrank added.\n   10 May 1988: First f77 version.\n   ================================================================== */\nvoid LU7ZAP(LUSOLrec *LUSOL, int JZAP, int *KZAP, int *LENU, int *LROW,\n            int NRANK)\n{\n  int K, I, LENI, LR1, LR2, L;\n\n  for(K = 1; K <= NRANK; K++) {\n    I = LUSOL->ip[K];\n    LENI = LUSOL->lenr[I];\n    if(LENI==0)\n      goto x90;\n    LR1 = LUSOL->locr[I];\n    LR2 = (LR1+LENI)-1;\n    for(L = LR1; L <= LR2; L++) {\n      if(LUSOL->indr[L]==JZAP)\n        goto x60;\n    }\n    goto x90;\n/*         Delete the old element. */\nx60:\n    LUSOL->a[L] = LUSOL->a[LR2];\n    LUSOL->indr[L] = LUSOL->indr[LR2];\n    LUSOL->indr[LR2] = 0;\n    LUSOL->lenr[I] = LENI-1;\n    (*LENU)--;\n/*         Stop if we know there are no more rows containing  jzap. */\nx90:\n    *KZAP = K;\n    if(LUSOL->iq[K]==JZAP)\n      goto x800;\n  }\n/*      nrank must be smaller than n because we haven't found kzap yet. */\n  L = LUSOL->n;\n  for(K = NRANK+1; K <= L; K++) {\n    *KZAP = K;\n    if(LUSOL->iq[K]==JZAP)\n      break;\n  }\n/*      See if we zapped the last element in the file. */\nx800:\n  if(*LROW>0) {\n    if(LUSOL->indr[*LROW]==0)\n      (*LROW)--;\n  }\n\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/LUSOL/lusol8a.c",
    "content": "\n/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n   File  lusol8a\n      lu8rpc\n      Sparse LU update: Replace Column\n      LUSOL's sparse implementation of the Bartels-Golub update.\n\n   01 May 2002: Derived from LUSOL's original lu8a.f file.\n   01 May 2002: Current version of lusol8a.f.\n   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */\n\n/* ==================================================================\n   lu8rpc  updates the LU factorization  A = L*U  when column  jrep\n   is replaced by some vector  a(new).\n   lu8rpc  is an implementation of the Bartels-Golub update,\n   designed for the case where A is rectangular and/or singular.\n   L is a product of stabilized eliminations (m x m, nonsingular).\n   P U Q is upper trapezoidal (m x n, rank nrank).\n\n   If  mode1 = 0,  the old column is taken to be zero\n                   (so it does not have to be removed from  U).\n   If  mode1 = 1,  the old column need not have been zero.\n   If  mode2 = 0,  the new column is taken to be zero.\n                   v(*)  is not used or altered.\n   If  mode2 = 1,  v(*)  must contain the new column  a(new).\n                   On exit,  v(*)  will satisfy  L*v = a(new).\n   If  mode2 = 2,  v(*)  must satisfy  L*v = a(new).\n\n   The array  w(*)  is not used or altered.\n   On entry, all elements of  locc  are assumed to be zero.\n   On a successful exit (inform != 7), this will again be true.\n   On exit:\n\n   inform = -1  if the rank of U decreased by 1.\n   inform =  0  if the rank of U stayed the same.\n   inform =  1  if the rank of U increased by 1.\n   inform =  2  if the update seemed to be unstable\n                (diag much bigger than vnorm).\n   inform =  7  if the update was not completed (lack of storage).\n   inform =  8  if jrep is not between 1 and n.\n   ------------------------------------------------------------------\n   -- Jan 1985: Original F66 version.\n   -- Jul 1987: Modified to maintain U in trapezoidal form.\n   10 May 1988: First f77 version.\n   16 Oct 2000: Added test for instability (inform = 2).\n   ================================================================== */\nvoid LU8RPC(LUSOLrec *LUSOL, int MODE1, int MODE2,\n            int JREP, REAL V[], REAL W[],\n            int *INFORM, REAL *DIAG, REAL *VNORM)\n{\n  MYBOOL SINGLR;\n  int    LPRINT, NRANK, LENL, LENU, LROW, NRANK0, KREP, KLAST, IW, L1, J1, JSING;\n  REAL   UTOL1, UTOL2;\n\n  LPRINT = LUSOL->luparm[LUSOL_IP_PRINTLEVEL];\n  NRANK  = LUSOL->luparm[LUSOL_IP_RANK_U];\n  LENL   = LUSOL->luparm[LUSOL_IP_NONZEROS_L];\n  LENU   = LUSOL->luparm[LUSOL_IP_NONZEROS_U];\n  LROW   = LUSOL->luparm[LUSOL_IP_NONZEROS_ROW];\n  UTOL1  = LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U];\n  UTOL2  = LUSOL->parmlu[LUSOL_RP_EPSDIAG_U];\n  NRANK0 = NRANK;\n  *DIAG  = ZERO;\n  *VNORM = ZERO;\n  if(JREP<1)\n    goto x980;\n  if(JREP>LUSOL->n)\n    goto x980;\n\n/*      ------------------------------------------------------------------\n        If mode1 = 0, there are no elements to be removed from  U\n        but we still have to set  krep  (using a backward loop).\n        Otherwise, use lu7zap to remove column  jrep  from  U\n        and set  krep  at the same time.\n        ------------------------------------------------------------------ */\n  if(MODE1==LUSOL_UPDATE_OLDEMPTY) {\n    KREP = LUSOL->n+1;\nx10:\n    KREP--;\n    if(LUSOL->iq[KREP]!=JREP)\n      goto x10;\n  }\n  else\n    LU7ZAP(LUSOL, JREP,&KREP,&LENU,&LROW,NRANK);\n\n/*      ------------------------------------------------------------------\n        Insert a new column of u and find klast.\n        ------------------------------------------------------------------ */\n  if(MODE2==LUSOL_UPDATE_NEWEMPTY) {\n    KLAST = 0;\n  }\n  else {\n    if(MODE2==LUSOL_UPDATE_NEWNONEMPTY) {\n/*            Transform v = a(new) to satisfy  L*v = a(new). */\n      LU6SOL(LUSOL, LUSOL_SOLVE_Lv_v, V,W, NULL, INFORM);\n    }\n    else if(V==NULL)\n/* Otherwise, the V vector is taken to satisfy this already, or stored earlier. */\n      V=LUSOL->vLU6L;\n\n\n/*         Insert into  U  any nonzeros in the top of  v.\n           row  ip(klast)  will contain the last nonzero in pivotal order.\n           Note that  klast  will be in the range  ( 0, nrank ). */\n    LU7ADD(LUSOL, JREP,V,LENL,&LENU,&LROW,NRANK,INFORM,&KLAST,VNORM);\n    if(*INFORM==LUSOL_INFORM_ANEEDMEM)\n      goto x970;\n  }\n/*      ------------------------------------------------------------------\n        In general, the new column causes U to look like this:\n                    krep        n                 krep  n\n                   ....a.........          ..........a...\n                    .  a        .           .        a  .\n                     . a        .            .       a  .\n                      .a        .             .      a  .\n           P U Q =     a        .    or        .     a  .\n                       b.       .               .    a  .\n                       b .      .                .   a  .\n                       b  .     .                 .  a  .\n                       b   ......                  ..a...  nrank\n                       c                             c\n                       c                             c\n                       c                             c     m\n        klast points to the last nonzero \"a\" or \"b\".\n        klast = 0 means all \"a\" and \"b\" entries are zero.\n        ------------------------------------------------------------------ */\n  if(MODE2==LUSOL_UPDATE_NEWEMPTY) {\n    if(KREP>NRANK)\n      goto x900;\n  }\n  else if(NRANK<LUSOL->m) {\n/*         Eliminate any \"c\"s (in either case).\n           Row nrank + 1 may end up containing one nonzero. */\n    LU7ELM(LUSOL, JREP,V,&LENL,&LROW,NRANK,INFORM,DIAG);\n    if(*INFORM==LUSOL_INFORM_ANEEDMEM)\n      goto x970;\n    if(*INFORM==LUSOL_INFORM_LUSINGULAR) {\n/*            The nonzero is apparently significant.\n              Increase nrank by 1 and make klast point to the bottom. */\n      NRANK++;\n      KLAST = NRANK;\n    }\n  }\n  if(NRANK<LUSOL->n) {\n/*         The column rank is low.\n           In the first case, we want the new column to end up in\n           position nrank, so the trapezoidal columns will have a chance\n           later on (in lu7rnk) to pivot in that position.\n           Otherwise the new column is not part of the triangle.  We\n           swap it into position nrank so we can judge it for singularity.\n           lu7rnk might choose some other trapezoidal column later. */\n    if(KREP<NRANK)\n      KLAST = NRANK;\n    else {\n      LUSOL->iq[KREP] = LUSOL->iq[NRANK];\n      LUSOL->iq[NRANK] = JREP;\n      KREP = NRANK;\n    }\n  }\n/*      ------------------------------------------------------------------\n        If krep .lt. klast, there are some \"b\"s to eliminate:\n                     krep\n                   ....a.........\n                    .  a        .\n                     . a        .\n                      .a        .\n           P U Q =     a        .  krep\n                       b.       .\n                       b .      .\n                       b  .     .\n                       b   ......  nrank\n        If krep .eq. klast, there are no \"b\"s, but the last \"a\" still\n        has to be moved to the front of row krep (by lu7for).\n        ------------------------------------------------------------------ */\n  if(KREP<=KLAST) {\n/*         Perform a cyclic permutation on the current pivotal order,\n           and eliminate the resulting row spike.  krep becomes klast.\n           The final diagonal (if any) will be correctly positioned at\n           the front of the new krep-th row.  nrank stays the same. */\n    LU7CYC(LUSOL, KREP,KLAST,LUSOL->ip);\n    LU7CYC(LUSOL, KREP,KLAST,LUSOL->iq);\n    LU7FOR(LUSOL, KREP,KLAST,&LENL,&LENU,&LROW,INFORM,DIAG);\n    if(*INFORM==LUSOL_INFORM_ANEEDMEM)\n      goto x970;\n    KREP = KLAST;\n/*         Test for instability (diag much bigger than vnorm). */\n    SINGLR = (MYBOOL) ((*VNORM)<UTOL2*fabs(*DIAG));\n    if(SINGLR)\n      goto x920;\n  }\n/*      ------------------------------------------------------------------\n        Test for singularity in column krep (where krep<=nrank).\n        ------------------------------------------------------------------ */\n  *DIAG = ZERO;\n  IW = LUSOL->ip[KREP];\n  SINGLR = (MYBOOL) (LUSOL->lenr[IW]==0);\n  if(!SINGLR) {\n    L1 = LUSOL->locr[IW];\n    J1 = LUSOL->indr[L1];\n    SINGLR = (MYBOOL) (J1!=JREP);\n    if(!SINGLR) {\n      *DIAG = LUSOL->a[L1];\n      SINGLR = (MYBOOL) (fabs(*DIAG)<=UTOL1 || fabs(*DIAG)<=UTOL2*(*VNORM));\n    }\n  }\n  if(SINGLR && (KREP<NRANK)) {\n/*         Perform cyclic permutations to move column jrep to the end.\n           Move the corresponding row to position nrank\n           then eliminate the resulting row spike. */\n    LU7CYC(LUSOL, KREP,NRANK,LUSOL->ip);\n    LU7CYC(LUSOL, KREP,LUSOL->n,LUSOL->iq);\n    LU7FOR(LUSOL, KREP,NRANK,&LENL,&LENU,&LROW,INFORM,DIAG);\n    if(*INFORM==LUSOL_INFORM_ANEEDMEM)\n      goto x970;\n  }\n/*      Find the best column to be in position nrank.\n        If singlr, it can't be the new column, jrep.\n        If nothing satisfactory exists, nrank will be decreased. */\n  if(SINGLR || (NRANK<LUSOL->n)) {\n    JSING = 0;\n    if(SINGLR)\n      JSING = JREP;\n    LU7RNK(LUSOL, JSING,&LENU,&LROW,&NRANK,INFORM,DIAG);\n  }\n\n/*      ------------------------------------------------------------------\n        Update indeces of optional row-based version of L0.\n        ------------------------------------------------------------------ */\n#if 0\n  if(LUSOL->L0 != NULL)\n    LU1L0UPD(LUSOL, INFORM);\n#endif\n\n/*      ------------------------------------------------------------------\n        Set inform for exit.\n        ------------------------------------------------------------------ */\nx900:\n  if(NRANK==NRANK0)\n    *INFORM = LUSOL_INFORM_LUSUCCESS;\n  else if(NRANK<NRANK0) {\n    *INFORM = LUSOL_INFORM_RANKLOSS;\n    if(NRANK0==LUSOL->n) {\n      if(LPRINT>=LUSOL_MSG_SINGULARITY)\n        LUSOL_report(LUSOL, 0, \"lu8rpc  warning...\\nSingularity after replacing column.    jrep=%8d    diag=%g\\n\",\n                            JREP,DIAG);\n    }\n  }\n  else\n    *INFORM = LUSOL_INFORM_LUSINGULAR;\n  goto x990;\n/*      Instability. */\nx920:\n  *INFORM = LUSOL_INFORM_LUUNSTABLE;\n  if(LPRINT>=LUSOL_MSG_SINGULARITY)\n    LUSOL_report(LUSOL, 0, \"lu8rpc  warning...\\nInstability after replacing column.    jrep=%8d    diag=%g\\n\",\n                        JREP,DIAG);\n  goto x990;\n/*      Not enough storage. */\nx970:\n  *INFORM = LUSOL_INFORM_ANEEDMEM;\n  if(LPRINT>=LUSOL_MSG_SINGULARITY)\n    LUSOL_report(LUSOL, 0, \"lu8rpc  error...\\nInsufficient memory.    lena=%8d\\n\",\n                        LUSOL->lena);\n  goto x990;\n/*      jrep  is out of range. */\nx980:\n  *INFORM = LUSOL_INFORM_FATALERR;\n  if(LPRINT>=LUSOL_MSG_SINGULARITY)\n    LUSOL_report(LUSOL, 0, \"lu8rpc  error...\\njrep  is out of range.    m=%8d    n=%8d    jrep=%8d\\n\",\n                        LUSOL->m,LUSOL->n,JREP);\n/*      Exit. */\nx990:\n  LUSOL->luparm[LUSOL_IP_UPDATECOUNT]++;\n  LUSOL->luparm[LUSOL_IP_RANK_U]       = NRANK;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_L]   = LENL;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_U]   = LENU;\n  LUSOL->luparm[LUSOL_IP_NONZEROS_ROW] = LROW;\n  LUSOL->luparm[LUSOL_IP_INFORM]       = *INFORM;\n}\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/lp_LUSOL.c",
    "content": "\n/*  Modularized simplex basis factorization module - w/interface for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      lusol.h, lp_lib.h, myblas.h\n\n    Release notes:\n    v2.0.0  1 March 2004        First implementation of the LUSOL v2.0 C translation.\n    v2.0.1  1 April 2004        Added singularity recovery and fast/reuse update logic.\n    v2.0.2  23 May 2004         Moved mustrefact() function into the BFP structure.\n    v2.0.3  5 September 2004    Reworked pivot threshold tightening logic and default\n                                values.\n    v2.1.0  18 June 2005        Made changes to allow for \"pure\" factorization;\n                                i.e. without the objective function included.\n\n   ---------------------------------------------------------------------------------- */\n\n/* Generic include libraries */\n#include <stdlib.h>\n#include <string.h>\n#include \"lp_lib.h\"\n\n/* Include libraries for this factorization system */\n#include \"myblas.h\"\n#include \"commonlib.h\"\n#include \"lp_LUSOL.h\"\n#include \"lusol.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n/* Include routines common to factorization engine implementations */\n#include \"lp_BFP1.c\"\n#include \"lp_BFP2.c\"\n\n\n/* MUST MODIFY */\nconst char * BFP_CALLMODEL bfp_name(void)\n{\n  return( \"LUSOL v2.2.1.0\" );\n}\n\n\n/* MUST MODIFY */\nMYBOOL BFP_CALLMODEL bfp_resize(lprec *lp, int newsize)\n{\n  INVrec *lu;\n\n  lu = lp->invB;\n\n  /* Increment dimensionality since we put the objective row at the top */\n  newsize = newsize + bfp_rowoffset(lp);\n  lu->dimalloc = newsize;\n\n  /* Allocate index tracker arrays, LU matrices and various work vectors */\n  if(!allocREAL(lp, &(lu->value), newsize+MATINDEXBASE, AUTOMATIC))\n    return( FALSE );\n\n  /* Data specific to the factorization engine */\n  if(lu->LUSOL != NULL) {\n    if(newsize > 0 || 1)\n      LUSOL_sizeto(lu->LUSOL, newsize, newsize, 0);\n    else {\n      LUSOL_free(lu->LUSOL);\n      lu->LUSOL = NULL;\n    }\n  }\n  else if(newsize > 0 || 1) {\n    int  asize;\n    REAL bsize;\n\n    lu->LUSOL = LUSOL_create(NULL, 0, LUSOL_PIVMOD_TPP, bfp_pivotmax(lp)*0);\n\n#if 1\n    lu->LUSOL->luparm[LUSOL_IP_ACCELERATION]  = LUSOL_AUTOORDER;\n    lu->LUSOL->parmlu[LUSOL_RP_SMARTRATIO]    = 0.50;\n#endif\n#if 0\n    lu->timed_refact = DEF_TIMEDREFACT;\n#else\n    lu->timed_refact = FALSE;\n#endif\n\n    /* The following adjustments seem necessary to make the really tough NETLIB\n       models perform reliably and still performant (e.g. cycle.mps) */\n#if 0\n    lu->LUSOL->parmlu[LUSOL_RP_SMALLDIAG_U]   =\n    lu->LUSOL->parmlu[LUSOL_RP_EPSDIAG_U]     = lp->epsprimal;\n#endif\n#if 0\n    lu->LUSOL->parmlu[LUSOL_RP_ZEROTOLERANCE] = lp->epsvalue;\n#endif\n\n#if 1\n    LUSOL_setpivotmodel(lu->LUSOL, LUSOL_PIVMOD_NOCHANGE, LUSOL_PIVTOL_SLIM);\n#else\n    LUSOL_setpivotmodel(lu->LUSOL, LUSOL_PIVMOD_NOCHANGE, LUSOL_PIVTOL_TIGHT);\n#endif\n\n#ifdef LUSOL_UseBLAS\n/*    if(fileSearchPath(\"PATH\", \"myBLAS.DLL\", NULL) && load_BLAS(\"myBLAS\")) */\n    if(is_nativeBLAS() && load_BLAS(libnameBLAS))\n      lp->report(lp, NORMAL, \"Optimized BLAS was successfully loaded for bfp_LUSOL.\\n\");\n#endif\n\n    /* Try to minimize memory allocation if we have a large number of unit columns */\n    bsize = (REAL) lp->get_nonzeros(lp);\n    if(newsize > lp->columns)\n      bsize += newsize;\n    else\n      bsize = bsize/lp->columns*newsize;\n    /* Add a \"reasonable\" delta to allow for B and associated factorizations\n       that are denser than average; this makes reallocations less frequent.\n       Values between 1.2 and 1.5 appear to be reasonable. */\n    asize = (int) (bsize*MAX_DELTAFILLIN*1.3333);\n    if(!LUSOL_sizeto(lu->LUSOL, newsize, newsize, asize))\n      return( FALSE );\n  }\n  lu->dimcount = newsize;\n  return( TRUE );\n}\n\n\n/* MUST MODIFY */\nvoid BFP_CALLMODEL bfp_free(lprec *lp)\n{\n  INVrec *lu;\n\n  lu = lp->invB;\n  if(lu == NULL)\n    return;\n\n  /* General arrays */\n  FREE(lu->opts);\n  FREE(lu->value);\n\n  /* Data specific to the factorization engine */\n  LUSOL_free(lu->LUSOL);\n\n  FREE(lu);\n  lp->invB = NULL;\n}\n\n\n/* MUST MODIFY */\nint BFP_CALLMODEL bfp_nonzeros(lprec *lp, MYBOOL maximum)\n{\n  INVrec *lu;\n\n  lu = lp->invB;\n  if(maximum == TRUE)\n    return(lu->max_LUsize);\n  else if(maximum == AUTOMATIC)\n    return(lu->max_Bsize);\n  else\n    return(lu->LUSOL->luparm[LUSOL_IP_NONZEROS_L0]+lu->LUSOL->luparm[LUSOL_IP_NONZEROS_U0]);\n/*    return(lu->LUSOL->luparm[LUSOL_IP_NONZEROS_ROW]); */\n}\n\n\n/* MUST MODIFY (or ignore) */\nint BFP_CALLMODEL bfp_memallocated(lprec *lp)\n{\n  int      mem;\n  LUSOLrec *LUSOL = lp->invB->LUSOL;\n\n  mem = sizeof(REAL) * (LUSOL->lena+LUSOL->maxm+LUSOL_RP_LASTITEM);\n  mem += sizeof(int) * (2*LUSOL->lena+5*LUSOL->maxm+5*LUSOL->maxn+LUSOL_IP_LASTITEM);\n  if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TCP)\n    mem += sizeof(REAL) * LUSOL->maxn + 2*sizeof(REAL)*LUSOL->maxn;\n  else if(LUSOL->luparm[LUSOL_IP_PIVOTTYPE] == LUSOL_PIVMOD_TRP)\n    mem += sizeof(REAL) * LUSOL->maxn;\n  if(!LUSOL->luparm[LUSOL_IP_KEEPLU])\n    mem += sizeof(REAL) * LUSOL->maxn;\n  return( mem );\n}\n\n\n/* MUST MODIFY */\nint BFP_CALLMODEL bfp_preparefactorization(lprec *lp)\n{\n  INVrec *lu = lp->invB;\n\n  /* Finish any outstanding business */\n  if(lu->is_dirty == AUTOMATIC)\n    lp->bfp_finishfactorization(lp);\n\n  /* Clear or resize the existing LU matrices - specific for the factorization engine */\n  LUSOL_clear(lu->LUSOL, TRUE);\n  if(lu->dimcount != lp->rows + bfp_rowoffset(lp))\n    lp->bfp_resize(lp, lp->rows);\n\n  /* Reset additional indicators */\n  lp->bfp_updaterefactstats(lp);\n  lu->col_pos = 0;\n\n  return(0);\n\n}\n\n\n/* LOCAL HELPER ROUTINE - Replace a basis column with corresponding slack */\nint bfp_LUSOLsetcolumn(lprec *lp, int posnr, int colnr)\n{\n  int nz, inform;\n\n  nz = lp->get_lpcolumn(lp, colnr, lp->invB->LUSOL->w + bfp_rowoffset(lp), NULL, NULL);\n  inform = LUSOL_replaceColumn(lp->invB->LUSOL, posnr, lp->invB->LUSOL->w);\n  return( inform );\n}\n\n\n/* LOCAL HELPER ROUTINE - force the basis to be the identity matrix */\nint bfp_LUSOLidentity(lprec *lp, int *rownum)\n{\n  int    i, nz;\n  INVrec *invB = lp->invB;\n\n  /* Reset the factorization engine */\n  LUSOL_clear(invB->LUSOL, TRUE);\n\n  /* Add the basis columns */\n  lp->invB->set_Bidentity = TRUE;\n  for(i = 1; i <= invB->dimcount; i++) {\n    nz = lp->get_basiscolumn(lp, i, rownum, invB->value);\n    LUSOL_loadColumn(invB->LUSOL, rownum, i, invB->value, nz, 0);\n  }\n  lp->invB->set_Bidentity = FALSE;\n\n  /* Factorize */\n  i = LUSOL_factorize(invB->LUSOL);\n\n  return( i );\n}\n\n\n/* LOCAL HELPER ROUTINE */\nint bfp_LUSOLfactorize(lprec *lp, MYBOOL *usedpos, int *rownum, int *singular)\n{\n  (void) usedpos;\n  int    i, j, nz, deltarows = bfp_rowoffset(lp);\n  INVrec *invB = lp->invB;\n  (void) usedpos;\n\n  /* Handle normal, presumed nonsingular case */\n  if(singular == NULL) {\n\n  /* Optionally do a symbolic minimum degree ordering;\n     not that slack variables should not be processed */\n/*#define UsePreprocessMDO*/\n#ifdef UsePreprocessMDO\n    int *mdo;\n    mdo = lp->bfp_createMDO(lp, usedpos, lp->rows, TRUE);\n    if(mdo != NULL) {\n      for(i = 1; i <= lp->rows; i++)\n        lp->set_basisvar(lp, i, mdo[i]);\n      FREE(mdo);\n    }\n#endif\n\n    /* Reset the factorization engine */\n    LUSOL_clear(invB->LUSOL, TRUE);\n\n    /* Add the basis columns in the original order */\n    for(i = 1; i <= invB->dimcount; i++) {\n      nz = lp->get_basiscolumn(lp, i, rownum, invB->value);\n      LUSOL_loadColumn(invB->LUSOL, rownum, i, invB->value, nz, 0);\n      if((i > deltarows) && (lp->var_basic[i-deltarows] > lp->rows))\n        lp->invB->user_colcount++;\n    }\n\n    /* Factorize */\n    i = LUSOL_factorize(invB->LUSOL);\n  }\n\n  /* Handle case where a column may be singular */\n  else {\n    LLrec *map;\n\n    /* Reset the factorization engine */\n    i = bfp_LUSOLidentity(lp, rownum);\n\n    /* Build map of available columns */\n    nz = createLink(lp->rows, &map, NULL);\n    for(i = 1; i <= lp->rows; i++) {\n      if(lp->var_basic[i] <= lp->rows)\n        removeLink(map, i);\n    }\n\n    /* Rebuild the basis, column by column, while skipping slack columns */\n    j = firstActiveLink(map);\n    for(i = 1; i <= lp->rows; i++) {\n      if(lp->var_basic[i] <= lp->rows)\n        continue;\n      nz = bfp_LUSOLsetcolumn(lp, j+deltarows, lp->var_basic[i]);\n      if(nz == LUSOL_INFORM_LUSUCCESS)\n        lp->invB->user_colcount++;\n      else {\n        nz = bfp_LUSOLsetcolumn(lp, j+deltarows, i);\n        lp->set_basisvar(lp, i, i);\n      }\n      j = nextActiveLink(map, j);\n    }\n\n    /* Sort the basis list */\n    MEMCOPY(rownum, lp->var_basic, lp->rows+1);\n    sortByINT(lp->var_basic, rownum, lp->rows, 1, TRUE);\n\n  }\n\n  return( i );\n}\n/* LOCAL HELPER ROUTINE */\nvoid bfp_LUSOLtighten(lprec *lp)\n{\n  int infolevel = DETAILED;\n\n  switch(LUSOL_tightenpivot(lp->invB->LUSOL)) {\n    case FALSE: lp->report(lp, infolevel, \"bfp_factorize: Very hard numerics, but cannot tighten LUSOL thresholds further.\\n\");\n                 break;\n    case TRUE:  lp->report(lp, infolevel, \"bfp_factorize: Frequent refact pivot count %d at iter %.0f; tightened thresholds.\\n\",\n                                           lp->invB->num_pivots, (REAL) lp->get_total_iter(lp));\n                 break;\n    default:    lp->report(lp, infolevel, \"bfp_factorize: LUSOL switched to %s pivoting model to enhance stability.\\n\",\n                                           LUSOL_pivotLabel(lp->invB->LUSOL));\n  }\n}\n\n#define is_fixedvar is_fixedvar_ /* resolves a compiler warning/error conflict with lp_lib.h */\n\nstatic MYBOOL is_fixedvar(lprec *lp, int variable)\n{\n  if((lp->bb_bounds != NULL && lp->bb_bounds->UBzerobased) || (variable <= lp->rows))\n    return( (MYBOOL) (lp->upbo[variable] < lp->epsprimal) );\n  else\n    return( (MYBOOL) (lp->upbo[variable]-lp->lowbo[variable] < lp->epsprimal) );\n} /* is_fixedvar */\n\n/* MUST MODIFY */\nint BFP_CALLMODEL bfp_factorize(lprec *lp, int uservars, int Bsize, MYBOOL *usedpos, MYBOOL final)\n{\n  int      kcol, inform,\n           *rownum = NULL,\n           singularities = 0,\n           dimsize = lp->invB->dimcount;\n  LUSOLrec *LUSOL = lp->invB->LUSOL;\n\n /* Set dimensions and create work array */\n  SETMAX(lp->invB->max_Bsize, Bsize+(1+lp->rows-uservars));\n  kcol = lp->invB->dimcount;\n  LUSOL->m = kcol;\n  LUSOL->n = kcol;\n  allocINT(lp, &rownum, kcol+1, FALSE);\n\n /* Check if the refactorization frequency is low;\n    tighten pivot thresholds if appropriate */\n  inform = lp->bfp_pivotcount(lp);\n  if(!final &&                        /* No solution update-based refactorization */\n     !lp->invB->force_refact &&       /* No sparsity-based refactorization */\n     !lp->is_action(lp->spx_action,\n          ACTION_TIMEDREINVERT) &&    /* No optimal time-based refactorization */\n     (inform > 5) && (inform < 0.25*lp->bfp_pivotmax(lp)))\n    bfp_LUSOLtighten(lp);\n\n\n /* Reload B and factorize */\n  inform = bfp_LUSOLfactorize(lp, usedpos, rownum, NULL);\n\n /* Do some checks */\n#ifdef Paranoia\n  if(uservars != lp->invB->user_colcount) {\n    lp->report(lp, SEVERE, \"bfp_factorize: User variable count reconciliation failed\\n\");\n    return( singularities );\n  }\n#endif\n\n  /* Check result and do further remedial action if necessary */\n  if(inform != LUSOL_INFORM_LUSUCCESS) {\n    int  singularcols,\n         replacedcols = 0;\n    REAL hold;\n\n    /* Make sure we do not tighten factorization pivot criteria too often, and simply\n       accept the substitution of slack columns into the basis */\n    if((lp->invB->num_singular+1) % TIGHTENAFTER == 0)\n      bfp_LUSOLtighten(lp);\n\n    /* Try to restore a non-singular basis by substituting singular columns with slacks */\n    while((inform == LUSOL_INFORM_LUSINGULAR) && (replacedcols < dimsize)) {\n      int    iLeave, jLeave, iEnter;\n      MYBOOL isfixed;\n\n      singularities++;\n      singularcols = LUSOL->luparm[LUSOL_IP_SINGULARITIES];\n      hold = (REAL) lp->get_total_iter(lp);\n      lp->report(lp, NORMAL, \"bfp_factorize: Resolving %d singularit%s at refact %d, iter %.0f\\n\",\n                             singularcols, my_plural_y(singularcols), lp->invB->num_refact, hold);\n\n      /* Find the failing / singular column(s) and make slack substitutions */\n      for(kcol = 1; kcol <= singularcols; kcol++) {\n\n        /* Determine leaving and entering columns. */\n        iLeave = LUSOL_getSingularity(LUSOL, kcol);        /* This is the singular column as natural index */\n        iEnter = iLeave;                                   /* This is the target replacement slack         */\n#if 1\n        iEnter = LUSOL->iqinv[iEnter];\n        iEnter = LUSOL->ip[iEnter];\n#endif\n        iLeave-= bfp_rowextra(lp);                         /* This is the original B column/basis index    */\n        jLeave = lp->var_basic[iLeave];                    /* This is the IA column index in lp_solve      */\n\n        /* Express the slack index in original lp_solve [1..rows] reference and check validity */\n /*       if(B4 != NULL) iEnter = B4->B4_row[iEnter]; v6 FUNCTIONALITY */\n        iEnter -=  bfp_rowextra(lp);\n        if(lp->is_basic[iEnter]) {\n          lp->report(lp, DETAILED, \"bfp_factorize: Replacement slack %d is already basic!\\n\", iEnter);\n\n          /* See if we can find a good alternative slack variable to enter */\n          iEnter = 0;\n          for(inform = 1; inform <= lp->rows; inform++)\n            if(!lp->is_basic[inform]) {\n              if((iEnter == 0) || (lp->upbo[inform] > lp->upbo[iEnter])) {\n                iEnter = inform;\n                if(my_infinite(lp, lp->upbo[iEnter]))\n                  break;\n              }\n            }\n          if(iEnter == 0) {\n            lp->report(lp, SEVERE, \"bfp_factorize: Could not find replacement slack variable!\\n\");\n            break;\n          }\n        }\n\n        /* We should update bound states for both the entering and leaving variables.\n           Note that this may cause (primal or dual) infeasibility, but I assume that\n           lp_solve traps this and takes necessary corrective action. */\n        isfixed = is_fixedvar(lp, iEnter);\n        if(isfixed)\n          lp->fixedvars++;\n        hold = lp->upbo[jLeave];\n        lp->is_lower[jLeave] = isfixed || (fabs(hold)>=lp->infinite) || (lp->rhs[iLeave] < hold);\n        lp->is_lower[iEnter] = TRUE;\n\n        /* Do the basis replacement */\n        lp->set_basisvar(lp, iLeave, iEnter);\n\n      }\n\n      /* Refactorize with slack substitutions */\n      inform = bfp_LUSOLfactorize(lp, NULL, rownum, NULL);\n      replacedcols += singularcols;\n    }\n\n    /* Check if we had a fundamental problem */\n    if(singularities >= dimsize) {\n      lp->report(lp, IMPORTANT, \"bfp_factorize: LUSOL was unable to recover from a singular basis\\n\");\n      lp->spx_status = NUMFAILURE;\n    }\n  }\n\n  /* Clean up before returning */\n  FREE(rownum);\n\n  /* Update statistics */\n  /* SETMAX(lp->invB->max_Bsize, (*Bsize)); */\n  lp->invB->num_singular += singularities;    /* The total number of singular updates */\n\n  return( singularities );\n}\n\n/* MUST MODIFY */\nMYBOOL BFP_CALLMODEL bfp_finishupdate(lprec *lp, MYBOOL changesign)\n/* Was addetacol() in versions of lp_solve before 4.0.1.8 - KE */\n{\n  int      i, k, kcol, deltarows = bfp_rowoffset(lp);\n  REAL     DIAG, VNORM;\n  INVrec   *lu = lp->invB;\n  LUSOLrec *LUSOL = lu->LUSOL;\n\n  if(!lu->is_dirty)\n    return( FALSE );\n  if(lu->is_dirty != AUTOMATIC)\n    lu->is_dirty = FALSE;\n\n  /* Perform the update */\n  k = lu->col_pos+deltarows;\n  lu->num_pivots++;\n  if(lu->col_leave > lu->dimcount-deltarows)\n    lu->user_colcount--;\n  if(lu->col_enter > lu->dimcount-deltarows)\n    lu->user_colcount++;\n  kcol = lu->col_pos;\n  lu->col_pos = 0;\n\n  /* Do standard update */\n#ifdef LUSOLSafeFastUpdate      /* NB! Defined in lusol.h */\n  if(TRUE || !changesign) {\n    if(changesign) {\n      REAL *temp = LUSOL->vLU6L;\n      for(i = 1, temp++; i <= lp->rows+deltarows; i++, temp++)\n        if(*temp != 0)\n          *temp = -(*temp);\n    }\n    /* Execute the update using data prepared earlier */\n    LU8RPC(LUSOL, LUSOL_UPDATE_OLDNONEMPTY, LUSOL_UPDATE_USEPREPARED,\n           k, NULL, NULL, &i, &DIAG, &VNORM);\n  }\n  else\n#endif\n  {\n    /* Retrieve the data for the entering column (base 0) */\n    i = lp->get_lpcolumn(lp, lu->col_enter, lu->value+deltarows, NULL, NULL);\n    lu->value[0] = 0;\n    /* Execute the update */\n    LU8RPC(LUSOL, LUSOL_UPDATE_OLDNONEMPTY, LUSOL_UPDATE_NEWNONEMPTY,\n           k, lu->value, NULL, &i, &DIAG, &VNORM);\n  }\n\n  if(i == LUSOL_INFORM_LUSUCCESS) {\n\n    /* Check if we should refactorize based on accumulation of fill-in */\n    DIAG  = LUSOL->luparm[LUSOL_IP_NONZEROS_L]+LUSOL->luparm[LUSOL_IP_NONZEROS_U];\n    VNORM = LUSOL->luparm[LUSOL_IP_NONZEROS_L0]+LUSOL->luparm[LUSOL_IP_NONZEROS_U0];\n#if 0\n    /* This is Michael Saunder's fixed parameter */\n    VNORM *= MAX_DELTAFILLIN;\n#else\n    /* This is Kjell Eikland's dynamic error accumulation measure */\n    VNORM *= pow(MAX_DELTAFILLIN, pow((0.5*LUSOL->nelem/VNORM), 0.25));\n#endif\n    lu->force_refact = (MYBOOL) ((DIAG > VNORM) && (lu->num_pivots > 20));\n\n#if 0\n    /* Additional KE logic to reduce maximum pivot count based on the density of B */\n    if(!lu->force_refact) {\n      VNORM = lp->rows+1;\n      VNORM = 1.0 - pow((REAL) LUSOL->nelem/VNORM/VNORM, 0.2);\n      lu->force_refact = (MYBOOL) (lu->num_pivots > VNORM*lp->bfp_pivotmax(lp));\n    }\n#endif\n  }\n\n  /* Handle errors */\n  else {\n/*    int infolevel = NORMAL; */\n    int infolevel = DETAILED;\n    lp->report(lp, infolevel, \"bfp_finishupdate: Failed at iter %.0f, pivot %d;\\n%s\\n\",\n                   (REAL) (lp->total_iter+lp->current_iter), lu->num_pivots, LUSOL_informstr(LUSOL, i));\n    if(i == LUSOL_INFORM_ANEEDMEM) {       /* To compress used memory and realloc, if necessary */\n      lp->invert(lp, INITSOL_USEZERO, FALSE);\n      if(i != LUSOL_INFORM_LUSUCCESS)\n        lp->report(lp, NORMAL, \"bfp_finishupdate: Insufficient memory at iter %.0f;\\n%s\\n\",\n                       (REAL) (lp->total_iter+lp->current_iter), LUSOL_informstr(LUSOL, i));\n    }\n    else if(i == LUSOL_INFORM_RANKLOSS) {  /* To fix rank loss and clear cumulative errors */\n#if 0\n      /* This is test code to do pivot in slack BEFORE refactorization (pessimistic approach);\n        assumes that LUSOL returns correct information about the source of the singularity */\n      kcol = LUSOL->luparm[LUSOL_IP_SINGULARINDEX];\n#ifdef MAPSINGULARCOLUMN\n      kcol = LUSOL_findColumnPosition(LUSOL, kcol);\n#endif\n      lp->set_basisvar(lp, kcol-deltarows, kcol-deltarows);\n#endif\n      lp->invert(lp, INITSOL_USEZERO, FALSE);\n      i = LUSOL->luparm[LUSOL_IP_INFORM];\n      if(i != LUSOL_INFORM_LUSUCCESS)\n        lp->report(lp, NORMAL, \"bfp_finishupdate: Recovery attempt unsuccessful at iter %.0f;\\n%s\\n\",\n                       (REAL) (lp->total_iter+lp->current_iter), LUSOL_informstr(LUSOL, i));\n      else\n        lp->report(lp, infolevel, \"bfp_finishupdate: Correction or recovery was successful.\\n\");\n    }\n  }\n  return( (MYBOOL) (i == LUSOL_INFORM_LUSUCCESS) );\n\n} /* bfp_finishupdate */\n\n\n/* MUST MODIFY */\nvoid BFP_CALLMODEL bfp_ftran_normal(lprec *lp, REAL *pcol, int *nzidx)\n{\n  int    i;\n  INVrec *lu;\n\n  lu = lp->invB;\n\n  /* Do the LUSOL ftran */\n  i = LUSOL_ftran(lu->LUSOL, pcol-bfp_rowoffset(lp), nzidx, FALSE);\n  if(i != LUSOL_INFORM_LUSUCCESS) {\n    lu->status = BFP_STATUS_ERROR;\n    lp->report(lp, NORMAL, \"bfp_ftran_normal: Failed at iter %.0f, pivot %d;\\n%s\\n\",\n                   (REAL) (lp->total_iter+lp->current_iter), lu->num_pivots, LUSOL_informstr(lu->LUSOL, i));\n  }\n}\n\n\n/* MAY MODIFY */\nvoid BFP_CALLMODEL bfp_ftran_prepare(lprec *lp, REAL *pcol, int *nzidx)\n{\n  int    i;\n  INVrec *lu;\n\n  lu = lp->invB;\n\n  /* Do the LUSOL ftran */\n  i = LUSOL_ftran(lu->LUSOL, pcol-bfp_rowoffset(lp), nzidx, TRUE);\n  if(i != LUSOL_INFORM_LUSUCCESS) {\n    lu->status = BFP_STATUS_ERROR;\n    lp->report(lp, NORMAL, \"bfp_ftran_prepare: Failed at iter %.0f, pivot %d;\\n%s\\n\",\n                   (REAL) (lp->total_iter+lp->current_iter), lu->num_pivots, LUSOL_informstr(lu->LUSOL, i));\n  }\n}\n\n\n/* MUST MODIFY */\nvoid BFP_CALLMODEL bfp_btran_normal(lprec *lp, REAL *prow, int *nzidx)\n{\n  int    i;\n  INVrec *lu;\n\n  lu = lp->invB;\n\n  /* Do the LUSOL btran */\n  i = LUSOL_btran(lu->LUSOL, prow-bfp_rowoffset(lp), nzidx);\n  if(i != LUSOL_INFORM_LUSUCCESS) {\n    lu->status = BFP_STATUS_ERROR;\n    lp->report(lp, NORMAL, \"bfp_btran_normal: Failed at iter %.0f, pivot %d;\\n%s\\n\",\n                   (REAL) (lp->total_iter+lp->current_iter), lu->num_pivots, LUSOL_informstr(lu->LUSOL, i));\n  }\n\n  /* Check performance data */\n#if 0\n  if(lu->num_pivots == 1) {\n    if(lu->LUSOL->luparm[LUSOL_IP_ACCELERATION] > 0)\n      lp->report(lp, NORMAL, \"RowL0 R:%10.7f  C:%10.7f  NZ:%10.7f\\n\",\n                             (REAL) lu->LUSOL->luparm[LUSOL_IP_ROWCOUNT_L0] / lu->LUSOL->m,\n                             (REAL) lu->LUSOL->luparm[LUSOL_IP_COLCOUNT_L0] / lu->LUSOL->m,\n                             (REAL) lu->LUSOL->luparm[LUSOL_IP_NONZEROS_L0] / pow((REAL) lu->LUSOL->m, 2));\n    else\n      lp->report(lp, NORMAL, \"ColL0 C:%10.7f  NZ:%10.7f\\n\",\n                             (REAL) lu->LUSOL->luparm[LUSOL_IP_COLCOUNT_L0] / lu->LUSOL->m,\n                             (REAL) lu->LUSOL->luparm[LUSOL_IP_NONZEROS_L0] / pow((REAL) lu->LUSOL->m, 2));\n  }\n#endif\n\n}\n\n/* MUST MODIFY - Routine to find maximum rank of equality constraints */\nint BFP_CALLMODEL bfp_findredundant(lprec *lp, int items, getcolumnex_func cb, int *maprow, int *mapcol)\n{\n  int       i, j, nz = 0, m = 0, n = 0, *nzrows = NULL;\n  REAL      *nzvalues = NULL, *arraymax = NULL;\n  LUSOLrec  *LUSOL;\n\n  /* Are we capable of finding redundancy with this BFP? */\n  if((maprow == NULL) && (mapcol == NULL))\n    return( n );\n\n  /* If so, initialize memory structures */\n  if(!allocINT(lp, &nzrows, items, FALSE) ||\n     !allocREAL(lp, &nzvalues, items, FALSE))\n    return( n );\n\n  /* Compute the number of non-empty columns */\n  m = 0;\n  for(j = 1; j <= mapcol[0]; j++) {\n    n = cb(lp, mapcol[j], NULL, NULL, maprow);\n    if(n > 0) {\n      m++;\n      mapcol[m] = mapcol[j];\n      nz += n;\n    }\n  }\n  mapcol[0] = m;\n\n  /* Instantiate a LUSOL object */\n  LUSOL = LUSOL_create(NULL, 0, LUSOL_PIVMOD_TRP, 0);\n  if((LUSOL == NULL) || !LUSOL_sizeto(LUSOL, items, m, nz*LUSOL_MULT_nz_a))\n    goto Finish;\n\n  /* Modify relevant LUSOL parameters */\n  LUSOL->m = items;\n  LUSOL->n = m;\n#if 0\n  LUSOL->luparm[LUSOL_IP_KEEPLU]        = FALSE;\n  LUSOL->luparm[LUSOL_IP_PIVOTTYPE]     = LUSOL_PIVMOD_TRP;\n  LUSOL->parmlu[LUSOL_RP_FACTORMAX_Lij] = 2.0;\n#endif\n\n  /* Load the columns into LUSOL */\n  for(j = 1; j <= m; j++) {\n    n = cb(lp, mapcol[j], nzvalues, nzrows, maprow);\n    i = LUSOL_loadColumn(LUSOL, nzrows, j, nzvalues, n, -1);\n    if(n != i) {\n      lp->report(lp, IMPORTANT, \"bfp_findredundant: Error %d while loading column %d with %d nz\\n\",\n                                i, j, n);\n      n = 0;\n      goto Finish;\n    }\n  }\n\n  /* Scale rows to prevent numerical problems */\n  if((lp->scalemode != SCALE_NONE) && allocREAL(lp, &arraymax, items+1, TRUE)) {\n    for(i = 1; i <= nz; i++) {\n      SETMAX(arraymax[LUSOL->indc[i]], fabs(LUSOL->a[i]));\n    }\n    for(i = 1; i <= nz; i++)\n      LUSOL->a[i] /= arraymax[LUSOL->indc[i]];\n    FREE(arraymax);\n  }\n\n  /* Factorize for maximum rank */\n  n = 0;\n  i = LUSOL_factorize(LUSOL);\n  /*  lp->report(lp, NORMAL, \"bfp_findredundant: r=%d c=%d - %s\\n\", items, m, LUSOL_informstr(LUSOL, i));*/\n  if((i == LUSOL_INFORM_LUSUCCESS) || (i != LUSOL_INFORM_LUSINGULAR))\n    goto Finish;\n\n  /* We have a singular matrix, obtain the indeces of the singular rows */\n  for(i = LUSOL->luparm[LUSOL_IP_RANK_U] + 1; i <= items; i++) {\n    n++;\n    maprow[n] = LUSOL->ip[i];\n  }\n  maprow[0] = n;\n\n  /* Clean up */\nFinish:\n  LUSOL_free(LUSOL);\n  FREE(nzrows);\n  FREE(nzvalues);\n\n  return( n );\n}\n"
  },
  {
    "path": "utilities/lp_solve/bfp/bfp_LUSOL/lp_LUSOL.h",
    "content": "#ifndef HEADER_lp_LUSOL\n#define HEADER_lp_LUSOL\n\n/* Include libraries for this inverse system */\n#include \"lp_types.h\"\n#include \"lusol.h\"\n\n/* LUSOL defines */\n#ifdef WIN32\n# define LUSOL_UseBLAS\n#endif\n/*#define MAPSINGULARCOLUMN*/\n#define MATINDEXBASE LUSOL_ARRAYOFFSET /* Inversion engine index start for arrays */\n#define LU_START_SIZE           10000  /* Start size of LU; realloc'ed if needed */\n#define DEF_MAXPIVOT              250  /* Maximum number of pivots before refactorization */\n#define MAX_DELTAFILLIN           2.0  /* Do refactorizations based on sparsity considerations */\n#define TIGHTENAFTER               10  /* Tighten LU pivot criteria only after this number of singularities */\n\n/* typedef */ struct _INVrec\n{\n  int       status;                 /* Last operation status code */\n  int       dimcount;               /* The actual number of LU rows/columns */\n  int       dimalloc;               /* The allocated LU rows/columns size */\n  int       user_colcount;          /* The number of user LU columns */\n  LUSOLrec  *LUSOL;\n  int       col_enter;              /* The full index of the entering column */\n  int       col_leave;              /* The full index of the leaving column */\n  int       col_pos;                /* The B column to be changed at the next update using data in value[.]*/\n  REAL      *value;\n  REAL      *pcol;                  /* Reference to the elimination vector */\n  REAL      theta_enter;            /* Value of the entering column theta */\n\n  int       max_Bsize;              /* The largest B matrix of user variables */\n  int       max_colcount;           /* The maximum number of user columns in LU */\n  int       max_LUsize;             /* The largest NZ-count of LU-files generated */\n  int       num_refact;             /* Number of times the basis was refactored */\n  int       num_timed_refact;\n  int       num_dense_refact;\n  double    time_refactstart;       /* Time since start of last refactorization-pivots cyle */\n  double    time_refactnext;        /* Time estimated to next refactorization */\n  int       num_pivots;             /* Number of pivots since last refactorization */\n  int       num_singular;           /* The total number of singular updates */\n  char      *opts;\n  MYBOOL    is_dirty;               /* Specifies if a column is incompletely processed */\n  MYBOOL    force_refact;           /* Force refactorization at the next opportunity */\n  MYBOOL    timed_refact;           /* Set if timer-driven refactorization should be active */\n  MYBOOL    set_Bidentity;          /* Force B to be the identity matrix at the next refactorization */\n} /* INVrec */;\n\n\n#ifdef __cplusplus\n/* namespace LUSOL */\nextern \"C\" {\n#endif\n\n/* Put function headers here */\n#include \"lp_BFP.h\"\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_LUSOL */\n"
  },
  {
    "path": "utilities/lp_solve/bfp/lp_BFP.h",
    "content": "\n/* ---------------------------------------------------------------------------------- */\n/* lp_solve v5+ headers for basis inversion / factorization libraries                 */\n/* ---------------------------------------------------------------------------------- */\n#define BFP_STATUS_RANKLOSS     -1\n#define BFP_STATUS_SUCCESS       0\n#define BFP_STATUS_SINGULAR      1\n#define BFP_STATUS_UNSTABLE      2\n#define BFP_STATUS_NOPIVOT       3\n#define BFP_STATUS_DIMERROR      4\n#define BFP_STATUS_DUPLICATE     5\n#define BFP_STATUS_NOMEMORY      6\n#define BFP_STATUS_ERROR         7             /* Unspecified, command-related error */\n#define BFP_STATUS_FATAL         8\n\n#define BFP_STAT_ERROR          -1\n#define BFP_STAT_REFACT_TOTAL    0\n#define BFP_STAT_REFACT_TIMED    1\n#define BFP_STAT_REFACT_DENSE    2\n\n#ifndef BFP_CALLMODEL\n  #ifdef WIN32\n    #define BFP_CALLMODEL __stdcall   /* \"Standard\" call model */\n  #else\n    #define BFP_CALLMODEL\n  #endif\n#endif\n\n#ifdef RoleIsExternalInvEngine\n  #define __BFP_EXPORT_TYPE __EXPORT_TYPE\n#else\n  #define __BFP_EXPORT_TYPE\n#endif\n\n\n/* Routines with UNIQUE implementations for each inversion engine                     */\n/* ---------------------------------------------------------------------------------- */\nconst char   __BFP_EXPORT_TYPE *(BFP_CALLMODEL bfp_name)(void);\nvoid   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_free)(lprec *lp);\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_resize)(lprec *lp, int newsize);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_nonzeros)(lprec *lp, MYBOOL maximum);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_memallocated)(lprec *lp);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_preparefactorization)(lprec *lp);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_factorize)(lprec *lp, int uservars, int Bsize, MYBOOL *usedpos, MYBOOL final);\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_finishupdate)(lprec *lp, MYBOOL changesign);\nvoid   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_ftran_normal)(lprec *lp, REAL *pcol, int *nzidx);\nvoid   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_ftran_prepare)(lprec *lp, REAL *pcol, int *nzidx);\nvoid   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_btran_normal)(lprec *lp, REAL *prow, int *nzidx);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_status)(lprec *lp);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_findredundant)(lprec *lp, int items, getcolumnex_func cb, int *maprow, int*mapcol);\n\n\n/* Routines SHARED for all inverse implementations; located in lp_BFP1.c              */\n/* ---------------------------------------------------------------------------------- */\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_compatible)(lprec *lp, int bfpversion, int lpversion, int sizeofvar);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_indexbase)(lprec *lp);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_rowoffset)(lprec *lp);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_pivotmax)(lprec *lp);\nREAL   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_efficiency)(lprec *lp);\nREAL   __BFP_EXPORT_TYPE *(BFP_CALLMODEL bfp_pivotvector)(lprec *lp);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_pivotcount)(lprec *lp);\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_mustrefactorize)(lprec *lp);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_refactcount)(lprec *lp, int kind);\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_isSetI)(lprec *lp);\nint    *bfp_createMDO(lprec *lp, MYBOOL *usedpos, int count, MYBOOL doMDO);\nvoid   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_updaterefactstats)(lprec *lp);\nint    BFP_CALLMODEL bfp_rowextra(lprec *lp);\n\n/* Routines with OPTIONAL SHARED code; template routines suitable for canned          */\n/* inverse engines are located in lp_BFP2.c                                           */\n/* ---------------------------------------------------------------------------------- */\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_init)(lprec *lp, int size, int deltasize, const char *options);\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_restart)(lprec *lp);\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_implicitslack)(lprec *lp);\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_pivotalloc)(lprec *lp, int newsize);\nint    __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_colcount)(lprec *lp);\nMYBOOL __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_canresetbasis)(lprec *lp);\nvoid   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_finishfactorization)(lprec *lp);\nLREAL  __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_prepareupdate)(lprec *lp, int row_nr, int col_nr, REAL *pcol);\nREAL   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_pivotRHS)(lprec *lp, LREAL theta, REAL *pcol);\nvoid   __BFP_EXPORT_TYPE (BFP_CALLMODEL bfp_btran_double)(lprec *lp, REAL *prow, int *pnzidx, REAL *drow, int *dnzidx);\n\n"
  },
  {
    "path": "utilities/lp_solve/bfp/lp_BFP1.c",
    "content": "\n/* Routines located in lp_BFP1.cpp; common for all factorization engines              */\n/* Cfr. lp_BFP.h for definitions                                                      */\n/* ---------------------------------------------------------------------------------- */\n/* Changes:                                                                           */\n/* 29 May 2004       Corrected calculation of bfp_efficiency(), which required        */\n/*                   modifying the max_Bsize to include slack variables. KE.          */\n/* 16 June 2004      Make the symbolic minimum degree ordering routine available      */\n/*                   to BFPs as a routine internal to the library. KE                 */\n/* 1  July 2004      Change due to change in MDO naming.                              */\n/* ---------------------------------------------------------------------------------- */\n\n\n/* MUST MODIFY */\nMYBOOL BFP_CALLMODEL bfp_compatible(lprec *lp, int bfpversion, int lpversion, int sizeofvar)\n{\n  (void) lpversion; /* unused variable */\n  MYBOOL status = FALSE;\n\n  (void) lpversion; /* unused variable */\n\n  if((lp != NULL) && (bfpversion == BFPVERSION) && (sizeof(REAL) == sizeofvar)) {\n#if 0\n    if(lpversion == MAJORVERSION)  /* Forces BFP renewal at lp_solve major version changes */\n#endif\n      status = TRUE;\n  }\n  return( status );\n}\n\n/* DON'T MODIFY */\nint BFP_CALLMODEL bfp_status(lprec *lp)\n{\n  return(lp->invB->status);\n}\n\n/* DON'T MODIFY */\nint BFP_CALLMODEL bfp_indexbase(lprec *lp)\n{\n  (void)lp; /* unused variable*/\n  return( MATINDEXBASE );\n}\n\n/* DON'T MODIFY */\nint BFP_CALLMODEL bfp_rowoffset(lprec *lp)\n{\n  if(lp->obj_in_basis)\n    return( 1 );\n  else\n    return( 0 );\n}\n\n/* DON'T MODIFY */\nint BFP_CALLMODEL bfp_pivotmax(lprec *lp)\n{\n  if(lp->max_pivots > 0)\n    return( lp->max_pivots );\n  else\n    return( DEF_MAXPIVOT );\n}\n\n/* DON'T MODIFY */\nREAL * BFP_CALLMODEL bfp_pivotvector(lprec *lp)\n{\n  return( lp->invB->pcol );\n}\n\n/* DON'T MODIFY */\nREAL BFP_CALLMODEL bfp_efficiency(lprec *lp)\n{\n  REAL hold;\n\n  hold = lp->bfp_nonzeros(lp, AUTOMATIC);\n  if(hold == 0)\n    hold = 1 + lp->rows;\n  hold = lp->bfp_nonzeros(lp, TRUE)/hold;\n\n  return(hold);\n}\n\n/* DON'T MODIFY */\nint BFP_CALLMODEL bfp_pivotcount(lprec *lp)\n{\n  return(lp->invB->num_pivots);\n}\n\n\n/* DON'T MODIFY */\nint BFP_CALLMODEL bfp_refactcount(lprec *lp, int kind)\n{\n  if(kind == BFP_STAT_REFACT_TOTAL)\n    return(lp->invB->num_refact);\n  else if(kind == BFP_STAT_REFACT_TIMED)\n    return(lp->invB->num_timed_refact);\n  else if(kind == BFP_STAT_REFACT_DENSE)\n    return(lp->invB->num_dense_refact);\n  else\n    return( BFP_STAT_ERROR );\n}\n\n/* DON'T MODIFY */\nMYBOOL BFP_CALLMODEL bfp_mustrefactorize(lprec *lp)\n{\n  MYBOOL test = lp->is_action(lp->spx_action, ACTION_REINVERT | ACTION_TIMEDREINVERT);\n  if(!test) {\n    REAL   f;\n    INVrec *lu = lp->invB;\n\n    if(lu->num_pivots > 0)\n      f = (timeNow()-lu->time_refactstart) / (REAL) lu->num_pivots;\n    else\n      f = 0;\n\n    /* Always refactorize if we are above the set pivot limit */\n    if(lu->force_refact ||\n       (lu->num_pivots >= lp->bfp_pivotmax(lp)))\n      lp->set_action(&lp->spx_action, ACTION_REINVERT);\n\n    /* Check if we should do an optimal time-based refactorization */\n    else if(lu->timed_refact && (lu->num_pivots > 1) &&\n            (f > MIN_TIMEPIVOT) && (f > lu->time_refactnext)) {\n      /* If we have excessive time usage in automatic mode then\n         treat as untimed case and update optimal time metric, ... */\n      if((lu->timed_refact == AUTOMATIC) &&\n         (lu->num_pivots < 0.4*lp->bfp_pivotmax(lp)))\n        lu->time_refactnext = f;\n      /* ... otherwise set flag for the optimal time-based refactorization */\n      else\n        lp->set_action(&lp->spx_action, ACTION_TIMEDREINVERT);\n    }\n\n    /* Otherwise simply update the optimal time metric */\n    else\n      lu->time_refactnext = f;\n#if 0\n    if(lu->num_pivots % 10 == 0)\n      lp->report(lp, NORMAL, \"bfp pivot %d - start %f - timestat %f\",\n                             lu->num_pivots, lu->time_refactstart, f);\n#endif\n  }\n\n  test = lp->is_action(lp->spx_action, ACTION_REINVERT | ACTION_TIMEDREINVERT);\n  return(test);\n}\n\n/* DON'T MODIFY */\nMYBOOL BFP_CALLMODEL bfp_isSetI(lprec *lp)\n{\n  return( (MYBOOL) lp->invB->set_Bidentity );\n}\n\n/* DON'T MODIFY */\nint *bfp_createMDO(lprec *lp, MYBOOL *usedpos, int count, MYBOOL doMDO)\n{\n  int *mdo, i, j, kk;\n\n  mdo = (int *) malloc((count + 1)*sizeof(*mdo));\n/*  allocINT(lp, &mdo, count + 1, FALSE); */\n\n /* Fill the mdo[] array with remaining full-pivot basic user variables */\n  kk = 0;\n  for(j = 1; j <= lp->columns; j++) {\n    i = lp->rows + j;\n    if(usedpos[i] == TRUE) {\n      kk++;\n      mdo[kk] = i;\n    }\n  }\n  mdo[0] = kk;\n  if(kk == 0)\n    goto Process;\n\n /* Calculate the approximate minimum degree column ordering */\n  if(doMDO) {\n    i = lp->getMDO(lp, usedpos, mdo, NULL, FALSE);\n    if(i != 0) {\n      lp->report(lp, CRITICAL, \"bfp_createMDO: Internal error %d in minimum degree ordering routine\", i);\n      FREE(mdo);\n    }\n  }\nProcess:\n  return( mdo );\n}\nvoid BFP_CALLMODEL bfp_updaterefactstats(lprec *lp)\n{\n  INVrec *lu = lp->invB;\n\n  /* Signal that we are refactorizing */\n  lu->is_dirty = AUTOMATIC;\n\n  /* Set time of start of current refactorization cycle */\n  lu->time_refactstart = timeNow();\n  lu->time_refactnext  = 0;\n  lu->user_colcount = 0;\n\n  /* Do the numbers */\n  if(lu->force_refact)\n    lu->num_dense_refact++;\n  else if(lu->timed_refact && lp->is_action(lp->spx_action, ACTION_TIMEDREINVERT))\n    lu->num_timed_refact++;\n  lu->num_refact++;\n}\n\nint BFP_CALLMODEL bfp_rowextra(lprec *lp)\n{\n  if(lp->is_obj_in_basis(lp))\n    return( 1 );\n  else\n    return( 0 );\n}\n"
  },
  {
    "path": "utilities/lp_solve/bfp/lp_BFP2.c",
    "content": "\n\n/* Routines located in lp_BFP2.cpp; optional shared for canned implementations        */\n/* Cfr. lp_BFP.h for definitions                                                      */\n/* ---------------------------------------------------------------------------------- */\n\n\n/* DON'T MODIFY */\nMYBOOL BFP_CALLMODEL bfp_init(lprec *lp, int size, int delta, const char *options)\n{\n  (void) delta;\n  INVrec *lu;\n  (void) delta;\n\n  lp->invB = (INVrec *) calloc(1, sizeof(*(lp->invB)));\n  lu = lp->invB;\n  if((lu == NULL) ||\n     !lp->bfp_resize(lp, size) ||\n     !lp->bfp_restart(lp))\n    return( FALSE );\n\n  /* Store any passed options */\n  if(options != NULL) {\n    size_t len = strlen(options);\n    lu->opts = (char *) malloc(len + 1);\n    strcpy(lu->opts, options);\n  }\n\n  /* Prepare for factorization and undo values reset by bfp_preparefactorization */\n  lp->bfp_preparefactorization(lp);\n  lu->num_refact = 0;\n\n  return( TRUE );\n}\n\n/* DON'T MODIFY */\nMYBOOL BFP_CALLMODEL bfp_restart(lprec *lp)\n{\n  INVrec *lu;\n\n  lu = lp->invB;\n  if(lu == NULL)\n    return( FALSE );\n\n  lu->status = BFP_STATUS_SUCCESS;\n  lu->max_Bsize = 0;          /* The largest NZ-count of the B matrix            */\n  lu->max_colcount = 0;       /* The maximum number of user columns in B         */\n  lu->max_LUsize = 0;         /* The largest NZ-count of LU-files generated      */\n  lu->num_refact = 0;         /* The number of times the basis has been factored */\n  lu->num_timed_refact = 0;\n  lu->num_dense_refact = 0;\n  lu->num_pivots = 0;         /* The number of pivots since last factorization   */\n  lu->pcol = NULL;\n  lu->set_Bidentity = FALSE;\n\n  return( TRUE );\n}\n\n/* DON'T MODIFY */\nMYBOOL BFP_CALLMODEL bfp_implicitslack(lprec *lp)\n{\n  (void) lp;\n  return( FALSE );\n}\n\n/* DON'T MODIFY */\nint BFP_CALLMODEL bfp_colcount(lprec *lp)\n{\n  return(lp->invB->user_colcount);\n}\n\n\n/* DON'T MODIFY */\nMYBOOL BFP_CALLMODEL bfp_canresetbasis(lprec *lp)\n{\n  (void) lp;\n  return( FALSE );\n}\n\n\n/* DON'T MODIFY */\nMYBOOL BFP_CALLMODEL bfp_pivotalloc(lprec *lp, int newsize)\n{\n  (void)lp;\n  (void)newsize;\n  /* Does nothing in the default implementation */\n  return( TRUE );\n}\n\n\n/* DON'T MODIFY */\nvoid BFP_CALLMODEL bfp_finishfactorization(lprec *lp)\n{\n  INVrec *lu;\n\n  lu = lp->invB;\n\n  SETMAX(lu->max_colcount, lp->bfp_colcount(lp));\n  SETMAX(lu->max_LUsize, lp->bfp_nonzeros(lp, FALSE));\n\n  /* Signal that we done factorizing/reinverting */\n  lu->is_dirty = FALSE;\n  lp->clear_action(&lp->spx_action, ACTION_REINVERT | ACTION_TIMEDREINVERT);\n  lu->force_refact = FALSE;\n\n  /* Store information about the current inverse */\n  lu->num_pivots = 0;\n\n}\n\n\n/* DON'T MODIFY */\nLREAL BFP_CALLMODEL bfp_prepareupdate(lprec *lp, int row_nr, int col_nr, REAL *pcol)\n/* Was condensecol() in versions of lp_solve before 4.0.1.8 - KE */\n{\n  LREAL  pivValue;\n  INVrec *lu;\n\n  lu = lp->invB;\n\n  /* Store the incoming pivot value for RHS update purposes */\n  lu->col_enter = col_nr;  /* The index of the new data column */\n  lu->col_pos   = row_nr;  /* The basis column to be replaced */\n  lu->col_leave = lp->var_basic[row_nr];\n  if(pcol == NULL)\n    pivValue = 0;\n  else\n    pivValue = pcol[row_nr];\n  lu->theta_enter = pivValue;\n\n  /* Save reference to the elimination vector */\n  lu->pcol = pcol;\n\n  /* Set completion status; but hold if we are reinverting */\n  if(lu->is_dirty != AUTOMATIC)\n    lu->is_dirty = TRUE;\n\n  return( pivValue );\n}\n\n\n/* DON'T MODIFY */\nREAL BFP_CALLMODEL bfp_pivotRHS(lprec *lp, LREAL theta, REAL *pcol)\n/* This function is used to adjust the RHS in bound swap operations as\n   well as handling the updating of the RHS for normal basis changes.\n   Was rhsmincol(), ie. \"rhs minus column\" in versions of lp_solve before 4.0.1.8 - KE */\n{\n  INVrec    *lu;\n\n  lu = lp->invB;\n\n  if(pcol == NULL)\n    pcol = lu->pcol;\n\n  if(theta != 0) {\n    int    i, n = lp->rows;\n    LREAL  roundzero = lp->epsvalue;\n    LREAL  *rhs = lp->rhs, rhsmax = 0;\n\n    for(i = 0; i <= n; i++, rhs++, pcol++) {\n      (*rhs) -= theta * (*pcol);\n      my_roundzero(*rhs, roundzero);\n      SETMAX(rhsmax, fabs(*rhs));\n    }\n    lp->rhsmax = rhsmax;\n  }\n\n  if(pcol == lu->pcol)\n    return( lu->theta_enter );\n  else\n    return( 0.0 );\n}\n\n\n/* DON'T MODIFY */\nvoid BFP_CALLMODEL bfp_btran_double(lprec *lp, REAL *prow, int *pnzidx, REAL *drow, int *dnzidx)\n{\n  if(prow != NULL)\n    lp->bfp_btran_normal(lp, prow, pnzidx);\n  if(drow != NULL)\n    lp->bfp_btran_normal(lp, drow, dnzidx);\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/colamd/colamd.c",
    "content": "/* ========================================================================== */\n/* === colamd/symamd - a sparse matrix column ordering algorithm ============ */\n/* ========================================================================== */\n\n/*\n    colamd:  an approximate minimum degree column ordering algorithm,\n    \tfor LU factorization of symmetric or unsymmetric matrices,\n\tQR factorization, least squares, interior point methods for\n\tlinear programming problems, and other related problems.\n\n    symamd:  an approximate minimum degree ordering algorithm for Cholesky\n    \tfactorization of symmetric matrices.\n\n    Purpose:\n\n\tColamd computes a permutation Q such that the Cholesky factorization of\n\t(AQ)'(AQ) has less fill-in and requires fewer floating point operations\n\tthan A'A.  This also provides a good ordering for sparse partial\n\tpivoting methods, P(AQ) = LU, where Q is computed prior to numerical\n\tfactorization, and P is computed during numerical factorization via\n\tconventional partial pivoting with row interchanges.  Colamd is the\n\tcolumn ordering method used in SuperLU, part of the ScaLAPACK library.\n\tIt is also available as built-in function in Matlab Version 6,\n\tavailable from MathWorks, Inc. (https://www.mathworks.com).  This\n\troutine can be used in place of colmmd in Matlab.  By default, the \\\n\tand / operators in Matlab perform a column ordering (using colmmd\n\tor colamd) prior to LU factorization using sparse partial pivoting,\n\tin the built-in Matlab lu(A) routine.\n\n    \tSymamd computes a permutation P of a symmetric matrix A such that the\n\tCholesky factorization of PAP' has less fill-in and requires fewer\n\tfloating point operations than A.  Symamd constructs a matrix M such\n\tthat M'M has the same nonzero pattern of A, and then orders the columns\n\tof M using colmmd.  The column ordering of M is then returned as the\n\trow and column ordering P of A.\n\n    Authors:\n\n\tThe authors of the code itself are Stefan I. Larimore and Timothy A.\n\tDavis (davis@cise.ufl.edu), University of Florida.  The algorithm was\n\tdeveloped in collaboration with John Gilbert, Xerox PARC, and Esmond\n\tNg, Oak Ridge National Laboratory.\n\n    Date:\n\n\tMay 4, 2001.  Version 2.1.\n\n    Acknowledgements:\n\n\tThis work was supported by the National Science Foundation, under\n\tgrants DMS-9504974 and DMS-9803599.\n\n    Notice:\n\n\tCopyright (c) 1998-2001 by the University of Florida.\n\tAll Rights Reserved.\n\n\tTHIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY\n\tEXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n\n\tPermission is hereby granted to use or copy this program for any\n\tpurpose, provided the above notices are retained on all copies.\n\tUser documentation of any code that uses this code must cite the\n\tAuthors, the Copyright, and \"Used by permission.\"  If this code is\n\taccessible from within Matlab, then typing \"help colamd\" and \"help\n\tsymamd\" must cite the Authors.  Permission to modify the code and to\n\tdistribute modified code is granted, provided the above notices are\n\tretained, and a notice that the code was modified is included with the\n\tabove copyright notice.  You must also retain the Availability\n\tinformation below, of the original version.\n\n\tThis software is provided free of charge.\n\n    Availability:\n\n\tThe colamd/symamd library is available at\n\n\t    https://www.cise.ufl.edu/research/sparse/colamd/\n\n\tThis is the https://www.cise.ufl.edu/research/sparse/colamd/colamd.c\n\tfile.  It requires the colamd.h file.  It is required by the colamdmex.c\n\tand symamdmex.c files, for the Matlab interface to colamd and symamd.\n\n    Changes to the colamd library since Version 1.0 and 1.1:\n\n\tNo bugs were found in version 1.1.  These changes merely add new\n\tfunctionality.\n\n    \t* added the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro.\n\n\t* moved the output statistics, from A, to a separate output argument.\n\t\tThe arguments changed for the C-callable routines.\n\n\t* added colamd_report and symamd_report.\n\n\t* added a C-callable symamd routine.  Formerly, symamd was only\n\t\tavailable as a mexFunction from Matlab.\n\n\t* added error-checking to symamd.  Formerly, it assumed its input\n\t\twas error-free.\n\n\t* added the optional stats and knobs arguments to the symamd mexFunction\n\n\t* deleted colamd_help.  A help message is still available from\n\t\t\"help colamd\" and \"help symamd\" in Matlab.\n\n\t* deleted colamdtree.m and symamdtree.m.  Now, colamd.m and symamd.m\n\t\talso do the elimination tree post-ordering.  The Version 1.1\n\t\tcolamd and symamd mexFunctions, which do not do the post-\n\t\tordering, are now visible as colamdmex and symamdmex from\n\t\tMatlab.  Essentialy, the post-ordering is now the default\n\t\tbehavior of colamd.m and symamd.m, to match the behavior of\n\t\tcolmmd and symmmd.  The post-ordering is only available in the\n\t\tMatlab interface, not the C-callable interface.\n\n\t* made a slight change to the dense row/column detection in symamd,\n\t\tto match the stated specifications.\n\n    Changes from Version 2.0 to 2.1:\n\n\t* TRUE and FALSE are predefined on some systems, so they are defined\n\t\there only if not already defined.\n\t\n\t* web site changed\n\n\t* UNIX Makefile modified, to handle the case if \".\" is not in your path.\n\n*/\n\n/* ========================================================================== */\n/* === Description of user-callable routines ================================ */\n/* ========================================================================== */\n\n/*\n    ----------------------------------------------------------------------------\n    colamd_recommended:\n    ----------------------------------------------------------------------------\n\n\tC syntax:\n\n\t    #include \"colamd.h\"\n\t    int colamd_recommended (int nnz, int n_row, int n_col) ;\n\n\t    or as a C macro\n\n\t    #include \"colamd.h\"\n\t    Alen = COLAMD_RECOMMENDED (int nnz, int n_row, int n_col) ;\n\n\tPurpose:\n\n\t    Returns recommended value of Alen for use by colamd.  Returns -1\n\t    if any input argument is negative.  The use of this routine\n\t    or macro is optional.  Note that the macro uses its arguments\n\t    more than once, so be careful for side effects, if you pass\n\t    expressions as arguments to COLAMD_RECOMMENDED.  Not needed for\n\t    symamd, which dynamically allocates its own memory.\n\n\tArguments (all input arguments):\n\n\t    int nnz ;\t\tNumber of nonzeros in the matrix A.  This must\n\t\t\t\tbe the same value as p [n_col] in the call to\n\t\t\t\tcolamd - otherwise you will get a wrong value\n\t\t\t\tof the recommended memory to use.\n\n\t    int n_row ;\t\tNumber of rows in the matrix A.\n\n\t    int n_col ;\t\tNumber of columns in the matrix A.\n\n    ----------------------------------------------------------------------------\n    colamd_set_defaults:\n    ----------------------------------------------------------------------------\n\n\tC syntax:\n\n\t    #include \"colamd.h\"\n\t    colamd_set_defaults (int knobs [COLAMD_KNOBS]) ;\n\n\tPurpose:\n\n\t    Sets the default parameters.  The use of this routine is optional.\n\n\tArguments:\n\n\t    double knobs [COLAMD_KNOBS] ;\tOutput only.\n\n\t\tColamd: rows with more than (knobs [COLAMD_DENSE_ROW] * n_col)\n\t\tentries are removed prior to ordering.  Columns with more than\n\t\t(knobs [COLAMD_DENSE_COL] * n_row) entries are removed prior to\n\t\tordering, and placed last in the output column ordering.\n\n\t\tSymamd: uses only knobs [COLAMD_DENSE_ROW], which is knobs [0].\n\t\tRows and columns with more than (knobs [COLAMD_DENSE_ROW] * n)\n\t\tentries are removed prior to ordering, and placed last in the\n\t\toutput ordering.\n\n\t\tCOLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1,\n\t\trespectively, in colamd.h.  Default values of these two knobs\n\t\tare both 0.5.  Currently, only knobs [0] and knobs [1] are\n\t\tused, but future versions may use more knobs.  If so, they will\n\t\tbe properly set to their defaults by the future version of\n\t\tcolamd_set_defaults, so that the code that calls colamd will\n\t\tnot need to change, assuming that you either use\n\t\tcolamd_set_defaults, or pass a (double *) NULL pointer as the\n\t\tknobs array to colamd or symamd.\n\n    ----------------------------------------------------------------------------\n    colamd:\n    ----------------------------------------------------------------------------\n\n\tC syntax:\n\n\t    #include \"colamd.h\"\n\t    int colamd (int n_row, int n_col, int Alen, int *A, int *p,\n\t    \tdouble knobs [COLAMD_KNOBS], int stats [COLAMD_STATS]) ;\n\n\tPurpose:\n\n\t    Computes a column ordering (Q) of A such that P(AQ)=LU or\n\t    (AQ)'AQ=LL' have less fill-in and require fewer floating point\n\t    operations than factorizing the unpermuted matrix A or A'A,\n\t    respectively.\n\t\n\tReturns:\n\n\t    TRUE (1) if successful, FALSE (0) otherwise.\n\n\tArguments:\n\n\t    int n_row ;\t\tInput argument.\n\n\t\tNumber of rows in the matrix A.\n\t\tRestriction:  n_row >= 0.\n\t\tColamd returns FALSE if n_row is negative.\n\n\t    int n_col ;\t\tInput argument.\n\n\t\tNumber of columns in the matrix A.\n\t\tRestriction:  n_col >= 0.\n\t\tColamd returns FALSE if n_col is negative.\n\n\t    int Alen ;\t\tInput argument.\n\n\t\tRestriction (see note):\n\t\tAlen >= 2*nnz + 6*(n_col+1) + 4*(n_row+1) + n_col\n\t\tColamd returns FALSE if these conditions are not met.\n\n\t\tNote:  this restriction makes an modest assumption regarding\n\t\tthe size of the two typedef's structures in colamd.h.\n\t\tWe do, however, guarantee that\n\n\t\t\tAlen >= colamd_recommended (nnz, n_row, n_col)\n\t\t\n\t\tor equivalently as a C preprocessor macro:\n\n\t\t\tAlen >= COLAMD_RECOMMENDED (nnz, n_row, n_col)\n\n\t\twill be sufficient.\n\n\t    int A [Alen] ;\tInput argument, undefined on output.\n\n\t\tA is an integer array of size Alen.  Alen must be at least as\n\t\tlarge as the bare minimum value given above, but this is very\n\t\tlow, and can result in excessive run time.  For best\n\t\tperformance, we recommend that Alen be greater than or equal to\n\t\tcolamd_recommended (nnz, n_row, n_col), which adds\n\t\tnnz/5 to the bare minimum value given above.\n\n\t\tOn input, the row indices of the entries in column c of the\n\t\tmatrix are held in A [(p [c]) ... (p [c+1]-1)].  The row indices\n\t\tin a given column c need not be in ascending order, and\n\t\tduplicate row indices may be be present.  However, colamd will\n\t\twork a little faster if both of these conditions are met\n\t\t(Colamd puts the matrix into this format, if it finds that the\n\t\tthe conditions are not met).\n\n\t\tThe matrix is 0-based.  That is, rows are in the range 0 to\n\t\tn_row-1, and columns are in the range 0 to n_col-1.  Colamd\n\t\treturns FALSE if any row index is out of range.\n\n\t\tThe contents of A are modified during ordering, and are\n\t\tundefined on output.\n\n\t    int p [n_col+1] ;\tBoth input and output argument.\n\n\t\tp is an integer array of size n_col+1.  On input, it holds the\n\t\t\"pointers\" for the column form of the matrix A.  Column c of\n\t\tthe matrix A is held in A [(p [c]) ... (p [c+1]-1)].  The first\n\t\tentry, p [0], must be zero, and p [c] <= p [c+1] must hold\n\t\tfor all c in the range 0 to n_col-1.  The value p [n_col] is\n\t\tthus the total number of entries in the pattern of the matrix A.\n\t\tColamd returns FALSE if these conditions are not met.\n\n\t\tOn output, if colamd returns TRUE, the array p holds the column\n\t\tpermutation (Q, for P(AQ)=LU or (AQ)'(AQ)=LL'), where p [0] is\n\t\tthe first column index in the new ordering, and p [n_col-1] is\n\t\tthe last.  That is, p [k] = j means that column j of A is the\n\t\tkth pivot column, in AQ, where k is in the range 0 to n_col-1\n\t\t(p [0] = j means that column j of A is the first column in AQ).\n\n\t\tIf colamd returns FALSE, then no permutation is returned, and\n\t\tp is undefined on output.\n\n\t    double knobs [COLAMD_KNOBS] ;\tInput argument.\n\n\t\tSee colamd_set_defaults for a description.\n\n\t    int stats [COLAMD_STATS] ;\t\tOutput argument.\n\n\t\tStatistics on the ordering, and error status.\n\t\tSee colamd.h for related definitions.\n\t\tColamd returns FALSE if stats is not present.\n\n\t\tstats [0]:  number of dense or empty rows ignored.\n\n\t\tstats [1]:  number of dense or empty columns ignored (and\n\t\t\t\tordered last in the output permutation p)\n\t\t\t\tNote that a row can become \"empty\" if it\n\t\t\t\tcontains only \"dense\" and/or \"empty\" columns,\n\t\t\t\tand similarly a column can become \"empty\" if it\n\t\t\t\tonly contains \"dense\" and/or \"empty\" rows.\n\n\t\tstats [2]:  number of garbage collections performed.\n\t\t\t\tThis can be excessively high if Alen is close\n\t\t\t\tto the minimum required value.\n\n\t\tstats [3]:  status code.  < 0 is an error code.\n\t\t\t    > 1 is a warning or notice.\n\n\t\t\t0\tOK.  Each column of the input matrix contained\n\t\t\t\trow indices in increasing order, with no\n\t\t\t\tduplicates.\n\n\t\t\t1\tOK, but columns of input matrix were jumbled\n\t\t\t\t(unsorted columns or duplicate entries).  Colamd\n\t\t\t\thad to do some extra work to sort the matrix\n\t\t\t\tfirst and remove duplicate entries, but it\n\t\t\t\tstill was able to return a valid permutation\n\t\t\t\t(return value of colamd was TRUE).\n\n\t\t\t\t\tstats [4]: highest numbered column that\n\t\t\t\t\t\tis unsorted or has duplicate\n\t\t\t\t\t\tentries.\n\t\t\t\t\tstats [5]: last seen duplicate or\n\t\t\t\t\t\tunsorted row index.\n\t\t\t\t\tstats [6]: number of duplicate or\n\t\t\t\t\t\tunsorted row indices.\n\n\t\t\t-1\tA is a null pointer\n\n\t\t\t-2\tp is a null pointer\n\n\t\t\t-3 \tn_row is negative\n\n\t\t\t\t\tstats [4]: n_row\n\n\t\t\t-4\tn_col is negative\n\n\t\t\t\t\tstats [4]: n_col\n\n\t\t\t-5\tnumber of nonzeros in matrix is negative\n\n\t\t\t\t\tstats [4]: number of nonzeros, p [n_col]\n\n\t\t\t-6\tp [0] is nonzero\n\n\t\t\t\t\tstats [4]: p [0]\n\n\t\t\t-7\tA is too small\n\n\t\t\t\t\tstats [4]: required size\n\t\t\t\t\tstats [5]: actual size (Alen)\n\n\t\t\t-8\ta column has a negative number of entries\n\n\t\t\t\t\tstats [4]: column with < 0 entries\n\t\t\t\t\tstats [5]: number of entries in col\n\n\t\t\t-9\ta row index is out of bounds\n\n\t\t\t\t\tstats [4]: column with bad row index\n\t\t\t\t\tstats [5]: bad row index\n\t\t\t\t\tstats [6]: n_row, # of rows of matrx\n\n\t\t\t-10\t(unused; see symamd.c)\n\n\t\t\t-999\t(unused; see symamd.c)\n\n\t\tFuture versions may return more statistics in the stats array.\n\n\tExample:\n\t\n\t    See https://www.cise.ufl.edu/research/sparse/colamd/example.c\n\t    for a complete example.\n\n\t    To order the columns of a 5-by-4 matrix with 11 nonzero entries in\n\t    the following nonzero pattern\n\n\t    \tx 0 x 0\n\t\tx 0 x x\n\t\t0 x x 0\n\t\t0 0 x x\n\t\tx x 0 0\n\n\t    with default knobs and no output statistics, do the following:\n\n\t\t#include \"colamd.h\"\n\t\t#define ALEN COLAMD_RECOMMENDED (11, 5, 4)\n\t\tint A [ALEN] = {1, 2, 5, 3, 5, 1, 2, 3, 4, 2, 4} ;\n\t\tint p [ ] = {0, 3, 5, 9, 11} ;\n\t\tint stats [COLAMD_STATS] ;\n\t\tcolamd (5, 4, ALEN, A, p, (double *) NULL, stats) ;\n\n\t    The permutation is returned in the array p, and A is destroyed.\n\n    ----------------------------------------------------------------------------\n    symamd:\n    ----------------------------------------------------------------------------\n\n\tC syntax:\n\n\t    #include \"colamd.h\"\n\t    int symamd (int n, int *A, int *p, int *perm,\n\t    \tint knobs [COLAMD_KNOBS], int stats [COLAMD_STATS],\n\t\tvoid (*allocate) (size_t, size_t), void (*release) (void *)) ;\n\n\tPurpose:\n\n    \t    The symamd routine computes an ordering P of a symmetric sparse\n\t    matrix A such that the Cholesky factorization PAP' = LL' remains\n\t    sparse.  It is based on a column ordering of a matrix M constructed\n\t    so that the nonzero pattern of M'M is the same as A.  The matrix A\n\t    is assumed to be symmetric; only the strictly lower triangular part\n\t    is accessed.  You must pass your selected memory allocator (usually\n\t    calloc/free or mxCalloc/mxFree) to symamd, for it to allocate\n\t    memory for the temporary matrix M.\n\n\tReturns:\n\n\t    TRUE (1) if successful, FALSE (0) otherwise.\n\n\tArguments:\n\n\t    int n ;\t\tInput argument.\n\n\t    \tNumber of rows and columns in the symmetrix matrix A.\n\t\tRestriction:  n >= 0.\n\t\tSymamd returns FALSE if n is negative.\n\n\t    int A [nnz] ;\tInput argument.\n\n\t    \tA is an integer array of size nnz, where nnz = p [n].\n\t\t\n\t\tThe row indices of the entries in column c of the matrix are\n\t\theld in A [(p [c]) ... (p [c+1]-1)].  The row indices in a\n\t\tgiven column c need not be in ascending order, and duplicate\n\t\trow indices may be present.  However, symamd will run faster\n\t\tif the columns are in sorted order with no duplicate entries.\n\n\t\tThe matrix is 0-based.  That is, rows are in the range 0 to\n\t\tn-1, and columns are in the range 0 to n-1.  Symamd\n\t\treturns FALSE if any row index is out of range.\n\n\t\tThe contents of A are not modified.\n\n\t    int p [n+1] ;   \tInput argument.\n\n\t\tp is an integer array of size n+1.  On input, it holds the\n\t\t\"pointers\" for the column form of the matrix A.  Column c of\n\t\tthe matrix A is held in A [(p [c]) ... (p [c+1]-1)].  The first\n\t\tentry, p [0], must be zero, and p [c] <= p [c+1] must hold\n\t\tfor all c in the range 0 to n-1.  The value p [n] is\n\t\tthus the total number of entries in the pattern of the matrix A.\n\t\tSymamd returns FALSE if these conditions are not met.\n\n\t\tThe contents of p are not modified.\n\n\t    int perm [n+1] ;   \tOutput argument.\n\n\t\tOn output, if symamd returns TRUE, the array perm holds the\n\t\tpermutation P, where perm [0] is the first index in the new\n\t\tordering, and perm [n-1] is the last.  That is, perm [k] = j\n\t\tmeans that row and column j of A is the kth column in PAP',\n\t\twhere k is in the range 0 to n-1 (perm [0] = j means\n\t\tthat row and column j of A are the first row and column in\n\t\tPAP').  The array is used as a workspace during the ordering,\n\t\twhich is why it must be of length n+1, not just n.\n\n\t    double knobs [COLAMD_KNOBS] ;\tInput argument.\n\n\t\tSee colamd_set_defaults for a description.\n\n\t    int stats [COLAMD_STATS] ;\t\tOutput argument.\n\n\t\tStatistics on the ordering, and error status.\n\t\tSee colamd.h for related definitions.\n\t\tSymamd returns FALSE if stats is not present.\n\n\t\tstats [0]:  number of dense or empty row and columns ignored\n\t\t\t\t(and ordered last in the output permutation\n\t\t\t\tperm).  Note that a row/column can become\n\t\t\t\t\"empty\" if it contains only \"dense\" and/or\n\t\t\t\t\"empty\" columns/rows.\n\n\t\tstats [1]:  (same as stats [0])\n\n\t\tstats [2]:  number of garbage collections performed.\n\n\t\tstats [3]:  status code.  < 0 is an error code.\n\t\t\t    > 1 is a warning or notice.\n\n\t\t\t0\tOK.  Each column of the input matrix contained\n\t\t\t\trow indices in increasing order, with no\n\t\t\t\tduplicates.\n\n\t\t\t1\tOK, but columns of input matrix were jumbled\n\t\t\t\t(unsorted columns or duplicate entries).  Symamd\n\t\t\t\thad to do some extra work to sort the matrix\n\t\t\t\tfirst and remove duplicate entries, but it\n\t\t\t\tstill was able to return a valid permutation\n\t\t\t\t(return value of symamd was TRUE).\n\n\t\t\t\t\tstats [4]: highest numbered column that\n\t\t\t\t\t\tis unsorted or has duplicate\n\t\t\t\t\t\tentries.\n\t\t\t\t\tstats [5]: last seen duplicate or\n\t\t\t\t\t\tunsorted row index.\n\t\t\t\t\tstats [6]: number of duplicate or\n\t\t\t\t\t\tunsorted row indices.\n\n\t\t\t-1\tA is a null pointer\n\n\t\t\t-2\tp is a null pointer\n\n\t\t\t-3\t(unused, see colamd.c)\n\n\t\t\t-4 \tn is negative\n\n\t\t\t\t\tstats [4]: n\n\n\t\t\t-5\tnumber of nonzeros in matrix is negative\n\n\t\t\t\t\tstats [4]: # of nonzeros (p [n]).\n\n\t\t\t-6\tp [0] is nonzero\n\n\t\t\t\t\tstats [4]: p [0]\n\n\t\t\t-7\t(unused)\n\n\t\t\t-8\ta column has a negative number of entries\n\n\t\t\t\t\tstats [4]: column with < 0 entries\n\t\t\t\t\tstats [5]: number of entries in col\n\n\t\t\t-9\ta row index is out of bounds\n\n\t\t\t\t\tstats [4]: column with bad row index\n\t\t\t\t\tstats [5]: bad row index\n\t\t\t\t\tstats [6]: n_row, # of rows of matrx\n\n\t\t\t-10\tout of memory (unable to allocate temporary\n\t\t\t\tworkspace for M or count arrays using the\n\t\t\t\t\"allocate\" routine passed into symamd).\n\n\t\t\t-999\tinternal error.  colamd failed to order the\n\t\t\t\tmatrix M, when it should have succeeded.  This\n\t\t\t\tindicates a bug.  If this (and *only* this)\n\t\t\t\terror code occurs, please contact the authors.\n\t\t\t\tDon't contact the authors if you get any other\n\t\t\t\terror code.\n\n\t\tFuture versions may return more statistics in the stats array.\n\n\t    void * (*allocate) (size_t, size_t)\n\n\t    \tA pointer to a function providing memory allocation.  The\n\t\tallocated memory must be returned initialized to zero.  For a\n\t\tC application, this argument should normally be a pointer to\n\t\tcalloc.  For a Matlab mexFunction, the routine mxCalloc is\n\t\tpassed instead.\n\n\t    void (*release) (size_t, size_t)\n\n\t    \tA pointer to a function that frees memory allocated by the\n\t\tmemory allocation routine above.  For a C application, this\n\t\targument should normally be a pointer to free.  For a Matlab\n\t\tmexFunction, the routine mxFree is passed instead.\n\n\n    ----------------------------------------------------------------------------\n    colamd_report:\n    ----------------------------------------------------------------------------\n\n\tC syntax:\n\n\t    #include \"colamd.h\"\n\t    colamd_report (int stats [COLAMD_STATS]) ;\n\n\tPurpose:\n\n\t    Prints the error status and statistics recorded in the stats\n\t    array on the standard error output (for a standard C routine)\n\t    or on the Matlab output (for a mexFunction).\n\n\tArguments:\n\n\t    int stats [COLAMD_STATS] ;\tInput only.  Statistics from colamd.\n\n\n    ----------------------------------------------------------------------------\n    symamd_report:\n    ----------------------------------------------------------------------------\n\n\tC syntax:\n\n\t    #include \"colamd.h\"\n\t    symamd_report (int stats [COLAMD_STATS]) ;\n\n\tPurpose:\n\n\t    Prints the error status and statistics recorded in the stats\n\t    array on the standard error output (for a standard C routine)\n\t    or on the Matlab output (for a mexFunction).\n\n\tArguments:\n\n\t    int stats [COLAMD_STATS] ;\tInput only.  Statistics from symamd.\n\n\n*/\n\n/* ========================================================================== */\n/* === Scaffolding code definitions  ======================================== */\n/* ========================================================================== */\n\n/* Ensure that debugging is turned off: */\n#ifndef NDEBUG\n#define NDEBUG\n#endif /* NDEBUG */\n\n/*\n   Our \"scaffolding code\" philosophy:  In our opinion, well-written library\n   code should keep its \"debugging\" code, and just normally have it turned off\n   by the compiler so as not to interfere with performance.  This serves\n   several purposes:\n\n   (1) assertions act as comments to the reader, telling you what the code\n\texpects at that point.  All assertions will always be true (unless\n\tthere really is a bug, of course).\n\n   (2) leaving in the scaffolding code assists anyone who would like to modify\n\tthe code, or understand the algorithm (by reading the debugging output,\n\tone can get a glimpse into what the code is doing).\n\n   (3) (gasp!) for actually finding bugs.  This code has been heavily tested\n\tand \"should\" be fully functional and bug-free ... but you never know...\n\n    To enable debugging, comment out the \"#define NDEBUG\" above.  For a Matlab\n    mexFunction, you will also need to modify mexopts.sh to remove the -DNDEBUG\n    definition.  The code will become outrageously slow when debugging is\n    enabled.  To control the level of debugging output, set an environment\n    variable D to 0 (little), 1 (some), 2, 3, or 4 (lots).  When debugging,\n    you should see the following message on the standard output:\n\n    \tcolamd: debug version, D = 1 (THIS WILL BE SLOW!)\n\n    or a similar message for symamd.  If you don't, then debugging has not\n    been enabled.\n\n*/\n\n/* ========================================================================== */\n/* === Include files ======================================================== */\n/* ========================================================================== */\n\n#include \"colamd.h\"\n#include <limits.h>\n\n#ifdef MATLAB_MEX_FILE\n#include \"mex.h\"\n#include \"matrix.h\"\n#else\n#include <stdio.h>\n#include <assert.h>\n#endif /* MATLAB_MEX_FILE */\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n/* ========================================================================== */\n/* === Definitions ========================================================== */\n/* ========================================================================== */\n\n/* Routines are either PUBLIC (user-callable) or PRIVATE (not user-callable) */\n#define PUBLIC\n#define PRIVATE static\n\n#define MAX(a,b) (((a) > (b)) ? (a) : (b))\n#define MIN(a,b) (((a) < (b)) ? (a) : (b))\n\n#define ONES_COMPLEMENT(r) (-(r)-1)\n\n/* -------------------------------------------------------------------------- */\n/* Change for version 2.1:  define TRUE and FALSE only if not yet defined */\n/* -------------------------------------------------------------------------- */\n\n#ifndef TRUE\n#define TRUE (1)\n#endif\n\n#ifndef FALSE\n#define FALSE (0)\n#endif\n\n/* -------------------------------------------------------------------------- */\n\n#define EMPTY\t(-1)\n\n/* Row and column status */\n#define ALIVE\t(0)\n#define DEAD\t(-1)\n\n/* Column status */\n#define DEAD_PRINCIPAL\t\t(-1)\n#define DEAD_NON_PRINCIPAL\t(-2)\n\n/* Macros for row and column status update and checking. */\n#define ROW_IS_DEAD(r)\t\t\tROW_IS_MARKED_DEAD (Row[r].shared2.mark)\n#define ROW_IS_MARKED_DEAD(row_mark)\t(row_mark < ALIVE)\n#define ROW_IS_ALIVE(r)\t\t\t(Row [r].shared2.mark >= ALIVE)\n#define COL_IS_DEAD(c)\t\t\t(Col [c].start < ALIVE)\n#define COL_IS_ALIVE(c)\t\t\t(Col [c].start >= ALIVE)\n#define COL_IS_DEAD_PRINCIPAL(c)\t(Col [c].start == DEAD_PRINCIPAL)\n#define KILL_ROW(r)\t\t\t{ Row [r].shared2.mark = DEAD ; }\n#define KILL_PRINCIPAL_COL(c)\t\t{ Col [c].start = DEAD_PRINCIPAL ; }\n#define KILL_NON_PRINCIPAL_COL(c)\t{ Col [c].start = DEAD_NON_PRINCIPAL ; }\n\n/* ========================================================================== */\n/* === Colamd reporting mechanism =========================================== */\n/* ========================================================================== */\n\n#ifdef MATLAB_MEX_FILE\n\n/* use mexPrintf in a Matlab mexFunction, for debugging and statistics output */\n#define PRINTF mexPrintf\n\n/* In Matlab, matrices are 1-based to the user, but 0-based internally */\n#define INDEX(i) ((i)+1)\n\n#else\n\n/* Use printf in standard C environment, for debugging and statistics output. */\n/* Output is generated only if debugging is enabled at compile time, or if */\n/* the caller explicitly calls colamd_report or symamd_report. */\n#define PRINTF printf\n\n/* In C, matrices are 0-based and indices are reported as such in *_report */\n#define INDEX(i) (i)\n\n#endif /* MATLAB_MEX_FILE */\n\n/* ========================================================================== */\n/* === Prototypes of PRIVATE routines ======================================= */\n/* ========================================================================== */\n\nPRIVATE int init_rows_cols\n(\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int A [],\n    int p [],\n    int stats [COLAMD_STATS]\n) ;\n\nPRIVATE void init_scoring\n(\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int A [],\n    int head [],\n    double knobs [COLAMD_KNOBS],\n    int *p_n_row2,\n    int *p_n_col2,\n    int *p_max_deg\n) ;\n\nPRIVATE int find_ordering\n(\n    int n_row,\n    int n_col,\n    int Alen,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int A [],\n    int head [],\n    int n_col2,\n    int max_deg,\n    int pfree\n) ;\n\nPRIVATE void order_children\n(\n    int n_col,\n    Colamd_Col Col [],\n    int p []\n) ;\n\nPRIVATE void detect_super_cols\n(\n\n#ifndef NDEBUG\n    int n_col,\n    Colamd_Row Row [],\n#endif /* NDEBUG */\n\n    Colamd_Col Col [],\n    int A [],\n    int head [],\n    int row_start,\n    int row_length\n) ;\n\nPRIVATE int garbage_collection\n(\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int A [],\n    int *pfree\n) ;\n\nPRIVATE int clear_mark\n(\n    int n_row,\n    Colamd_Row Row []\n) ;\n\nPRIVATE void print_report\n(\n    const char * method,\n    int stats [COLAMD_STATS]\n) ;\n\n/* ========================================================================== */\n/* === Debugging prototypes and definitions ================================= */\n/* ========================================================================== */\n\n#ifndef NDEBUG\n\n/* colamd_debug is the *ONLY* global variable, and is only */\n/* present when debugging */\n\nPRIVATE int colamd_debug ;\t/* debug print level */\n\n#define DEBUG0(params) { (void) PRINTF params ; }\n#define DEBUG1(params) { if (colamd_debug >= 1) (void) PRINTF params ; }\n#define DEBUG2(params) { if (colamd_debug >= 2) (void) PRINTF params ; }\n#define DEBUG3(params) { if (colamd_debug >= 3) (void) PRINTF params ; }\n#define DEBUG4(params) { if (colamd_debug >= 4) (void) PRINTF params ; }\n\n#ifdef MATLAB_MEX_FILE\n#define ASSERT(expression) (mxAssert ((expression), \"\"))\n#else\n#define ASSERT(expression) (assert (expression))\n#endif /* MATLAB_MEX_FILE */\n\nPRIVATE void colamd_get_debug\t/* gets the debug print level from getenv */\n(\n    char *method\n) ;\n\nPRIVATE void debug_deg_lists\n(\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int head [],\n    int min_score,\n    int should,\n    int max_deg\n) ;\n\nPRIVATE void debug_mark\n(\n    int n_row,\n    Colamd_Row Row [],\n    int tag_mark,\n    int max_mark\n) ;\n\nPRIVATE void debug_matrix\n(\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int A []\n) ;\n\nPRIVATE void debug_structures\n(\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int A [],\n    int n_col2\n) ;\n\n#else /* NDEBUG */\n\n/* === No debugging ========================================================= */\n\n#define DEBUG0(params) ;\n#define DEBUG1(params) ;\n#define DEBUG2(params) ;\n#define DEBUG3(params) ;\n#define DEBUG4(params) ;\n\n#define ASSERT(expression) ((void) 0)\n\n#endif /* NDEBUG */\n\n/* ========================================================================== */\n\n\n\n/* ========================================================================== */\n/* === USER-CALLABLE ROUTINES: ============================================== */\n/* ========================================================================== */\n\n\n/* ========================================================================== */\n/* === colamd_recommended =================================================== */\n/* ========================================================================== */\n\n/*\n    The colamd_recommended routine returns the suggested size for Alen.  This\n    value has been determined to provide good balance between the number of\n    garbage collections and the memory requirements for colamd.  If any\n    argument is negative, a -1 is returned as an error condition.  This\n    function is also available as a macro defined in colamd.h, so that you\n    can use it for a statically-allocated array size.\n*/\n\nPUBLIC int colamd_recommended\t/* returns recommended value of Alen. */\n(\n    /* === Parameters ======================================================= */\n\n    int nnz,\t\t\t/* number of nonzeros in A */\n    int n_row,\t\t\t/* number of rows in A */\n    int n_col\t\t\t/* number of columns in A */\n)\n{\n    return (COLAMD_RECOMMENDED (nnz, n_row, n_col)) ;\n}\n\n\n/* ========================================================================== */\n/* === colamd_set_defaults ================================================== */\n/* ========================================================================== */\n\n/*\n    The colamd_set_defaults routine sets the default values of the user-\n    controllable parameters for colamd:\n\n\tknobs [0]\trows with knobs[0]*n_col entries or more are removed\n\t\t\tprior to ordering in colamd.  Rows and columns with\n\t\t\tknobs[0]*n_col entries or more are removed prior to\n\t\t\tordering in symamd and placed last in the output\n\t\t\tordering.\n\n\tknobs [1]\tcolumns with knobs[1]*n_row entries or more are removed\n\t\t\tprior to ordering in colamd, and placed last in the\n\t\t\tcolumn permutation.  Symamd ignores this knob.\n\n\tknobs [2..19]\tunused, but future versions might use this\n*/\n\nPUBLIC void colamd_set_defaults\n(\n    /* === Parameters ======================================================= */\n\n    double knobs [COLAMD_KNOBS]\t\t/* knob array */\n)\n{\n    /* === Local variables ================================================== */\n\n    int i ;\n\n    if (!knobs)\n    {\n\treturn ;\t\t\t/* no knobs to initialize */\n    }\n    for (i = 0 ; i < COLAMD_KNOBS ; i++)\n    {\n\tknobs [i] = 0 ;\n    }\n    knobs [COLAMD_DENSE_ROW] = 0.5 ;\t/* ignore rows over 50% dense */\n    knobs [COLAMD_DENSE_COL] = 0.5 ;\t/* ignore columns over 50% dense */\n}\n\n\n/* ========================================================================== */\n/* === symamd =============================================================== */\n/* ========================================================================== */\n\nPUBLIC int symamd\t\t\t/* return TRUE if OK, FALSE otherwise */\n(\n    /* === Parameters ======================================================= */\n\n    int n,\t\t\t\t/* number of rows and columns of A */\n    int A [],\t\t\t\t/* row indices of A */\n    int p [],\t\t\t\t/* column pointers of A */\n    int perm [],\t\t\t/* output permutation, size n+1 */\n    double knobs [COLAMD_KNOBS],\t/* parameters (uses defaults if NULL) */\n    int stats [COLAMD_STATS],\t\t/* output statistics and error codes */\n    void * (*allocate) (size_t, size_t),\n    \t\t\t\t\t/* pointer to calloc (ANSI C) or */\n\t\t\t\t\t/* mxCalloc (for Matlab mexFunction) */\n    void (*release) (void *)\n    \t\t\t\t\t/* pointer to free (ANSI C) or */\n    \t\t\t\t\t/* mxFree (for Matlab mexFunction) */\n)\n{\n    /* === Local variables ================================================== */\n\n    int *count ;\t\t/* length of each column of M, and col pointer*/\n    int *mark ;\t\t\t/* mark array for finding duplicate entries */\n    int *M ;\t      /* row indices of matrix M */\n    int Mlen ;\t\t\t/* length of M */\n    int n_row ;\t\t\t/* number of rows in M */\n    int nnz ;\t\t\t/* number of entries in A */\n    int i ;\t\t\t/* row index of A */\n    int j ;\t\t\t/* column index of A */\n    int k ;\t\t\t/* row index of M */\n    int mnz ;\t\t\t/* number of nonzeros in M */\n    int pp ;\t\t\t/* index into a column of A */\n    int last_row ;\t\t/* last row seen in the current column */\n    int length ;\t\t/* number of nonzeros in a column */\n\n    double cknobs [COLAMD_KNOBS] ;\t\t/* knobs for colamd */\n    double default_knobs [COLAMD_KNOBS] ;\t/* default knobs for colamd */\n    int cstats [COLAMD_STATS] ;\t\t\t/* colamd stats */\n\n#ifndef NDEBUG\n    colamd_get_debug (\"symamd\") ;\n#endif /* NDEBUG */\n\n    /* === Check the input arguments ======================================== */\n\n    if (!stats)\n    {\n\tDEBUG0 ((\"symamd: stats not present\\n\")) ;\n\treturn (FALSE) ;\n    }\n    for (i = 0 ; i < COLAMD_STATS ; i++)\n    {\n\tstats [i] = 0 ;\n    }\n    stats [COLAMD_STATUS] = COLAMD_OK ;\n    stats [COLAMD_INFO1] = -1 ;\n    stats [COLAMD_INFO2] = -1 ;\n\n    if (!A)\n    {\n    \tstats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ;\n\tDEBUG0 ((\"symamd: A not present\\n\")) ;\n\treturn (FALSE) ;\n    }\n\n    if (!p)\t\t/* p is not present */\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ;\n\tDEBUG0 ((\"symamd: p not present\\n\")) ;\n    \treturn (FALSE) ;\n    }\n\n    if (n < 0)\t\t/* n must be >= 0 */\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ;\n\tstats [COLAMD_INFO1] = n ;\n\tDEBUG0 ((\"symamd: n negative %d\\n\", n)) ;\n    \treturn (FALSE) ;\n    }\n\n    nnz = p [n] ;\n    if (nnz < 0)\t/* nnz must be >= 0 */\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ;\n\tstats [COLAMD_INFO1] = nnz ;\n\tDEBUG0 ((\"symamd: number of entries negative %d\\n\", nnz)) ;\n\treturn (FALSE) ;\n    }\n\n    if (p [0] != 0)\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ;\n\tstats [COLAMD_INFO1] = p [0] ;\n\tDEBUG0 ((\"symamd: p[0] not zero %d\\n\", p [0])) ;\n\treturn (FALSE) ;\n    }\n\n    /* === If no knobs, set default knobs =================================== */\n\n    if (!knobs)\n    {\n\tcolamd_set_defaults (default_knobs) ;\n\tknobs = default_knobs ;\n    }\n\n    /* === Allocate count and mark ========================================== */\n\n    count = (int *) ((*allocate) (n+1, sizeof (int))) ;\n    if (!count)\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;\n\tDEBUG0 ((\"symamd: allocate count (size %d) failed\\n\", n+1)) ;\n\treturn (FALSE) ;\n    }\n\n    mark = (int *) ((*allocate) (n+1, sizeof (int))) ;\n    if (!mark)\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;\n\t(*release) ((void *) count) ;\n\tDEBUG0 ((\"symamd: allocate mark (size %d) failed\\n\", n+1)) ;\n\treturn (FALSE) ;\n    }\n\n    /* === Compute column counts of M, check if A is valid ================== */\n\n    stats [COLAMD_INFO3] = 0 ;  /* number of duplicate or unsorted row indices*/\n\n    for (i = 0 ; i < n ; i++)\n    {\n    \tmark [i] = -1 ;\n    }\n\n    for (j = 0 ; j < n ; j++)\n    {\n\tlast_row = -1 ;\n\n\tlength = p [j+1] - p [j] ;\n\tif (length < 0)\n\t{\n\t    /* column pointers must be non-decreasing */\n\t    stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;\n\t    stats [COLAMD_INFO1] = j ;\n\t    stats [COLAMD_INFO2] = length ;\n\t    (*release) ((void *) count) ;\n\t    (*release) ((void *) mark) ;\n\t    DEBUG0 ((\"symamd: col %d negative length %d\\n\", j, length)) ;\n\t    return (FALSE) ;\n\t}\n\n\tfor (pp = p [j] ; pp < p [j+1] ; pp++)\n\t{\n\t    i = A [pp] ;\n\t    if (i < 0 || i >= n)\n\t    {\n\t\t/* row index i, in column j, is out of bounds */\n\t\tstats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ;\n\t\tstats [COLAMD_INFO1] = j ;\n\t\tstats [COLAMD_INFO2] = i ;\n\t\tstats [COLAMD_INFO3] = n ;\n\t\t(*release) ((void *) count) ;\n\t\t(*release) ((void *) mark) ;\n\t\tDEBUG0 ((\"symamd: row %d col %d out of bounds\\n\", i, j)) ;\n\t\treturn (FALSE) ;\n\t    }\n\n\t    if (i <= last_row || mark [i] == j)\n\t    {\n\t\t/* row index is unsorted or repeated (or both), thus col */\n\t\t/* is jumbled.  This is a notice, not an error condition. */\n\t\tstats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ;\n\t\tstats [COLAMD_INFO1] = j ;\n\t\tstats [COLAMD_INFO2] = i ;\n\t\t(stats [COLAMD_INFO3]) ++ ;\n\t\tDEBUG1 ((\"symamd: row %d col %d unsorted/duplicate\\n\", i, j)) ;\n\t    }\n\n\t    if (i > j && mark [i] != j)\n\t    {\n\t\t/* row k of M will contain column indices i and j */\n\t\tcount [i]++ ;\n\t\tcount [j]++ ;\n\t    }\n\n\t    /* mark the row as having been seen in this column */\n\t    mark [i] = j ;\n\n\t    last_row = i ;\n\t}\n    }\n\n    if (stats [COLAMD_STATUS] == COLAMD_OK)\n    {\n\t/* if there are no duplicate entries, then mark is no longer needed */\n\t(*release) ((void *) mark) ;\n    }\n\n    /* === Compute column pointers of M ===================================== */\n\n    /* use output permutation, perm, for column pointers of M */\n    perm [0] = 0 ;\n    for (j = 1 ; j <= n ; j++)\n    {\n\tperm [j] = perm [j-1] + count [j-1] ;\n    }\n    for (j = 0 ; j < n ; j++)\n    {\n\tcount [j] = perm [j] ;\n    }\n\n    /* === Construct M ====================================================== */\n\n    mnz = perm [n] ;\n    n_row = mnz / 2 ;\n    Mlen = colamd_recommended (mnz, n_row, n) ;\n    M = (int *) ((*allocate) (Mlen, sizeof (int))) ;\n    DEBUG0 ((\"symamd: M is %d-by-%d with %d entries, Mlen = %d\\n\",\n    \tn_row, n, mnz, Mlen)) ;\n\n    if (!M)\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ;\n\t(*release) ((void *) count) ;\n\t(*release) ((void *) mark) ;\n\tDEBUG0 ((\"symamd: allocate M (size %d) failed\\n\", Mlen)) ;\n\treturn (FALSE) ;\n    }\n\n    k = 0 ;\n\n    if (stats [COLAMD_STATUS] == COLAMD_OK)\n    {\n\t/* Matrix is OK */\n\tfor (j = 0 ; j < n ; j++)\n\t{\n\t    ASSERT (p [j+1] - p [j] >= 0) ;\n\t    for (pp = p [j] ; pp < p [j+1] ; pp++)\n\t    {\n\t\ti = A [pp] ;\n\t\tASSERT (i >= 0 && i < n) ;\n\t\tif (i > j)\n\t\t{\n\t\t    /* row k of M contains column indices i and j */\n\t\t    M [count [i]++] = k ;\n\t\t    M [count [j]++] = k ;\n\t\t    k++ ;\n\t\t}\n\t    }\n\t}\n    }\n    else\n    {\n\t/* Matrix is jumbled.  Do not add duplicates to M.  Unsorted cols OK. */\n\tDEBUG0 ((\"symamd: Duplicates in A.\\n\")) ;\n\tfor (i = 0 ; i < n ; i++)\n\t{\n\t    mark [i] = -1 ;\n\t}\n\tfor (j = 0 ; j < n ; j++)\n\t{\n\t    ASSERT (p [j+1] - p [j] >= 0) ;\n\t    for (pp = p [j] ; pp < p [j+1] ; pp++)\n\t    {\n\t\ti = A [pp] ;\n\t\tASSERT (i >= 0 && i < n) ;\n\t\tif (i > j && mark [i] != j)\n\t\t{\n\t\t    /* row k of M contains column indices i and j */\n\t\t    M [count [i]++] = k ;\n\t\t    M [count [j]++] = k ;\n\t\t    k++ ;\n\t\t    mark [i] = j ;\n\t\t}\n\t    }\n\t}\n\t(*release) ((void *) mark) ;\n    }\n\n    /* count and mark no longer needed */\n    (*release) ((void *) count) ;\n    ASSERT (k == n_row) ;\n\n    /* === Adjust the knobs for M =========================================== */\n\n    for (i = 0 ; i < COLAMD_KNOBS ; i++)\n    {\n\tcknobs [i] = knobs [i] ;\n    }\n\n    /* there are no dense rows in M */\n    cknobs [COLAMD_DENSE_ROW] = 1.0 ;\n\n    if (n_row != 0 && n < n_row)\n    {\n\t/* On input, the knob is a fraction of 1..n, the number of rows of A. */\n\t/* Convert it to a fraction of 1..n_row, of the number of rows of M. */\n    \tcknobs [COLAMD_DENSE_COL] = (knobs [COLAMD_DENSE_ROW] * n) / n_row ;\n    }\n    else\n    {\n\t/* no dense columns in M */\n    \tcknobs [COLAMD_DENSE_COL] = 1.0 ;\n    }\n\n    DEBUG0 ((\"symamd: dense col knob for M: %g\\n\", cknobs [COLAMD_DENSE_COL])) ;\n\n    /* === Order the columns of M =========================================== */\n\n    if (!colamd (n_row, n, Mlen, M, perm, cknobs, cstats))\n    {\n\t/* This \"cannot\" happen, unless there is a bug in the code. */\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_internal_error ;\n\t(*release) ((void *) M) ;\n\tDEBUG0 ((\"symamd: internal error!\\n\")) ;\n\treturn (FALSE) ;\n    }\n\n    /* Note that the output permutation is now in perm */\n\n    /* === get the statistics for symamd from colamd ======================== */\n\n    /* note that a dense column in colamd means a dense row and col in symamd */\n    stats [COLAMD_DENSE_ROW]    = cstats [COLAMD_DENSE_COL] ;\n    stats [COLAMD_DENSE_COL]    = cstats [COLAMD_DENSE_COL] ;\n    stats [COLAMD_DEFRAG_COUNT] = cstats [COLAMD_DEFRAG_COUNT] ;\n\n    /* === Free M =========================================================== */\n\n    (*release) ((void *) M) ;\n    DEBUG0 ((\"symamd: done.\\n\")) ;\n    return (TRUE) ;\n\n}\n\n/* ========================================================================== */\n/* === colamd =============================================================== */\n/* ========================================================================== */\n\n/*\n    The colamd routine computes a column ordering Q of a sparse matrix\n    A such that the LU factorization P(AQ) = LU remains sparse, where P is\n    selected via partial pivoting.   The routine can also be viewed as\n    providing a permutation Q such that the Cholesky factorization\n    (AQ)'(AQ) = LL' remains sparse.\n*/\n\nPUBLIC int colamd\t\t/* returns TRUE if successful, FALSE otherwise*/\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\t\t\t/* number of rows in A */\n    int n_col,\t\t\t/* number of columns in A */\n    int Alen,\t\t\t/* length of A */\n    int A [],\t\t\t/* row indices of A */\n    int p [],\t\t\t/* pointers to columns in A */\n    double knobs [COLAMD_KNOBS],/* parameters (uses defaults if NULL) */\n    int stats [COLAMD_STATS]\t/* output statistics and error codes */\n)\n{\n    /* === Local variables ================================================== */\n\n    int i ;\t\t\t/* loop index */\n    int nnz ;\t\t\t/* nonzeros in A */\n    int Row_size ;\t\t/* size of Row [], in integers */\n    int Col_size ;\t\t/* size of Col [], in integers */\n    int need ;\t\t\t/* minimum required length of A */\n    Colamd_Row *Row ;\t\t/* pointer into A of Row [0..n_row] array */\n    Colamd_Col *Col ;\t\t/* pointer into A of Col [0..n_col] array */\n    int n_col2 ;\t\t/* number of non-dense, non-empty columns */\n    int n_row2 ;\t\t/* number of non-dense, non-empty rows */\n    int ngarbage ;\t\t/* number of garbage collections performed */\n    int max_deg ;\t\t/* maximum row degree */\n    double default_knobs [COLAMD_KNOBS] ;\t/* default knobs array */\n\n#ifndef NDEBUG\n    colamd_get_debug (\"colamd\") ;\n#endif /* NDEBUG */\n\n    /* === Check the input arguments ======================================== */\n\n    if (!stats)\n    {\n\tDEBUG0 ((\"colamd: stats not present\\n\")) ;\n\treturn (FALSE) ;\n    }\n    for (i = 0 ; i < COLAMD_STATS ; i++)\n    {\n\tstats [i] = 0 ;\n    }\n    stats [COLAMD_STATUS] = COLAMD_OK ;\n    stats [COLAMD_INFO1] = -1 ;\n    stats [COLAMD_INFO2] = -1 ;\n\n    if (!A)\t\t/* A is not present */\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ;\n\tDEBUG0 ((\"colamd: A not present\\n\")) ;\n\treturn (FALSE) ;\n    }\n\n    if (!p)\t\t/* p is not present */\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ;\n\tDEBUG0 ((\"colamd: p not present\\n\")) ;\n    \treturn (FALSE) ;\n    }\n\n    if (n_row < 0)\t/* n_row must be >= 0 */\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_nrow_negative ;\n\tstats [COLAMD_INFO1] = n_row ;\n\tDEBUG0 ((\"colamd: nrow negative %d\\n\", n_row)) ;\n    \treturn (FALSE) ;\n    }\n\n    if (n_col < 0)\t/* n_col must be >= 0 */\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ;\n\tstats [COLAMD_INFO1] = n_col ;\n\tDEBUG0 ((\"colamd: ncol negative %d\\n\", n_col)) ;\n    \treturn (FALSE) ;\n    }\n\n    nnz = p [n_col] ;\n    if (nnz < 0)\t/* nnz must be >= 0 */\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ;\n\tstats [COLAMD_INFO1] = nnz ;\n\tDEBUG0 ((\"colamd: number of entries negative %d\\n\", nnz)) ;\n\treturn (FALSE) ;\n    }\n\n    if (p [0] != 0)\n    {\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero\t;\n\tstats [COLAMD_INFO1] = p [0] ;\n\tDEBUG0 ((\"colamd: p[0] not zero %d\\n\", p [0])) ;\n\treturn (FALSE) ;\n    }\n\n    /* === If no knobs, set default knobs =================================== */\n\n    if (!knobs)\n    {\n\tcolamd_set_defaults (default_knobs) ;\n\tknobs = default_knobs ;\n    }\n\n    /* === Allocate the Row and Col arrays from array A ===================== */\n\n    Col_size = COLAMD_C (n_col) ;\n    Row_size = COLAMD_R (n_row) ;\n    need = 2*nnz + n_col + Col_size + Row_size ;\n\n    if (need > Alen)\n    {\n\t/* not enough space in array A to perform the ordering */\n\tstats [COLAMD_STATUS] = COLAMD_ERROR_A_too_small ;\n\tstats [COLAMD_INFO1] = need ;\n\tstats [COLAMD_INFO2] = Alen ;\n\tDEBUG0 ((\"colamd: Need Alen >= %d, given only Alen = %d\\n\", need,Alen));\n\treturn (FALSE) ;\n    }\n\n    Alen -= Col_size + Row_size ;\n    Col = (Colamd_Col *) &A [Alen] ;\n    Row = (Colamd_Row *) &A [Alen + Col_size] ;\n\n    /* === Construct the row and column data structures ===================== */\n\n    if (!init_rows_cols (n_row, n_col, Row, Col, A, p, stats))\n    {\n\t/* input matrix is invalid */\n\tDEBUG0 ((\"colamd: Matrix invalid\\n\")) ;\n\treturn (FALSE) ;\n    }\n\n    /* === Initialize scores, kill dense rows/columns ======================= */\n\n    init_scoring (n_row, n_col, Row, Col, A, p, knobs,\n\t&n_row2, &n_col2, &max_deg) ;\n\n    /* === Order the supercolumns =========================================== */\n\n    ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p,\n\tn_col2, max_deg, 2*nnz) ;\n\n    /* === Order the non-principal columns ================================== */\n\n    order_children (n_col, Col, p) ;\n\n    /* === Return statistics in stats ======================================= */\n\n    stats [COLAMD_DENSE_ROW] = n_row - n_row2 ;\n    stats [COLAMD_DENSE_COL] = n_col - n_col2 ;\n    stats [COLAMD_DEFRAG_COUNT] = ngarbage ;\n    DEBUG0 ((\"colamd: done.\\n\")) ;\n    return (TRUE) ;\n}\n\n\n/* ========================================================================== */\n/* === colamd_report ======================================================== */\n/* ========================================================================== */\n\nPUBLIC void colamd_report\n(\n    int stats [COLAMD_STATS]\n)\n{\n    print_report (\"colamd\", stats) ;\n}\n\n\n/* ========================================================================== */\n/* === symamd_report ======================================================== */\n/* ========================================================================== */\n\nPUBLIC void symamd_report\n(\n    int stats [COLAMD_STATS]\n)\n{\n    print_report (\"symamd\", stats) ;\n}\n\n\n\n/* ========================================================================== */\n/* === NON-USER-CALLABLE ROUTINES: ========================================== */\n/* ========================================================================== */\n\n/* There are no user-callable routines beyond this point in the file */\n\n\n/* ========================================================================== */\n/* === init_rows_cols ======================================================= */\n/* ========================================================================== */\n\n/*\n    Takes the column form of the matrix in A and creates the row form of the\n    matrix.  Also, row and column attributes are stored in the Col and Row\n    structs.  If the columns are un-sorted or contain duplicate row indices,\n    this routine will also sort and remove duplicate row indices from the\n    column form of the matrix.  Returns FALSE if the matrix is invalid,\n    TRUE otherwise.  Not user-callable.\n*/\n\nPRIVATE int init_rows_cols\t/* returns TRUE if OK, or FALSE otherwise */\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\t\t\t/* number of rows of A */\n    int n_col,\t\t\t/* number of columns of A */\n    Colamd_Row Row [],\t\t/* of size n_row+1 */\n    Colamd_Col Col [],\t\t/* of size n_col+1 */\n    int A [],\t\t\t/* row indices of A, of size Alen */\n    int p [],\t\t\t/* pointers to columns in A, of size n_col+1 */\n    int stats [COLAMD_STATS]\t/* colamd statistics */\n)\n{\n    /* === Local variables ================================================== */\n\n    int col ;\t\t\t/* a column index */\n    int row ;\t\t\t/* a row index */\n    int *cp ;\t\t\t/* a column pointer */\n    int *cp_end ;\t\t/* a pointer to the end of a column */\n    int *rp ;\t\t\t/* a row pointer */\n    int *rp_end ;\t\t/* a pointer to the end of a row */\n    int last_row ;\t\t/* previous row */\n\n    /* === Initialize columns, and check column pointers ==================== */\n\n    for (col = 0 ; col < n_col ; col++)\n    {\n\tCol [col].start = p [col] ;\n\tCol [col].length = p [col+1] - p [col] ;\n\n\tif (Col [col].length < 0)\n\t{\n\t    /* column pointers must be non-decreasing */\n\t    stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ;\n\t    stats [COLAMD_INFO1] = col ;\n\t    stats [COLAMD_INFO2] = Col [col].length ;\n\t    DEBUG0 ((\"colamd: col %d length %d < 0\\n\", col, Col [col].length)) ;\n\t    return (FALSE) ;\n\t}\n\n\tCol [col].shared1.thickness = 1 ;\n\tCol [col].shared2.score = 0 ;\n\tCol [col].shared3.prev = EMPTY ;\n\tCol [col].shared4.degree_next = EMPTY ;\n    }\n\n    /* p [0..n_col] no longer needed, used as \"head\" in subsequent routines */\n\n    /* === Scan columns, compute row degrees, and check row indices ========= */\n\n    stats [COLAMD_INFO3] = 0 ;\t/* number of duplicate or unsorted row indices*/\n\n    for (row = 0 ; row < n_row ; row++)\n    {\n\tRow [row].length = 0 ;\n\tRow [row].shared2.mark = -1 ;\n    }\n\n    for (col = 0 ; col < n_col ; col++)\n    {\n\tlast_row = -1 ;\n\n\tcp = &A [p [col]] ;\n\tcp_end = &A [p [col+1]] ;\n\n\twhile (cp < cp_end)\n\t{\n\t    row = *cp++ ;\n\n\t    /* make sure row indices within range */\n\t    if (row < 0 || row >= n_row)\n\t    {\n\t\tstats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ;\n\t\tstats [COLAMD_INFO1] = col ;\n\t\tstats [COLAMD_INFO2] = row ;\n\t\tstats [COLAMD_INFO3] = n_row ;\n\t\tDEBUG0 ((\"colamd: row %d col %d out of bounds\\n\", row, col)) ;\n\t\treturn (FALSE) ;\n\t    }\n\n\t    if (row <= last_row || Row [row].shared2.mark == col)\n\t    {\n\t\t/* row index are unsorted or repeated (or both), thus col */\n\t\t/* is jumbled.  This is a notice, not an error condition. */\n\t\tstats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ;\n\t\tstats [COLAMD_INFO1] = col ;\n\t\tstats [COLAMD_INFO2] = row ;\n\t\t(stats [COLAMD_INFO3]) ++ ;\n\t\tDEBUG1 ((\"colamd: row %d col %d unsorted/duplicate\\n\",row,col));\n\t    }\n\n\t    if (Row [row].shared2.mark != col)\n\t    {\n\t\tRow [row].length++ ;\n\t    }\n\t    else\n\t    {\n\t\t/* this is a repeated entry in the column, */\n\t\t/* it will be removed */\n\t\tCol [col].length-- ;\n\t    }\n\n\t    /* mark the row as having been seen in this column */\n\t    Row [row].shared2.mark = col ;\n\n\t    last_row = row ;\n\t}\n    }\n\n    /* === Compute row pointers ============================================= */\n\n    /* row form of the matrix starts directly after the column */\n    /* form of matrix in A */\n    Row [0].start = p [n_col] ;\n    Row [0].shared1.p = Row [0].start ;\n    Row [0].shared2.mark = -1 ;\n    for (row = 1 ; row < n_row ; row++)\n    {\n\tRow [row].start = Row [row-1].start + Row [row-1].length ;\n\tRow [row].shared1.p = Row [row].start ;\n\tRow [row].shared2.mark = -1 ;\n    }\n\n    /* === Create row form ================================================== */\n\n    if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED)\n    {\n\t/* if cols jumbled, watch for repeated row indices */\n\tfor (col = 0 ; col < n_col ; col++)\n\t{\n\t    cp = &A [p [col]] ;\n\t    cp_end = &A [p [col+1]] ;\n\t    while (cp < cp_end)\n\t    {\n\t\trow = *cp++ ;\n\t\tif (Row [row].shared2.mark != col)\n\t\t{\n\t\t    A [(Row [row].shared1.p)++] = col ;\n\t\t    Row [row].shared2.mark = col ;\n\t\t}\n\t    }\n\t}\n    }\n    else\n    {\n\t/* if cols not jumbled, we don't need the mark (this is faster) */\n\tfor (col = 0 ; col < n_col ; col++)\n\t{\n\t    cp = &A [p [col]] ;\n\t    cp_end = &A [p [col+1]] ;\n\t    while (cp < cp_end)\n\t    {\n\t\tA [(Row [*cp++].shared1.p)++] = col ;\n\t    }\n\t}\n    }\n\n    /* === Clear the row marks and set row degrees ========================== */\n\n    for (row = 0 ; row < n_row ; row++)\n    {\n\tRow [row].shared2.mark = 0 ;\n\tRow [row].shared1.degree = Row [row].length ;\n    }\n\n    /* === See if we need to re-create columns ============================== */\n\n    if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED)\n    {\n    \tDEBUG0 ((\"colamd: reconstructing column form, matrix jumbled\\n\")) ;\n\n#ifndef NDEBUG\n\t/* make sure column lengths are correct */\n\tfor (col = 0 ; col < n_col ; col++)\n\t{\n\t    p [col] = Col [col].length ;\n\t}\n\tfor (row = 0 ; row < n_row ; row++)\n\t{\n\t    rp = &A [Row [row].start] ;\n\t    rp_end = rp + Row [row].length ;\n\t    while (rp < rp_end)\n\t    {\n\t\tp [*rp++]-- ;\n\t    }\n\t}\n\tfor (col = 0 ; col < n_col ; col++)\n\t{\n\t    ASSERT (p [col] == 0) ;\n\t}\n\t/* now p is all zero (different than when debugging is turned off) */\n#endif /* NDEBUG */\n\n\t/* === Compute col pointers ========================================= */\n\n\t/* col form of the matrix starts at A [0]. */\n\t/* Note, we may have a gap between the col form and the row */\n\t/* form if there were duplicate entries, if so, it will be */\n\t/* removed upon the first garbage collection */\n\tCol [0].start = 0 ;\n\tp [0] = Col [0].start ;\n\tfor (col = 1 ; col < n_col ; col++)\n\t{\n\t    /* note that the lengths here are for pruned columns, i.e. */\n\t    /* no duplicate row indices will exist for these columns */\n\t    Col [col].start = Col [col-1].start + Col [col-1].length ;\n\t    p [col] = Col [col].start ;\n\t}\n\n\t/* === Re-create col form =========================================== */\n\n\tfor (row = 0 ; row < n_row ; row++)\n\t{\n\t    rp = &A [Row [row].start] ;\n\t    rp_end = rp + Row [row].length ;\n\t    while (rp < rp_end)\n\t    {\n\t\tA [(p [*rp++])++] = row ;\n\t    }\n\t}\n    }\n\n    /* === Done.  Matrix is not (or no longer) jumbled ====================== */\n\n    return (TRUE) ;\n}\n\n\n/* ========================================================================== */\n/* === init_scoring ========================================================= */\n/* ========================================================================== */\n\n/*\n    Kills dense or empty columns and rows, calculates an initial score for\n    each column, and places all columns in the degree lists.  Not user-callable.\n*/\n\nPRIVATE void init_scoring\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\t\t\t/* number of rows of A */\n    int n_col,\t\t\t/* number of columns of A */\n    Colamd_Row Row [],\t\t/* of size n_row+1 */\n    Colamd_Col Col [],\t\t/* of size n_col+1 */\n    int A [],\t\t\t/* column form and row form of A */\n    int head [],\t\t/* of size n_col+1 */\n    double knobs [COLAMD_KNOBS],/* parameters */\n    int *p_n_row2,\t\t/* number of non-dense, non-empty rows */\n    int *p_n_col2,\t\t/* number of non-dense, non-empty columns */\n    int *p_max_deg\t\t/* maximum row degree */\n)\n{\n    /* === Local variables ================================================== */\n\n    int c ;         /* a column index */\n    int r, row ;\t\t/* a row index */\n    int *cp ;\t\t    /* a column pointer */\n    int deg ;\t      /* degree of a row or column */\n    int *cp_end ;\t  /* a pointer to the end of a column */\n    int *new_cp ;\t  /* new column pointer */\n    int col_length ;\t\t/* length of pruned column */\n    int score ;\t    /* current column score */\n    int n_col2 ;    /* number of non-dense, non-empty columns */\n    int n_row2 ;    /* number of non-dense, non-empty rows */\n    int dense_row_count ;\t/* remove rows with more entries than this */\n    int dense_col_count ;\t/* remove cols with more entries than this */\n    int min_score ; /* smallest column score */\n    int max_deg ;\t  /* maximum row degree */\n    int next_col ;  /* Used to add to degree list.*/\n\n#ifndef NDEBUG\n    int debug_count ;\t\t/* debug only. */\n#endif /* NDEBUG */\n\n    /* === Extract knobs ==================================================== */\n\n    dense_row_count = (int) MAX (0, MIN (knobs [COLAMD_DENSE_ROW] * n_col, n_col)) ;\n    dense_col_count = (int) MAX (0, MIN (knobs [COLAMD_DENSE_COL] * n_row, n_row)) ;\n    DEBUG1 ((\"colamd: densecount: %d %d\\n\", dense_row_count, dense_col_count)) ;\n    max_deg = 0 ;\n    n_col2 = n_col ;\n    n_row2 = n_row ;\n\n    /* === Kill empty columns =============================================== */\n\n    /* Put the empty columns at the end in their natural order, so that LU */\n    /* factorization can proceed as far as possible. */\n    for (c = n_col-1 ; c >= 0 ; c--)\n    {\n\tdeg = Col [c].length ;\n\tif (deg == 0)\n\t{\n\t    /* this is a empty column, kill and order it last */\n\t    Col [c].shared2.order = --n_col2 ;\n\t    KILL_PRINCIPAL_COL (c) ;\n\t}\n    }\n    DEBUG1 ((\"colamd: null columns killed: %d\\n\", n_col - n_col2)) ;\n\n    /* === Kill dense columns =============================================== */\n\n    /* Put the dense columns at the end, in their natural order */\n    for (c = n_col-1 ; c >= 0 ; c--)\n    {\n\t/* skip any dead columns */\n\tif (COL_IS_DEAD (c))\n\t{\n\t    continue ;\n\t}\n\tdeg = Col [c].length ;\n\tif (deg > dense_col_count)\n\t{\n\t    /* this is a dense column, kill and order it last */\n\t    Col [c].shared2.order = --n_col2 ;\n\t    /* decrement the row degrees */\n\t    cp = &A [Col [c].start] ;\n\t    cp_end = cp + Col [c].length ;\n\t    while (cp < cp_end)\n\t    {\n\t\tRow [*cp++].shared1.degree-- ;\n\t    }\n\t    KILL_PRINCIPAL_COL (c) ;\n\t}\n    }\n    DEBUG1 ((\"colamd: Dense and null columns killed: %d\\n\", n_col - n_col2)) ;\n\n    /* === Kill dense and empty rows ======================================== */\n\n    for (r = 0 ; r < n_row ; r++)\n    {\n\tdeg = Row [r].shared1.degree ;\n\tASSERT (deg >= 0 && deg <= n_col) ;\n\tif (deg > dense_row_count || deg == 0)\n\t{\n\t    /* kill a dense or empty row */\n\t    KILL_ROW (r) ;\n\t    --n_row2 ;\n\t}\n\telse\n\t{\n\t    /* keep track of max degree of remaining rows */\n\t    max_deg = MAX (max_deg, deg) ;\n\t}\n    }\n    DEBUG1 ((\"colamd: Dense and null rows killed: %d\\n\", n_row - n_row2)) ;\n\n    /* === Compute initial column scores ==================================== */\n\n    /* At this point the row degrees are accurate.  They reflect the number */\n    /* of \"live\" (non-dense) columns in each row.  No empty rows exist. */\n    /* Some \"live\" columns may contain only dead rows, however.  These are */\n    /* pruned in the code below. */\n\n    /* now find the initial matlab score for each column */\n    for (c = n_col-1 ; c >= 0 ; c--)\n    {\n\t/* skip dead column */\n\tif (COL_IS_DEAD (c))\n\t{\n\t    continue ;\n\t}\n\tscore = 0 ;\n\tcp = &A [Col [c].start] ;\n\tnew_cp = cp ;\n\tcp_end = cp + Col [c].length ;\n\twhile (cp < cp_end)\n\t{\n\t    /* get a row */\n\t    row = *cp++ ;\n\t    /* skip if dead */\n\t    if (ROW_IS_DEAD (row))\n\t    {\n\t\tcontinue ;\n\t    }\n\t    /* compact the column */\n\t    *new_cp++ = row ;\n\t    /* add row's external degree */\n\t    score += Row [row].shared1.degree - 1 ;\n\t    /* guard against integer overflow */\n\t    score = MIN (score, n_col) ;\n\t}\n\t/* determine pruned column length */\n\tcol_length = (int) (new_cp - &A [Col [c].start]) ;\n\tif (col_length == 0)\n\t{\n\t    /* a newly-made null column (all rows in this col are \"dense\" */\n\t    /* and have already been killed) */\n\t    DEBUG2 ((\"Newly null killed: %d\\n\", c)) ;\n\t    Col [c].shared2.order = --n_col2 ;\n\t    KILL_PRINCIPAL_COL (c) ;\n\t}\n\telse\n\t{\n\t    /* set column length and set score */\n\t    ASSERT (score >= 0) ;\n\t    ASSERT (score <= n_col) ;\n\t    Col [c].length = col_length ;\n\t    Col [c].shared2.score = score ;\n\t}\n    }\n    DEBUG1 ((\"colamd: Dense, null, and newly-null columns killed: %d\\n\",\n    \tn_col-n_col2)) ;\n\n    /* At this point, all empty rows and columns are dead.  All live columns */\n    /* are \"clean\" (containing no dead rows) and simplicial (no supercolumns */\n    /* yet).  Rows may contain dead columns, but all live rows contain at */\n    /* least one live column. */\n\n#ifndef NDEBUG\n    debug_structures (n_row, n_col, Row, Col, A, n_col2) ;\n#endif /* NDEBUG */\n\n    /* === Initialize degree lists ========================================== */\n\n#ifndef NDEBUG\n    debug_count = 0 ;\n#endif /* NDEBUG */\n\n    /* clear the hash buckets */\n    for (c = 0 ; c <= n_col ; c++)\n    {\n\thead [c] = EMPTY ;\n    }\n    min_score = n_col ;\n    /* place in reverse order, so low column indices are at the front */\n    /* of the lists.  This is to encourage natural tie-breaking */\n    for (c = n_col-1 ; c >= 0 ; c--)\n    {\n\t/* only add principal columns to degree lists */\n\tif (COL_IS_ALIVE (c))\n\t{\n\t    DEBUG4 ((\"place %d score %d minscore %d ncol %d\\n\",\n\t\tc, Col [c].shared2.score, min_score, n_col)) ;\n\n\t    /* === Add columns score to DList =============================== */\n\n\t    score = Col [c].shared2.score ;\n\n\t    ASSERT (min_score >= 0) ;\n\t    ASSERT (min_score <= n_col) ;\n\t    ASSERT (score >= 0) ;\n\t    ASSERT (score <= n_col) ;\n\t    ASSERT (head [score] >= EMPTY) ;\n\n\t    /* now add this column to dList at proper score location */\n\t    next_col = head [score] ;\n\t    Col [c].shared3.prev = EMPTY ;\n\t    Col [c].shared4.degree_next = next_col ;\n\n\t    /* if there already was a column with the same score, set its */\n\t    /* previous pointer to this new column */\n\t    if (next_col != EMPTY)\n\t    {\n\t\tCol [next_col].shared3.prev = c ;\n\t    }\n\t    head [score] = c ;\n\n\t    /* see if this score is less than current min */\n\t    min_score = MIN (min_score, score) ;\n\n#ifndef NDEBUG\n\t    debug_count++ ;\n#endif /* NDEBUG */\n\n\t}\n    }\n\n#ifndef NDEBUG\n    DEBUG1 ((\"colamd: Live cols %d out of %d, non-princ: %d\\n\",\n\tdebug_count, n_col, n_col-debug_count)) ;\n    ASSERT (debug_count == n_col2) ;\n    debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ;\n#endif /* NDEBUG */\n\n    /* === Return number of remaining columns, and max row degree =========== */\n\n    *p_n_col2 = n_col2 ;\n    *p_n_row2 = n_row2 ;\n    *p_max_deg = max_deg ;\n}\n\n\n/* ========================================================================== */\n/* === find_ordering ======================================================== */\n/* ========================================================================== */\n\n/*\n    Order the principal columns of the supercolumn form of the matrix\n    (no supercolumns on input).  Uses a minimum approximate column minimum\n    degree ordering method.  Not user-callable.\n*/\n\nPRIVATE int find_ordering\t/* return the number of garbage collections */\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\t\t\t/* number of rows of A */\n    int n_col,\t\t\t/* number of columns of A */\n    int Alen,\t\t\t/* size of A, 2*nnz + n_col or larger */\n    Colamd_Row Row [],\t\t/* of size n_row+1 */\n    Colamd_Col Col [],\t\t/* of size n_col+1 */\n    int A [],\t\t\t/* column form and row form of A */\n    int head [],\t\t/* of size n_col+1 */\n    int n_col2,\t\t\t/* Remaining columns to order */\n    int max_deg,\t\t/* Maximum row degree */\n    int pfree\t\t\t/* index of first free slot (2*nnz on entry) */\n)\n{\n    /* === Local variables ================================================== */\n\n    int k ;\t\t\t/* current pivot ordering step */\n    int pivot_col ;\t\t/* current pivot column */\n    int *cp ;\t\t\t/* a column pointer */\n    int *rp ;\t\t\t/* a row pointer */\n    int pivot_row ;\t\t/* current pivot row */\n    int *new_cp ;\t\t/* modified column pointer */\n    int *new_rp ;\t\t/* modified row pointer */\n    int pivot_row_start ;\t/* pointer to start of pivot row */\n    int pivot_row_degree ;\t/* number of columns in pivot row */\n    int pivot_row_length ;\t/* number of supercolumns in pivot row */\n    int pivot_col_score ;\t/* score of pivot column */\n    int needed_memory ;\t\t/* free space needed for pivot row */\n    int *cp_end ;\t\t/* pointer to the end of a column */\n    int *rp_end ;\t\t/* pointer to the end of a row */\n    int row ;\t\t\t/* a row index */\n    int col ;\t\t\t/* a column index */\n    int max_score ;\t\t/* maximum possible score */\n    int cur_score ;\t\t/* score of current column */\n    unsigned int hash ;\t\t/* hash value for supernode detection */\n    int head_column ;\t\t/* head of hash bucket */\n    int first_col ;\t\t/* first column in hash bucket */\n    int tag_mark ;\t\t/* marker value for mark array */\n    int row_mark ;\t\t/* Row [row].shared2.mark */\n    int set_difference ;\t/* set difference size of row with pivot row */\n    int min_score ;\t\t/* smallest column score */\n    int col_thickness ;\t\t/* \"thickness\" (no. of columns in a supercol) */\n    int max_mark ;\t\t/* maximum value of tag_mark */\n    int pivot_col_thickness ;\t/* number of columns represented by pivot col */\n    int prev_col ;\t\t/* Used by Dlist operations. */\n    int next_col ;\t\t/* Used by Dlist operations. */\n    int ngarbage ;\t\t/* number of garbage collections performed */\n\n#ifndef NDEBUG\n    int debug_d ;\t\t/* debug loop counter */\n    int debug_step = 0 ;\t/* debug loop counter */\n#endif /* NDEBUG */\n\n    /* === Initialization and clear mark ==================================== */\n\n    max_mark = INT_MAX - n_col ;\t/* INT_MAX defined in <limits.h> */\n    tag_mark = clear_mark (n_row, Row) ;\n    min_score = 0 ;\n    ngarbage = 0 ;\n    DEBUG1 ((\"colamd: Ordering, n_col2=%d\\n\", n_col2)) ;\n\n    /* === Order the columns ================================================ */\n\n    for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */)\n    {\n\n#ifndef NDEBUG\n\tif (debug_step % 100 == 0)\n\t{\n\t    DEBUG2 ((\"\\n...       Step k: %d out of n_col2: %d\\n\", k, n_col2)) ;\n\t}\n\telse\n\t{\n\t    DEBUG3 ((\"\\n----------Step k: %d out of n_col2: %d\\n\", k, n_col2)) ;\n\t}\n\tdebug_step++ ;\n\tdebug_deg_lists (n_row, n_col, Row, Col, head,\n\t\tmin_score, n_col2-k, max_deg) ;\n\tdebug_matrix (n_row, n_col, Row, Col, A) ;\n#endif /* NDEBUG */\n\n\t/* === Select pivot column, and order it ============================ */\n\n\t/* make sure degree list isn't empty */\n\tASSERT (min_score >= 0) ;\n\tASSERT (min_score <= n_col) ;\n\tASSERT (head [min_score] >= EMPTY) ;\n\n#ifndef NDEBUG\n\tfor (debug_d = 0 ; debug_d < min_score ; debug_d++)\n\t{\n\t    ASSERT (head [debug_d] == EMPTY) ;\n\t}\n#endif /* NDEBUG */\n\n\t/* get pivot column from head of minimum degree list */\n\twhile (head [min_score] == EMPTY && min_score < n_col)\n\t{\n\t    min_score++ ;\n\t}\n\tpivot_col = head [min_score] ;\n\tASSERT (pivot_col >= 0 && pivot_col <= n_col) ;\n\tnext_col = Col [pivot_col].shared4.degree_next ;\n\thead [min_score] = next_col ;\n\tif (next_col != EMPTY)\n\t{\n\t    Col [next_col].shared3.prev = EMPTY ;\n\t}\n\n\tASSERT (COL_IS_ALIVE (pivot_col)) ;\n\tDEBUG3 ((\"Pivot col: %d\\n\", pivot_col)) ;\n\n\t/* remember score for defrag check */\n\tpivot_col_score = Col [pivot_col].shared2.score ;\n\n\t/* the pivot column is the kth column in the pivot order */\n\tCol [pivot_col].shared2.order = k ;\n\n\t/* increment order count by column thickness */\n\tpivot_col_thickness = Col [pivot_col].shared1.thickness ;\n\tk += pivot_col_thickness ;\n\tASSERT (pivot_col_thickness > 0) ;\n\n\t/* === Garbage_collection, if necessary ============================= */\n\n\tneeded_memory = MIN (pivot_col_score, n_col - k) ;\n\tif (pfree + needed_memory >= Alen)\n\t{\n\t    pfree = garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ;\n\t    ngarbage++ ;\n\t    /* after garbage collection we will have enough */\n\t    ASSERT (pfree + needed_memory < Alen) ;\n\t    /* garbage collection has wiped out the Row[].shared2.mark array */\n\t    tag_mark = clear_mark (n_row, Row) ;\n\n#ifndef NDEBUG\n\t    debug_matrix (n_row, n_col, Row, Col, A) ;\n#endif /* NDEBUG */\n\t}\n\n\t/* === Compute pivot row pattern ==================================== */\n\n\t/* get starting location for this new merged row */\n\tpivot_row_start = pfree ;\n\n\t/* initialize new row counts to zero */\n\tpivot_row_degree = 0 ;\n\n\t/* tag pivot column as having been visited so it isn't included */\n\t/* in merged pivot row */\n\tCol [pivot_col].shared1.thickness = -pivot_col_thickness ;\n\n\t/* pivot row is the union of all rows in the pivot column pattern */\n\tcp = &A [Col [pivot_col].start] ;\n\tcp_end = cp + Col [pivot_col].length ;\n\twhile (cp < cp_end)\n\t{\n\t    /* get a row */\n\t    row = *cp++ ;\n\t    DEBUG4 ((\"Pivot col pattern %d %d\\n\", ROW_IS_ALIVE (row), row)) ;\n\t    /* skip if row is dead */\n\t    if (ROW_IS_DEAD (row))\n\t    {\n\t\tcontinue ;\n\t    }\n\t    rp = &A [Row [row].start] ;\n\t    rp_end = rp + Row [row].length ;\n\t    while (rp < rp_end)\n\t    {\n\t\t/* get a column */\n\t\tcol = *rp++ ;\n\t\t/* add the column, if alive and untagged */\n\t\tcol_thickness = Col [col].shared1.thickness ;\n\t\tif (col_thickness > 0 && COL_IS_ALIVE (col))\n\t\t{\n\t\t    /* tag column in pivot row */\n\t\t    Col [col].shared1.thickness = -col_thickness ;\n\t\t    ASSERT (pfree < Alen) ;\n\t\t    /* place column in pivot row */\n\t\t    A [pfree++] = col ;\n\t\t    pivot_row_degree += col_thickness ;\n\t\t}\n\t    }\n\t}\n\n\t/* clear tag on pivot column */\n\tCol [pivot_col].shared1.thickness = pivot_col_thickness ;\n\tmax_deg = MAX (max_deg, pivot_row_degree) ;\n\n#ifndef NDEBUG\n\tDEBUG3 ((\"check2\\n\")) ;\n\tdebug_mark (n_row, Row, tag_mark, max_mark) ;\n#endif /* NDEBUG */\n\n\t/* === Kill all rows used to construct pivot row ==================== */\n\n\t/* also kill pivot row, temporarily */\n\tcp = &A [Col [pivot_col].start] ;\n\tcp_end = cp + Col [pivot_col].length ;\n\twhile (cp < cp_end)\n\t{\n\t    /* may be killing an already dead row */\n\t    row = *cp++ ;\n\t    DEBUG3 ((\"Kill row in pivot col: %d\\n\", row)) ;\n\t    KILL_ROW (row) ;\n\t}\n\n\t/* === Select a row index to use as the new pivot row =============== */\n\n\tpivot_row_length = pfree - pivot_row_start ;\n\tif (pivot_row_length > 0)\n\t{\n\t    /* pick the \"pivot\" row arbitrarily (first row in col) */\n\t    pivot_row = A [Col [pivot_col].start] ;\n\t    DEBUG3 ((\"Pivotal row is %d\\n\", pivot_row)) ;\n\t}\n\telse\n\t{\n\t    /* there is no pivot row, since it is of zero length */\n\t    pivot_row = EMPTY ;\n\t    ASSERT (pivot_row_length == 0) ;\n\t}\n\tASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ;\n\n\t/* === Approximate degree computation =============================== */\n\n\t/* Here begins the computation of the approximate degree.  The column */\n\t/* score is the sum of the pivot row \"length\", plus the size of the */\n\t/* set differences of each row in the column minus the pattern of the */\n\t/* pivot row itself.  The column (\"thickness\") itself is also */\n\t/* excluded from the column score (we thus use an approximate */\n\t/* external degree). */\n\n\t/* The time taken by the following code (compute set differences, and */\n\t/* add them up) is proportional to the size of the data structure */\n\t/* being scanned - that is, the sum of the sizes of each column in */\n\t/* the pivot row.  Thus, the amortized time to compute a column score */\n\t/* is proportional to the size of that column (where size, in this */\n\t/* context, is the column \"length\", or the number of row indices */\n\t/* in that column).  The number of row indices in a column is */\n\t/* monotonically non-decreasing, from the length of the original */\n\t/* column on input to colamd. */\n\n\t/* === Compute set differences ====================================== */\n\n\tDEBUG3 ((\"** Computing set differences phase. **\\n\")) ;\n\n\t/* pivot row is currently dead - it will be revived later. */\n\n\tDEBUG3 ((\"Pivot row: \")) ;\n\t/* for each column in pivot row */\n\trp = &A [pivot_row_start] ;\n\trp_end = rp + pivot_row_length ;\n\twhile (rp < rp_end)\n\t{\n\t    col = *rp++ ;\n\t    ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ;\n\t    DEBUG3 ((\"Col: %d\\n\", col)) ;\n\n\t    /* clear tags used to construct pivot row pattern */\n\t    col_thickness = -Col [col].shared1.thickness ;\n\t    ASSERT (col_thickness > 0) ;\n\t    Col [col].shared1.thickness = col_thickness ;\n\n\t    /* === Remove column from degree list =========================== */\n\n\t    cur_score = Col [col].shared2.score ;\n\t    prev_col = Col [col].shared3.prev ;\n\t    next_col = Col [col].shared4.degree_next ;\n\t    ASSERT (cur_score >= 0) ;\n\t    ASSERT (cur_score <= n_col) ;\n\t    ASSERT (cur_score >= EMPTY) ;\n\t    if (prev_col == EMPTY)\n\t    {\n\t\thead [cur_score] = next_col ;\n\t    }\n\t    else\n\t    {\n\t\tCol [prev_col].shared4.degree_next = next_col ;\n\t    }\n\t    if (next_col != EMPTY)\n\t    {\n\t\tCol [next_col].shared3.prev = prev_col ;\n\t    }\n\n\t    /* === Scan the column ========================================== */\n\n\t    cp = &A [Col [col].start] ;\n\t    cp_end = cp + Col [col].length ;\n\t    while (cp < cp_end)\n\t    {\n\t\t/* get a row */\n\t\trow = *cp++ ;\n\t\trow_mark = Row [row].shared2.mark ;\n\t\t/* skip if dead */\n\t\tif (ROW_IS_MARKED_DEAD (row_mark))\n\t\t{\n\t\t    continue ;\n\t\t}\n\t\tASSERT (row != pivot_row) ;\n\t\tset_difference = row_mark - tag_mark ;\n\t\t/* check if the row has been seen yet */\n\t\tif (set_difference < 0)\n\t\t{\n\t\t    ASSERT (Row [row].shared1.degree <= max_deg) ;\n\t\t    set_difference = Row [row].shared1.degree ;\n\t\t}\n\t\t/* subtract column thickness from this row's set difference */\n\t\tset_difference -= col_thickness ;\n\t\tASSERT (set_difference >= 0) ;\n\t\t/* absorb this row if the set difference becomes zero */\n\t\tif (set_difference == 0)\n\t\t{\n\t\t    DEBUG3 ((\"aggressive absorption. Row: %d\\n\", row)) ;\n\t\t    KILL_ROW (row) ;\n\t\t}\n\t\telse\n\t\t{\n\t\t    /* save the new mark */\n\t\t    Row [row].shared2.mark = set_difference + tag_mark ;\n\t\t}\n\t    }\n\t}\n\n#ifndef NDEBUG\n\tdebug_deg_lists (n_row, n_col, Row, Col, head,\n\t\tmin_score, n_col2-k-pivot_row_degree, max_deg) ;\n#endif /* NDEBUG */\n\n\t/* === Add up set differences for each column ======================= */\n\n\tDEBUG3 ((\"** Adding set differences phase. **\\n\")) ;\n\n\t/* for each column in pivot row */\n\trp = &A [pivot_row_start] ;\n\trp_end = rp + pivot_row_length ;\n\twhile (rp < rp_end)\n\t{\n\t    /* get a column */\n\t    col = *rp++ ;\n\t    ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ;\n\t    hash = 0 ;\n\t    cur_score = 0 ;\n\t    cp = &A [Col [col].start] ;\n\t    /* compact the column */\n\t    new_cp = cp ;\n\t    cp_end = cp + Col [col].length ;\n\n\t    DEBUG4 ((\"Adding set diffs for Col: %d.\\n\", col)) ;\n\n\t    while (cp < cp_end)\n\t    {\n\t\t/* get a row */\n\t\trow = *cp++ ;\n\t\tASSERT(row >= 0 && row < n_row) ;\n\t\trow_mark = Row [row].shared2.mark ;\n\t\t/* skip if dead */\n\t\tif (ROW_IS_MARKED_DEAD (row_mark))\n\t\t{\n\t\t    continue ;\n\t\t}\n\t\tASSERT (row_mark > tag_mark) ;\n\t\t/* compact the column */\n\t\t*new_cp++ = row ;\n\t\t/* compute hash function */\n\t\thash += row ;\n\t\t/* add set difference */\n\t\tcur_score += row_mark - tag_mark ;\n\t\t/* integer overflow... */\n\t\tcur_score = MIN (cur_score, n_col) ;\n\t    }\n\n\t    /* recompute the column's length */\n\t    Col [col].length = (int) (new_cp - &A [Col [col].start]) ;\n\n\t    /* === Further mass elimination ================================= */\n\n\t    if (Col [col].length == 0)\n\t    {\n\t\tDEBUG4 ((\"further mass elimination. Col: %d\\n\", col)) ;\n\t\t/* nothing left but the pivot row in this column */\n\t\tKILL_PRINCIPAL_COL (col) ;\n\t\tpivot_row_degree -= Col [col].shared1.thickness ;\n\t\tASSERT (pivot_row_degree >= 0) ;\n\t\t/* order it */\n\t\tCol [col].shared2.order = k ;\n\t\t/* increment order count by column thickness */\n\t\tk += Col [col].shared1.thickness ;\n\t    }\n\t    else\n\t    {\n\t\t/* === Prepare for supercolumn detection ==================== */\n\n\t\tDEBUG4 ((\"Preparing supercol detection for Col: %d.\\n\", col)) ;\n\n\t\t/* save score so far */\n\t\tCol [col].shared2.score = cur_score ;\n\n\t\t/* add column to hash table, for supercolumn detection */\n\t\thash %= n_col + 1 ;\n\n\t\tDEBUG4 ((\" Hash = %d, n_col = %d.\\n\", hash, n_col)) ;\n\t\tASSERT (hash <= n_col) ;\n\n\t\thead_column = head [hash] ;\n\t\tif (head_column > EMPTY)\n\t\t{\n\t\t    /* degree list \"hash\" is non-empty, use prev (shared3) of */\n\t\t    /* first column in degree list as head of hash bucket */\n\t\t    first_col = Col [head_column].shared3.headhash ;\n\t\t    Col [head_column].shared3.headhash = col ;\n\t\t}\n\t\telse\n\t\t{\n\t\t    /* degree list \"hash\" is empty, use head as hash bucket */\n\t\t    first_col = - (head_column + 2) ;\n\t\t    head [hash] = - (col + 2) ;\n\t\t}\n\t\tCol [col].shared4.hash_next = first_col ;\n\n\t\t/* save hash function in Col [col].shared3.hash */\n\t\tCol [col].shared3.hash = (int) hash ;\n\t\tASSERT (COL_IS_ALIVE (col)) ;\n\t    }\n\t}\n\n\t/* The approximate external column degree is now computed.  */\n\n\t/* === Supercolumn detection ======================================== */\n\n\tDEBUG3 ((\"** Supercolumn detection phase. **\\n\")) ;\n\n\tdetect_super_cols (\n\n#ifndef NDEBUG\n\t\tn_col, Row,\n#endif /* NDEBUG */\n\n\t\tCol, A, head, pivot_row_start, pivot_row_length) ;\n\n\t/* === Kill the pivotal column ====================================== */\n\n\tKILL_PRINCIPAL_COL (pivot_col) ;\n\n\t/* === Clear mark =================================================== */\n\n\ttag_mark += (max_deg + 1) ;\n\tif (tag_mark >= max_mark)\n\t{\n\t    DEBUG2 ((\"clearing tag_mark\\n\")) ;\n\t    tag_mark = clear_mark (n_row, Row) ;\n\t}\n\n#ifndef NDEBUG\n\tDEBUG3 ((\"check3\\n\")) ;\n\tdebug_mark (n_row, Row, tag_mark, max_mark) ;\n#endif /* NDEBUG */\n\n\t/* === Finalize the new pivot row, and column scores ================ */\n\n\tDEBUG3 ((\"** Finalize scores phase. **\\n\")) ;\n\n\t/* for each column in pivot row */\n\trp = &A [pivot_row_start] ;\n\t/* compact the pivot row */\n\tnew_rp = rp ;\n\trp_end = rp + pivot_row_length ;\n\twhile (rp < rp_end)\n\t{\n\t    col = *rp++ ;\n\t    /* skip dead columns */\n\t    if (COL_IS_DEAD (col))\n\t    {\n\t\tcontinue ;\n\t    }\n\t    *new_rp++ = col ;\n\t    /* add new pivot row to column */\n\t    A [Col [col].start + (Col [col].length++)] = pivot_row ;\n\n\t    /* retrieve score so far and add on pivot row's degree. */\n\t    /* (we wait until here for this in case the pivot */\n\t    /* row's degree was reduced due to mass elimination). */\n\t    cur_score = Col [col].shared2.score + pivot_row_degree ;\n\n\t    /* calculate the max possible score as the number of */\n\t    /* external columns minus the 'k' value minus the */\n\t    /* columns thickness */\n\t    max_score = n_col - k - Col [col].shared1.thickness ;\n\n\t    /* make the score the external degree of the union-of-rows */\n\t    cur_score -= Col [col].shared1.thickness ;\n\n\t    /* make sure score is less or equal than the max score */\n\t    cur_score = MIN (cur_score, max_score) ;\n\t    ASSERT (cur_score >= 0) ;\n\n\t    /* store updated score */\n\t    Col [col].shared2.score = cur_score ;\n\n\t    /* === Place column back in degree list ========================= */\n\n\t    ASSERT (min_score >= 0) ;\n\t    ASSERT (min_score <= n_col) ;\n\t    ASSERT (cur_score >= 0) ;\n\t    ASSERT (cur_score <= n_col) ;\n\t    ASSERT (head [cur_score] >= EMPTY) ;\n\t    next_col = head [cur_score] ;\n\t    Col [col].shared4.degree_next = next_col ;\n\t    Col [col].shared3.prev = EMPTY ;\n\t    if (next_col != EMPTY)\n\t    {\n\t\tCol [next_col].shared3.prev = col ;\n\t    }\n\t    head [cur_score] = col ;\n\n\t    /* see if this score is less than current min */\n\t    min_score = MIN (min_score, cur_score) ;\n\n\t}\n\n#ifndef NDEBUG\n\tdebug_deg_lists (n_row, n_col, Row, Col, head,\n\t\tmin_score, n_col2-k, max_deg) ;\n#endif /* NDEBUG */\n\n\t/* === Resurrect the new pivot row ================================== */\n\n\tif (pivot_row_degree > 0)\n\t{\n\t    /* update pivot row length to reflect any cols that were killed */\n\t    /* during super-col detection and mass elimination */\n\t    Row [pivot_row].start  = pivot_row_start ;\n\t    Row [pivot_row].length = (int) (new_rp - &A[pivot_row_start]) ;\n\t    Row [pivot_row].shared1.degree = pivot_row_degree ;\n\t    Row [pivot_row].shared2.mark = 0 ;\n\t    /* pivot row is no longer dead */\n\t}\n    }\n\n    /* === All principal columns have now been ordered ====================== */\n\n    return (ngarbage) ;\n}\n\n\n/* ========================================================================== */\n/* === order_children ======================================================= */\n/* ========================================================================== */\n\n/*\n    The find_ordering routine has ordered all of the principal columns (the\n    representatives of the supercolumns).  The non-principal columns have not\n    yet been ordered.  This routine orders those columns by walking up the\n    parent tree (a column is a child of the column which absorbed it).  The\n    final permutation vector is then placed in p [0 ... n_col-1], with p [0]\n    being the first column, and p [n_col-1] being the last.  It doesn't look\n    like it at first glance, but be assured that this routine takes time linear\n    in the number of columns.  Although not immediately obvious, the time\n    taken by this routine is O (n_col), that is, linear in the number of\n    columns.  Not user-callable.\n*/\n\nPRIVATE void order_children\n(\n    /* === Parameters ======================================================= */\n\n    int n_col,\t\t\t/* number of columns of A */\n    Colamd_Col Col [],\t\t/* of size n_col+1 */\n    int p []\t\t\t/* p [0 ... n_col-1] is the column permutation*/\n)\n{\n    /* === Local variables ================================================== */\n\n    int i ;\t\t\t/* loop counter for all columns */\n    int c ;\t\t\t/* column index */\n    int parent ;\t\t/* index of column's parent */\n    int order ;\t\t\t/* column's order */\n\n    /* === Order each non-principal column ================================== */\n\n    for (i = 0 ; i < n_col ; i++)\n    {\n\t/* find an un-ordered non-principal column */\n\tASSERT (COL_IS_DEAD (i)) ;\n\tif (!COL_IS_DEAD_PRINCIPAL (i) && Col [i].shared2.order == EMPTY)\n\t{\n\t    parent = i ;\n\t    /* once found, find its principal parent */\n\t    do\n\t    {\n\t\tparent = Col [parent].shared1.parent ;\n\t    } while (!COL_IS_DEAD_PRINCIPAL (parent)) ;\n\n\t    /* now, order all un-ordered non-principal columns along path */\n\t    /* to this parent.  collapse tree at the same time */\n\t    c = i ;\n\t    /* get order of parent */\n\t    order = Col [parent].shared2.order ;\n\n\t    do\n\t    {\n\t\tASSERT (Col [c].shared2.order == EMPTY) ;\n\n\t\t/* order this column */\n\t\tCol [c].shared2.order = order++ ;\n\t\t/* collaps tree */\n\t\tCol [c].shared1.parent = parent ;\n\n\t\t/* get immediate parent of this column */\n\t\tc = Col [c].shared1.parent ;\n\n\t\t/* continue until we hit an ordered column.  There are */\n\t\t/* guarranteed not to be anymore unordered columns */\n\t\t/* above an ordered column */\n\t    } while (Col [c].shared2.order == EMPTY) ;\n\n\t    /* re-order the super_col parent to largest order for this group */\n\t    Col [parent].shared2.order = order ;\n\t}\n    }\n\n    /* === Generate the permutation ========================================= */\n\n    for (c = 0 ; c < n_col ; c++)\n    {\n\tp [Col [c].shared2.order] = c ;\n    }\n}\n\n\n/* ========================================================================== */\n/* === detect_super_cols ==================================================== */\n/* ========================================================================== */\n\n/*\n    Detects supercolumns by finding matches between columns in the hash buckets.\n    Check amongst columns in the set A [row_start ... row_start + row_length-1].\n    The columns under consideration are currently *not* in the degree lists,\n    and have already been placed in the hash buckets.\n\n    The hash bucket for columns whose hash function is equal to h is stored\n    as follows:\n\n\tif head [h] is >= 0, then head [h] contains a degree list, so:\n\n\t\thead [h] is the first column in degree bucket h.\n\t\tCol [head [h]].headhash gives the first column in hash bucket h.\n\n\totherwise, the degree list is empty, and:\n\n\t\t-(head [h] + 2) is the first column in hash bucket h.\n\n    For a column c in a hash bucket, Col [c].shared3.prev is NOT a \"previous\n    column\" pointer.  Col [c].shared3.hash is used instead as the hash number\n    for that column.  The value of Col [c].shared4.hash_next is the next column\n    in the same hash bucket.\n\n    Assuming no, or \"few\" hash collisions, the time taken by this routine is\n    linear in the sum of the sizes (lengths) of each column whose score has\n    just been computed in the approximate degree computation.\n    Not user-callable.\n*/\n\nPRIVATE void detect_super_cols\n(\n    /* === Parameters ======================================================= */\n\n#ifndef NDEBUG\n    /* these two parameters are only needed when debugging is enabled: */\n    int n_col,\t\t\t/* number of columns of A */\n    Colamd_Row Row [],\t\t/* of size n_row+1 */\n#endif /* NDEBUG */\n\n    Colamd_Col Col [],\t\t/* of size n_col+1 */\n    int A [],\t\t\t/* row indices of A */\n    int head [],\t\t/* head of degree lists and hash buckets */\n    int row_start,\t\t/* pointer to set of columns to check */\n    int row_length\t\t/* number of columns to check */\n)\n{\n    /* === Local variables ================================================== */\n\n    int hash ;\t\t\t/* hash value for a column */\n    int *rp ;\t\t\t/* pointer to a row */\n    int c ;\t\t\t/* a column index */\n    int super_c ;\t\t/* column index of the column to absorb into */\n    int *cp1 ;\t\t\t/* column pointer for column super_c */\n    int *cp2 ;\t\t\t/* column pointer for column c */\n    int length ;\t\t/* length of column super_c */\n    int prev_c ;\t\t/* column preceding c in hash bucket */\n    int i ;\t\t\t/* loop counter */\n    int *rp_end ;\t\t/* pointer to the end of the row */\n    int col ;\t\t\t/* a column index in the row to check */\n    int head_column ;\t\t/* first column in hash bucket or degree list */\n    int first_col ;\t\t/* first column in hash bucket */\n\n    /* === Consider each column in the row ================================== */\n\n    rp = &A [row_start] ;\n    rp_end = rp + row_length ;\n    while (rp < rp_end)\n    {\n\tcol = *rp++ ;\n\tif (COL_IS_DEAD (col))\n\t{\n\t    continue ;\n\t}\n\n\t/* get hash number for this column */\n\thash = Col [col].shared3.hash ;\n\tASSERT (hash <= n_col) ;\n\n\t/* === Get the first column in this hash bucket ===================== */\n\n\thead_column = head [hash] ;\n\tif (head_column > EMPTY)\n\t{\n\t    first_col = Col [head_column].shared3.headhash ;\n\t}\n\telse\n\t{\n\t    first_col = - (head_column + 2) ;\n\t}\n\n\t/* === Consider each column in the hash bucket ====================== */\n\n\tfor (super_c = first_col ; super_c != EMPTY ;\n\t    super_c = Col [super_c].shared4.hash_next)\n\t{\n\t    ASSERT (COL_IS_ALIVE (super_c)) ;\n\t    ASSERT (Col [super_c].shared3.hash == hash) ;\n\t    length = Col [super_c].length ;\n\n\t    /* prev_c is the column preceding column c in the hash bucket */\n\t    prev_c = super_c ;\n\n\t    /* === Compare super_c with all columns after it ================ */\n\n\t    for (c = Col [super_c].shared4.hash_next ;\n\t\t c != EMPTY ; c = Col [c].shared4.hash_next)\n\t    {\n\t\tASSERT (c != super_c) ;\n\t\tASSERT (COL_IS_ALIVE (c)) ;\n\t\tASSERT (Col [c].shared3.hash == hash) ;\n\n\t\t/* not identical if lengths or scores are different */\n\t\tif (Col [c].length != length ||\n\t\t    Col [c].shared2.score != Col [super_c].shared2.score)\n\t\t{\n\t\t    prev_c = c ;\n\t\t    continue ;\n\t\t}\n\n\t\t/* compare the two columns */\n\t\tcp1 = &A [Col [super_c].start] ;\n\t\tcp2 = &A [Col [c].start] ;\n\n\t\tfor (i = 0 ; i < length ; i++)\n\t\t{\n\t\t    /* the columns are \"clean\" (no dead rows) */\n\t\t    ASSERT (ROW_IS_ALIVE (*cp1))  ;\n\t\t    ASSERT (ROW_IS_ALIVE (*cp2))  ;\n\t\t    /* row indices will same order for both supercols, */\n\t\t    /* no gather scatter nessasary */\n\t\t    if (*cp1++ != *cp2++)\n\t\t    {\n\t\t\tbreak ;\n\t\t    }\n\t\t}\n\n\t\t/* the two columns are different if the for-loop \"broke\" */\n\t\tif (i != length)\n\t\t{\n\t\t    prev_c = c ;\n\t\t    continue ;\n\t\t}\n\n\t\t/* === Got it!  two columns are identical =================== */\n\n\t\tASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ;\n\n\t\tCol [super_c].shared1.thickness += Col [c].shared1.thickness ;\n\t\tCol [c].shared1.parent = super_c ;\n\t\tKILL_NON_PRINCIPAL_COL (c) ;\n\t\t/* order c later, in order_children() */\n\t\tCol [c].shared2.order = EMPTY ;\n\t\t/* remove c from hash bucket */\n\t\tCol [prev_c].shared4.hash_next = Col [c].shared4.hash_next ;\n\t    }\n\t}\n\n\t/* === Empty this hash bucket ======================================= */\n\n\tif (head_column > EMPTY)\n\t{\n\t    /* corresponding degree list \"hash\" is not empty */\n\t    Col [head_column].shared3.headhash = EMPTY ;\n\t}\n\telse\n\t{\n\t    /* corresponding degree list \"hash\" is empty */\n\t    head [hash] = EMPTY ;\n\t}\n    }\n}\n\n\n/* ========================================================================== */\n/* === garbage_collection =================================================== */\n/* ========================================================================== */\n\n/*\n    Defragments and compacts columns and rows in the workspace A.  Used when\n    all avaliable memory has been used while performing row merging.  Returns\n    the index of the first free position in A, after garbage collection.  The\n    time taken by this routine is linear is the size of the array A, which is\n    itself linear in the number of nonzeros in the input matrix.\n    Not user-callable.\n*/\n\nPRIVATE int garbage_collection  /* returns the new value of pfree */\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\t\t\t/* number of rows */\n    int n_col,\t\t\t/* number of columns */\n    Colamd_Row Row [],\t\t/* row info */\n    Colamd_Col Col [],\t\t/* column info */\n    int A [],\t\t\t/* A [0 ... Alen-1] holds the matrix */\n    int *pfree\t\t\t/* &A [0] ... pfree is in use */\n)\n{\n    /* === Local variables ================================================== */\n\n    int *psrc ;\t\t\t/* source pointer */\n    int *pdest ;\t\t/* destination pointer */\n    int j ;\t\t\t/* counter */\n    int r ;\t\t\t/* a row index */\n    int c ;\t\t\t/* a column index */\n    int length ;\t\t/* length of a row or column */\n\n#ifndef NDEBUG\n    int debug_rows ;\n    DEBUG2 ((\"Defrag..\\n\")) ;\n    for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ;\n    debug_rows = 0 ;\n#endif /* NDEBUG */\n\n    /* === Defragment the columns =========================================== */\n\n    pdest = &A[0] ;\n    for (c = 0 ; c < n_col ; c++)\n    {\n\tif (COL_IS_ALIVE (c))\n\t{\n\t    psrc = &A [Col [c].start] ;\n\n\t    /* move and compact the column */\n\t    ASSERT (pdest <= psrc) ;\n\t    Col [c].start = (int) (pdest - &A [0]) ;\n\t    length = Col [c].length ;\n\t    for (j = 0 ; j < length ; j++)\n\t    {\n\t\tr = *psrc++ ;\n\t\tif (ROW_IS_ALIVE (r))\n\t\t{\n\t\t    *pdest++ = r ;\n\t\t}\n\t    }\n\t    Col [c].length = (int) (pdest - &A [Col [c].start]) ;\n\t}\n    }\n\n    /* === Prepare to defragment the rows =================================== */\n\n    for (r = 0 ; r < n_row ; r++)\n    {\n\tif (ROW_IS_ALIVE (r))\n\t{\n\t    if (Row [r].length == 0)\n\t    {\n\t\t/* this row is of zero length.  cannot compact it, so kill it */\n\t\tDEBUG3 ((\"Defrag row kill\\n\")) ;\n\t\tKILL_ROW (r) ;\n\t    }\n\t    else\n\t    {\n\t\t/* save first column index in Row [r].shared2.first_column */\n\t\tpsrc = &A [Row [r].start] ;\n\t\tRow [r].shared2.first_column = *psrc ;\n\t\tASSERT (ROW_IS_ALIVE (r)) ;\n\t\t/* flag the start of the row with the one's complement of row */\n\t\t*psrc = ONES_COMPLEMENT (r) ;\n\n#ifndef NDEBUG\n\t\tdebug_rows++ ;\n#endif /* NDEBUG */\n\n\t    }\n\t}\n    }\n\n    /* === Defragment the rows ============================================== */\n\n    psrc = pdest ;\n    while (psrc < pfree)\n    {\n\t/* find a negative number ... the start of a row */\n\tif (*psrc++ < 0)\n\t{\n\t    psrc-- ;\n\t    /* get the row index */\n\t    r = ONES_COMPLEMENT (*psrc) ;\n\t    ASSERT (r >= 0 && r < n_row) ;\n\t    /* restore first column index */\n\t    *psrc = Row [r].shared2.first_column ;\n\t    ASSERT (ROW_IS_ALIVE (r)) ;\n\n\t    /* move and compact the row */\n\t    ASSERT (pdest <= psrc) ;\n\t    Row [r].start = (int) (pdest - &A [0]) ;\n\t    length = Row [r].length ;\n\t    for (j = 0 ; j < length ; j++)\n\t    {\n\t\tc = *psrc++ ;\n\t\tif (COL_IS_ALIVE (c))\n\t\t{\n\t\t    *pdest++ = c ;\n\t\t}\n\t    }\n\t    Row [r].length = (int) (pdest - &A [Row [r].start]) ;\n\n#ifndef NDEBUG\n\t    debug_rows-- ;\n#endif /* NDEBUG */\n\n\t}\n    }\n    /* ensure we found all the rows */\n    ASSERT (debug_rows == 0) ;\n\n    /* === Return the new value of pfree ==================================== */\n\n    return ((int) (pdest - &A [0])) ;\n}\n\n\n/* ========================================================================== */\n/* === clear_mark =========================================================== */\n/* ========================================================================== */\n\n/*\n    Clears the Row [].shared2.mark array, and returns the new tag_mark.\n    Return value is the new tag_mark.  Not user-callable.\n*/\n\nPRIVATE int clear_mark\t/* return the new value for tag_mark */\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\t\t/* number of rows in A */\n    Colamd_Row Row []\t/* Row [0 ... n_row-1].shared2.mark is set to zero */\n)\n{\n    /* === Local variables ================================================== */\n\n    int r ;\n\n    for (r = 0 ; r < n_row ; r++)\n    {\n\tif (ROW_IS_ALIVE (r))\n\t{\n\t    Row [r].shared2.mark = 0 ;\n\t}\n    }\n    return (1) ;\n}\n\n\n/* ========================================================================== */\n/* === print_report ========================================================= */\n/* ========================================================================== */\n\nPRIVATE void print_report\n(\n    const char * method,\n    int stats [COLAMD_STATS]\n)\n{\n\n    int i1, i2, i3 ;\n\n    if (!stats)\n    {\n    \tPRINTF (\"%s: No statistics available.\\n\", method) ;\n\treturn ;\n    }\n\n    i1 = stats [COLAMD_INFO1] ;\n    i2 = stats [COLAMD_INFO2] ;\n    i3 = stats [COLAMD_INFO3] ;\n\n    if (stats [COLAMD_STATUS] >= 0)\n    {\n    \tPRINTF (\"%s: OK.  \", method) ;\n    }\n    else\n    {\n    \tPRINTF (\"%s: ERROR.  \", method) ;\n    }\n\n    switch (stats [COLAMD_STATUS])\n    {\n\n\tcase COLAMD_OK_BUT_JUMBLED:\n\n\t    PRINTF (\"Matrix has unsorted or duplicate row indices.\\n\") ;\n\n\t    PRINTF (\"%s: number of duplicate or out-of-order row indices: %d\\n\",\n\t    method, i3) ;\n\n\t    PRINTF (\"%s: last seen duplicate or out-of-order row index:   %d\\n\",\n\t    method, INDEX (i2)) ;\n\n\t    PRINTF (\"%s: last seen in column:                             %d\",\n\t    method, INDEX (i1)) ;\n\n\t    /* no break - fall through to next case instead */\n\n\tcase COLAMD_OK:\n\n\t    PRINTF (\"\\n\") ;\n\n \t    PRINTF (\"%s: number of dense or empty rows ignored:           %d\\n\",\n\t    method, stats [COLAMD_DENSE_ROW]) ;\n\n\t    PRINTF (\"%s: number of dense or empty columns ignored:        %d\\n\",\n\t    method, stats [COLAMD_DENSE_COL]) ;\n\n\t    PRINTF (\"%s: number of garbage collections performed:         %d\\n\",\n\t    method, stats [COLAMD_DEFRAG_COUNT]) ;\n\t    break ;\n\n\tcase COLAMD_ERROR_A_not_present:\n\n\t    PRINTF (\"Array A (row indices of matrix) not present.\\n\") ;\n\t    break ;\n\n\tcase COLAMD_ERROR_p_not_present:\n\n\t    PRINTF (\"Array p (column pointers for matrix) not present.\\n\") ;\n\t    break ;\n\n\tcase COLAMD_ERROR_nrow_negative:\n\n\t    PRINTF (\"Invalid number of rows (%d).\\n\", i1) ;\n\t    break ;\n\n\tcase COLAMD_ERROR_ncol_negative:\n\n\t    PRINTF (\"Invalid number of columns (%d).\\n\", i1) ;\n\t    break ;\n\n\tcase COLAMD_ERROR_nnz_negative:\n\n\t    PRINTF (\"Invalid number of nonzero entries (%d).\\n\", i1) ;\n\t    break ;\n\n\tcase COLAMD_ERROR_p0_nonzero:\n\n\t    PRINTF (\"Invalid column pointer, p [0] = %d, must be zero.\\n\", i1) ;\n\t    break ;\n\n\tcase COLAMD_ERROR_A_too_small:\n\n\t    PRINTF (\"Array A too small.\\n\") ;\n\t    PRINTF (\"        Need Alen >= %d, but given only Alen = %d.\\n\",\n\t    i1, i2) ;\n\t    break ;\n\n\tcase COLAMD_ERROR_col_length_negative:\n\n\t    PRINTF\n\t    (\"Column %d has a negative number of nonzero entries (%d).\\n\",\n\t    INDEX (i1), i2) ;\n\t    break ;\n\n\tcase COLAMD_ERROR_row_index_out_of_bounds:\n\n\t    PRINTF\n\t    (\"Row index (row %d) out of bounds (%d to %d) in column %d.\\n\",\n\t    INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1)) ;\n\t    break ;\n\n\tcase COLAMD_ERROR_out_of_memory:\n\n\t    PRINTF (\"Out of memory.\\n\") ;\n\t    break ;\n\n\tcase COLAMD_ERROR_internal_error:\n\n\t    /* if this happens, there is a bug in the code */\n\t    PRINTF\n\t    (\"Internal error! Please contact authors (davis@cise.ufl.edu).\\n\") ;\n\t    break ;\n    }\n}\n\n\n\n\n/* ========================================================================== */\n/* === colamd debugging routines ============================================ */\n/* ========================================================================== */\n\n/* When debugging is disabled, the remainder of this file is ignored. */\n\n#ifndef NDEBUG\n\n\n/* ========================================================================== */\n/* === debug_structures ===================================================== */\n/* ========================================================================== */\n\n/*\n    At this point, all empty rows and columns are dead.  All live columns\n    are \"clean\" (containing no dead rows) and simplicial (no supercolumns\n    yet).  Rows may contain dead columns, but all live rows contain at\n    least one live column.\n*/\n\nPRIVATE void debug_structures\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int A [],\n    int n_col2\n)\n{\n    /* === Local variables ================================================== */\n\n    int i ;\n    int c ;\n    int *cp ;\n    int *cp_end ;\n    int len ;\n    int score ;\n    int r ;\n    int *rp ;\n    int *rp_end ;\n    int deg ;\n\n    /* === Check A, Row, and Col ============================================ */\n\n    for (c = 0 ; c < n_col ; c++)\n    {\n\tif (COL_IS_ALIVE (c))\n\t{\n\t    len = Col [c].length ;\n\t    score = Col [c].shared2.score ;\n\t    DEBUG4 ((\"initial live col %5d %5d %5d\\n\", c, len, score)) ;\n\t    ASSERT (len > 0) ;\n\t    ASSERT (score >= 0) ;\n\t    ASSERT (Col [c].shared1.thickness == 1) ;\n\t    cp = &A [Col [c].start] ;\n\t    cp_end = cp + len ;\n\t    while (cp < cp_end)\n\t    {\n\t\tr = *cp++ ;\n\t\tASSERT (ROW_IS_ALIVE (r)) ;\n\t    }\n\t}\n\telse\n\t{\n\t    i = Col [c].shared2.order ;\n\t    ASSERT (i >= n_col2 && i < n_col) ;\n\t}\n    }\n\n    for (r = 0 ; r < n_row ; r++)\n    {\n\tif (ROW_IS_ALIVE (r))\n\t{\n\t    i = 0 ;\n\t    len = Row [r].length ;\n\t    deg = Row [r].shared1.degree ;\n\t    ASSERT (len > 0) ;\n\t    ASSERT (deg > 0) ;\n\t    rp = &A [Row [r].start] ;\n\t    rp_end = rp + len ;\n\t    while (rp < rp_end)\n\t    {\n\t\tc = *rp++ ;\n\t\tif (COL_IS_ALIVE (c))\n\t\t{\n\t\t    i++ ;\n\t\t}\n\t    }\n\t    ASSERT (i > 0) ;\n\t}\n    }\n}\n\n\n/* ========================================================================== */\n/* === debug_deg_lists ====================================================== */\n/* ========================================================================== */\n\n/*\n    Prints the contents of the degree lists.  Counts the number of columns\n    in the degree list and compares it to the total it should have.  Also\n    checks the row degrees.\n*/\n\nPRIVATE void debug_deg_lists\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int head [],\n    int min_score,\n    int should,\n    int max_deg\n)\n{\n    /* === Local variables ================================================== */\n\n    int deg ;\n    int col ;\n    int have ;\n    int row ;\n\n    /* === Check the degree lists =========================================== */\n\n    if (n_col > 10000 && colamd_debug <= 0)\n    {\n\treturn ;\n    }\n    have = 0 ;\n    DEBUG4 ((\"Degree lists: %d\\n\", min_score)) ;\n    for (deg = 0 ; deg <= n_col ; deg++)\n    {\n\tcol = head [deg] ;\n\tif (col == EMPTY)\n\t{\n\t    continue ;\n\t}\n\tDEBUG4 ((\"%d:\", deg)) ;\n\twhile (col != EMPTY)\n\t{\n\t    DEBUG4 ((\" %d\", col)) ;\n\t    have += Col [col].shared1.thickness ;\n\t    ASSERT (COL_IS_ALIVE (col)) ;\n\t    col = Col [col].shared4.degree_next ;\n\t}\n\tDEBUG4 ((\"\\n\")) ;\n    }\n    DEBUG4 ((\"should %d have %d\\n\", should, have)) ;\n    ASSERT (should == have) ;\n\n    /* === Check the row degrees ============================================ */\n\n    if (n_row > 10000 && colamd_debug <= 0)\n    {\n\treturn ;\n    }\n    for (row = 0 ; row < n_row ; row++)\n    {\n\tif (ROW_IS_ALIVE (row))\n\t{\n\t    ASSERT (Row [row].shared1.degree <= max_deg) ;\n\t}\n    }\n}\n\n\n/* ========================================================================== */\n/* === debug_mark =========================================================== */\n/* ========================================================================== */\n\n/*\n    Ensures that the tag_mark is less that the maximum and also ensures that\n    each entry in the mark array is less than the tag mark.\n*/\n\nPRIVATE void debug_mark\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\n    Colamd_Row Row [],\n    int tag_mark,\n    int max_mark\n)\n{\n    /* === Local variables ================================================== */\n\n    int r ;\n\n    /* === Check the Row marks ============================================== */\n\n    ASSERT (tag_mark > 0 && tag_mark <= max_mark) ;\n    if (n_row > 10000 && colamd_debug <= 0)\n    {\n\treturn ;\n    }\n    for (r = 0 ; r < n_row ; r++)\n    {\n\tASSERT (Row [r].shared2.mark < tag_mark) ;\n    }\n}\n\n\n/* ========================================================================== */\n/* === debug_matrix ========================================================= */\n/* ========================================================================== */\n\n/*\n    Prints out the contents of the columns and the rows.\n*/\n\nPRIVATE void debug_matrix\n(\n    /* === Parameters ======================================================= */\n\n    int n_row,\n    int n_col,\n    Colamd_Row Row [],\n    Colamd_Col Col [],\n    int A []\n)\n{\n    /* === Local variables ================================================== */\n\n    int r ;\n    int c ;\n    int *rp ;\n    int *rp_end ;\n    int *cp ;\n    int *cp_end ;\n\n    /* === Dump the rows and columns of the matrix ========================== */\n\n    if (colamd_debug < 3)\n    {\n\treturn ;\n    }\n    DEBUG3 ((\"DUMP MATRIX:\\n\")) ;\n    for (r = 0 ; r < n_row ; r++)\n    {\n\tDEBUG3 ((\"Row %d alive? %d\\n\", r, ROW_IS_ALIVE (r))) ;\n\tif (ROW_IS_DEAD (r))\n\t{\n\t    continue ;\n\t}\n\tDEBUG3 ((\"start %d length %d degree %d\\n\",\n\t\tRow [r].start, Row [r].length, Row [r].shared1.degree)) ;\n\trp = &A [Row [r].start] ;\n\trp_end = rp + Row [r].length ;\n\twhile (rp < rp_end)\n\t{\n\t    c = *rp++ ;\n\t    DEBUG4 ((\"\t%d col %d\\n\", COL_IS_ALIVE (c), c)) ;\n\t}\n    }\n\n    for (c = 0 ; c < n_col ; c++)\n    {\n\tDEBUG3 ((\"Col %d alive? %d\\n\", c, COL_IS_ALIVE (c))) ;\n\tif (COL_IS_DEAD (c))\n\t{\n\t    continue ;\n\t}\n\tDEBUG3 ((\"start %d length %d shared1 %d shared2 %d\\n\",\n\t\tCol [c].start, Col [c].length,\n\t\tCol [c].shared1.thickness, Col [c].shared2.score)) ;\n\tcp = &A [Col [c].start] ;\n\tcp_end = cp + Col [c].length ;\n\twhile (cp < cp_end)\n\t{\n\t    r = *cp++ ;\n\t    DEBUG4 ((\"\t%d row %d\\n\", ROW_IS_ALIVE (r), r)) ;\n\t}\n    }\n}\n\nPRIVATE void colamd_get_debug\n(\n    char *method\n)\n{\n    colamd_debug = 0 ;\t\t/* no debug printing */\n\n    /* get \"D\" environment variable, which gives the debug printing level */\n    if (getenv (\"D\"))\n    {\n    \tcolamd_debug = atoi (getenv (\"D\")) ;\n    }\n\n    DEBUG0 ((\"%s: debug version, D = %d (THIS WILL BE SLOW!)\\n\",\n    \tmethod, colamd_debug)) ;\n}\n\n#endif /* NDEBUG */\n\n"
  },
  {
    "path": "utilities/lp_solve/colamd/colamd.h",
    "content": "/* ========================================================================== */\n/* === colamd/symamd prototypes and definitions ============================= */\n/* ========================================================================== */\n\n/*\n    You must include this file (colamd.h) in any routine that uses colamd,\n    symamd, or the related macros and definitions.\n\n    Authors:\n\n\tThe authors of the code itself are Stefan I. Larimore and Timothy A.\n\tDavis (davis@cise.ufl.edu), University of Florida.  The algorithm was\n\tdeveloped in collaboration with John Gilbert, Xerox PARC, and Esmond\n\tNg, Oak Ridge National Laboratory.\n\n    Date:\n\n\tMay 4, 2001.  Version 2.1.\n\n    Acknowledgements:\n\n\tThis work was supported by the National Science Foundation, under\n\tgrants DMS-9504974 and DMS-9803599.\n\n    Notice:\n\n\tCopyright (c) 1998-2001 by the University of Florida.\n\tAll Rights Reserved.\n\n\tTHIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY\n\tEXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.\n\n\tPermission is hereby granted to use or copy this program for any\n\tpurpose, provided the above notices are retained on all copies.\n\tUser documentation of any code that uses this code must cite the\n\tAuthors, the Copyright, and \"Used by permission.\"  If this code is\n\taccessible from within Matlab, then typing \"help colamd\" and \"help\n\tsymamd\" must cite the Authors.  Permission to modify the code and to\n\tdistribute modified code is granted, provided the above notices are\n\tretained, and a notice that the code was modified is included with the\n\tabove copyright notice.  You must also retain the Availability\n\tinformation below, of the original version.\n\n\tThis software is provided free of charge.\n\n    Availability:\n\n\tThe colamd/symamd library is available at\n\n\t    https://www.cise.ufl.edu/research/sparse/colamd\n\n\tThis is the https://www.cise.ufl.edu/research/sparse/colamd/colamd.h\n\tfile.  It is required by the colamd.c, colamdmex.c, and symamdmex.c\n\tfiles, and by any C code that calls the routines whose prototypes are\n\tlisted below, or that uses the colamd/symamd definitions listed below.\n\n*/\n\n#ifndef COLAMD_H\n#define COLAMD_H\n\n/* ========================================================================== */\n/* === Include files ======================================================== */\n/* ========================================================================== */\n\n#include <stdlib.h>\n\n/* ========================================================================== */\n/* === Knob and statistics definitions ====================================== */\n/* ========================================================================== */\n\n/* size of the knobs [ ] array.  Only knobs [0..1] are currently used. */\n#define COLAMD_KNOBS 20\n\n/* number of output statistics.  Only stats [0..6] are currently used. */\n#define COLAMD_STATS 20\n\n/* knobs [0] and stats [0]: dense row knob and output statistic. */\n#define COLAMD_DENSE_ROW 0\n\n/* knobs [1] and stats [1]: dense column knob and output statistic. */\n#define COLAMD_DENSE_COL 1\n\n/* stats [2]: memory defragmentation count output statistic */\n#define COLAMD_DEFRAG_COUNT 2\n\n/* stats [3]: colamd status:  zero OK, > 0 warning or notice, < 0 error */\n#define COLAMD_STATUS 3\n\n/* stats [4..6]: error info, or info on jumbled columns */\n#define COLAMD_INFO1 4\n#define COLAMD_INFO2 5\n#define COLAMD_INFO3 6\n\n/* error codes returned in stats [3]: */\n#define COLAMD_OK\t\t\t\t(0)\n#define COLAMD_OK_BUT_JUMBLED\t\t\t(1)\n#define COLAMD_ERROR_A_not_present\t\t(-1)\n#define COLAMD_ERROR_p_not_present\t\t(-2)\n#define COLAMD_ERROR_nrow_negative\t\t(-3)\n#define COLAMD_ERROR_ncol_negative\t\t(-4)\n#define COLAMD_ERROR_nnz_negative\t\t(-5)\n#define COLAMD_ERROR_p0_nonzero\t\t\t(-6)\n#define COLAMD_ERROR_A_too_small\t\t(-7)\n#define COLAMD_ERROR_col_length_negative\t(-8)\n#define COLAMD_ERROR_row_index_out_of_bounds\t(-9)\n#define COLAMD_ERROR_out_of_memory\t\t(-10)\n#define COLAMD_ERROR_internal_error\t\t(-999)\n\n\n\n/* ========================================================================== */\n/* === Row and Column structures ============================================ */\n/* ========================================================================== */\n\n/* User code that makes use of the colamd/symamd routines need not directly */\n/* reference these structures.  They are used only for the COLAMD_RECOMMENDED */\n/* macro. */\n\ntypedef struct Colamd_Col_struct\n{\n    int start ;\t\t/* index for A of first row in this column, or DEAD */\n\t\t\t/* if column is dead */\n    int length ;\t/* number of rows in this column */\n    union\n    {\n\tint thickness ;\t/* number of original columns represented by this */\n\t\t\t/* col, if the column is alive */\n\tint parent ;\t/* parent in parent tree super-column structure, if */\n\t\t\t/* the column is dead */\n    } shared1 ;\n    union\n    {\n\tint score ;\t/* the score used to maintain heap, if col is alive */\n\tint order ;\t/* pivot ordering of this column, if col is dead */\n    } shared2 ;\n    union\n    {\n\tint headhash ;\t/* head of a hash bucket, if col is at the head of */\n\t\t\t/* a degree list */\n\tint hash ;\t/* hash value, if col is not in a degree list */\n\tint prev ;\t/* previous column in degree list, if col is in a */\n\t\t\t/* degree list (but not at the head of a degree list) */\n    } shared3 ;\n    union\n    {\n\tint degree_next ;\t/* next column, if col is in a degree list */\n\tint hash_next ;\t\t/* next column, if col is in a hash list */\n    } shared4 ;\n\n} Colamd_Col ;\n\ntypedef struct Colamd_Row_struct\n{\n    int start ;\t\t/* index for A of first col in this row */\n    int length ;\t/* number of principal columns in this row */\n    union\n    {\n\tint degree ;\t/* number of principal & non-principal columns in row */\n\tint p ;\t\t/* used as a row pointer in init_rows_cols () */\n    } shared1 ;\n    union\n    {\n\tint mark ;\t/* for computing set differences and marking dead rows*/\n\tint first_column ;/* first column in row (used in garbage collection) */\n    } shared2 ;\n\n} Colamd_Row ;\n\n/* ========================================================================== */\n/* === Colamd recommended memory size ======================================= */\n/* ========================================================================== */\n\n/*\n    The recommended length Alen of the array A passed to colamd is given by\n    the COLAMD_RECOMMENDED (nnz, n_row, n_col) macro.  It returns -1 if any\n    argument is negative.  2*nnz space is required for the row and column\n    indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is\n    required for the Col and Row arrays, respectively, which are internal to\n    colamd.  An additional n_col space is the minimal amount of \"elbow room\",\n    and nnz/5 more space is recommended for run time efficiency.\n\n    This macro is not needed when using symamd.\n*/\n\n#define COLAMD_C(n_col) (((n_col) + 1) * sizeof (Colamd_Col) / sizeof (int))\n#define COLAMD_R(n_row) (((n_row) + 1) * sizeof (Colamd_Row) / sizeof (int))\n\n#define COLAMD_RECOMMENDED(nnz, n_row, n_col)                                 \\\n(                                                                             \\\n((nnz) < 0 || (n_row) < 0 || (n_col) < 0)                                     \\\n?                                                                             \\\n    (-1)                                                                      \\\n:                                                                             \\\n    (int) (2 * (nnz) + COLAMD_C (n_col) + COLAMD_R (n_row) + (n_col) + ((nnz) / 5)) \\\n)\n\n/* ========================================================================== */\n/* === Prototypes of user-callable routines ================================= */\n/* ========================================================================== */\n\n/*\n#ifdef __cplusplus\n  #define __EXTERN_C extern \"C\"\n#else\n  #define __EXTERN_C\n#endif\n*/\n\n#ifndef __BORLANDC__\n\n  #ifdef __cplusplus\n    #define __EXTERN_C extern \"C\"\n  #else\n    #define __EXTERN_C\n  #endif\n\n#else  /* Otherwise set up for the Borland compiler */\n\n  #define __EXTERN_C extern \"C\"\n\n#endif\n\n#ifdef __cplusplus\n__EXTERN_C {\n#endif\n\n\n\nint colamd_recommended\t\t/* returns recommended value of Alen, */\n\t\t\t\t/* or (-1) if input arguments are erroneous */\n(\n    int nnz,\t\t\t/* nonzeros in A */\n    int n_row,\t\t/* number of rows in A */\n    int n_col\t\t\t/* number of columns in A */\n) ;\n\nvoid colamd_set_defaults\t/* sets default parameters */\n(\t\t\t\t/* knobs argument is modified on output */\n    double knobs [COLAMD_KNOBS]\t/* parameter settings for colamd */\n) ;\n\nint colamd\t\t\t/* returns (1) if successful, (0) otherwise*/\n(\t\t\t\t/* A and p arguments are modified on output */\n    int n_row,\t\t/* number of rows in A */\n    int n_col,\t\t/* number of columns in A */\n    int Alen,\t\t\t/* size of the array A */\n    int A [],\t\t\t/* row indices of A, of size Alen */\n    int p [],\t\t\t/* column pointers of A, of size n_col+1 */\n    double knobs [COLAMD_KNOBS],/* parameter settings for colamd */\n    int stats [COLAMD_STATS]\t/* colamd output statistics and error codes */\n) ;\n\nint symamd\t\t\t\t/* return (1) if OK, (0) otherwise */\n(\n    int n,\t\t\t\t/* number of rows and columns of A */\n    int A [],\t\t\t/* row indices of A */\n    int p [],\t\t\t/* column pointers of A */\n    int perm [],\t/* output permutation, size n_col+1 */\n    double knobs [COLAMD_KNOBS],\t/* parameters (uses defaults if NULL) */\n    int stats [COLAMD_STATS],\t\t/* output statistics and error codes */\n    void * (*allocate) (size_t, size_t),\n    \t\t\t\t\t/* pointer to calloc (ANSI C) or */\n\t\t\t\t\t/* mxCalloc (for Matlab mexFunction) */\n    void (*release) (void *)\n    \t\t\t\t\t/* pointer to free (ANSI C) or */\n    \t\t\t\t\t/* mxFree (for Matlab mexFunction) */\n) ;\n\nvoid colamd_report\n(\n    int stats [COLAMD_STATS]\n) ;\n\nvoid symamd_report\n(\n    int stats [COLAMD_STATS]\n) ;\n\n#endif /* COLAMD_H */\n\n\n#ifdef __cplusplus\n}\n#endif\n\n"
  },
  {
    "path": "utilities/lp_solve/fortify.c",
    "content": "/*\n * FILE:\n *   fortify.c\n *\n * DESCRIPTION:\n *     A fortified shell for malloc, realloc, calloc, strdup, getcwd, tempnam\n *     and free.\n *     To use Fortify, each source file will need to #include \"fortify.h\".  To\n * enable  Fortify,  define the symbol FORTIFY.  If FORTIFY is not defined, it\n * will compile away to nothing.  If you do not have stderr available, you may\n * wish  to  set  an  alternate output function.  See _Fortify_SetOutputFunc(),\n * below.\n *     You will also need to link in fortify.o\n *\n *     None of the functions in this file should really be called\n *   directly; they really should be called through the macros\n *   defined in fortify.h\n *\n */\n\n#if defined FORTIFY\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/types.h>\n#include <stdlib.h>\n\n#if defined MSDOS || defined __BORLANDC__ || defined WIN32 || defined __HIGHC__\n# include <direct.h>\n#endif\n\nextern int EndOfPgr(int);\n\n#define __FORTIFY_C__ /* So fortify.h knows to not define the fortify macros */\n#include \"fortify.h\"\n\n#include \"ufortify.h\" /* the user's options */\n\nchar *_Fortify_file=NULL;\nint _Fortify_line=0;\n\n#ifndef FORTIFY_TRANSPARENT\n\n#include <string.h>\n#include <math.h>\n#include <time.h>\n#include <ctype.h>\n\n#if defined MSDOS || defined __BORLANDC__ || defined WIN32 || defined __HIGHC__\n# if !defined WIN32\n#  undef MSDOS\n#  define MSDOS\n# endif\n# include <conio.h>\n#else\n# include <unistd.h>\n# include <termio.h>\n# define getch() getchar()\n#endif\n\n#if defined _WINDOWS\n# include \"windows.h\"\n# if !defined WIN32\n#  include \"toolhelp.h\"\n# endif\n#endif\n\n#if defined LONGNAME\n# include \"longname.h\"\n#endif\n\n#if !defined MIN\n# define MIN(a, b) ((a) < (b) ? (a) : (b))\n#endif\n\nstruct Header\n{\n\tchar          *File;   /* The sourcefile of the caller   */\n\tunsigned short Line;   /* The sourceline of the caller   */\n\tsize_t         Size;   /* The size of the malloc'd block */\n\tstruct Header *Prev,   /* List pointers                  */\n\t\t      *Next;\n\tint            Checksum;  /* For validating the Header structure; see ChecksumHeader() */\n\tunsigned char  Scope;\n};\n\n#if defined AViiON || defined __GNUC__ || defined _MSC_VER\n# define _static static\n#else\n# define _static\n#endif\n\n_static char *address __OF((void *addr));\n_static int TimeToCheck __OF((void));\n_static int CheckBlock __OF((struct Header *h, const char *file, unsigned long line));\n_static int CheckPointer __OF((unsigned char *ptr, unsigned long size, const char *file, unsigned long line));\n_static int CheckFortification __OF((unsigned char *ptr, unsigned char value, size_t size));\n_static void SetFortification __OF((unsigned char *ptr, unsigned char value, size_t size));\n_static void OutputFortification __OF((unsigned char *ptr, unsigned char value, size_t size));\n_static int IsHeaderValid __OF((struct Header *h));\n_static void MakeHeaderValid __OF((struct Header *h));\n_static int ChecksumHeader __OF((struct Header *h));\n_static int IsOnList __OF((struct Header *h));\n_static void OutputHeader __OF((struct Header *h));\n_static void OutputMemory __OF((struct Header *h));\n_static void st_DefaultOutput __OF((char *String));\n_static void WaitIfstdOutput __OF((void));\n\nstatic char stdOutput = 0;        /* If true, did some stderr output */\nstatic OutputFuncPtr  st_Output = st_DefaultOutput; /* Output function for errors */\n\n#if !defined MSDOS && !defined WIN32\nstatic int strnicmp(s1,s2,maxlen)\n char *s1,*s2;\n size_t maxlen;\n {\n  while ((maxlen) && (*s1) && (*s2) && (toupper(*s1)==toupper(*s2))) {\n   maxlen--;\n   s1++;\n   s2++;\n  }\n  return((maxlen) ? toupper(*s1)-toupper(*s2) : 0);\n }\n\nstatic int stricmp(s1,s2)\n char *s1,*s2;\n {\n  return(strnicmp(s1,s2,strlen(s1)+1));\n }\n#endif\n\nstatic char *address(void *addr)\n{\n        static char str[80];\n\n#if defined KNOWS_POINTER_TYPE\n        sprintf(str,\"%p\",addr);\n#else\n        sprintf(str,\"%lx\",(unsigned long) addr);\n#endif\n        return(str);\n}\n\n#ifdef FORTIFY_CheckInterval\nint TimeToCheck()\n{\n        static time_t lastcheck=0L;\n\ttime_t t;\n        int ret = 0;\n\n\ttime(&t);\n\tif ((lastcheck==0L) || (t-lastcheck>=FORTIFY_CheckInterval))\n        {\n                lastcheck = t;\n                ret = 1;\n        }\n        return(ret);\n}\n#endif\n\nstatic FILE *gfile=NULL;\nstatic int Nchars=0,Nlines=0;\nstatic char flag=0;\n\nstatic void _Fortify_NoOutput()\n {\n }\n\nstatic void st_DefaultOutput(char *String)\n{\n        static FILE *file;\n        static char first=1;\n\n        if (first) {\n                file=stderr;\n                first=0;\n        }\n\n        if (stdOutput==0) {\n        \tNchars=Nlines=0;\n                if (gfile!=NULL) rewind(gfile);\n        }\n\n        if (flag==0)\n        {\n                char *ptr;\n\n        \tfile=stderr;\n                flag = 1;\n                if ((ptr=getenv(\"FORTIFY_OUTPUT\"))!=NULL)\n                {\n                        if ((stricmp(ptr,\"null\")==0) || (stricmp(ptr,\"nul\")==0))\n                                file=NULL;\n                        else if (stricmp(ptr,\"stderr\")==0)\n                                file=stderr;\n                        else if (stricmp(ptr,\"stdout\")==0)\n                                file=stdout;\n#if defined MSDOS && !defined _WINDOWS && !defined WIN32\n                        else if (stricmp(ptr,\"stdprn\")==0)\n                                file=stdprn;\n#endif\n                        else if ((file=fopen(ptr,\"w\"))==NULL)\n                        {\n#if !defined _WINDOWS\n                                fprintf(stderr,\"\\r\\nFortify: Unable to create logfile %s\\r\\n\",ptr);\n\t\t\t\tEndOfPgr(4);\n#else\n    \t\t\t\t{\n    \t\t\t\t\tchar str[255];\n\n    \t\t\t\t\tsprintf(str,\"Unable to create logfile\\n \\\"%s\\\"\",ptr);\n    \t\t\t\t\tMessageBox((HWND) NULL,(LPCSTR) str,(LPCSTR) \"Fortify\",(UINT) MB_ICONSTOP);\n#if 0\n#if defined WIN32\n\t\t\t\t        /* TerminateProcess(GetCurrentProcess(),65535); */\n                                        ExitProcess(65535);\n#else\n    \t\t\t\t\tTerminateApp((HTASK) NULL,(WORD) NO_UAE_BOX);\n#endif\n#else\n                                        EndOfPgr(1);\n#endif\n    \t\t\t\t}\n#endif\n                        }\n\t\t}\n\t\tif ((file!=NULL) && (file!=stderr) && (file!=stdout))\n\t\t{\n\t\t\ttime_t t;\n\n\t\t\ttime(&t);\n\t\t\tfprintf(file,\"Generated on: %s%s\\n\",\n                                ctime(&t),\n                                (file==stdout) || (file==stderr) ? \"\\r\" : \"\"\n                               );\n\t\t}\n\t}\n\tif (file!=NULL)\n\t{\n#if defined _WINDOWS\n                if ((file==stdout) || (file==stderr)) {\n#if defined LINE_BY_LINE\n                \tif (MessageBox((HWND) NULL,(LPCSTR) String,(LPCSTR) \"Fortify\",(UINT) MB_OKCANCEL /* |MB_ICONINFORMATION */)==IDCANCEL)\n#if 0\n#if defined WIN32\n                         /* TerminateProcess(GetCurrentProcess(),65535); */\n                         ExitProcess(65535);\n#else\n    \t\t\t TerminateApp((HTASK) NULL,(WORD) NO_UAE_BOX);\n#endif\n#else\n                         EndOfPgr(1);\n#endif\n#else\n\t\t\t{\n                        \tchar *ptr;\n\n                        \tptr=\"fortify.tmp\";\n\t\t\t\tif ((ptr==NULL) || ((file=gfile=fopen(ptr,\"w+\"))==NULL))\n                        \t{\n    \t\t\t\t\tchar str[255];\n\n    \t\t\t\t\tsprintf(str,\"Unable to create temporary file\\n \\\"%s\\\"\",(ptr==NULL) ? \"(NULL)\" : ptr);\n    \t\t\t\t\tMessageBox((HWND) NULL,(LPCSTR) str,(LPCSTR) \"Fortify\",(UINT) MB_ICONSTOP);\n#if 0\n#if defined WIN32\n                                        /* TerminateProcess(GetCurrentProcess(),65535); */\n                                        ExitProcess(65535);\n#else\n    \t\t\t\t\tTerminateApp((HTASK) NULL,(WORD) NO_UAE_BOX);\n#endif\n#else\n                                        EndOfPgr(1);\n#endif\n                        \t}\n                    \t}\n#endif\n                }\n                if ((file!=stdout) && (file!=stderr))\n#endif\n                        {\n                                int i,ch=-1;\n\n                        \tfor (i=0;(String[i]) && (Nlines<30);i++)\n                                 if (String[i]=='\\n') Nlines++;\n\t\t\t\tif ((String[i]) && (String[i+1])) {\n\t\t\t\t\tch=String[i+1];\n\t\t\t\t\tString[i+1]=0;\n\t\t\t\t}\n                                if ((file==stdout) || (file==stderr)) {\n                                 char *ptr=String;\n                                 int i;\n\n                                 do {\n                                  for (i=0;(ptr[i]) && (ptr[i]!='\\r') && (ptr[i]!='\\n');i++);\n                                  Nchars+=fprintf(file,\"%-*.*s%s\",\n                                                  i,i,\n                                                  ptr,\n                                                  (ptr[i]) ? \"\\r\\n\" : \"\"\n                                                 );\n                                  ptr+=i;\n                                  if (ptr[0]=='\\r') ptr++;\n                                  if (ptr[0]=='\\n') ptr++;\n                                 } while (*ptr);\n                                }\n                                else Nchars+=fprintf(file,String);\n\t\t\t\tif (ch>=0) String[i+1]=(char)ch;\n\t\t\t\tif (Nlines>=30) {\n                                \tWaitIfstdOutput();\n                                    \tNchars=Nlines=0;\n                                    \tstdOutput = 0;\n                                        if ((String[i]) && (String[i+1])) {\n                                                if ((file==stderr) || (file==stdout) || ((gfile!=NULL) && (Nchars)))\n                                                \tstdOutput = 1;\n                                         \tst_DefaultOutput(String+i);\n                                        }\n                                }\n                        }\n                if ((file==stderr) || (file==stdout) || ((gfile!=NULL) && (Nchars)))\n                \tstdOutput = 1;\n\t}\n}\n\nstatic void WaitIfstdOutput()\n{\n#if !defined _WINDOWS\n        if((stdOutput) && (st_Output != (OutputFuncPtr) _Fortify_NoOutput))\n        {\n#ifdef FORTIFY_WAIT_FOR_KEY\n                static signed char wait_on_key=-1;\n\n                if(wait_on_key<0)\n\t\t{\n\t\t\tchar *ptr;\n\n                        if (((ptr=getenv(\"FORTIFY_WAIT_FOR_KEY\"))!=NULL) &&\n\t\t\t    (tolower(*ptr)=='n')) wait_on_key = 0;\n                        else wait_on_key = 1;\n\n                }\n\t\tif(wait_on_key)\n\t\t{\n                        char c;\n\n#if !defined MSDOS && !defined WIN32\n                        struct termio tio,tiobak;\n                        char flag;\n\n                        if ((flag=ioctl(0,TCGETA,&tio))==0) /* handle 0 is stdin */\n                        {\n                                tiobak=tio;\n                        \ttio.c_lflag&=~ICANON;\n                                tio.c_lflag&=~ECHO;\n                        \ttio.c_cc[VMIN]=1;\n                        \tioctl(0,TCSETA,&tio);\n\t                }\n#endif /* !MSDOS */\n\t\t\tc = (char)getch();\n\n#if !defined MSDOS && !defined WIN32\n                        if (flag==0)\n                        \tioctl(0,TCSETA,&tiobak);\n#endif /* !MSDOS */\n\n\t\t\tif ((c == 3) || (c == 0x1b)) EndOfPgr(3);\n\t\t}\n#endif /* FORTIFY_WAIT_FOR_KEY */\n\n        }\n#else\n# if !defined LINE_BY_LINE\n        if ((stdOutput) && (gfile!=NULL) && (Nchars))\n        {\n                char *ptr;\n\n                ptr=(char *) malloc(Nchars+1);\n                if (ptr!=NULL)\n                {\n                        int n=0,l=0;\n\n                        rewind(gfile);\n                        while ((n<Nchars) && (l<Nlines))\n                        {\n                                fgets(ptr+n,Nchars-n+1,gfile);\n                                n+=(int)strlen(ptr+n);\n                                l++;\n                        }\n                \tif (MessageBox((HWND) NULL,(LPCSTR) ptr,(LPCSTR) \"Fortify\",(UINT) MB_OKCANCEL /* |MB_ICONINFORMATION */)==IDCANCEL)\n#if 0\n#if defined WIN32\n                         /* TerminateProcess(GetCurrentProcess(),65535); */\n                         ExitProcess(65535);\n#else\n    \t\t\t TerminateApp((HTASK) NULL,(WORD) NO_UAE_BOX);\n#endif\n#else\n                         EndOfPgr(1);\n#endif\n                }\n                free(ptr);\n        }\n# endif\n#endif\n\tstdOutput = 0;\n}\n\nstatic struct Header *st_Head = NULL; /* Head of alloc'd memory list */\nstatic char st_Buffer[256];       /* Temporary buffer for sprintf's */\nstatic int st_Disabled = 0;       /* If true, Fortify is inactive */\nstatic int st_MallocFailRate = 0; /* % of the time to fail mallocs */\n\nstatic char          *st_LastVerifiedFile = \"unknown\";\nstatic unsigned short st_LastVerifiedLine = 0;\nstatic unsigned char  st_Scope            = 0;\nstatic void           OutputLastVerifiedPoint __OF((void));\n\nvoid FORTIFY_STORAGE\n_Fortify_Init(char *file,unsigned long line)\n{\n\tif (gfile!=NULL) fclose(gfile);\n\tgfile=NULL;\n\tNchars=Nlines=0;\n        flag=0;\n        st_Head=NULL;\n        stdOutput=0;\n        st_Output=st_DefaultOutput;\n        st_Disabled=0;\n        st_MallocFailRate=0;\n        st_LastVerifiedFile=\"unknown\";\n        st_LastVerifiedLine=0;\n        st_Scope=0;\n}\n\n\n/*\n * _Fortify_malloc() - Allocates a block of memory, with extra bits for\n *                    misuse protection/detection.\n *\n *    Features:\n *     +  Adds the malloc'd memory onto Fortify's own private list.\n *        (With a checksum'd header to detect corruption of the memory list)\n *     +  Places sentinals on either side of the user's memory with\n *        known data in them, to detect use outside of the bounds\n *        of the block\n *     +  Initializes the malloc'd memory to some \"nasty\" value, so code\n *        can't rely on it's contents.\n *     +  Can check all sentinals on every malloc.\n *     +  Can generate a warning message on a malloc fail.\n *     +  Can randomly \"fail\" at a set fail rate\n */\nvoid *FORTIFY_STORAGE\n_Fortify_malloc(size_t size,char *file,unsigned long line)\n{\n\tunsigned char *ptr;\n\tstruct Header *h;\n\n        stdOutput = 0;\n\n\tFORTIFY_LOCK();\n\n\tif(st_Disabled)\n\t{\n\t\tptr = (unsigned char *) malloc(size);\n\t\tFORTIFY_UNLOCK();\n                WaitIfstdOutput();\n\t\treturn((void *) ptr);\n\t}\n\n#ifdef CHECK_ALL_MEMORY_ON_MALLOC\n#ifdef FORTIFY_CheckInterval\n        if (TimeToCheck())\n#endif\n\t\t_Fortify_CheckAllMemory(file, line);\n#endif\n\n\tif(size == 0)\n\t{\n#ifdef WARN_ON_ZERO_MALLOC\n    \tsprintf(st_Buffer,\n        \t    \"\\nFortify: %s.%ld\\n         malloc(0) attempted failed\\n\",\n            \tfile, line);\n\t\tst_Output(st_Buffer);\n#endif\n\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\tif(st_MallocFailRate > 0)\n\t{\n\t\tif(rand() % 100 < st_MallocFailRate)\n\t\t{\n#ifdef WARN_ON_FALSE_FAIL\n\t\t\tsprintf(st_Buffer,\n\t\t\t\t\t\"\\nFortify: %s.%ld\\n         malloc(%ld) \\\"false\\\" failed\\n\",\n\t\t\t\t\t\t\tfile, line, (unsigned long)size);\n\t\t\tst_Output(st_Buffer);\n#endif\n\t\t\tFORTIFY_UNLOCK();\n                        WaitIfstdOutput();\n                        return(0);\n\t\t}\n\t}\n\n\t/*\n\t * malloc the memory, including the space for the header and fortification\n\t * buffers\n\t */\n#ifdef WARN_ON_SIZE_T_OVERFLOW\n\t{\n\t\tsize_t private_size = sizeof(struct Header)\n\t\t\t\t\t\t\t+ FORTIFY_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE;\n\n\t\tif(private_size < size) /* Check to see if the added baggage is larger than size_t */\n\t\t{\n\t\t\tsprintf(st_Buffer,\n\t\t\t\t\t\"\\nFortify: %s.%ld\\n         malloc(%ld) has overflowed size_t.\\n\",\n\t\t\t\t\tfile, line, (unsigned long)size);\n\t\t\tst_Output(st_Buffer);\n\t\t\tFORTIFY_UNLOCK();\n\t\t\tWaitIfstdOutput();\n\t\t\treturn(0);\n\t\t}\n\t}\n#endif\n\n\tptr = (unsigned char *) malloc(sizeof(struct Header) +\n\t\t\t\t FORTIFY_BEFORE_SIZE + size + FORTIFY_AFTER_SIZE);\n\tif(!ptr)\n\t{\n#ifdef WARN_ON_MALLOC_FAIL\n\t\tsprintf(st_Buffer, \"\\nFortify: %s.%ld\\n         malloc(%ld) failed\\n\",\n\t\t\t\tfile, line, (unsigned long)size);\n\t\tst_Output(st_Buffer);\n#endif\n\n\t\tFORTIFY_UNLOCK();\n                WaitIfstdOutput();\n                return(0);\n\t}\n\n\t/*\n\t * Initialize and validate the header\n\t */\n\th = (struct Header *)ptr;\n\n\th->Size = size;\n\n\th->File = file;\n\th->Line = (unsigned short) line;\n\n\th->Next = st_Head;\n\th->Prev = 0;\n\n\th->Scope = st_Scope;\n\n\tif(st_Head)\n\t{\n\t\tst_Head->Prev = h;\n\t\tMakeHeaderValid(st_Head);\n\t}\n\n\tst_Head = h;\n\n\tMakeHeaderValid(h);\n\n\n\t/*\n\t * Initialize the fortifications\n\t */\n\tSetFortification(ptr + sizeof(struct Header),\n\t                 FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE);\n\tSetFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + size,\n\t                 FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);\n\n#ifdef FILL_ON_MALLOC\n\t/*\n\t * Fill the actual user memory\n\t */\n\tSetFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE,\n\t                 FILL_ON_MALLOC_VALUE, size);\n#endif\n\n\t/*\n\t * We return the address of the user's memory, not the start of the block,\n\t * which points to our magic cookies\n\t */\n\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n\treturn((void *) (ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE));\n}\n\n/*\n * _Fortify_free() - This free must be used for all memory allocated with\n *                  _Fortify_malloc().\n *\n *   Features:\n *     + Pointers are validated before attempting a free - the pointer\n *       must point to a valid malloc'd bit of memory.\n *     + Detects attempts at freeing the same block of memory twice\n *     + Can clear out memory as it is free'd, to prevent code from using\n *       the memory after it's been freed.\n *     + Checks the sentinals of the memory being freed.\n *     + Can check the sentinals of all memory.\n */\n\nvoid FORTIFY_STORAGE\n_Fortify_free(void *uptr,char *file,unsigned long line)\n{\n\tunsigned char *ptr;\n\tstruct Header *h;\n\n\tif(uptr == NULL)\n\t\treturn;\n\n\tptr = (unsigned char *)uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE;\n\th = (struct Header *)ptr;\n\n\tstdOutput = 0;\n\n\tFORTIFY_LOCK();\n\n\tif(st_Disabled)\n\t{\n\t\tfree(uptr);\n\t\tFORTIFY_UNLOCK();\n                WaitIfstdOutput();\n                return;\n\t}\n\n#ifdef CHECK_ALL_MEMORY_ON_FREE\n#ifdef FORTIFY_CheckInterval\n        if (TimeToCheck())\n#endif\n\t\t_Fortify_CheckAllMemory(file, line);\n#endif\n\n#ifdef PARANOID_FREE\n\tif(!IsOnList(h))\n\t{\n\t\tsprintf(st_Buffer,\n\t\t \"\\nFortify: %s.%ld\\n         Invalid pointer, corrupted header, or possible free twice\\n\",\n\t\t\t\tfile, line);\n\t\tst_Output(st_Buffer);\n\t\tOutputLastVerifiedPoint();\n\t\tgoto fail;\n\t}\n#endif\n\n\tif(!CheckBlock(h, file, line))\n\t\tgoto fail;\n\n\t/*\n\t * Remove the block from the list\n\t */\n\tif(h->Prev)\n\t{\n\t\tif(!CheckBlock(h->Prev, file, line))\n\t\t\tgoto fail;\n\n\t\th->Prev->Next = h->Next;\n\t\tMakeHeaderValid(h->Prev);\n\t}\n\telse\n\t\tst_Head = h->Next;\n\n\tif(h->Next)\n\t{\n\t\tif(!CheckBlock(h->Next, file, line))\n\t\t\tgoto fail;\n\n\t\th->Next->Prev = h->Prev;\n\t\tMakeHeaderValid(h->Next);\n\t}\n\n#ifdef FILL_ON_FREE\n\t/*\n\t * Nuke out all memory that is about to be freed\n\t */\n\tSetFortification(ptr, FILL_ON_FREE_VALUE,\n\t                 sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size + FORTIFY_AFTER_SIZE);\n#endif\n\n\t/*\n\t * And do the actual free\n\t */\n\tfree(ptr);\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n        return;\n\nfail:\n\tsprintf(st_Buffer, \"         free(%s) failed\\n\", address(uptr));\n\tst_Output(st_Buffer);\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n}\n\n/*\n * _Fortify_realloc() - Uses _Fortify_malloc() and _Fortify_free() to implement\n *                     realloc().\n *\n *   Features:\n *        + The realloc'd block is ALWAYS moved.\n *        + The pointer passed to realloc() is verified in the same way that\n *          _Fortify_free() verifies pointers before it frees them.\n *        + All the _Fortify_malloc() and _Fortify_free() protection\n */\nvoid *FORTIFY_STORAGE\n_Fortify_realloc(void *ptr,size_t new_size,char *file,unsigned long line)\n{\n\tvoid *new_ptr;\n\tstruct Header *h;\n\n\tif(new_size == 0)\n\t{\n\t\t_Fortify_free(ptr,file,line);\n\t\treturn(NULL);\n\t}\n\n\th = (struct Header *)((unsigned char *)ptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE);\n\n        stdOutput = 0;\n\n\tif(st_Disabled)\n\t{\n\t\tFORTIFY_LOCK();\n\t\tnew_ptr = (void *) realloc(ptr, new_size);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n                return(new_ptr);\n\t}\n\n\tif(!ptr)\n        {\n\t\tvoid *FORTIFY_STORAGE ret = _Fortify_malloc(new_size, file, line);\n\n                WaitIfstdOutput();\n\t\treturn(ret);\n        }\n\n\tFORTIFY_LOCK();\n\n\tif(!IsOnList(h))\n\t{\n\t\tsprintf(st_Buffer,\n\t\t\t\t\"\\nFortify: %s.%ld\\n         Invalid pointer or corrupted header passed to realloc\\n\",\n\t\t\t\tfile, line);\n\t\tst_Output(st_Buffer);\n\t\tgoto fail;\n\t}\n\n\tif(!CheckBlock(h, file, line))\n\t\tgoto fail;\n\n\tnew_ptr = _Fortify_malloc(new_size, file, line);\n\tif(!new_ptr)\n\t{\n\t\tFORTIFY_UNLOCK();\n                WaitIfstdOutput();\n                return(0);\n\t}\n\n\tif(h->Size < new_size)\n\t\tmemcpy(new_ptr, ptr, h->Size);\n\telse\n\t\tmemcpy(new_ptr, ptr, new_size);\n\n\t_Fortify_free(ptr, file, line);\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n        return(new_ptr);\n\nfail:\n\tsprintf(st_Buffer, \"         realloc(%s, %ld) failed\\n\", address(ptr), (unsigned long)new_size);\n\tst_Output(st_Buffer);\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n        return(NULL);\n}\n\n\n/*\n * __Fortify_CheckPointer() - Returns true if the uptr points to a valid\n *   piece of _Fortify_malloc()'d memory. The memory must be on the malloc'd\n *   list, and it's sentinals must be in tact.\n *     If anything is wrong, an error message is issued.\n *\n *   (Note - if fortify is disabled, this function always returns true).\n */\nstatic int FORTIFY_STORAGE\n__Fortify_CheckPointer(void *uptr,char OnlyStart,unsigned long size,char *file,unsigned long line)\n{\n\tunsigned char *ptr = (unsigned char *)uptr - sizeof(struct Header) - FORTIFY_BEFORE_SIZE;\n\tint r = 1, StartPointer;\n\n        stdOutput = 0;\n\n\tif(st_Disabled)\n        {\n                WaitIfstdOutput();\n\t\treturn(1);\n        }\n\n\tFORTIFY_LOCK();\n\n\tStartPointer = IsOnList((struct Header *)ptr);\n\tif((OnlyStart) && (!StartPointer))\n\t{\n\t\tsprintf(st_Buffer,\n\t\t       \"\\nFortify: %s.%ld\\n         Invalid pointer or corrupted header detected (%s)\\n\",\n\t\t       file, line, address(uptr));\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n                WaitIfstdOutput();\n                return(0);\n\t}\n\n\tif((OnlyStart) || (StartPointer))\n\t\tr = CheckBlock((struct Header *)ptr, file, line);\n\tif(!OnlyStart)\n\t\tr = CheckPointer((unsigned char *)uptr, size, file, line);\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n        return(r);\n}\n\n\nint FORTIFY_STORAGE\n_Fortify_CheckPointer(void *uptr,char *file,unsigned long line)\n{\n\treturn(__Fortify_CheckPointer(uptr,1,0,file,line));\n}\n\n/*\n * Fortify_SetOutputFunc(OutputFuncPtr Output) - Sets the function used to\n *   output all error and diagnostic messages by fortify. The output function\n *   takes a single unsigned char * argument, and must be able to handle newlines.\n *     The function returns the old pointer.\n */\nFortify_OutputFuncPtr FORTIFY_STORAGE\n_Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output)\n{\n\tOutputFuncPtr Old = st_Output;\n\n\tst_Output = (OutputFuncPtr) Output;\n\n\treturn((Fortify_OutputFuncPtr FORTIFY_STORAGE) Old);\n}\n\n/*\n * _Fortify_SetMallocFailRate(int Percent) - _Fortify_malloc() will make the\n *   malloc attempt fail this Percent of the time, even if the memory is\n *   available. Useful to \"stress-test\" an application. Returns the old\n *   value. The fail rate defaults to 0.\n */\nint FORTIFY_STORAGE\n_Fortify_SetMallocFailRate(int Percent)\n{\n\tint Old = st_MallocFailRate;\n\n\tst_MallocFailRate = Percent;\n\n\treturn(Old);\n}\n\n\n/*\n * _Fortify_CheckAllMemory() - Checks the sentinals of all malloc'd memory.\n *   Returns the number of blocks that failed.\n *\n *  (If Fortify is disabled, this function always returns 0).\n */\nint FORTIFY_STORAGE\n_Fortify_CheckAllMemory(char *file,unsigned long line)\n{\n\tstruct Header *curr = st_Head;\n\tint count = 0;\n\n\tstdOutput = 0;\n\n\tif(st_Disabled)\n\t{\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\tFORTIFY_LOCK();\n\n\twhile(curr)\n\t{\n\t\tif(!CheckBlock(curr, file, line))\n\t\t\tcount++;\n\n\t\tcurr = curr->Next;\n\t}\n\n\tif(file)\n\t{\n\t\tst_LastVerifiedFile = file;\n\t\tst_LastVerifiedLine = (short) line;\n\t}\n\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n        return(count);\n}\n\n/* _Fortify_EnterScope - enters a new Fortify scope level.\n * returns the new scope level.\n */\nint FORTIFY_STORAGE\n_Fortify_EnterScope(char *file,unsigned long line)\n{\n\treturn((int) ++st_Scope);\n}\n\n/* _Fortify_LeaveScope - leaves a Fortify scope level,\n * also prints a memory dump of all non-freed memory that was allocated\n * during the scope being exited.\n */\nint FORTIFY_STORAGE\n_Fortify_LeaveScope(char *file,unsigned long line)\n{\n\tstruct Header *curr = st_Head;\n\tint count = 0;\n\tsize_t size = 0;\n\n        stdOutput = 0;\n\n\tif(st_Disabled)\n        {\n                WaitIfstdOutput();\n                return(0);\n        }\n\n\tFORTIFY_LOCK();\n\n\tst_Scope--;\n\twhile(curr)\n\t{\n\t\tif(curr->Scope > st_Scope)\n\t\t{\n\t\t\tif(count == 0)\n\t\t\t{\n\t\t\t\tsprintf(st_Buffer, \"\\nFortify: Memory Dump at %s.%ld\\n\", file, line);\n\t\t\t\tst_Output(st_Buffer);\n\t\t\t\tOutputLastVerifiedPoint();\n\t\t\t\tsprintf(st_Buffer, \"%11s %8s %s\\n\", \"Address\", \"Size\", \"Allocator\");\n\t\t\t\tst_Output(st_Buffer);\n\t\t\t}\n\n\t\t\tOutputHeader(curr);\n\t\t\tcount++;\n\t\t\tsize += curr->Size;\n\t\t}\n\n\t\tcurr = curr->Next;\n\t}\n\n\tif(count)\n\t{\n\t\tsprintf(st_Buffer, \"%11s %8ld bytes overhead\\n\", \"and\",\n\t\t\t\t\t\t(unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE)));\n\t\t\t\t\t\tst_Output(st_Buffer);\n\n\t\tsprintf(st_Buffer,\"%11s %8ld bytes in %d blocks\\n\", \"total\", size, count);\n\t\tst_Output(st_Buffer);\n\t}\n\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n        return(count);\n}\n\n/*\n * _Fortify_OutputAllMemory() - Outputs the entire list of currently\n *     malloc'd memory. For each malloc'd block is output it's Address,\n *   Size, and the SourceFile and Line that allocated it.\n *\n *   If there is no memory on the list, this function outputs nothing.\n *\n *   It returns the number of blocks on the list, unless fortify has been\n *   disabled, in which case it always returns 0.\n */\nint FORTIFY_STORAGE\n_Fortify_OutputAllMemory(char *file,unsigned long line)\n{\n\tstruct Header *curr = st_Head;\n\tint count = 0;\n\tsize_t size = 0;\n\n        stdOutput = 0;\n\n\tif(st_Disabled)\n        {\n                WaitIfstdOutput();\n                return(0);\n        }\n\n\tFORTIFY_LOCK();\n\n\tif(curr)\n\t{\n\t\tsprintf(st_Buffer, \"\\nFortify: Memory Dump at %s.%ld\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tOutputLastVerifiedPoint();\n\t\tsprintf(st_Buffer, \"%11s %8s %s\\n\", \"Address\", \"Size\", \"Allocator\");\n\t\tst_Output(st_Buffer);\n\n\t\twhile(curr)\n\t\t{\n\t\t\tOutputHeader(curr);\n\t\t\tcount++;\n\t\t\tsize += curr->Size;\n\t\t\tcurr = curr->Next;\n\t\t}\n\n\t\tsprintf(st_Buffer, \"%11s %8ld bytes overhead\\n\", \"and\",\n\t\t\t\t(unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE)));\n\t\tst_Output(st_Buffer);\n\n\t\tsprintf(st_Buffer,\"%11s %8ld bytes in %d blocks\\n\", \"total\", size, count);\n\t\tst_Output(st_Buffer);\n\t}\n\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n\treturn(count);\n}\n\n/* _Fortify_DumpAllMemory(Scope) - Outputs the entire list of currently\n * new'd memory within the specified scope. For each new'd block is output\n * it's Address, Size, the SourceFile and Line that allocated it, a hex dump\n * of the contents of the memory and an ascii dump of printable characters.\n *\n * If there is no memory on the list, this function outputs nothing.\n *\n * It returns the number of blocks on the list, unless Fortify has been\n * disabled, in which case it always returns 0.\n */\nint FORTIFY_STORAGE\n_Fortify_DumpAllMemory(int scope,char *file,unsigned long line)\n{\n\tstruct Header *curr = st_Head;\n\tint count = 0;\n\tsize_t size = 0;\n\n        stdOutput = 0;\n\n\tif(st_Disabled)\n        {\n                WaitIfstdOutput();\n\t\treturn(0);\n        }\n\n\tFORTIFY_LOCK();\n\n\twhile(curr)\n\t{\n\t\tif(curr->Scope >= scope)\n\t\t{\n\t\t\tif(count == 0)\n\t\t\t{\n\t\t\t\tsprintf(st_Buffer, \"\\nFortify: Memory Dump at %s.%ld\\n\", file, line);\n\t\t\t\tst_Output(st_Buffer);\n\t\t\t\tOutputLastVerifiedPoint();\n\t\t\t\tsprintf(st_Buffer, \"%11s %8s %s\\n\", \"Address\", \"Size\", \"Allocator\");\n\t\t\t\tst_Output(st_Buffer);\n\t\t\t}\n\n\t\t\tOutputHeader(curr);\n\t\t\tOutputMemory(curr);\n\t\t\tst_Output(\"\\n\");\n\t\t\tcount++;\n\t\t\tsize += curr->Size;\n\t\t}\n\n\t\tcurr = curr->Next;\n\t}\n\n\tif(count)\n\t{\n\t\tsprintf(st_Buffer, \"%11s %8ld bytes overhead\\n\", \"and\",\n\t\t\t\t\t\t(unsigned long)(count * (sizeof(struct Header) + FORTIFY_BEFORE_SIZE + FORTIFY_AFTER_SIZE)));\n\t\t\t\t\t\tst_Output(st_Buffer);\n\n\t\tsprintf(st_Buffer,\"%11s %8ld bytes in %d blocks\\n\", \"total\", size, count);\n\t\tst_Output(st_Buffer);\n\t}\n\n\tFORTIFY_UNLOCK();\n        WaitIfstdOutput();\n        return(count);\n}\n\n/*\n * _Fortify_Disable() - This function provides a mechanism to disable Fortify\n *   without recompiling all the sourcecode.\n *   If 'how' is zero then it can only be called when there is no memory on the\n *   Fortify malloc'd list. (Ideally, at the start of the program before any\n *   memory has been allocated). If you call this function when there IS\n *   memory on the Fortify malloc'd list, it will issue an error, and fortify\n *   will not be disabled.\n *   If 'how' is nonzero then output will only be disabled. This can always be\n *   done.\n */\n\nint FORTIFY_STORAGE\n_Fortify_Disable(char *file,unsigned long line,int how)\n{\n\tint result;\n\n        if (how <= 0)\n        {\n    \t    stdOutput = 0;\n\n    \t    FORTIFY_LOCK();\n\n    \t    if((st_Head) && (how == 0))\n    \t    {\n    \t\t    sprintf(st_Buffer, \"Fortify: %s.%d\\n\", file, line);\n    \t\t    st_Output(st_Buffer);\n    \t\t    st_Output(\"         Fortify_Disable failed\\n\");\n    \t\t    st_Output(\"         (because there is memory on the Fortify memory list)\\n\");\n\n    \t\t    _Fortify_OutputAllMemory(file, line);\n    \t\t    result = 0;\n    \t    }\n    \t    else\n    \t    {\n    \t\t    st_Disabled = (how >= -1 ? 1 : 0);\n    \t\t    result = 1;\n    \t    }\n\n    \t    FORTIFY_UNLOCK();\n            WaitIfstdOutput();\n        }\n        else\n        {\n            _Fortify_SetOutputFunc((Fortify_OutputFuncPtr) _Fortify_NoOutput);\n            result = 1;\n        }\n\treturn(result);\n}\n\n/*\n * Check a block's header and fortifications.\n */\nstatic int CheckBlock(struct Header *h,char *file,unsigned long line)\n{\n\tunsigned char *ptr = (unsigned char *)h;\n\tint result = 1;\n\n        stdOutput = 0;\n\n\tif(!IsHeaderValid(h))\n\t{\n\t\tsprintf(st_Buffer,\n\t\t\t\t\"\\nFortify: %s.%ld\\n         Invalid pointer or corrupted header detected (%s)\\n\",\n\t\t\t\tfile, line, address(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE));\n\t\tst_Output(st_Buffer);\n\t\tOutputLastVerifiedPoint();\n                WaitIfstdOutput();\n                return(0);\n\t}\n\n\tif(!CheckFortification(ptr + sizeof(struct Header),\n\t\t                   FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE))\n\t{\n\t\tsprintf(st_Buffer,\n\t\t        \"\\nFortify: %s.%ld\\n         Memory overrun detected before block\\n\",\n\t\t        file, line);\n\t\tst_Output(st_Buffer);\n\n\t\tsprintf(st_Buffer,\"         (%s,%ld,%s.%u)\\n\",\n\t\t\taddress(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE),\n\t\t       (unsigned long)h->Size, h->File, h->Line);\n\t\tst_Output(st_Buffer);\n\n\t\tOutputFortification(ptr + sizeof(struct Header),\n\t\t                    FORTIFY_BEFORE_VALUE, FORTIFY_BEFORE_SIZE);\n\t\tOutputLastVerifiedPoint();\n\t\tresult = 0;\n\t}\n\n\tif(!CheckFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size,\n\t                       FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE))\n\t{\n\t\tsprintf(st_Buffer, \"\\nFortify: %s.%ld\\n         Memory overrun detected after block\\n\",\n\t\t                   file, line);\n\t\tst_Output(st_Buffer);\n\n\t\tsprintf(st_Buffer,\"         (%s,%ld,%s.%u)\\n\",\n\t\t\t\t  address(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE),\n\t\t\t\t (unsigned long)h->Size, h->File, h->Line);\n\t\tst_Output(st_Buffer);\n\n\t\tOutputFortification(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE + h->Size,\n\t\t                    FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);\n\t\tOutputLastVerifiedPoint();\n\t\tresult = 0;\n\t}\n\n        WaitIfstdOutput();\n\treturn(result);\n}\n\nstatic int CheckPointer(unsigned char *ptr,unsigned long size,char *file,unsigned long line)\n{\n\tstruct Header *curr;\n\tunsigned char *ptr1;\n\n\tcurr = st_Head;\n\twhile(curr)\n\t{\n\t\tptr1 = (unsigned char *)curr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE;\n\t\tif(ptr + size <= (unsigned char *)curr)\n\t\t\t;\n\t\telse if(ptr >= ptr1)\n\t\t\t;\n\t\telse\n\t\t{\n\t\t\tsprintf(st_Buffer, \"\\nFortify: %s.%ld\\n         Memory access detected before block\\n\",\n\t\t                file, line);\n\t\t\tst_Output(st_Buffer);\n\n\t\t\tsprintf(st_Buffer,\"         (%s,%ld,%s.%u)\\n\",\n\t\t\t\t\taddress(ptr1),\n\t\t\t\t\t(unsigned long)curr->Size, curr->File, curr->Line);\n\t\t\tst_Output(st_Buffer);\n\n\t\t\tWaitIfstdOutput();\n\t\t\treturn(0);\n\t\t}\n\n\t\tif(ptr + size <= ptr1 + curr->Size)\n\t\t\t;\n\t\telse if(ptr >= ptr1 + curr->Size + FORTIFY_AFTER_SIZE)\n\t\t\t;\n\t\telse\n\t\t{\n\t\t\tsprintf(st_Buffer, \"\\nFortify: %s.%ld\\n         Memory access detected after block\\n\",\n\t\t                file, line);\n\t\t\tst_Output(st_Buffer);\n\n\t\t\tsprintf(st_Buffer,\"         (%s,%ld,%s.%u)\\n\",\n\t\t\t\t\taddress(ptr1),\n\t\t\t\t\t(unsigned long)curr->Size, curr->File, curr->Line);\n\t\t\tst_Output(st_Buffer);\n\n\t\t\tWaitIfstdOutput();\n\t\t\treturn(0);\n\t\t}\n\n\t\tif((ptr >= ptr1) && (ptr < ptr1 + curr->Size) && (ptr + size > ptr1 + curr->Size))\n\t\t{\n\t\t\tsprintf(st_Buffer, \"\\nFortify: %s.%ld\\n         Memory access detected after block\\n\",\n\t\t                file, line);\n\t\t\tst_Output(st_Buffer);\n\n\t\t\tsprintf(st_Buffer,\"         (%s,%ld,%s.%u)\\n\",\n\t\t\t\t\taddress(ptr + sizeof(struct Header) + FORTIFY_BEFORE_SIZE),\n\t\t\t\t\t(unsigned long)curr->Size, curr->File, curr->Line);\n\t\t\tst_Output(st_Buffer);\n\t\t\tWaitIfstdOutput();\n\t\t\treturn(0);\n\t\t}\n\n\t\tcurr = curr->Next;\n\t}\n\treturn(1);\n}\n\n/*\n * Checks if the _size_ bytes from _ptr_ are all set to _value_\n */\nstatic int CheckFortification(unsigned char *ptr,unsigned char value,size_t size)\n{\n\twhile(size--)\n\t\tif(*ptr++ != value)\n\t\t\treturn(0);\n\n\treturn(1);\n}\n\n/*\n * Set the _size_ bytes from _ptr_ to _value_.\n */\nstatic void SetFortification(unsigned char *ptr,unsigned char value,size_t size)\n{\n\tmemset(ptr, value, size);\n}\n\n/*\n * Output the corrupted section of the fortification\n */\n/* Output the corrupted section of the fortification */\nstatic void\nOutputFortification(unsigned char *ptr,unsigned char value,size_t size)\n{\n\tunsigned long offset, column;\n\tchar\tascii[17];\n\n\tst_Output(\"Address     Offset Data\");\n\n\toffset = 0;\n\tcolumn = 0;\n\n\twhile(offset < size)\n\t{\n\t\tif(column == 0)\n\t\t{\n\t\t\tsprintf(st_Buffer, \"\\n%8s %8d \", address(ptr), offset);\n\t\t\tst_Output(st_Buffer);\n\t\t}\n\n\t\tsprintf(st_Buffer, \"%02x \", *ptr);\n\t\tst_Output(st_Buffer);\n\n\t\tascii[ (int) column ] = isprint( *ptr ) ? (char)(*ptr) : (char)(' ');\n\t\tascii[ (int) (column + 1) ] = '\\0';\n\n\t\tptr++;\n\t\toffset++;\n\t\tcolumn++;\n\n\t\tif(column == 16)\n\t\t{\n\t\t\tst_Output( \"   \\\"\" );\n\t\t\tst_Output( ascii );\n\t\t\tst_Output( \"\\\"\" );\n\t\t\tcolumn = 0;\n\t\t}\n\t}\n\n\tif ( column != 0 )\n\t{\n\t\twhile ( column ++ < 16 )\n\t\t{\n\t\t\tst_Output( \"   \" );\n\t\t}\n\t\tst_Output( \"   \\\"\" );\n\t\tst_Output( ascii );\n\t\tst_Output( \"\\\"\" );\n\t}\n\n\tst_Output(\"\\n\");\n}\n\n/*\n * Returns true if the supplied pointer does indeed point to a real Header\n */\nstatic int IsHeaderValid(struct Header *h)\n{\n\treturn(!ChecksumHeader(h));\n}\n\n/*\n * Updates the checksum to make the header valid\n */\nstatic void MakeHeaderValid(struct Header *h)\n{\n\th->Checksum = 0;\n\th->Checksum = -ChecksumHeader(h);\n}\n\n/*\n * Calculate (and return) the checksum of the header. (Including the Checksum\n * variable itself. If all is well, the checksum returned by this function should\n * be 0.\n */\nstatic int ChecksumHeader(struct Header *h)\n{\n\tint c, checksum, *p;\n\n\tfor(c = 0, checksum = 0, p = (int *)h; c < sizeof(struct Header)/sizeof(int); c++)\n\t\tchecksum += *p++;\n\n\treturn(checksum);\n}\n\n/*\n * Examines the malloc'd list to see if the given header is on it.\n */\nstatic int IsOnList(struct Header *h)\n{\n\tstruct Header *curr;\n\n\tcurr = st_Head;\n\twhile(curr)\n\t{\n\t\tif(curr == h)\n\t\t\treturn(1);\n\t\tcurr = curr->Next;\n\t}\n\n\treturn(0);\n}\n\n\n/*\n * Hex and ascii dump the memory\n */\nstatic void\nOutputMemory(struct Header *h)\n{\n\tOutputFortification((unsigned char*)h + sizeof(struct Header) + FORTIFY_BEFORE_SIZE,\n\t\t\t\t\t\t0, h->Size);\n}\n\n\n/*\n * Output the header...\n */\nstatic void OutputHeader(struct Header *h)\n{\n\tsprintf(st_Buffer, \"%11s %8ld %s.%u (%d)\\n\",\n\t\t\t   address((unsigned char*)h + sizeof(struct Header) + FORTIFY_BEFORE_SIZE),\n\t\t\t   (unsigned long)h->Size,\n\t\t\t   h->File, h->Line, (int) h->Scope);\n\tst_Output(st_Buffer);\n}\n\nstatic void OutputLastVerifiedPoint()\n{\n\tsprintf(st_Buffer, \"\\nLast Verified point: %s.%u\\n\",\n\t\t\t   st_LastVerifiedFile,\n\t\t\t   st_LastVerifiedLine);\n\tst_Output(st_Buffer);\n}\n\n#else  /* FORTIFY_TRANSPARENT */\n\nvoid *FORTIFY_STORAGE\n_Fortify_malloc(size,file,line)\n size_t size;\n char *file;\n unsigned long line;\n{\n\treturn(malloc(size));\n}\n\nvoid FORTIFY_STORAGE\n_Fortify_free(uptr,file,line)\n void *uptr;\n char *file;\n unsigned long line;\n{\n\tfree(uptr);\n}\n\nvoid *FORTIFY_STORAGE\n_Fortify_realloc(ptr,new_size,file,line)\n void *ptr;\n size_t new_size;\n char *file;\n unsigned long line;\n{\n\treturn(realloc(ptr, new_size));\n}\n\nint FORTIFY_STORAGE\n_Fortify_CheckPointer(uptr,file,line)\n void *uptr;\n char *file;\n unsigned long line;\n{\n\treturn(1);\n}\n\nFortify_OutputFuncPtr FORTIFY_STORAGE\n_Fortify_SetOutputFunc(Output)\n Fortify_OutputFuncPtr Output;\n{\n\treturn(0);\n}\n\nint FORTIFY_STORAGE\n_Fortify_SetMallocFailRate(Percent)\n int Percent;\n{\n\treturn(0);\n}\n\nint FORTIFY_STORAGE\n_Fortify_CheckAllMemory(file,line)\n char *file;\n unsigned long line;\n{\n\treturn(0);\n}\n\nint FORTIFY_STORAGE\n_Fortify_EnterScope(file,line)\n char *file;\n unsigned long line;\n{\n\treturn(0);\n}\n\nint FORTIFY_STORAGE\n_Fortify_LeaveScope(file,line)\n char *file;\n unsigned long line;\n{\n\treturn(0);\n}\n\nint FORTIFY_STORAGE\n_Fortify_OutputAllMemory(file,line)\n char *file;\n unsigned long line;\n{\n\treturn(0);\n}\n\nint FORTIFY_STORAGE\n_Fortify_DumpAllMemory(scope,file,line)\n int scope;\n char *file;\n unsigned long line;\n{\n\treturn(0);\n}\n\nint FORTIFY_STORAGE\n_Fortify_Disable(file,line)\n char *file;\n unsigned long line;\n{\n\treturn(1);\n}\n\n#endif /* !FORTIFY_TRANSPARENT */\n\n/* function that use _Fortify_malloc(), _Fortify_realloc(), _Fortify_free() */\n\n/*\n * Fortifty_calloc() - Uses _Fortify_malloc() to implement calloc(). Much\n *                     the same protection as _Fortify_malloc().\n */\nvoid *FORTIFY_STORAGE\n_Fortify_calloc(size_t nitems,size_t size,char *file,unsigned long line)\n{\n\tvoid *ptr;\n\n\tptr = _Fortify_malloc(nitems * size, file, line);\n\n\tif(ptr)\n\t\tmemset(ptr, 0, nitems * size);\n\n\treturn(ptr);\n}\n\n/*\n * Fortifty_strdup() - Uses _Fortify_malloc() to implement strdup(). Much\n *                     the same protection as _Fortify_malloc().\n * The library function is not used because it is not certain that getpwd\n * uses the library malloc function (if linked with an alternate library)\n * and if the memory is freed then strange things can happen\n */\nchar *FORTIFY_STORAGE\n_Fortify_strdup(char *str,char *file,unsigned long line)\n{\n\tchar *ptr;\n\tunsigned long l;\n\n\tif(str == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strdup pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\tl = (int) strlen(str) + 1;\n\t__Fortify_CheckPointer(str,0,l,file,line);\n\n\tptr = (char *) _Fortify_malloc(l, file, line);\n\n\tif(ptr)\n\t\tstrcpy(ptr, str);\n\n\treturn(ptr);\n}\n\n/*\n * Fortifty_getpwd() - Uses _Fortify_malloc() to implement getpwd(). Much\n *                     the same protection as _Fortify_malloc().\n * Memory is not allocated bu getcwd but by our routine for the same reason\n * as for strdup\n */\nchar *FORTIFY_STORAGE\n_Fortify_getcwd(char *buf,int size,char *file,unsigned long line)\n{\n\tchar *ptr;\n\n        if(buf!=NULL)\n                ptr = buf;\n\telse\n        \tptr = (char *) _Fortify_malloc(size + 1, file, line);\n\n\tif(ptr)\n\t\tptr = getcwd(ptr, size);\n\n\treturn(ptr);\n}\n\n/*\n * Fortifty_tempnam() - Uses _Fortify_strdup() to implement tempnam(). Much\n *                     the same protection as _Fortify_malloc().\n */\nchar *FORTIFY_STORAGE\n_Fortify_tempnam(char *dir,char *pfx,char *file,unsigned long line)\n{\n\tchar *ptr1, *ptr2;\n\n        ptr1 = tempnam(dir,pfx);\n\n\tif(ptr1)\n        {\n                ptr2=_Fortify_strdup(ptr1,file,line);\n                free(ptr1);\n                ptr1=ptr2;\n        }\n\n\treturn(ptr1);\n}\n\n/*\n * Fortify_memcpy()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nvoid *FORTIFY_STORAGE\n_Fortify_memcpy(void *to,void *from,size_t size,char *file,unsigned long line)\n{\n    if (size) {\n\t    if((from == NULL) || (to == NULL)) {\n\t\t    sprintf(st_Buffer,\n\t\t\t    \"\\nFortify: %s.%ld\\n         \", file, line);\n\t\t    if(from == NULL)\n\t\t\t    sprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"memcpy from pointer is NULL\", file, line);\n\t\t    if(to == NULL)\n\t\t\t    sprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (from == NULL) ? \"\" : \" and \", \"memcpy to pointer is NULL\", file, line);\n\t\t    strcat(st_Buffer, \"\\n\");\n\t\t    st_Output(st_Buffer);\n\t\t    FORTIFY_UNLOCK();\n\t\t    WaitIfstdOutput();\n\t\t    return(NULL);\n\t    }\n\n\t    __Fortify_CheckPointer(to,0,size,file,line);\n\t    __Fortify_CheckPointer(from,0,size,file,line);\n    }\n\treturn(memcpy(to,from,size));\n}\n\n/*\n * Fortify_memmove()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nvoid *FORTIFY_STORAGE\n_Fortify_memmove(void *to,void *from,size_t size,char *file,unsigned long line)\n{\n\tif((from == NULL) || (to == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(from == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"memmove from pointer is NULL\", file, line);\n\t\tif(to == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (from == NULL) ? \"\" : \" and \", \"memmove to pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(to,0,size,file,line);\n\t__Fortify_CheckPointer(from,0,size,file,line);\n\treturn(memmove(to,from,size));\n}\n\n/*\n * Fortify_memccpy()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nvoid *FORTIFY_STORAGE\n_Fortify_memccpy(void *to,void *from,int c,size_t size,char *file,unsigned long line)\n{\n\tif((from == NULL) || (to == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(from == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"memccpy from pointer is NULL\", file, line);\n\t\tif(to == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (from == NULL) ? \"\" : \" and \", \"memccpy to pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(to,0,size,file,line);\n\t__Fortify_CheckPointer(from,0,size,file,line);\n\treturn(memccpy(to,from,c,size));\n}\n\n/*\n * Fortify_memset()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nvoid *FORTIFY_STORAGE\n_Fortify_memset(void *buffer,int c,size_t size,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         memset pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,size,file,line);\n\treturn(memset(buffer,c,size));\n}\n\n/*\n * Fortify_memchr()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nvoid *FORTIFY_STORAGE\n_Fortify_memchr(void *buffer,int c,size_t size,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         memchr pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,size,file,line);\n\treturn(memchr(buffer,c,size));\n}\n\n/*\n * Fortify_memcmp()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nint FORTIFY_STORAGE\n_Fortify_memcmp(void *buffer1,void *buffer2,size_t size,char *file,unsigned long line)\n{\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"memcmp first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"memcmp second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,size,file,line);\n\t__Fortify_CheckPointer(buffer2,0,size,file,line);\n\treturn(memcmp(buffer1,buffer2,size));\n}\n\n/*\n * Fortify_memicmp()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nint FORTIFY_STORAGE\n_Fortify_memicmp(void *buffer1,void *buffer2,size_t size,char *file,unsigned long line)\n{\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"memicmp first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"memicmp second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,size,file,line);\n\t__Fortify_CheckPointer(buffer2,0,size,file,line);\n\treturn(memicmp(buffer1,buffer2,size));\n}\n\n/*\n * Fortify_strcoll()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nint FORTIFY_STORAGE\n_Fortify_strcoll(char *buffer1,char *buffer2,char *file,unsigned long line)\n{\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strcoll first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strcoll second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\t__Fortify_CheckPointer(buffer2,0,strlen(buffer2)+1,file,line);\n\treturn(strcoll(buffer1,buffer2));\n}\n\n/*\n * Fortify_strcspn()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nsize_t FORTIFY_STORAGE\n_Fortify_strcspn(char *buffer1,char *buffer2,char *file,unsigned long line)\n{\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strcspn first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strcspn second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\t__Fortify_CheckPointer(buffer2,0,strlen(buffer2)+1,file,line);\n\treturn(strcspn(buffer1,buffer2));\n}\n\n/*\n * Fortify_strcmp()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nint FORTIFY_STORAGE\n_Fortify_strcmp(char *buffer1,char *buffer2,char *file,unsigned long line)\n{\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strcmp first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strcmp second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\t__Fortify_CheckPointer(buffer2,0,strlen(buffer2)+1,file,line);\n\treturn(strcmp(buffer1,buffer2));\n}\n\n/*\n * Fortify_strcmpi()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nint FORTIFY_STORAGE\n_Fortify_strcmpi(char *buffer1,char *buffer2,char *file,unsigned long line)\n{\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strcmpi first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strcmpi second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\t__Fortify_CheckPointer(buffer2,0,strlen(buffer2)+1,file,line);\n\treturn(strcmpi(buffer1,buffer2));\n}\n\n/*\n * Fortify_strncmp()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nint FORTIFY_STORAGE\n_Fortify_strncmp(char *buffer1,char *buffer2,size_t size,char *file,unsigned long line)\n{\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strncmp first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strncmp second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,MIN(strlen(buffer1)+1,size),file,line);\n\t__Fortify_CheckPointer(buffer2,0,MIN(strlen(buffer2)+1,size),file,line);\n\treturn(strncmp(buffer1,buffer2,size));\n}\n\n/*\n * Fortify_strnicmp()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nint FORTIFY_STORAGE\n_Fortify_strnicmp(char *buffer1,char *buffer2,size_t size,char *file,unsigned long line)\n{\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strnicmp first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strnicmp second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,MIN(strlen(buffer1)+1,size),file,line);\n\t__Fortify_CheckPointer(buffer2,0,MIN(strlen(buffer2)+1,size),file,line);\n\treturn(strnicmp(buffer1,buffer2,size));\n}\n\n/*\n * Fortify_strchr()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strchr(char *buffer,int c,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         strchr pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);\n\treturn(strchr(buffer,c));\n}\n\n/*\n * Fortify_strrchr()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strrchr(char *buffer,int c,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         strchr pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);\n\treturn(strrchr(buffer,c));\n}\n\n/*\n * Fortify_strlwr()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strlwr(char *buffer,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         strlwr pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);\n\treturn(strlwr(buffer));\n}\n\n/*\n * Fortify_strlwr()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strupr(char *buffer,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         strupr pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);\n\treturn(strupr(buffer));\n}\n\n/*\n * Fortify_strrev()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strrev(char *buffer,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         strrev pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);\n\treturn(strrev(buffer));\n}\n\n/*\n * Fortify_strlen()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nsize_t FORTIFY_STORAGE\n_Fortify_strlen(char *buffer,char *file,unsigned long line)\n{\n\tunsigned long l;\n\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         strlen pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\tl = strlen(buffer);\n\t__Fortify_CheckPointer(buffer,0,l+1,file,line);\n\treturn(l);\n}\n\n/*\n * Fortify_strcat()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strcat(char *buffer1,char *buffer2,char *file,unsigned long line)\n{\n\tunsigned long l;\n\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strcat first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strcat second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\tl = strlen(buffer2)+1;\n\t__Fortify_CheckPointer(buffer1,0,l,file,line);\n\t__Fortify_CheckPointer(buffer2,0,l,file,line);\n\treturn(strcat(buffer1,buffer2));\n}\n\n/*\n * Fortify_strpbrk()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strpbrk(char *buffer1,char *buffer2,char *file,unsigned long line)\n{\n\tunsigned long l;\n\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strpbrk first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strpbrk second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\tl = strlen(buffer2)+1;\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\t__Fortify_CheckPointer(buffer2,0,l,file,line);\n\treturn(strpbrk(buffer1,buffer2));\n}\n\n/*\n * Fortify_strstr()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strstr(char *buffer1,char *buffer2,char *file,unsigned long line)\n{\n\tunsigned long l;\n\n\tif((buffer1 == NULL) || (buffer2 == NULL)) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tif(buffer1 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strstr first pointer is NULL\", file, line);\n\t\tif(buffer2 == NULL)\n\t\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s%s\", (buffer2 == NULL) ? \"\" : \" and \", \"strstr second pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\tl = strlen(buffer2)+1;\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\t__Fortify_CheckPointer(buffer2,0,l,file,line);\n\treturn(strstr(buffer1,buffer2));\n}\n\n/*\n * Fortify_strtol()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nlong FORTIFY_STORAGE\n_Fortify_strtol(char *buffer1,char **buffer2,int n,char *file,unsigned long line)\n{\n\tif(buffer1 == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strtol first pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\treturn(strtol(buffer1,buffer2,n));\n}\n\n/*\n * Fortify_atoi()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nint FORTIFY_STORAGE\n_Fortify_atoi(char *buffer1,char *file,unsigned long line)\n{\n\tif(buffer1 == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"atoi first pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\treturn(atoi(buffer1));\n}\n\n/*\n * Fortify_atol()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nlong FORTIFY_STORAGE\n_Fortify_atol(char *buffer1,char *file,unsigned long line)\n{\n\tif(buffer1 == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"atol first pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\treturn(atol(buffer1));\n}\n\n/*\n * Fortify_atod()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\ndouble FORTIFY_STORAGE\n_Fortify_atof(char *buffer1,char *file,unsigned long line)\n{\n\tif(buffer1 == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"atod first pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\treturn(atof(buffer1));\n}\n\n/*\n * Fortify_strtoul()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nunsigned long FORTIFY_STORAGE\n_Fortify_strtoul(char *buffer1,char **buffer2,int n,char *file,unsigned long line)\n{\n\tif(buffer1 == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strtoul first pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\treturn(strtoul(buffer1,buffer2,n));\n}\n\n/*\n * Fortify_strtod()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\ndouble FORTIFY_STORAGE\n_Fortify_strtod(char *buffer1,char **buffer2,char *file,unsigned long line)\n{\n\tif(buffer1 == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         \", file, line);\n\t\tsprintf(st_Buffer + strlen(st_Buffer), \"%s\", \"strtod first pointer is NULL\", file, line);\n\t\tstrcat(st_Buffer, \"\\n\");\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(0);\n\t}\n\n\t__Fortify_CheckPointer(buffer1,0,strlen(buffer1)+1,file,line);\n\treturn(strtod(buffer1,buffer2));\n}\n\n/*\n * Fortify_strset()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strset(char *buffer,int c,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         strset pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);\n\treturn(strset(buffer,c));\n}\n\n/*\n * Fortify_strnset()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strnset(char *buffer,int c,size_t size,char *file,unsigned long line)\n{\n\tif(buffer == NULL) {\n\t\tsprintf(st_Buffer,\n\t\t\t\"\\nFortify: %s.%ld\\n         strnset pointer is NULL\\n\", file, line);\n\t\tst_Output(st_Buffer);\n\t\tFORTIFY_UNLOCK();\n\t\tWaitIfstdOutput();\n\t\treturn(NULL);\n\t}\n\n\t__Fortify_CheckPointer(buffer,0,strlen(buffer)+1,file,line);\n\treturn(strnset(buffer,c,size));\n}\n\n/*\n * Fortify_strncpy()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nstatic char *FORTIFY_STORAGE\n__Fortify_strncpy(char *to,char *from,size_t size,int usesize,char *file,unsigned long line)\n{\n\tsize_t size1;\n\n\tsize1 = strlen(from) + 1;\n\tif(usesize)\n\t{\n\t\tif(size < size1)\n\t\t\tsize1 = size;\n\t}\n\n\treturn((char *) _Fortify_memcpy(to,from,size1,file,line));\n}\n\n/*\n * Fortify_strncpy()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strncpy(char *to,char *from,size_t size,char *file,unsigned long line)\n{\n\treturn(__Fortify_strncpy(to,from,size,1,file,line));\n}\n\n/*\n * Fortify_strncpy()  - check if from/to is in allocated space and if so, then check if start/end is not outside allocated space.\n */\nchar *FORTIFY_STORAGE\n_Fortify_strcpy(char *to,char *from,char *file,unsigned long line)\n{\n\treturn(__Fortify_strncpy(to,from,0,0,file,line));\n}\n\n#endif /* FORTIFY */\n"
  },
  {
    "path": "utilities/lp_solve/ini.c",
    "content": "#include <stdio.h>\n#include <ctype.h>\n#include <string.h>\n\n#include \"lp_lib.h\"\n\n#include \"ini.h\"\n\nFILE *ini_create(const char *filename)\n{\n  FILE *fp;\n\n  fp = fopen(filename, \"w\");\n\n  return(fp);\n}\n\nFILE *ini_open(const char *filename)\n{\n  FILE *fp;\n\n  fp = fopen(filename, \"r\");\n\n  return(fp);\n}\n\nvoid ini_writecomment(FILE *fp, const char *comment)\n{\n  fprintf(fp, \"; %s\\n\", comment);\n}\n\nvoid ini_writeheader(FILE *fp, const char *header, int addnewline)\n{\n  if((addnewline) && (ftell(fp) > 0))\n    fputs(\"\\n\", fp);\n  fprintf(fp, \"[%s]\\n\", header);\n}\n\nvoid ini_writedata(FILE *fp, const char *name, const char *data)\n{\n  if(name != NULL)\n    fprintf(fp, \"%s=%s\\n\", name, data);\n  else\n    fprintf(fp, \"%s\\n\", data);\n}\n\nint ini_readdata(FILE *fp, char * const data, int szdata, int withcomment)\n{\n  int l;\n  char *ptr;\n\n  if(fgets(data, szdata, fp) == NULL)\n    return(0);\n\n  if(!withcomment) {\n    ptr = strchr(data, ';');\n    if(ptr != NULL)\n      *ptr = 0;\n  }\n\n  l = (int) strlen(data);\n  while((l > 0) && (isspace(data[l - 1])))\n    l--;\n  data[l] = 0;\n  if((l >= 2) && (data[0] == '[') && (data[l - 1] == ']')) {\n    memcpy(data, data + 1, l - 2);\n    data[l - 2] = 0;\n    return(1);\n  }\n  return(2);\n}\n\nvoid ini_close(FILE *fp)\n{\n  fclose(fp);\n}\n"
  },
  {
    "path": "utilities/lp_solve/ini.h",
    "content": "#include <stdio.h>\n\n#ifdef __cplusplus\n__EXTERN_C {\n#endif\n\nextern FILE *ini_create(const char *filename);\nextern FILE *ini_open(const char *filename);\nextern void ini_writecomment(FILE *fp, const char *comment);\nextern void ini_writeheader(FILE *fp, const char *header, int addnewline);\nextern void ini_writedata(FILE *fp, const char *name, const char *data);\nextern int ini_readdata(FILE *fp, char * const data, int szdata, int withcomment);\nextern void ini_close(FILE *fp);\n\n#ifdef __cplusplus\n}\n#endif\n"
  },
  {
    "path": "utilities/lp_solve/lp_Hash.c",
    "content": "\n#include <stdlib.h>\n#include <string.h>\n#include \"lp_lib.h\"\n#include \"lp_utils.h\"\n#include \"lp_report.h\"\n#include \"lp_Hash.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n#define HASH_START_SIZE  5000  /* Hash table size for row and column name storage */\n#define NUMHASHPRIMES      45\n\nSTATIC hashtable *create_hash_table(int size, int base)\n{\n  int i;\n  int HashPrimes[ ] = {\n             29,     229,     883,    1671,    2791,    4801,    8629,   10007,\n          15289,   25303,   34843,   65269,   99709,  129403,  147673,  166669,\n         201403,  222163,  242729,  261431,  303491,  320237,  402761,  501131,\n         602309,  701507,  800999,  900551, 1000619, 1100837, 1200359, 1300021,\n        1400017, 1500007, 1750009, 2000003, 2500009, 3000017, 4000037, 5000011,\n        6000011, 7000003, 8000009, 9000011, 9999991};\n  hashtable *ht;\n\n  /* Find a good size for the hash table */\n  if(size < HASH_START_SIZE)\n    size = HASH_START_SIZE;\n  for(i = 0; i < NUMHASHPRIMES-1; i++)\n    if(HashPrimes[i] > size)\n      break;\n  size = HashPrimes[i];\n\n  /* Then allocate and initialize memory */\n  ht = (hashtable *) calloc(1 , sizeof(*ht));\n  ht->table = (hashelem **) calloc(size, sizeof(*(ht->table)));\n  ht->size = size;\n  ht->base = base;\n  ht->count = base-1;\n\n  return(ht);\n}\n\nSTATIC void free_hash_item(hashelem **hp)\n{\n  free((*hp)->name);\n  free(*hp);\n  *hp = NULL;\n}\n\nSTATIC void free_hash_table(hashtable *ht)\n{\n  hashelem *hp, *thp;\n\n  hp = ht->first;\n  while(hp != NULL) {\n    thp = hp;\n    hp = hp->nextelem;\n    free_hash_item(&thp);\n  }\n  free(ht->table);\n  free(ht);\n}\n\n\n/* make a good hash function for any int size */\n/* inspired by Aho, Sethi and Ullman, Compilers ..., p436 */\n#define HASH_1 sizeof(unsigned int)\n#define HASH_2 (sizeof(unsigned int) * 6)\n#define HASH_3 (((unsigned int)0xF0) << ((sizeof(unsigned int) - 1) * CHAR_BIT))\n\nSTATIC int hashval(const char *string, int size)\n{\n  unsigned int result = 0, tmp;\n\n  for(; *string; string++) {\n    result = (result << HASH_1) + *string;\n    if((tmp = result & HASH_3) != 0) {\n      /* if any of the most significant bits is on */\n      result ^= tmp >> HASH_2; /* xor them in in a less significant part */\n      result ^= tmp; /* and reset the most significant bits to 0 */\n    }\n  }\n  return(result % size);\n} /* hashval */\n\n\nSTATIC hashelem *findhash(const char *name, hashtable *ht)\n{\n  hashelem *h_tab_p;\n  for(h_tab_p = ht->table[hashval(name, ht->size)];\n      h_tab_p != NULL;\n      h_tab_p = h_tab_p->next)\n    if(strcmp(name, h_tab_p->name) == 0) /* got it! */\n      break;\n  return(h_tab_p);\n} /* findhash */\n\n\nSTATIC hashelem *puthash(const char *name, int index, hashelem **list, hashtable *ht)\n{\n  hashelem *hp = NULL;\n  int      hashindex;\n\n  if(list != NULL) {\n    hp = list[index];\n    if(hp != NULL)\n      list[index] = NULL;\n  }\n\n  if((hp = findhash(name, ht)) == NULL) {\n\n    hashindex = hashval(name, ht->size);\n    hp = (hashelem *) calloc(1, sizeof(*hp));\n    allocCHAR(NULL, &hp->name, (int) (strlen(name) + 1), FALSE);\n    strcpy(hp->name, name);\n    hp->index = index;\n    ht->count++;\n    if(list != NULL)\n      list[index] = hp;\n\n    hp->next = ht->table[hashindex];\n    ht->table[hashindex] = hp;\n    if(ht->first == NULL)\n      ht->first = hp;\n    if(ht->last != NULL)\n      ht->last->nextelem = hp;\n    ht->last = hp;\n\n  }\n  return(hp);\n}\n\nSTATIC void drophash(const char *name, hashelem **list, hashtable *ht) {\n  hashelem *hp, *hp1, *hp2;\n  int      hashindex;\n\n  if((hp = findhash(name, ht)) != NULL) {\n    hashindex = hashval(name, ht->size);\n    if((hp1 = ht->table[hashindex]) != NULL) {\n      hp2 = NULL;\n      while((hp1 != NULL) && (hp1 != hp)) {\n        hp2 = hp1;\n        hp1 = hp1->next;\n      }\n      if(hp1 == hp) {\n        if(hp2 != NULL)\n          hp2->next = hp->next;\n        else\n          ht->table[hashindex] = hp->next;\n      }\n\n      hp1 = ht->first;\n      hp2 = NULL;\n      while((hp1 != NULL) && (hp1 != hp)) {\n        hp2 = hp1;\n        hp1 = hp1->nextelem;\n      }\n      if(hp1 == hp) {\n        if(hp2 != NULL)\n          hp2->nextelem = hp->nextelem;\n        else {\n          ht->first = hp->nextelem;\n          if (ht->first == NULL)\n            ht->last = NULL;\n        }\n      }\n      if(list != NULL)\n        list[hp->index] = NULL;\n      free_hash_item(&hp);\n      ht->count--;\n    }\n  }\n}\n\nSTATIC hashtable *copy_hash_table(hashtable *ht, hashelem **list, int newsize)\n{\n  hashtable *copy;\n  hashelem  *elem, *new_elem;\n\n  if(newsize < ht->size)\n    newsize = ht->size;\n\n  copy = create_hash_table(newsize, ht->base);\n  if (copy != NULL) {\n    elem = ht->first;\n    while (elem != NULL) {\n      if((new_elem = puthash(elem->name, elem->index, list, copy)) == NULL) {\n        free_hash_table(copy);\n        return(NULL);\n      }\n      elem = elem ->nextelem;\n    }\n  }\n\n  return(copy);\n}\n\nSTATIC int find_row(lprec *lp, const char *name, MYBOOL Unconstrained_rows_found)\n{\n  hashelem *hp;\n\n  if (lp->rowname_hashtab != NULL)\n      hp = findhash(name, lp->rowname_hashtab);\n  else\n      hp = NULL;\n\n  if (hp == NULL) {\n    if(Unconstrained_rows_found) { /* just ignore them in this case */\n         return(-1);\n    }\n    else {\n      return(-1);\n    }\n  }\n  return(hp->index);\n}\n\nSTATIC int find_var(lprec *lp, const char *name, MYBOOL verbose)\n{\n  hashelem *hp;\n\n  if (lp->colname_hashtab != NULL)\n      hp = findhash(name, lp->colname_hashtab);\n  else\n      hp = NULL;\n\n  if (hp == NULL) {\n    if(verbose)\n      report(lp, SEVERE, \"find_var: Unknown variable name '%s'\\n\", name);\n    return(-1);\n  }\n  return(hp->index);\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_Hash.h",
    "content": "#ifndef HEADER_lp_hash\n#define HEADER_lp_hash\n\n/* For row and column name hash tables */\n\ntypedef struct _hashelem\n{\n  char             *name;\n  int               index;\n  struct _hashelem *next;\n  struct _hashelem *nextelem;\n} hashelem;\n\ntypedef struct /* _hashtable */\n{\n  hashelem         **table;\n  int              size;\n  int              base;\n  int              count;\n  struct _hashelem *first;\n  struct _hashelem *last;\n} hashtable;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nSTATIC hashtable *create_hash_table(int size, int base);\nSTATIC void      free_hash_table(hashtable *ht);\nSTATIC hashelem  *findhash(const char *name, hashtable *ht);\nSTATIC hashelem  *puthash(const char *name, int index, hashelem **list, hashtable *ht);\nSTATIC void      drophash(const char *name, hashelem **list, hashtable *ht);\nSTATIC void      free_hash_item(hashelem **hp);\nSTATIC hashtable *copy_hash_table(hashtable *ht, hashelem **list, int newsize);\nSTATIC int find_var(lprec *lp, const char *name, MYBOOL verbose);\nSTATIC int find_row(lprec *lp, const char *name, MYBOOL Unconstrained_rows_found);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_hash */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_MDO.c",
    "content": "/*\n    Minimum matrix inverse fill-in modules - interface for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      string.h, colamd.h, lp_lib.h\n\n    Release notes:\n    v1.0    1 September 2003    Preprocessing routines for minimum fill-in column\n                                ordering for inverse factorization using the open\n                                source COLAMD library.  Suitable for the dense parts\n                                of both the product form and LU factorization inverse\n                                methods.\n    v1.1    1 July 2004         Renamed from lp_colamdMDO to lp_MDO.\n\n   ----------------------------------------------------------------------------------\n*/\n\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"colamd.h\"\n#include \"lp_MDO.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\nSTATIC MYBOOL includeMDO(MYBOOL *usedpos, int item)\n{\n/*  Legend:   TRUE            => A basic slack variable already in the basis\n              FALSE           => A column free for being pivoted in\n              AUTOMATIC+TRUE  => A row-singleton user column pivoted into the basis\n              AUTOMATIC+FALSE => A column-singleton user column pivoted into the basis */\n\n  /* Handle case where we are processing all columns */\n  if(usedpos == NULL)\n    return( TRUE );\n\n  else {\n  /* Otherwise do the selective case */\n    MYBOOL test = usedpos[item];\n#if 1\n    return( test != TRUE );\n#else\n    test = test & TRUE;\n    return( test == FALSE );\n#endif\n  }\n}\n\nSTATIC int prepareMDO(lprec *lp, MYBOOL *usedpos, int *colorder, int *data, int *rowmap)\n/* This routine prepares data structures for colamd().  It is called twice, the first\n   time to count applicable non-zero elements by column, and the second time to fill in\n   the row indexes of the non-zero values from the first call.  Note that the colamd()\n   row index base is 0 (which suits lp_solve fine). */\n{\n  int     i, ii, j, k, kk;\n  int     nrows = lp->rows+1, ncols = colorder[0];\n  int     offset = 0, Bnz = 0, Tnz;\n  MYBOOL  dotally = (MYBOOL) (rowmap == NULL);\n  MATrec  *mat = lp->matA;\n  REAL    hold;\n  REAL    *value;\n  int     *rownr;\n\n  if(dotally)\n    data[0] = 0;\n\n  Tnz = nrows - ncols;\n  for(j = 1; j <= ncols; j++) {\n    kk = colorder[j];\n\n    /* Process slacks */\n    if(kk <= lp->rows) {\n      if(includeMDO(usedpos, kk)) {\n        if(!dotally)\n          data[Bnz] = rowmap[kk]+offset;\n        Bnz++;\n      }\n      Tnz++;\n    }\n    /* Process user columns */\n    else {\n      k = kk - lp->rows;\n      i = mat->col_end[k-1];\n      ii= mat->col_end[k];\n      Tnz += ii-i;\n#ifdef Paranoia\n      if(i >= ii)\n        lp->report(lp, SEVERE, \"prepareMDO: Encountered empty basic column %d\\n\", k);\n#endif\n\n      /* Detect if we need to do phase 1 adjustments of zero-valued OF variable */\n      rownr = &COL_MAT_ROWNR(i);\n      value = &COL_MAT_VALUE(i);\n      hold = 0;\n      if((*rownr > 0) && includeMDO(usedpos, 0) && modifyOF1(lp, kk, &hold, 1.0)) {\n        if(!dotally)\n          data[Bnz] = offset;\n        Bnz++;\n      }\n      /* Loop over all NZ-variables */\n      for(; i < ii;\n          i++, value += matValueStep, rownr += matRowColStep) {\n        if(!includeMDO(usedpos, *rownr))\n          continue;\n        /* See if we need to change phase 1 OF value */\n        if(*rownr == 0) {\n          hold = *value;\n          if(!modifyOF1(lp, kk, &hold, 1.0))\n            continue;\n        }\n        /* Tally uneliminated constraint row values */\n        if(!dotally)\n          data[Bnz] = rowmap[*rownr]+offset;\n        Bnz++;\n      }\n    }\n    if(dotally)\n      data[j] = Bnz;\n  }\n  return( Tnz );\n}\n\nSTATIC MYBOOL verifyMDO(lprec *lp, int *col_end, int *row_nr, int rowmax, int colmax)\n{\n  int i, j, n, err = 0;\n\n  for(i = 1; i <= colmax; i++) {\n    n = 0;\n    for(j = col_end[i-1]; (j < col_end[i]) && (err == 0); j++, n++) {\n      if(row_nr[j] < 0 || row_nr[j] > rowmax)\n        err = 1;\n      if(n > 0 && row_nr[j] <= row_nr[j-1])\n        err = 2;\n      n++;\n    }\n  }\n  if(err != 0)\n    lp->report(lp, SEVERE, \"verifyMDO: Invalid MDO input structure generated (error %d)\\n\", err);\n  return( (MYBOOL) (err == 0) );\n}\n\nvoid *mdo_calloc(size_t size, size_t count)\n{\n  return ( calloc(size, count) );\n}\nvoid mdo_free(void *mem)\n{\n  free( mem );\n}\n\n\nint __WINAPI getMDO(lprec *lp, MYBOOL *usedpos, int *colorder, int *size, MYBOOL symmetric)\n{\n  int    error = FALSE;\n  int    nrows = lp->rows+1, ncols = colorder[0];\n  int    i, j, kk, n;\n  int    *col_end, *row_map = NULL;\n  int    Bnz, Blen, *Brows = NULL;\n  int    stats[COLAMD_STATS];\n  double knobs[COLAMD_KNOBS];\n\n /* Tally the non-zero counts of the unused columns/rows of the\n    basis matrix and store corresponding \"net\" starting positions */\n  allocINT(lp, &col_end, ncols+1, FALSE);\n  n = prepareMDO(lp, usedpos, colorder, col_end, NULL);\n  Bnz = col_end[ncols];\n\n /* Check that we have unused basic columns, otherwise skip analysis */\n  if(ncols == 0 || Bnz == 0)\n    goto Transfer;\n\n /* Get net number of rows and fill mapper */\n  allocINT(lp, &row_map, nrows, FALSE);\n  nrows = 0;\n  for(i = 0; i <= lp->rows; i++) {\n    row_map[i] = i-nrows;\n   /* Increment eliminated row counter if necessary */\n    if(!includeMDO(usedpos, i))\n      nrows++;\n  }\n  nrows = lp->rows+1 - nrows;\n\n /* Store row indeces of non-zero values in the basic columns */\n  Blen = colamd_recommended(Bnz, nrows, ncols);\n  allocINT(lp, &Brows, Blen, FALSE);\n  prepareMDO(lp, usedpos, colorder, Brows, row_map);\n#ifdef Paranoia\n  verifyMDO(lp, col_end, Brows, nrows, ncols);\n#endif\n\n /* Compute the MDO */\n#if 1\n  colamd_set_defaults(knobs);\n  knobs [COLAMD_DENSE_ROW] = 0.2+0.2 ;    /* default changed for UMFPACK */\n  knobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW];\n  if(symmetric && (nrows == ncols)) {\n    MEMCOPY(colorder, Brows, ncols + 1);\n    error = !symamd(nrows, colorder, col_end, Brows, knobs, stats, mdo_calloc, mdo_free);\n  }\n  else\n    error = !colamd(nrows, ncols, Blen, Brows, col_end, knobs, stats);\n#else\n  if(symmetric && (nrows == ncols)) {\n    MEMCOPY(colorder, Brows, ncols + 1);\n    error = !symamd(nrows, colorder, col_end, Brows, knobs, stats, mdo_calloc, mdo_free);\n  }\n  else\n    error = !colamd(nrows, ncols, Blen, Brows, col_end, (double *) NULL, stats);\n#endif\n\n /* Transfer the estimated optimal ordering, adjusting for index offsets */\nTransfer:\n  if(error)\n    error = stats[COLAMD_STATUS];\n  else {\n    MEMCOPY(Brows, colorder, ncols + 1);\n    for(j = 0; j < ncols; j++) {\n      kk = col_end[j];\n      n = Brows[kk+1];\n      colorder[j+1] = n;\n    }\n  }\n\n  /* Free temporary vectors */\n  FREE(col_end);\n  if(row_map != NULL)\n    FREE(row_map);\n  if(Brows != NULL)\n    FREE(Brows);\n\n  if(size != NULL)\n    *size = ncols;\n  return( error );\n}\n\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_MDO.h",
    "content": "#ifndef HEADER_MDO\n#define HEADER_MDO\n\n#include \"lp_types.h\"\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nint __WINAPI getMDO(lprec *lp, MYBOOL *usedpos, int *colorder, int *size, MYBOOL symmetric);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_MDO */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_MPS.c",
    "content": "\n#include <string.h>\n#include <stdarg.h>\n#include <ctype.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_scale.h\"\n#include \"lp_report.h\"\n#include \"lp_MPS.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n/* Define buffer-size controled function mapping */\n# if defined _MSC_VER\n#  define vsnprintf _vsnprintf\n# endif\n\n/* MPS file input and output routines for lp_solve                           */\n/* ------------------------------------------------------------------------- */\n\n/*\nA:  MPS format was named after an early IBM LP product and has emerged\nas a de facto standard ASCII medium among most of the commercial LP\ncodes.  Essentially all commercial LP codes accept this format, but if\nyou are using public domain software and have MPS files, you may need\nto write your own reader routine for this.  It's not too hard.  The\nmain things to know about MPS format are that it is column oriented (as\nopposed to entering the model as equations), and everything (variables,\nrows, etc.) gets a name.  MPS format is described in more detail in\nMurtagh's book, referenced in another section. Also,\n\nftp://softlib.cs.rice.edu/pub/miplib/mps_format\n\nis a nice short introduction.  exports\n\nMPS is an old format, so it is set up as though you were using punch\ncards, and is not free format. Fields start in column 1, 5, 15, 25, 40\nand 50.  Sections of an MPS file are marked by so-called header cards,\nwhich are distinguished by their starting in column 1.  Although it is\ntypical to use upper-case throughout the file (like I said, MPS has\nlong historical roots), many MPS-readers will accept mixed-case for\nanything except the header cards, and some allow mixed-case anywhere.\nThe names that you choose for the individual entities (constraints or\nvariables) are not important to the solver; you should pick names that\nare meaningful to you, or will be easy for a post-processing code to\nread.\n\nHere is a little sample model written in MPS format (explained in more\ndetail below):\n\nNAME          TESTPROB\nROWS\n N  COST\n L  LIM1\n G  LIM2\n E  MYEQN\nCOLUMNS\n    XONE      COST                 1   LIM1                 1\n    XONE      LIM2                 1\n    YTWO      COST                 4   LIM1                 1\n    YTWO      MYEQN               -1\n    ZTHREE    COST                 9   LIM2                 1\n    ZTHREE    MYEQN                1\nRHS\n    RHS1      LIM1                 5   LIM2                10\n    RHS1      MYEQN                7\nBOUNDS\n UP BND1      XONE                 4\n LO BND1      YTWO                -1\n UP BND1      YTWO                 1\nENDATA\n\nmeans:\n\nOptimize\n COST:    XONE + 4 YTWO + 9 ZTHREE\nSubject To\n LIM1:    XONE + YTWO <= 5\n LIM2:    XONE + ZTHREE >= 10\n MYEQN:   - YTWO + ZTHREE  = 7\nBounds\n 0 <= XONE <= 4\n-1 <= YTWO <= 1\nEnd\n\n*/\n\n/* copy a MPS name, only trailing spaces are removed. In MPS, names can have\n   embedded spaces! */\nSTATIC void namecpy(char *into, const char *from)\n{\n  int i;\n\n  /* copy at most 8 characters of from, stop at end of string or newline */\n  for(i = 0; (from[i] != '\\0') && (from[i] != '\\n') && (from[i] != '\\r') && (i < 8); i++)\n    into[i] = from[i];\n\n  /* end with end of string */\n  into[i] = '\\0';\n\n  /* remove trailing spaces, if any */\n  for(i--; (i >= 0) && (into[i] == ' '); i--)\n    into[i] = '\\0';\n}\n\n/* scan an MPS line, and pick up the information in the fields that are\n   present */\n\n/* scan_line for fixed MPS format */\nSTATIC int scan_lineFIXED(lprec *lp, int section, char* line, char *field1, char *field2, char *field3,\n                          double *field4, char *field5, double *field6)\n{\n  (void)section;\n  int  items = 0, line_len;\n  char buf[16], *ptr1, *ptr2;\n  (void)section;\n\n  line_len = (int) strlen(line);\n  while ((line_len) && ((line[line_len-1] == '\\n') || (line[line_len-1] == '\\r') || (line[line_len-1] == ' ')))\n   line_len--;\n\n  if(line_len >= 1) { /* spaces or N/L/G/E or UP/LO */\n    strncpy(buf, line, 4);\n    buf[4] = '\\0';\n    sscanf(buf, \"%s\", field1);\n    items++;\n  }\n  else\n    field1[0] = '\\0';\n\n  line += 4;\n\n  if(line_len >= 5) { /* name */\n    if (line[-1] != ' ') {\n      report(lp, IMPORTANT, \"MPS_readfile: invalid data card; column 4 must be blank\\n\");\n      return(-1);\n    }\n    namecpy(field2, line);\n    items++;\n  }\n  else\n    field2[0] = '\\0';\n\n  line += 10;\n\n  if(line_len >= 14) { /* name */\n    if (line[-1] != ' ' || line[-2] != ' ') {\n      report(lp, IMPORTANT, \"MPS_readfile: invalid data card; columns 13-14 must be blank\\n\");\n      return(-1);\n    }\n    namecpy(field3, line);\n    items++;\n  }\n  else\n    field3[0] = '\\0';\n\n  line += 10;\n\n  if(line_len >= 25) { /* number */\n    if (line[-1] != ' ' || line[-2] != ' ') {\n      report(lp, IMPORTANT, \"MPS_readfile: invalid data card; columns 23-24 must be blank\\n\");\n      return(-1);\n    }\n    strncpy(buf, line, 15);\n    buf[15] = '\\0';\n    for(ptr1 = ptr2 = buf; ; ptr1++)\n      if(!isspace((unsigned char) *ptr1))\n        if((*(ptr2++) = *ptr1) == 0)\n          break;\n    /* *field4 = atof(buf); */\n    *field4 = strtod(buf, &ptr1);\n    if(*ptr1) {\n      report(lp, IMPORTANT, \"MPS_readfile: invalid number in columns 25-36 \\n\");\n      return(-1);\n    }\n    items++;\n  }\n  else\n    *field4 = 0;\n\n  line += 15;\n\n  if(line_len >= 40) { /* name */\n    if (line[-1] != ' ' || line[-2] != ' ' || line[-3] != ' ') {\n      report(lp, IMPORTANT, \"MPS_readfile: invalid data card; columns 37-39 must be blank\\n\");\n      return(-1);\n    }\n    namecpy(field5, line);\n    items++;\n  }\n  else\n    field5[0] = '\\0';\n  line += 10;\n\n  if(line_len >= 50) { /* number */\n    if (line[-1] != ' ' || line[-2] != ' ') {\n      report(lp, IMPORTANT, \"MPS_readfile: invalid data card; columns 48-49 must be blank\\n\");\n      return(-1);\n    }\n    strncpy(buf, line, 15);\n    buf[15] = '\\0';\n    for(ptr1 = ptr2 = buf; ; ptr1++)\n      if(!isspace((unsigned char) *ptr1))\n        if((*(ptr2++) = *ptr1) == 0)\n          break;\n    /* *field6 = atof(buf); */\n    *field6 = strtod(buf, &ptr1);\n    if(*ptr1) {\n      report(lp, IMPORTANT, \"MPS_readfile: invalid number in columns 50-61 \\n\");\n      return(-1);\n    }\n    items++;\n  }\n  else\n    *field6 = 0;\n\n  return(items);\n}\n\nSTATIC int spaces(char *line, int line_len)\n{\n  int l;\n  char *line1 = line;\n\n  while (*line1 == ' ')\n    line1++;\n  l = (int) (line1 - line);\n  if (line_len < l)\n    l = line_len;\n  return(l);\n}\n\nSTATIC int lenfield(char *line, int line_len)\n{\n  int l;\n  char *line1 = line;\n\n  while ((*line1) && (*line1 != ' '))\n    line1++;\n  l = (int) (line1 - line);\n  if (line_len < l)\n    l = line_len;\n  return(l);\n}\n\n/* scan_line for fixed MPS format */\nSTATIC int scan_lineFREE(lprec *lp, int section, char* line, char *field1, char *field2, char *field3,\n                         double *field4, char *field5, double *field6)\n{\n  (void)lp;\n  int  items = 0, line_len, len;\n  char buf[256], *ptr1 = NULL, *ptr2;\n  (void)lp;\n\n  line_len = (int) strlen(line);\n  while ((line_len) && ((line[line_len-1] == '\\n') || (line[line_len-1] == '\\r') || (line[line_len-1] == ' ')))\n   line_len--;\n\n  len = spaces(line, line_len);\n  line += len;\n  line_len -= len;\n\n  if ((section == MPSCOLUMNS) || (section == MPSRHS) || (section == MPSRANGES)) {\n    field1[0] = '\\0';\n    items++;\n  }\n  else {\n    len = lenfield(line, line_len);\n    if(line_len >= 1) { /* spaces or N/L/G/E or UP/LO */\n      strncpy(buf, line, len);\n      buf[len] = '\\0';\n      sscanf(buf, \"%s\", field1);\n      if(section == MPSBOUNDS) {\n        for(ptr1 = field1; *ptr1; ptr1++)\n          *ptr1=(char)toupper(*ptr1);\n      }\n      items++;\n    }\n    else\n      field1[0] = '\\0';\n\n    line += len;\n    line_len -= len;\n\n    len = spaces(line, line_len);\n    line += len;\n    line_len -= len;\n  }\n\n  len = lenfield(line, line_len);\n  if(line_len >= 1) { /* name */\n    strncpy(field2, line, len);\n    field2[len] = '\\0';\n    items++;\n  }\n  else\n    field2[0] = '\\0';\n\n  line += len;\n  line_len -= len;\n\n  len = spaces(line, line_len);\n  line += len;\n  line_len -= len;\n\n  len = lenfield(line, line_len);\n  if(line_len >= 1) { /* name */\n    strncpy(field3, line, len);\n    field3[len] = '\\0';\n    items++;\n  }\n  else\n    field3[0] = '\\0';\n\n  line += len;\n  line_len -= len;\n\n  len = spaces(line, line_len);\n  line += len;\n  line_len -= len;\n\n  if (*field3) {\n    if((section == MPSCOLUMNS) && (strcmp(field3, \"'MARKER'\") == 0)) {\n      *field4 = 0;\n      items++;\n      ptr1 = field3;\n    }\n    else if((section == MPSBOUNDS) &&\n            ((strcmp(field1, \"FR\") == 0) || (strcmp(field1, \"MI\") == 0) || (strcmp(field1, \"PL\") == 0) || (strcmp(field1, \"BV\") == 0)))\n      /* field3 *is* the variable name */;\n    else {\n      /* Some free MPS formats allow that field 2 is not provided after the first time.\n         The fieldname is then the same as the the defined field the line before.\n         In that case field2 shifts to field3, field1 shifts to field 2.\n         This situation is tested by checking if field3 is numerical AND there are an even number of fields after.\n      */\n      char *line1 = line;\n      int line_len1 = line_len;\n      int items1 = 0;\n\n      while (line_len1 > 0) {\n        len = lenfield(line1, line_len1);\n        if (len > 0) {\n          line1 += len;\n          line_len1 -= len;\n          items1++;\n        }\n        len = spaces(line1, line_len1);\n        line1 += len;\n        line_len1 -= len;\n      }\n      if ((items1 % 2) == 0) {\n        *field4 = strtod(field3, &ptr1);\n        if(*ptr1 == 0) {\n          strcpy(field3, field2);\n          if ((section == MPSROWS) || (section == MPSBOUNDS) /* || (section == MPSSOS) */)\n            *field2 = 0;\n          else {\n            strcpy(field2, field1);\n            *field1 = 0;\n          }\n          items++;\n        }\n        else\n          ptr1 = NULL;\n      }\n      else\n        ptr1 = NULL;\n    }\n  }\n  else {\n    ptr1 = NULL;\n    if((section == MPSBOUNDS) &&\n       ((strcmp(field1, \"FR\") == 0) || (strcmp(field1, \"MI\") == 0) || (strcmp(field1, \"PL\") == 0) || (strcmp(field1, \"BV\") == 0))) {\n      strcpy(field3, field2);\n      *field2 = 0;\n      items++;\n    }\n  }\n\n  if(ptr1 == NULL) {\n    len = lenfield(line, line_len);\n    if(line_len >= 1) { /* number */\n      strncpy(buf, line, len);\n      buf[len] = '\\0';\n      for(ptr1 = ptr2 = buf; ; ptr1++)\n        if(!isspace((unsigned char) *ptr1))\n          if((*(ptr2++) = *ptr1) == 0)\n            break;\n      /* *field4 = atof(buf); */\n      *field4 = strtod(buf, &ptr1);\n      if(*ptr1)\n        return(-1);\n      items++;\n    }\n    else\n      *field4 = 0;\n\n    line += len;\n    line_len -= len;\n\n    len = spaces(line, line_len);\n    line += len;\n    line_len -= len;\n  }\n\n  len = lenfield(line, line_len);\n  if(line_len >= 1) { /* name */\n    strncpy(field5, line, len);\n    field5[len] = '\\0';\n    items++;\n  }\n  else\n    field5[0] = '\\0';\n  line += len;\n  line_len -= len;\n\n  len = spaces(line, line_len);\n  line += len;\n  line_len -= len;\n\n  len = lenfield(line, line_len);\n  if(line_len >= 1) { /* number */\n    strncpy(buf, line, len);\n    buf[len] = '\\0';\n    for(ptr1 = ptr2 = buf; ; ptr1++)\n      if(!isspace((unsigned char) *ptr1))\n        if((*(ptr2++) = *ptr1) == 0)\n          break;\n    /* *field6 = atof(buf); */\n    *field6 = strtod(buf, &ptr1);\n    if(*ptr1)\n      return(-1);\n    items++;\n  }\n  else\n    *field6 = 0;\n\n  if((section == MPSSOS) && (items == 2)) {\n    strcpy(field3, field2);\n    strcpy(field2, field1);\n    *field1 = 0;\n  }\n\n  if((section != MPSOBJNAME) && (section != MPSBOUNDS)) {\n    for(ptr1 = field1; *ptr1; ptr1++)\n      *ptr1=(char)toupper(*ptr1);\n  }\n\n  return(items);\n}\n\nSTATIC int addmpscolumn(lprec *lp, MYBOOL Int_section, int typeMPS, MYBOOL *Column_ready,\n                        int *count, REAL *Last_column, int *Last_columnno, const char *Last_col_name)\n{\n  int ok = TRUE;\n\n  if (*Column_ready) {\n    ok = add_columnex(lp, *count, Last_column, Last_columnno);\n    if (ok) {\n      ok = set_col_name(lp, lp->columns, Last_col_name);\n    }\n    if (ok) {\n      set_int(lp, lp->columns, Int_section);\n      if ((Int_section) && (typeMPS & MPSIBM))\n        set_bounds(lp, lp->columns, 10.0 / DEF_INFINITE, DEF_INFINITE / 10.0);\n    }\n  }\n  *Column_ready = FALSE;\n  *count = 0;\n  return(ok);\n}\n\n#if 0\nSTATIC MYBOOL appendmpsitem(int *count, int rowIndex[], REAL rowValue[])\n{\n  int i = *count;\n\n  if(rowValue[i] == 0)\n    return( FALSE );\n\n  while((i > 0) && (rowIndex[i] < rowIndex[i-1])) {\n    swapINT (rowIndex+i, rowIndex+i-1);\n    swapREAL(rowValue+i, rowValue+i-1);\n    i--;\n  }\n  (*count)++;\n  return( TRUE );\n}\n#endif\n\nSTATIC MYBOOL appendmpsitem(int *count, int rowIndex[], REAL rowValue[])\n{\n  int i = *count;\n\n  /* Check for non-negativity of the index */\n  if(rowIndex[i] < 0)\n    return( FALSE );\n\n  /* Move the element so that the index list is sorted ascending */\n  while((i > 0) && (rowIndex[i] < rowIndex[i-1])) {\n    swapINT (rowIndex+i, rowIndex+i-1);\n    swapREAL(rowValue+i, rowValue+i-1);\n    i--;\n  }\n\n  /* Add same-indexed items (which is rarely encountered), and shorten the list */\n  if((i < *count) && (rowIndex[i] == rowIndex[i+1])) {\n    int ii = i + 1;\n    rowValue[i] += rowValue[ii];\n    (*count)--;\n    while(ii < *count) {\n      rowIndex[ii] = rowIndex[ii+1];\n      rowValue[ii] = rowValue[ii+1];\n      ii++;\n    }\n  }\n\n  /* Update the count and return */\n  (*count)++;\n  return( TRUE );\n}\n\nMYBOOL MPS_readfile(lprec **newlp, const char *filename, int typeMPS, int verbose)\n{\n  MYBOOL status = FALSE;\n  FILE   *fpin;\n\n  fpin = fopen(filename, \"r\");\n  if(fpin != NULL) {\n    status = MPS_readhandle(newlp, fpin, typeMPS, verbose);\n    fclose(fpin);\n  }\n  return( status );\n}\n\nstatic int __WINAPI MPS_input(void *fpin, char *buf, int max_size)\n{\n  return(fgets(buf, max_size, (FILE *) fpin) != NULL);\n}\n\nMYBOOL __WINAPI MPS_readhandle(lprec **newlp, FILE *filehandle, int typeMPS, int verbose)\n{\n  return(MPS_readex(newlp, (void *) filehandle, MPS_input, typeMPS, verbose));\n}\n\nMYBOOL __WINAPI MPS_readex(lprec **newlp, void *userhandle, read_modeldata_func read_modeldata, int typeMPS, int verbose)\n{\n  char   field1[BUFSIZ], field2[BUFSIZ], field3[BUFSIZ], field5[BUFSIZ], line[BUFSIZ], tmp[BUFSIZ],\n         Last_col_name[BUFSIZ], probname[BUFSIZ], OBJNAME[BUFSIZ], *ptr;\n  int    items, row, Lineno, var,\n         section = MPSUNDEF, variant = 0, NZ = 0, SOS = 0;\n  MYBOOL Int_section, Column_ready, Column_ready1,\n         Unconstrained_rows_found = FALSE, OF_found = FALSE, CompleteStatus = FALSE;\n  double field4, field6;\n  REAL   *Last_column = NULL;\n  int    count = 0, *Last_columnno = NULL;\n  int    OBJSENSE = ROWTYPE_EMPTY;\n  lprec  *lp;\n  int    (*scan_line)(lprec *lp, int section, char* line, char *field1, char *field2, char *field3,\n                      double *field4, char *field5, double *field6);\n\n  if(newlp == NULL)\n    return( CompleteStatus );\n  else if(*newlp == NULL)\n    lp = make_lp(0, 0);\n  else\n    lp = *newlp;\n\n  if((typeMPS & MPSFIXED) == MPSFIXED)\n    scan_line = scan_lineFIXED;\n  else if((typeMPS & MPSFREE) == MPSFREE)\n    scan_line = scan_lineFREE;\n  else {\n    report(lp, IMPORTANT, \"MPS_readfile: Unrecognized MPS line type.\\n\");\n    if (*newlp == NULL)\n      delete_lp(lp);\n    return( CompleteStatus );\n  }\n\n  if (lp != NULL) {\n    lp->source_is_file = TRUE;\n    lp->verbose = verbose;\n    strcpy(Last_col_name, \"\");\n    strcpy(OBJNAME, \"\");\n    Int_section = FALSE;\n    Column_ready = FALSE;\n    Lineno = 0;\n\n    /* let's initialize line to all zero's */\n    MEMCLEAR(line, BUFSIZ);\n\n    while(read_modeldata(userhandle, line, BUFSIZ - 1)) {\n      Lineno++;\n\n      for(ptr = line; (*ptr) && (isspace((unsigned char) *ptr)); ptr++);\n\n      /* skip lines which start with \"*\", they are comment */\n      if((line[0] == '*') || (*ptr == 0) || (*ptr == '\\n') || (*ptr == '\\r')) {\n        report(lp, FULL, \"Comment on line %d: %s\", Lineno, line);\n        continue;\n      }\n\n      report(lp, FULL, \"Line %6d: %s\", Lineno, line);\n\n      /* first check for \"special\" lines: NAME, ROWS, BOUNDS .... */\n      /* this must start in the first position of line */\n      if(line[0] != ' ') {\n        sscanf(line, \"%s\", tmp);\n        if(strcmp(tmp, \"NAME\") == 0) {\n          section = MPSNAME;\n          *probname = 0;\n          sscanf(line, \"NAME %s\", probname);\n          if (!set_lp_name(lp, probname))\n            break;\n        }\n        else if(((typeMPS & MPSFREE) == MPSFREE) && (strcmp(tmp, \"OBJSENSE\") == 0)) {\n          section = MPSOBJSENSE;\n          report(lp, FULL, \"Switching to OBJSENSE section\\n\");\n        }\n        else if(((typeMPS & MPSFREE) == MPSFREE) && (strcmp(tmp, \"OBJNAME\") == 0)) {\n          section = MPSOBJNAME;\n          report(lp, FULL, \"Switching to OBJNAME section\\n\");\n        }\n        else if(strcmp(tmp, \"ROWS\") == 0) {\n          section = MPSROWS;\n          report(lp, FULL, \"Switching to ROWS section\\n\");\n        }\n        else if(strcmp(tmp, \"COLUMNS\") == 0) {\n          allocREAL(lp, &Last_column, lp->rows + 1, TRUE);\n          allocINT(lp, &Last_columnno, lp->rows + 1, TRUE);\n          count = 0;\n          if ((Last_column == NULL) || (Last_columnno == NULL))\n            break;\n          section = MPSCOLUMNS;\n          report(lp, FULL, \"Switching to COLUMNS section\\n\");\n        }\n        else if(strcmp(tmp, \"RHS\") == 0) {\n          if (!addmpscolumn(lp, Int_section, typeMPS, &Column_ready, &count, Last_column, Last_columnno, Last_col_name))\n            break;\n          section = MPSRHS;\n          report(lp, FULL, \"Switching to RHS section\\n\");\n        }\n        else if(strcmp(tmp, \"BOUNDS\") == 0) {\n          section = MPSBOUNDS;\n          report(lp, FULL, \"Switching to BOUNDS section\\n\");\n        }\n        else if(strcmp(tmp, \"RANGES\") == 0) {\n          section = MPSRANGES;\n          report(lp, FULL, \"Switching to RANGES section\\n\");\n        }\n        else if((strcmp(tmp, \"SOS\") == 0) || (strcmp(tmp, \"SETS\") == 0)) {\n          section = MPSSOS;\n          if(strcmp(tmp, \"SOS\") == 0)\n            variant = 0;\n          else\n            variant = 1;\n          report(lp, FULL, \"Switching to %s section\\n\", tmp);\n        }\n        else if(strcmp(tmp, \"ENDATA\") == 0) {\n          report(lp, FULL, \"Finished reading MPS file\\n\");\n          CompleteStatus = TRUE;\n          break;\n        }\n        else { /* line does not start with space and does not match above */\n          report(lp, IMPORTANT, \"Unrecognized MPS line %d: %s\\n\", Lineno, line);\n          break;\n        }\n      }\n      else { /* normal line, process */\n        items = scan_line(lp, section, line, field1, field2, field3, &field4, field5, &field6);\n        if(items < 0){\n          report(lp, IMPORTANT, \"Syntax error on line %d: %s\\n\", Lineno, line);\n          break;\n        }\n\n        switch(section) {\n\n        case MPSNAME:\n          report(lp, IMPORTANT, \"Error, extra line under NAME line\\n\");\n          break;\n\n        case MPSOBJSENSE:\n          if(OBJSENSE != ROWTYPE_EMPTY) {\n            report(lp, IMPORTANT, \"Error, extra line under OBJSENSE line\\n\");\n            break;\n          }\n          if((strcmp(field1, \"MAXIMIZE\") == 0) || (strcmp(field1, \"MAX\") == 0)) {\n            OBJSENSE = ROWTYPE_OFMAX;\n            set_maxim(lp);\n          }\n          else if((strcmp(field1, \"MINIMIZE\") == 0) || (strcmp(field1, \"MIN\") == 0)) {\n            OBJSENSE = ROWTYPE_OFMIN;\n            set_minim(lp);\n          }\n          else {\n            report(lp, SEVERE, \"Unknown OBJSENSE direction '%s' on line %d\\n\", field1, Lineno);\n            break;\n          }\n          continue;\n\n        case MPSOBJNAME:\n          if(*OBJNAME) {\n            report(lp, IMPORTANT, \"Error, extra line under OBJNAME line\\n\");\n            break;\n          }\n          strcpy(OBJNAME, field1);\n          continue;\n\n        /* Process entries in the ROWS section */\n        case MPSROWS:\n          /* field1: rel. operator; field2: name of constraint */\n\n          report(lp, FULL, \"Row   %5d: %s %s\\n\", lp->rows + 1, field1, field2);\n\n          if(strcmp(field1, \"N\") == 0) {\n            if((*OBJNAME) && (strcmp(field2, OBJNAME)))\n              /* Ignore this objective name since it is not equal to the OBJNAME name */;\n            else if(!OF_found) { /* take the first N row as OF, ignore others */\n              if (!set_row_name(lp, 0, field2))\n                break;\n              OF_found = TRUE;\n            }\n            else if(!Unconstrained_rows_found) {\n              report(lp, IMPORTANT, \"Unconstrained row %s ignored\\n\", field2);\n              report(lp, IMPORTANT, \"Further messages of this kind will be suppressed\\n\");\n              Unconstrained_rows_found = TRUE;\n            }\n          }\n          else if(strcmp(field1, \"L\") == 0) {\n            if ((!str_add_constraint(lp, \"\" ,LE ,0)) || (!set_row_name(lp, lp->rows, field2)))\n              break;\n          }\n          else if(strcmp(field1, \"G\") == 0) {\n            if ((!str_add_constraint(lp, \"\" ,GE ,0)) || (!set_row_name(lp, lp->rows, field2)))\n              break;\n          }\n          else if(strcmp(field1, \"E\") == 0) {\n            if ((!str_add_constraint(lp, \"\",EQ ,0)) || (!set_row_name(lp, lp->rows, field2)))\n              break;\n          }\n          else {\n            report(lp, SEVERE, \"Unknown relation code '%s' on line %d\\n\", field1, Lineno);\n            break;\n          }\n\n          continue;\n\n        /* Process entries in the COLUMNS section */\n        case MPSCOLUMNS:\n          /* field2: variable; field3: constraint; field4: coef */\n          /* optional: field5: constraint; field6: coef */\n\n          report(lp, FULL, \"Column %4d: %s %s %g %s %g\\n\",\n                            lp->columns + 1, field2, field3, field4, field5, field6);\n\n          if((items == 4) || (items == 5) || (items == 6)) {\n            if (NZ == 0)\n              strcpy(Last_col_name, field2);\n            else if(*field2) {\n              Column_ready1 = (MYBOOL) (strcmp(field2, Last_col_name) != 0);\n              if(Column_ready1) {\n                if (find_var(lp, field2, FALSE) >= 0) {\n                  report(lp, SEVERE, \"Variable name (%s) is already used!\\n\", field2);\n                  break;\n                }\n\n                if(Column_ready) {  /* Added ability to handle non-standard \"same as above\" column name */\n                  if (addmpscolumn(lp, Int_section, typeMPS, &Column_ready, &count, Last_column, Last_columnno, Last_col_name)) {\n                    strcpy(Last_col_name, field2);\n                    NZ = 0;\n                  }\n                  else\n                    break;\n                }\n              }\n            }\n            if(items == 5) { /* there might be an INTEND or INTORG marker */\n             /* look for \"    <name>  'MARKER'                 'INTORG'\"\n                      or \"    <name>  'MARKER'                 'INTEND'\"  */\n              if(strcmp(field3, \"'MARKER'\") != 0)\n                break;\n              if(strcmp(field5, \"'INTORG'\") == 0) {\n                Int_section = TRUE;\n                report(lp, FULL, \"Switching to integer section\\n\");\n              }\n              else if(strcmp(field5, \"'INTEND'\") == 0) {\n                Int_section = FALSE;\n                report(lp, FULL, \"Switching to non-integer section\\n\");\n              }\n              else\n                report(lp, IMPORTANT, \"Unknown marker (ignored) at line %d: %s\\n\",\n                                       Lineno, field5);\n            }\n            else if((row = find_row(lp, field3, Unconstrained_rows_found)) >= 0) {\n              if(row > lp->rows)\n                report(lp, CRITICAL, \"Invalid row %s encountered in the MPS file\\n\", field3);\n              Last_columnno[count] = row;\n              Last_column[count] = (REAL)field4;\n              if(appendmpsitem(&count, Last_columnno, Last_column)) {\n                NZ++;\n                Column_ready = TRUE;\n              }\n            }\n          }\n          if(items == 6) {\n            if((row = find_row(lp, field5, Unconstrained_rows_found)) >= 0) {\n              if(row > lp->rows)\n                report(lp, CRITICAL, \"Invalid row %s encountered in the MPS file\\n\", field5);\n              Last_columnno[count] = row;\n              Last_column[count] = (REAL)field6;\n              if(appendmpsitem(&count, Last_columnno, Last_column)) {\n                NZ++;\n                Column_ready = TRUE;\n              }\n            }\n          }\n\n          if((items < 4) || (items > 6)) { /* Wrong! */\n            report(lp, CRITICAL, \"Wrong number of items (%d) in COLUMNS section (line %d)\\n\",\n                                  items, Lineno);\n            break;\n          }\n\n          continue;\n\n        /* Process entries in the RHS section */\n        /* field2: uninteresting name; field3: constraint name */\n        /* field4: value */\n        /* optional: field5: constraint name; field6: value */\n        case MPSRHS:\n\n          report(lp, FULL, \"RHS line: %s %s %g %s %g\\n\",\n                            field2, field3, field4, field5, field6);\n\n          if((items != 4) && (items != 6)) {\n            report(lp, CRITICAL, \"Wrong number of items (%d) in RHS section line %d\\n\",\n                                  items, Lineno);\n            break;\n          }\n\n          if((row = find_row(lp, field3, Unconstrained_rows_found)) >= 0) {\n            if ((row == 0) && ((typeMPS & MPSNEGOBJCONST) == MPSNEGOBJCONST))\n              field4 = -field4;\n            set_rh(lp, row, (REAL)field4);\n          }\n\n          if(items == 6) {\n            if((row = find_row(lp, field5, Unconstrained_rows_found)) >= 0) {\n              if ((row == 0) && ((typeMPS & MPSNEGOBJCONST) == MPSNEGOBJCONST))\n                field6 = -field6;\n              set_rh(lp, row, (REAL)field6);\n            }\n          }\n\n          continue;\n\n        /* Process entries in the BOUNDS section */\n        /* field1: bound type; field2: uninteresting name; */\n        /* field3: variable name; field4: value */\n        case MPSBOUNDS:\n\n          report(lp, FULL, \"BOUNDS line: %s %s %s %g\\n\",\n                            field1, field2, field3, field4);\n\n          var = find_var(lp, field3, FALSE);\n          if(var < 0){ /* bound on undefined var in COLUMNS section ... */\n            Column_ready = TRUE;\n            if (!addmpscolumn(lp, FALSE, typeMPS, &Column_ready, &count, Last_column, Last_columnno, field3))\n              break;\n            Column_ready = TRUE;\n            var = find_var(lp, field3, TRUE);\n          }\n          if(var < 0) /* undefined var and could add ... */;\n          else if(strcmp(field1, \"UP\") == 0) {\n          /* upper bound */\n            /* if(!set_bounds(lp, var, get_lowbo(lp, var), field4)) */\n            if(!set_upbo(lp, var, field4))\n              break;\n          }\n          else if(strcmp(field1, \"SC\") == 0) {\n            /* upper bound */\n            if(field4 == 0)\n              field4 = lp->infinite;\n            /* if(!set_bounds(lp, var, get_lowbo(lp, var), field4)) */\n            if(!set_upbo(lp, var, field4))\n              break;\n            set_semicont(lp, var, TRUE);\n          }\n          else if(strcmp(field1, \"SI\") == 0) {\n            /* upper bound */\n            if(field4 == 0)\n              field4 = lp->infinite;\n            /* if(!set_bounds(lp, var, get_lowbo(lp, var), field4)) */\n            if(!set_upbo(lp, var, field4))\n              break;\n            set_int(lp, var, TRUE);\n            set_semicont(lp, var, TRUE);\n          }\n          else if(strcmp(field1, \"LO\") == 0) {\n            /* lower bound */\n            /* if(!set_bounds(lp, var, field4, get_upbo(lp, var))) */\n            if(!set_lowbo(lp, var, field4))\n              break;\n          }\n          else if(strcmp(field1, \"PL\") == 0) { /* plus-ranged variable */\n            /* if(!set_bounds(lp, var, get_lowbo(lp, var), lp->infinite)) */\n            if(!set_upbo(lp, var, lp->infinite))\n              break;\n          }\n          else if(strcmp(field1, \"MI\") == 0) { /* minus-ranged variable */\n            /* if(!set_bounds(lp, var, -lp->infinite, get_upbo(lp, var))) */\n            if(!set_lowbo(lp, var, -lp->infinite))\n              break;\n          }\n          else if(strcmp(field1, \"FR\") == 0) { /* free variable */\n            set_unbounded(lp, var);\n          }\n          else if(strcmp(field1, \"FX\") == 0) {\n            /* fixed, upper _and_ lower  */\n            if(!set_bounds(lp, var, field4, field4))\n              break;\n          }\n          else if(strcmp(field1, \"BV\") == 0) { /* binary variable */\n            set_binary(lp, var, TRUE);\n          }\n          /* AMPL bounds type UI and LI added by E.Imamura (CRIEPI)  */\n          else if(strcmp(field1, \"UI\") == 0) { /* upper bound for integer variable */\n            /* if(!set_bounds(lp, var, get_lowbo(lp, var), field4)) */\n            if(!set_upbo(lp, var, field4))\n              break;\n            set_int(lp, var, TRUE);\n          }\n          else if(strcmp(field1, \"LI\") == 0) { /* lower bound for integer variable - corrected by KE */\n            /* if(!set_bounds(lp, var, field4, get_upbo(lp, var))) */\n            if(!set_lowbo(lp, var, field4))\n              break;\n            set_int(lp, var, TRUE);\n          }\n          else {\n            report(lp, CRITICAL, \"BOUND type %s on line %d is not supported\",\n                                  field1, Lineno);\n            break;\n          }\n\n          continue;\n\n          /* Process entries in the BOUNDS section */\n\n      /* We have to implement the following semantics:\n\n      D. The RANGES section is for constraints of the form: h <=\n      constraint <= u .  The range of the constraint is r = u - h .  The\n      value of r is specified in the RANGES section, and the value of u or\n      h is specified in the RHS section.  If b is the value entered in the\n      RHS section, and r is the value entered in the RANGES section, then\n      u and h are thus defined:\n\n      row type       sign of r       h          u\n      ----------------------------------------------\n     G            + or -         b        b + |r|\n     L            + or -       b - |r|      b\n     E              +            b        b + |r|\n     E              -          b - |r|      b            */\n\n        /* field2: uninteresting name; field3: constraint name */\n        /* field4: value */\n        /* optional: field5: constraint name; field6: value */\n\n        case MPSRANGES:\n\n          report(lp, FULL, \"RANGES line: %s %s %g %s %g\",\n                            field2, field3, field4, field5, field6);\n\n          if((items != 4) && (items != 6)) {\n            report(lp, CRITICAL, \"Wrong number of items (%d) in RANGES section line %d\",\n                                  items, Lineno);\n            break;\n          }\n\n          if((row = find_row(lp, field3, Unconstrained_rows_found)) >= 0) {\n            /* Determine constraint type */\n\n            if(fabs(field4) >= lp->infinite) {\n              report(lp, IMPORTANT,\n                          \"Warning, Range for row %s >= infinity (value %g) on line %d, ignored\",\n                          field3, field4, Lineno);\n            }\n            else if(field4 == 0) {\n              /* Change of a GE or LE to EQ */\n              if(lp->orig_upbo[row] != 0)\n                set_constr_type(lp, row, EQ);\n            }\n            else if(is_chsign(lp, row)) {\n              /* GE */\n              lp->orig_upbo[row] = fabs(field4);\n            }\n            else if((lp->orig_upbo[row] == 0) && (field4 >= 0)) {\n              /*  EQ with positive sign of r value */\n              set_constr_type(lp, row, GE);\n              lp->orig_upbo[row] = field4;\n            }\n            else if(lp->orig_upbo[row] == lp->infinite) {\n              /* LE */\n              lp->orig_upbo[row] = fabs(field4);\n            }\n            else if((lp->orig_upbo[row] == 0) && (field4 < 0)) {\n              /* EQ with negative sign of r value */\n              set_constr_type(lp, row, LE);\n              lp->orig_upbo[row] = my_flipsign(field4);\n            }\n            else { /* let's be paranoid */\n              report(lp, IMPORTANT,\n                          \"Cannot figure out row type, row = %d, is_chsign = %d, upbo = %g on line %d\",\n                          row, is_chsign(lp, row), (double)lp->orig_upbo[row], Lineno);\n            }\n          }\n\n          if(items == 6) {\n            if((row = find_row(lp, field5, Unconstrained_rows_found)) >= 0) {\n              /* Determine constraint type */\n\n              if(fabs(field6) >= lp->infinite) {\n                report(lp, IMPORTANT,\n                            \"Warning, Range for row %s >= infinity (value %g) on line %d, ignored\",\n                            field5, field6, Lineno);\n              }\n              else if(field6 == 0) {\n                /* Change of a GE or LE to EQ */\n                if(lp->orig_upbo[row] != 0)\n                  set_constr_type(lp, row, EQ);\n              }\n              else if(is_chsign(lp, row)) {\n                /* GE */\n                lp->orig_upbo[row] = fabs(field6);\n              }\n              else if(lp->orig_upbo[row] == 0 && field6 >= 0) {\n                /*  EQ with positive sign of r value */\n                set_constr_type(lp, row, GE);\n                lp->orig_upbo[row] = field6;\n              }\n              else if(lp->orig_upbo[row] == lp->infinite) {\n                /* LE */\n                lp->orig_upbo[row] = fabs(field6);\n              }\n              else if((lp->orig_upbo[row] == 0) && (field6 < 0)) {\n                /* EQ with negative sign of r value */\n                set_constr_type(lp, row, LE);\n                lp->orig_upbo[row] = my_flipsign(field6);\n              }\n              else { /* let's be paranoid */\n                report(lp, IMPORTANT,\n                            \"Cannot figure out row type, row = %d, is_chsign = %d, upbo = %g on line %d\",\n                            row, is_chsign(lp,row), (double) lp->orig_upbo[row], Lineno);\n              }\n            }\n          }\n\n          continue;\n\n        /* Process entries in the SOS section */\n\n        /* We have to implement the following semantics:\n\n          E. The SOS section is for ordered variable sets of the form:\n      x1, x2, x3 ... xn where only a given number of consequtive variables\n          may be non-zero.  Each set definition is prefaced by type, name\n      and priority data.  Each set member has an optional weight that\n      determines its order.  There are two forms supported; a full format\n      and a reduced CPLEX-like format.                                       */\n\n        case MPSSOS:\n          report(lp, FULL, \"SOS line: %s %s %g %s %g\",\n                             field2, field3, field4, field5, field6);\n\n          if((items == 0) || (items > 4)) {\n            report(lp, IMPORTANT,\n                   \"Invalid number of items (%d) in SOS section line %d\\n\",\n                   items, Lineno);\n            break;\n          }\n\n          if(strlen(field1) == 0) items--;  /* fix scanline anomoly! */\n\n          /* Check if this is the start of a new SOS */\n          if(items == 1 || items == 4) {\n            row = (int) (field1[1] - '0');\n            if((row <= 0) || (row > 9)) {\n              report(lp, IMPORTANT,\n                     \"Error: Invalid SOS type %s line %d\\n\", field1, Lineno);\n              break;\n            }\n            field1[0] = '\\0';               /* fix scanline anomoly! */\n\n            /* lp_solve needs a name for the SOS */\n            if(variant == 0) {\n              if(strlen(field3) == 0)  /* CPLEX format does not provide a SOS name; create one */\n                sprintf(field3, \"SOS_%d\", SOS_count(lp) + 1);\n            }\n            else {                     /* Remap XPRESS format name */\n              strcpy(field3, field1);\n            }\n            /* Obtain the SOS priority */\n            if(items == 4)\n              SOS = (int) field4;\n            else\n              SOS = 1;\n\n            /* Define a new SOS instance */\n\n            SOS = add_SOS(lp, field3, (int) row, SOS, 0, NULL, NULL);\n          }\n          /* Otherwise, add set members to the active SOS */\n          else {\n            char *field = (items == 3) ? field3 /* Native lp_solve and XPRESS formats */ : field2 /* CPLEX format */;\n\n            var = find_var(lp, field, FALSE);  /* Native lp_solve and XPRESS formats */\n            if(var < 0){ /* SOS on undefined var in COLUMNS section ... */\n              Column_ready = TRUE;\n              if (!addmpscolumn(lp, FALSE, typeMPS, &Column_ready, &count, Last_column, Last_columnno, field))\n                break;\n              Column_ready = TRUE;\n              var = find_var(lp, field, TRUE);\n            }\n            if((var < 0) || (SOS < 1)) /* undefined var and could add ... */;\n            else append_SOSrec(lp->SOS->sos_list[SOS-1], 1, &var, &field4);\n          }\n\n          continue;\n        }\n\n        /* If we got here there was an error \"upstream\" */\n         report(lp, IMPORTANT,\n                     \"Error: Cannot handle line %d\\n\", Lineno);\n         break;\n      }\n    }\n\n    if((*OBJNAME) && (!OF_found)) {\n      report(lp, IMPORTANT,\n                  \"Error: Objective function specified by OBJNAME card not found\\n\");\n      CompleteStatus = FALSE;\n    }\n\n    if(CompleteStatus == FALSE) {\n      if (*newlp == NULL)\n        delete_lp(lp);\n    }\n    else {\n      if (typeMPS & MPSIBM) {\n        REAL lower, upper;\n\n        for (var = 1; var <= lp->columns; var++)\n          if (is_int(lp, var)) {\n            lower = get_lowbo(lp, var);\n            upper = get_upbo(lp, var);\n            if ((lower == 10.0 / DEF_INFINITE) && (upper == DEF_INFINITE / 10.0))\n              upper = 1.0;\n            if (lower == 10.0 / DEF_INFINITE)\n              lower = 0.0;\n            if (upper == DEF_INFINITE / 10.0)\n              upper = lp->infinite;\n            set_bounds(lp, var, lower, upper);\n          }\n      }\n      *newlp = lp;\n    }\n    if(Last_column != NULL)\n      FREE(Last_column);\n    if(Last_columnno != NULL)\n      FREE(Last_columnno);\n  }\n\n  return( CompleteStatus );\n}\n\nstatic void number(char *str,REAL value)\n {\n  char __str[80], *_str;\n  int  i;\n\n  /* sprintf(_str,\"%12.6G\",value); */\n  _str=__str+2;\n  if (value>=0.0)\n   if ((value!=0.0) && ((value>0.99999999e12) || (value<0.0001))) {\n    int n=15;\n\n    do {\n     n--;\n     i=sprintf(_str,\"%*.*E\",n,n-6,(double) value);\n     if (i>12) {\n      char *ptr=strchr(_str,'E');\n\n      if (ptr!=NULL) {\n       if (*(++ptr)=='-') ptr++;\n       while ((i>12) && ((*ptr=='+') || (*ptr=='0'))) {\n        strcpy(ptr,ptr+1);\n        i--;\n       }\n      }\n     }\n    } while (i>12);\n   }\n   else if (value>=1.0e10) {\n    int n=13;\n\n    do {\n     i=sprintf(_str,\"%*.0f\",--n,(double) value);\n    } while (i>12);\n   }\n   else {\n    if (((i=sprintf(_str,\"%12.10f\",(double) value))>12) && (_str[12]>='5')) {\n     for (i=11;i>=0;i--)\n      if (_str[i]!='.') {\n       if (++_str[i]>'9') _str[i]='0';\n       else break;\n      }\n     if (i<0) {\n      *(--_str)='1';\n      *(--_str)=' ';\n     }\n    }\n   }\n  else\n   if ((value<-0.99999999e11) || (value>-0.0001)) {\n    int n=15;\n\n    do {\n     n--;\n     i=sprintf(_str,\"%*.*E\",n,n-7,(double) value);\n     if (i>12) {\n      char *ptr=strchr(_str,'E');\n\n      if (ptr!=NULL) {\n       if (*(++ptr)=='-') ptr++;\n       while ((i>12) && ((*ptr=='+') || (*ptr=='0'))) {\n        strcpy(ptr,ptr+1);\n        i--;\n       }\n      }\n     }\n    } while (i>12);\n   }\n   else if (value<=-1.0e9) {\n    int n=13;\n\n    do {\n     i=sprintf(_str,\"%*.0f\",--n,(double) value);\n    } while (i>12);\n   }\n   else\n    if (((i=sprintf(_str,\"%12.9f\",(double) value))>12) && (_str[12]>='5')) {\n     for (i=11;i>=1;i--)\n      if (_str[i]!='.') {\n       if (++_str[i]>'9') _str[i]='0';\n       else break;\n      }\n     if (i<1) {\n      *_str='1';\n      *(--_str)='-';\n      *(--_str)=' ';\n     }\n    }\n  strncpy(str,_str,12);\n }\n\nstatic char *formatnumber12(char *numberbuffer, double a)\n{\n#if 0\n  return(sprintf(numberbuffer, \"%12g\", a));\n#else\n  number(numberbuffer, a);\n  return(numberbuffer);\n#endif\n}\n\nSTATIC const char *MPSnameFIXED(char *name0, const char *name)\n{\n  sprintf(name0, \"%-8.8s\", name);\n  return(name0);\n}\n\nSTATIC const char *MPSnameFREE(char *name0, const char *name)\n{\n  if(strlen(name) < 8)\n    return(MPSnameFIXED(name0, name));\n  else\n    return(name);\n}\n\nstatic void write_data(void *userhandle, write_modeldata_func write_modeldata, const char *format, ...)\n{\n  char buff[DEF_STRBUFSIZE+1];\n  va_list ap;\n\n  va_start(ap, format);\n  vsnprintf(buff, DEF_STRBUFSIZE, format, ap);\n  va_end(ap);\n  write_modeldata(userhandle, buff);\n}\n\nMYBOOL __WINAPI MPS_writefileex(lprec *lp, int typeMPS, void *userhandle, write_modeldata_func write_modeldata)\n{\n  int    i, j, jj, je, k, marker, putheader, ChangeSignObj = FALSE, *idx, *idx1;\n  MYBOOL ok = TRUE, names_used;\n  REAL   a, *val, *val1;\n  const char * (*MPSname)(char *name0, const char *name);\n  char numberbuffer[15];\n  char name0[9];\n\n  if((typeMPS & MPSFIXED) == MPSFIXED) {\n    MPSname = MPSnameFIXED;\n    ChangeSignObj = is_maxim(lp);\n  }\n  else if((typeMPS & MPSFREE) == MPSFREE) {\n    MPSname = MPSnameFREE;\n  }\n  else {\n    report(lp, IMPORTANT, \"MPS_writefile: unrecognized MPS name type.\\n\");\n    return(FALSE);\n  }\n\n  names_used = lp->names_used;\n\n  if((typeMPS & MPSFIXED) == MPSFIXED) {\n    /* Check if there is no variable name where the first 8 charachters are equal to the first 8 characters of anothe variable */\n    if(names_used)\n      for(i = 1; (i <= lp->columns) && (ok); i++)\n        if((lp->col_name[i] != NULL) && (lp->col_name[i]->name != NULL) && (!is_splitvar(lp, i)) && (strlen(lp->col_name[i]->name) > 8))\n          for(j = 1; (j < i) && (ok); j++)\n    if((lp->col_name[j] != NULL) && (lp->col_name[j]->name != NULL) && (!is_splitvar(lp, j)))\n      if(strncmp(lp->col_name[i]->name, lp->col_name[j]->name, 8) == 0)\n        ok = FALSE;\n  }\n\n  if(!ok) {\n    lp->names_used = FALSE;\n    ok = TRUE;\n  }\n\n  memset(numberbuffer, 0, sizeof(numberbuffer));\n\n  marker = 0;\n\n  /* First write metadata in structured comment form (lp_solve style) */\n  write_data(userhandle, write_modeldata, \"*<meta creator='lp_solve v%d.%d'>\\n\",\n                  (int) MAJORVERSION, (int) MINORVERSION);\n  write_data(userhandle, write_modeldata, \"*<meta rows=%d>\\n\", lp->rows);\n  write_data(userhandle, write_modeldata, \"*<meta columns=%d>\\n\", lp->columns);\n  write_data(userhandle, write_modeldata, \"*<meta equalities=%d>\\n\", lp->equalities);\n  if(SOS_count(lp) > 0)\n    write_data(userhandle, write_modeldata, \"*<meta SOS=%d>\\n\", SOS_count(lp));\n  write_data(userhandle, write_modeldata, \"*<meta integers=%d>\\n\", lp->int_vars);\n  if(lp->sc_vars > 0)\n    write_data(userhandle, write_modeldata, \"*<meta scvars=%d>\\n\", lp->sc_vars);\n  write_data(userhandle, write_modeldata, \"*<meta origsense='%s'>\\n\", (is_maxim(lp) ? \"MAX\" : \"MIN\"));\n  write_data(userhandle, write_modeldata, \"*\\n\");\n\n  /* Write the MPS content */\n  write_data(userhandle, write_modeldata, \"NAME          %s\\n\", MPSname(name0, get_lp_name(lp)));\n  if(((typeMPS & MPSFREE) == MPSFREE) && (is_maxim(lp)))\n    write_data(userhandle, write_modeldata, \"OBJSENSE\\n MAX\\n\");\n  write_data(userhandle, write_modeldata, \"ROWS\\n\");\n  for(i = 0; i <= lp->rows; i++) {\n    if(i == 0)\n      write_data(userhandle, write_modeldata, \" N  \");\n    else if(lp->orig_upbo[i] != 0) {\n      if(is_chsign(lp,i))\n        write_data(userhandle, write_modeldata, \" G  \");\n      else\n        write_data(userhandle, write_modeldata, \" L  \");\n    }\n    else\n      write_data(userhandle, write_modeldata, \" E  \");\n    write_data(userhandle, write_modeldata, \"%s\\n\", MPSname(name0, get_row_name(lp, i)));\n  }\n\n  allocREAL(lp, &val, 1 + lp->rows, TRUE);\n  allocINT(lp, &idx, 1 + lp->rows, TRUE);\n  write_data(userhandle, write_modeldata, \"COLUMNS\\n\");\n  for(i = 1; i <= lp->columns; i++) {\n    if(!is_splitvar(lp, i)) {\n      if(is_int(lp,i) && (marker % 2) == 0) {\n        write_data(userhandle, write_modeldata, \"    MARK%04d  'MARKER'                 'INTORG'\\n\",\n                marker);\n        marker++;\n      }\n      if(!is_int(lp,i) && (marker % 2) == 1) {\n        write_data(userhandle, write_modeldata, \"    MARK%04d  'MARKER'                 'INTEND'\\n\",\n                marker);\n        marker++;\n      }\n\n      /* Loop over non-zero column entries */\n      je = get_columnex(lp, i, val, idx);\n      for(k = 1, val1 = val, idx1 = idx, jj = 0; jj < je; jj++) {\n        k = 1 - k;\n        j = *(idx1++);\n        a = *(val1++);\n        if (k == 0) {\n          write_data(userhandle, write_modeldata, \"    %s\",\n                          MPSname(name0, get_col_name(lp, i)));\n          write_data(userhandle, write_modeldata, \"  %s  %s\",\n                          MPSname(name0, get_row_name(lp, j)),\n/*                          formatnumber12(numberbuffer, (double) a)); */\n                          formatnumber12(numberbuffer, (double) (a * (j == 0 && ChangeSignObj ? -1 : 1))));\n    }\n        else\n          write_data(userhandle, write_modeldata, \"   %s  %s\\n\",\n                          MPSname(name0, get_row_name(lp, j)),\n                          formatnumber12(numberbuffer, (double) (a * (j == 0 && ChangeSignObj ? -1 : 1))));\n/*                          formatnumber12(numberbuffer, (double) a)); */\n      }\n      if(k == 0)\n        write_data(userhandle, write_modeldata, \"\\n\");\n    }\n  }\n  if((marker % 2) == 1) {\n    write_data(userhandle, write_modeldata, \"    MARK%04d  'MARKER'                 'INTEND'\\n\",\n            marker);\n  /* marker++; */ /* marker not used after this */\n  }\n  FREE(idx);\n  FREE(val);\n\n  write_data(userhandle, write_modeldata, \"RHS\\n\");\n  for(k = 1, i = 0; i <= lp->rows; i++) {\n    a = lp->orig_rhs[i];\n    if(a) {\n      a = unscaled_value(lp, a, i);\n      if ((i == 0) && ((typeMPS & MPSNEGOBJCONST) == MPSNEGOBJCONST))\n        a = -a;\n      if((i == 0) || is_chsign(lp, i))\n        a = my_flipsign(a);\n      k = 1 - k;\n      if(k == 0)\n        write_data(userhandle, write_modeldata, \"    RHS       %s  %s\",\n                        MPSname(name0, get_row_name(lp, i)),\n                        formatnumber12(numberbuffer, (double)a));\n      else\n        write_data(userhandle, write_modeldata, \"   %s  %s\\n\",\n                        MPSname(name0, get_row_name(lp, i)),\n                        formatnumber12(numberbuffer, (double)a));\n    }\n  }\n  if(k == 0)\n    write_data(userhandle, write_modeldata, \"\\n\");\n\n  putheader = TRUE;\n  for(k = 1, i = 1; i <= lp->rows; i++){\n    a = 0;\n    if((lp->orig_upbo[i] < lp->infinite) && (lp->orig_upbo[i] != 0.0))\n      a = lp->orig_upbo[i];\n    if(a) {\n      if(putheader) {\n        write_data(userhandle, write_modeldata, \"RANGES\\n\");\n        putheader = FALSE;\n      }\n      a = unscaled_value(lp, a, i);\n      k = 1 - k;\n      if(k == 0)\n        write_data(userhandle, write_modeldata, \"    RGS       %s  %s\",\n                        MPSname(name0, get_row_name(lp, i)),\n                        formatnumber12(numberbuffer, (double)a));\n      else\n        write_data(userhandle, write_modeldata, \"   %s  %s\\n\",\n                        MPSname(name0, get_row_name(lp, i)),\n                        formatnumber12(numberbuffer, (double)a));\n    }\n  }\n  if(k == 0)\n    write_data(userhandle, write_modeldata, \"\\n\");\n\n  putheader = TRUE;\n  for(i = lp->rows + 1; i <= lp->sum; i++)\n    if(!is_splitvar(lp, i - lp->rows)) {\n      j = i - lp->rows;\n      if((lp->orig_lowbo[i] != 0) && (lp->orig_upbo[i] < lp->infinite) &&\n         (lp->orig_lowbo[i] == lp->orig_upbo[i])) {\n        a = lp->orig_upbo[i];\n        a = unscaled_value(lp, a, i);\n        if(putheader) {\n          write_data(userhandle, write_modeldata, \"BOUNDS\\n\");\n          putheader = FALSE;\n        }\n        write_data(userhandle, write_modeldata, \" FX BND       %s  %s\\n\",\n                        MPSname(name0, get_col_name(lp, j)),\n                        formatnumber12(numberbuffer, (double)a));\n      }\n      else if(is_binary(lp, j)) {\n        if(putheader) {\n          write_data(userhandle, write_modeldata, \"BOUNDS\\n\");\n          putheader = FALSE;\n        }\n        write_data(userhandle, write_modeldata, \" BV BND       %s\\n\",\n                        MPSname(name0, get_col_name(lp, j)));\n      }\n      else if(is_unbounded(lp, j)) {\n        if(putheader) {\n          write_data(userhandle, write_modeldata, \"BOUNDS\\n\");\n          putheader = FALSE;\n        }\n        write_data(userhandle, write_modeldata, \" FR BND       %s\\n\",\n                        MPSname(name0, get_col_name(lp, j)));\n      }\n      else {\n        if((lp->orig_lowbo[i] != 0) || (is_int(lp, j))) { /* Some solvers like CPLEX need to have a bound on a variable if it is integer, but not binary else it is interpreted as binary which is not ment */\n          a = lp->orig_lowbo[i];\n          a = unscaled_value(lp, a, i);\n          if(putheader) {\n            write_data(userhandle, write_modeldata, \"BOUNDS\\n\");\n            putheader = FALSE;\n          }\n          if(lp->orig_lowbo[i] != -lp->infinite)\n            write_data(userhandle, write_modeldata, \" LO BND       %s  %s\\n\",\n                            MPSname(name0, get_col_name(lp, j)),\n                            formatnumber12(numberbuffer, (double)a));\n          else\n            write_data(userhandle, write_modeldata, \" MI BND       %s\\n\",\n                            MPSname(name0, get_col_name(lp, j)));\n        }\n\n        if((lp->orig_upbo[i] < lp->infinite) || (is_semicont(lp, j))) {\n          a = lp->orig_upbo[i];\n          if(a < lp->infinite)\n            a = unscaled_value(lp, a, i);\n          if(putheader) {\n            write_data(userhandle, write_modeldata, \"BOUNDS\\n\");\n            putheader = FALSE;\n          }\n          if(is_semicont(lp, j)) {\n            if(is_int(lp, j))\n              write_data(userhandle, write_modeldata, \" SI BND       %s  %s\\n\",\n                              MPSname(name0, get_col_name(lp, j)),\n                  (a < lp->infinite) ? formatnumber12(numberbuffer, (double)a) : \"            \");\n            else\n              write_data(userhandle, write_modeldata, \" SC BND       %s  %s\\n\",\n                              MPSname(name0, get_col_name(lp, j)),\n                              (a < lp->infinite) ? formatnumber12(numberbuffer, (double)a) : \"            \");\n          }\n          else\n            write_data(userhandle, write_modeldata, \" UP BND       %s  %s\\n\",\n                            MPSname(name0, get_col_name(lp, j)),\n                            formatnumber12(numberbuffer, (double)a));\n        }\n      }\n    }\n\n /* Write optional SOS section */\n  putheader = TRUE;\n  for(i = 0; i < SOS_count(lp); i++) {\n    SOSgroup *SOS = lp->SOS;\n\n    if(putheader) {\n      write_data(userhandle, write_modeldata, \"SOS\\n\");\n      putheader = FALSE;\n    }\n    write_data(userhandle, write_modeldata, \" S%1d SOS       %s  %s\\n\",\n                    SOS->sos_list[i]->type,\n                    MPSname(name0, SOS->sos_list[i]->name),\n                    formatnumber12(numberbuffer, (double) SOS->sos_list[i]->priority));\n    for(j = 1; j <= SOS->sos_list[i]->size; j++) {\n      write_data(userhandle, write_modeldata, \"    SOS       %s  %s\\n\",\n                      MPSname(name0, get_col_name(lp, SOS->sos_list[i]->members[j])),\n                      formatnumber12(numberbuffer, (double) SOS->sos_list[i]->weights[j]));\n    }\n  }\n\n  write_data(userhandle, write_modeldata, \"ENDATA\\n\");\n\n  lp->names_used = names_used;\n\n  return(ok);\n}\n\nstatic int __WINAPI write_lpdata(void *userhandle, char *buf)\n{\n  fputs(buf, (FILE *) userhandle);\n  return(TRUE);\n}\n\nMYBOOL MPS_writefile(lprec *lp, int typeMPS, const char *filename)\n{\n  FILE *output = stdout;\n  MYBOOL ok;\n\n  if (filename != NULL) {\n    ok = ((output = fopen(filename, \"w\")) != NULL);\n    if(!ok)\n      return(ok);\n  }\n  else\n    output = lp->outstream;\n\n  ok = MPS_writefileex(lp, typeMPS, (void *) output, write_lpdata);\n\n  if (filename != NULL)\n    fclose(output);\n\n  return(ok);\n}\n\nMYBOOL MPS_writehandle(lprec *lp, int typeMPS, FILE *output)\n{\n  MYBOOL ok;\n\n  if (output != NULL)\n    set_outputstream(lp, output);\n\n  output = lp->outstream;\n\n  ok = MPS_writefileex(lp, typeMPS, (void *) output, write_lpdata);\n\n  return(ok);\n}\n\n\n/* Read and write BAS files */\n/* #define OldNameMatch */\n#ifdef OldNameMatch\nstatic int MPS_getnameidx(lprec *lp, const char *varname, MYBOOL isrow)\n{\n  int in = -1;\n\n  in = get_nameindex(lp, varname, isrow);\n  if((in < 0) && (strncmp(varname, (isrow ? ROWNAMEMASK : COLNAMEMASK), 1) == 0)) {\n    if(sscanf(varname + 1, \"%d\", &in) != 1)\n      in = -1;\n  }\n  return( in );\n}\n#else\nstatic int MPS_getnameidx(lprec *lp, const char *varname, MYBOOL tryrowfirst)\n{\n  int in = -1;\n\n  /* Have we defined our own variable names? */\n  if(lp->names_used) {\n    /* First check the primary name list */\n    in = get_nameindex(lp, varname, tryrowfirst);\n    if((in > 0) && !tryrowfirst)\n      in += lp->rows;\n    /* If we were unsuccessful, try the secondary name list */\n    else if(in < 0) {\n      in = get_nameindex(lp, varname, (MYBOOL) !tryrowfirst);\n      if((in > 0) && tryrowfirst)\n        in += lp->rows;\n    }\n  }\n  /* If not, see if we can match the standard name mask */\n\n  if(in == -1) {\n    if(strncmp(varname, (tryrowfirst ? ROWNAMEMASK : COLNAMEMASK), 1) == 0) {\n      /* Fail if we did not successfully scan as a valid integer */\n      if((sscanf(varname + 1, \"%d\", &in) != 1) ||\n         (in < (tryrowfirst ? 0 : 1)) || (in > (tryrowfirst ? lp->rows : lp->columns)))\n        in = -1;\n    }\n    else if(strncmp(varname, (!tryrowfirst ? ROWNAMEMASK : COLNAMEMASK), 1) == 0) {\n      /* Fail if we did not successfully scan as a valid integer */\n      if((sscanf(varname + 1, \"%d\", &in) != 1) ||\n         (in < (tryrowfirst ? 0 : 1)) || (in > (tryrowfirst ? lp->rows : lp->columns)))\n        in = -1;\n    }\n  }\n  return( in );\n}\n#endif\n\nMYBOOL MPS_readBAS(lprec *lp, int typeMPS, const char *filename, char *info)\n{\n  char   field1[BUFSIZ], field2[BUFSIZ], field3[BUFSIZ], field5[BUFSIZ],\n         line[BUFSIZ], tmp[BUFSIZ], *ptr;\n  double field4, field6;\n  int    ib, in, items, Lineno = 0;\n  MYBOOL ok;\n  FILE   *input = stdin;\n  int    (*scan_line)(lprec *lp, int section, char* line, char *field1, char *field2, char *field3,\n                      double *field4, char *field5, double *field6);\n\n  if((typeMPS & MPSFIXED) == MPSFIXED)\n    scan_line = scan_lineFIXED;\n  else if((typeMPS & MPSFREE) == MPSFREE)\n    scan_line = scan_lineFREE;\n  else {\n    report(lp, IMPORTANT, \"MPS_readBAS: unrecognized MPS line type.\\n\");\n    return(FALSE);\n  }\n\n  ok = (MYBOOL) ((filename != NULL) && ((input = fopen(filename,\"r\")) != NULL));\n  if(!ok)\n    return(ok);\n  default_basis(lp);\n\n  /* Let's initialize line to all zero's */\n  MEMCLEAR(line, BUFSIZ);\n  ok = FALSE;\n  while(fgets(line, BUFSIZ - 1, input)) {\n    Lineno++;\n\n    for(ptr = line; (*ptr) && (isspace((unsigned char) *ptr)); ptr++);\n\n    /* skip lines which start with \"*\", they are comment */\n    if((line[0] == '*') || (*ptr == 0) || (*ptr == '\\n') || (*ptr == '\\r')) {\n      report(lp, FULL, \"Comment on line %d: %s\", Lineno, line);\n      continue;\n    }\n\n    report(lp, FULL, \"Line %6d: %s\", Lineno, line);\n\n    /* first check for \"special\" lines: in our case only NAME and ENDATA,\n       ...this must start in the first position of line */\n    if(line[0] != ' ') {\n      sscanf(line, \"%s\", tmp);\n      if(strcmp(tmp, \"NAME\") == 0) {\n        if(info != NULL) {\n          *info = 0;\n          for(ptr = line + 4; (*ptr) && (isspace((unsigned char) *ptr)); ptr++);\n          in = (int) strlen(ptr);\n          while ((in > 0) && ((ptr[in - 1] == '\\r') || (ptr[in - 1] == '\\n') || isspace(ptr[in - 1])))\n            in--;\n          ptr[in] = 0;\n          strcpy(info, ptr);\n        }\n      }\n      else if(strcmp(tmp, \"ENDATA\") == 0) {\n        report(lp, FULL, \"Finished reading BAS file\\n\");\n        ok = TRUE;\n        break;\n      }\n      else { /* line does not start with space and does not match above */\n        report(lp, IMPORTANT, \"Unrecognized BAS line %d: %s\\n\", Lineno, line);\n        break;\n      }\n    }\n    else { /* normal line, process */\n      items = scan_line(lp, /* MPSRHS */ MPSBOUNDS, line, field1, field2, field3, &field4, field5, &field6);\n      if(items < 0){\n        report(lp, IMPORTANT, \"Syntax error on line %d: %s\\n\", Lineno, line);\n        break;\n      }\n      /* find first variable index value */\n      in = MPS_getnameidx(lp, field2, FALSE);\n#ifdef OldNameMatch\n      if(in < 0)\n        in = MPS_getnameidx(lp, field2, TRUE);\n      else\n        in += lp->rows;\n#endif\n      if(in < 0)\n        break;\n\n      /* check if we have the basic/non-basic variable format */\n      if(field1[0] == 'X') {\n        /* find second variable index value */\n        ib = in;\n        in = MPS_getnameidx(lp, field3, FALSE);\n#ifdef OldNameMatch\n        if(in < 0)\n          in = MPS_getnameidx(lp, field3, TRUE);\n        else\n          in += lp->rows;\n#endif\n        if(in < 0)\n          break;\n\n        lp->is_lower[in] = (MYBOOL) (field1[1] == 'L');\n        lp->is_basic[ib] = TRUE;\n      }\n      else\n        lp->is_lower[in] = (MYBOOL) (field1[0] == 'L');\n\n      lp->is_basic[in] = FALSE;\n\n    }\n  }\n  /* Update the basis index-to-variable array */\n  ib = 0;\n  items = lp->sum;\n  for(in = 1; in <= items; in++)\n    if(lp->is_basic[in]) {\n      ib++;\n      lp->var_basic[ib] = in;\n    }\n\n  fclose(input);\n  return( ok );\n}\n\nMYBOOL MPS_writeBAS(lprec *lp, int typeMPS, const char *filename)\n{\n  int    ib, in;\n  MYBOOL ok;\n  char   name1[100], name2[100];\n  FILE   *output = stdout;\n  const char * (*MPSname)(char *name0, const char *name);\n  char name0[9];\n\n  /* Set name formatter */\n  if((typeMPS & MPSFIXED) == MPSFIXED)\n    MPSname = MPSnameFIXED;\n  else if((typeMPS & MPSFREE) == MPSFREE)\n    MPSname = MPSnameFREE;\n  else {\n    report(lp, IMPORTANT, \"MPS_writeBAS: unrecognized MPS name type.\\n\");\n    return(FALSE);\n  }\n\n  /* Open the file for writing */\n  ok = (MYBOOL) ((filename == NULL) || ((output = fopen(filename,\"w\")) != NULL));\n  if(!ok)\n    return(ok);\n  if(filename == NULL && lp->outstream != NULL)\n    output = lp->outstream;\n\n  fprintf(output, \"NAME          %s Rows %d Cols %d Iters %.0f\\n\",\n                  get_lp_name(lp), lp->rows, lp->columns, (double) get_total_iter(lp));\n\n  ib = lp->rows;\n  in = 0;\n  while ((ib < lp->sum) || (in < lp->sum)) {\n\n    /* Find next basic variable (skip slacks) */\n    ib++;\n    while((ib <= lp->sum) && !lp->is_basic[ib])\n      ib++;\n\n    /* Find next non-basic variable (skip lower-bounded structural variables) */\n    in++;\n    while((in <= lp->sum) && (lp->is_basic[in] ||\n                              ((in > lp->rows) && lp->is_lower[in])))\n      in++;\n\n    /* Check if we have a basic/non-basic variable pair */\n    if((ib <= lp->sum) && (in <= lp->sum)) {\n      strcpy(name1, MPSname(name0, (ib <= lp->rows ? get_row_name(lp, ib) :\n                                              get_col_name(lp, ib-lp->rows))));\n      strcpy(name2, MPSname(name0, (in <= lp->rows ? get_row_name(lp, in) :\n                                              get_col_name(lp, in-lp->rows))));\n      fprintf(output, \" %2s %s  %s\\n\", (lp->is_lower[in] ? \"XL\" : \"XU\"), name1, name2);\n    }\n\n    /* Otherwise just write the bound state of the non-basic variable */\n    else if(in <= lp->sum) {\n      strcpy(name1, MPSname(name0, (in <= lp->rows ? get_row_name(lp, in) :\n                                              get_col_name(lp, in-lp->rows))));\n      fprintf(output, \" %2s %s\\n\", (lp->is_lower[in] ? \"LL\" : \"UL\"), name1);\n    }\n\n  }\n  fprintf(output, \"ENDATA\\n\");\n\n  if(filename != NULL)\n    fclose(output);\n  return( ok );\n}\n"
  },
  {
    "path": "utilities/lp_solve/lp_MPS.h",
    "content": "#ifndef HEADER_lp_MPS\n#define HEADER_lp_MPS\n\n#include \"lp_types.h\"\n\n/* For MPS file reading and writing */\n#define ROWNAMEMASK          \"R%d\"\n#define ROWNAMEMASK2         \"r%d\"\n#define COLNAMEMASK          \"C%d\"\n#define COLNAMEMASK2         \"c%d\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Read an MPS file */\nMYBOOL MPS_readfile(lprec **newlp, const char *filename, int typeMPS, int verbose);\nMYBOOL __WINAPI MPS_readhandle(lprec **newlp, FILE *filehandle, int typeMPS, int verbose);\n\n/* Write a MPS file to output */\nMYBOOL MPS_writefile(lprec *lp, int typeMPS, const char *filename);\nMYBOOL MPS_writehandle(lprec *lp, int typeMPS, FILE *output);\n\n/* Read and write BAS files */\nMYBOOL MPS_readBAS(lprec *lp, int typeMPS, const char *filename, char *info);\nMYBOOL MPS_writeBAS(lprec *lp, int typeMPS, const char *filename);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_MPS */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_SOS.c",
    "content": "\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_report.h\"\n#include \"lp_SOS.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n/*\n    Specially Ordered Set (SOS) routines - w/interface for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      lp_lib.h\n\n    Release notes:\n    v1.0    1 September 2003    Complete package for SOS creation and use in a LP\n                                setting.  Notable feature of this implementation\n                                compared to those in other commercial systems is\n                                the generalization to SOS'es of \"unlimited\" order.\n    v1.1     8 December 2003    Added variable (index) deletion method.\n    v1.2    17 December 2004    Added bound change tracking functionality.\n    v1.3    18 September 2005   Added sparse SOS handling to speed up processing\n                                of large number of SOS'es.\n\n   ----------------------------------------------------------------------------------\n*/\n\n/* SOS group functions */\nSTATIC SOSgroup *create_SOSgroup(lprec *lp)\n{\n  SOSgroup *group;\n\n  group = (SOSgroup *) calloc(1, sizeof(*group));\n  group->lp = lp;\n  group->sos_alloc = SOS_START_SIZE;\n  group->sos_list = (SOSrec **) malloc((group->sos_alloc) * sizeof(*group->sos_list));\n  return(group);\n}\n\nSTATIC void resize_SOSgroup(SOSgroup *group)\n{\n  if(group->sos_count == group->sos_alloc) {\n    group->sos_alloc = (int)((double) group->sos_alloc*RESIZEFACTOR);\n    group->sos_list = (SOSrec **) realloc(group->sos_list,\n                                          (group->sos_alloc) * sizeof(*group->sos_list));\n  }\n}\n\nSTATIC int append_SOSgroup(SOSgroup *group, SOSrec *SOS)\n{\n  int    i, k;\n  SOSrec *SOSHold;\n\n  /* Check if we should resize */\n  resize_SOSgroup(group);\n\n  /* First append to the end of the list */\n  group->sos_list[group->sos_count] = SOS;\n  group->sos_count++;\n  i = abs(SOS->type);\n  SETMAX(group->maxorder, i);\n  if(i == 1)\n    group->sos1_count++;\n  k = group->sos_count;\n  SOS->tagorder = k;\n\n  /* Sort the SOS list by given priority */\n  for(i = group->sos_count-1; i > 0; i--) {\n    if(group->sos_list[i]->priority < group->sos_list[i-1]->priority) {\n      SOSHold = group->sos_list[i];\n      group->sos_list[i] = group->sos_list[i-1];\n      group->sos_list[i-1] = SOSHold;\n      if(SOSHold == SOS)\n        k = i; /* This is the index in the [1..> range */\n    }\n    else\n      break;\n  }\n  /* Return the list index of the new SOS */\n  return( k );\n}\n\n\nSTATIC int clean_SOSgroup(SOSgroup *group, MYBOOL forceupdatemap)\n{\n  int    i, n, k;\n  SOSrec *SOS;\n\n  if(group == NULL)\n    return( 0 );\n\n  /* Delete any SOS without members or trivial member count */\n  n = 0;\n  if(group->sos_alloc > 0) {\n    group->maxorder = 0;\n    for(i = group->sos_count; i > 0; i--) {\n      SOS = group->sos_list[i-1];\n      k = SOS->members[0];\n      if((k == 0) ||                              /* Empty */\n         ((k == abs(SOS->type)) && (k <= 2))) {   /* Trivial */\n        delete_SOSrec(group, i);\n        n++;\n      }\n      else {\n        SETMAX(group->maxorder, abs(SOS->type));\n      }\n    }\n    if((n > 0) || forceupdatemap)\n      SOS_member_updatemap(group);\n  }\n  return( n );\n}\n\n\nSTATIC void free_SOSgroup(SOSgroup **group)\n{\n  int i;\n\n  if((group == NULL) || (*group == NULL))\n    return;\n  if((*group)->sos_alloc > 0) {\n    for(i = 0; i < (*group)->sos_count; i++)\n      free_SOSrec((*group)->sos_list[i]);\n    FREE((*group)->sos_list);\n    FREE((*group)->membership);\n    FREE((*group)->memberpos);\n  }\n  FREE(*group);\n}\n\n/* SOS record functions */\nSTATIC SOSrec *create_SOSrec(SOSgroup *group, const char *name, int type, int priority, int size, int *variables, REAL *weights)\n{\n  SOSrec *SOS;\n\n  SOS = (SOSrec *) calloc(1 , sizeof(*SOS));\n  SOS->parent = group;\n  SOS->type = type;\n  if(name == NULL)\n    SOS->name = NULL;\n  else\n  {\n    allocCHAR(group->lp, &SOS->name, (int) (strlen(name)+1), FALSE);\n    strcpy(SOS->name, name);\n  }\n  if(type < 0)\n    type = abs(type);\n  SOS->tagorder = 0;\n  SOS->size = 0;\n  SOS->priority = priority;\n  SOS->members = NULL;\n  SOS->weights = NULL;\n  SOS->membersSorted = NULL;\n  SOS->membersMapped = NULL;\n\n  if(size > 0)\n    size = append_SOSrec(SOS, size, variables, weights);\n\n  return(SOS);\n}\n\n\nSTATIC int append_SOSrec(SOSrec *SOS, int size, int *variables, REAL *weights)\n{\n  int   i, oldsize, newsize, nn;\n  lprec *lp = SOS->parent->lp;\n\n  oldsize = SOS->size;\n  newsize = oldsize + size;\n  nn = abs(SOS->type);\n\n /* Shift existing active data right (normally zero) */\n  if(SOS->members == NULL)\n    allocINT(lp, &SOS->members, 1+newsize+1+nn, TRUE);\n  else {\n    allocINT(lp, &SOS->members, 1+newsize+1+nn, AUTOMATIC);\n    for(i = newsize+1+nn; i > newsize+1; i--)\n    SOS->members[i] = SOS->members[i-size];\n  }\n  SOS->members[0] = newsize;\n  SOS->members[newsize+1] = nn;\n\n /* Copy the new data into the arrays */\n  if(SOS->weights == NULL)\n    allocREAL(lp, &SOS->weights, 1+newsize, TRUE);\n  else\n    allocREAL(lp, &SOS->weights, 1+newsize, AUTOMATIC);\n  for(i = oldsize+1; i <= newsize; i++) {\n    SOS->members[i] = variables[i-oldsize-1];\n    if((SOS->members[i] < 1) || (SOS->members[i] > lp->columns))\n      report(lp, IMPORTANT, \"append_SOS_rec: Invalid SOS variable definition for index %d\\n\", SOS->members[i]);\n    else {\n      if(SOS->isGUB)\n        lp->var_type[SOS->members[i]] |= ISGUB;\n      else\n        lp->var_type[SOS->members[i]] |= ISSOS;\n    }\n    if(weights == NULL)\n      SOS->weights[i] = i;  /* Follow standard, which is sorted ascending */\n    else\n      SOS->weights[i] = weights[i-oldsize-1];\n    SOS->weights[0] += SOS->weights[i];\n  }\n\n /* Sort the new paired lists ascending by weight (simple bubble sort) */\n  i = sortByREAL(SOS->members, SOS->weights, newsize, 1, TRUE);\n  if(i > 0)\n    report(lp, DETAILED, \"append_SOS_rec: Non-unique SOS variable weight for index %d\\n\", i);\n\n /* Define mapping arrays to search large SOS's faster */\n  allocINT(lp, &SOS->membersSorted, newsize, AUTOMATIC);\n  allocINT(lp, &SOS->membersMapped, newsize, AUTOMATIC);\n  for(i = oldsize+1; i <= newsize; i++) {\n    SOS->membersSorted[i - 1] = SOS->members[i];\n    SOS->membersMapped[i - 1] = i;\n  }\n  sortByINT(SOS->membersMapped, SOS->membersSorted, newsize, 0, TRUE);\n\n /* Confirm the new size */\n  SOS->size = newsize;\n\n  return(newsize);\n\n}\n\nSTATIC int make_SOSchain(lprec *lp, MYBOOL forceresort)\n{\n  int      i, j, k, n;\n  MYBOOL   *hold = NULL;\n  REAL     *order, sum, weight;\n  SOSgroup *group = lp->SOS;\n\n  /* PART A: Resort individual SOS member lists, if specified */\n  if(forceresort)\n    SOS_member_sortlist(group, 0);\n\n  /* PART B: Tally SOS variables and create master SOS variable list */\n  n = 0;\n  for(i = 0; i < group->sos_count; i++)\n    n += group->sos_list[i]->size;\n  lp->sos_vars = n;\n  if(lp->sos_vars > 0) /* Prevent memory loss in case of multiple solves */\n    FREE(lp->sos_priority);\n  allocINT(lp, &lp->sos_priority, n, FALSE);\n  allocREAL(lp, &order, n, FALSE);\n\n  /* Move variable data to the master SOS list and sort by ascending weight */\n  n = 0;\n  sum = 0;\n  for(i = 0; i < group->sos_count; i++) {\n    for(j = 1; j <= group->sos_list[i]->size; j++) {\n      lp->sos_priority[n] = group->sos_list[i]->members[j];\n      weight = group->sos_list[i]->weights[j];\n      sum += weight;\n      order[n] = sum;\n      n++;\n    }\n  }\n  hpsortex(order, n, 0, sizeof(*order), FALSE, compareREAL, lp->sos_priority);\n  FREE(order);\n\n  /* Remove duplicate SOS variables */\n  allocMYBOOL(lp, &hold, lp->columns+1, TRUE);\n  k = 0;\n  for(i = 0; i < n; i++) {\n    j = lp->sos_priority[i];\n    if(!hold[j]) {\n      hold[j] = TRUE;\n      if(k < i)\n        lp->sos_priority[k] = j;\n      k++;\n    }\n  }\n  FREE(hold);\n\n  /* Adjust the size of the master variable list, if necessary */\n  if(k < lp->sos_vars) {\n    allocINT(lp, &lp->sos_priority, k, AUTOMATIC);\n    lp->sos_vars = k;\n  }\n\n  return( k );\n\n}\n\n\nSTATIC MYBOOL delete_SOSrec(SOSgroup *group, int sosindex)\n{\n#ifdef Paranoia\n  if((sosindex <= 0) || (sosindex > group->sos_count)) {\n    report(group->lp, IMPORTANT, \"delete_SOSrec: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  /* Delete and free the SOS record */\n  if(abs(SOS_get_type(group, sosindex)) == 1)\n    group->sos1_count--;\n  free_SOSrec(group->sos_list[sosindex-1]);\n  while(sosindex < group->sos_count) {\n    group->sos_list[sosindex-1] = group->sos_list[sosindex];\n    sosindex++;\n  }\n  group->sos_count--;\n\n  /* Update maxorder */\n  group->maxorder = 0;\n  for(sosindex = 0; sosindex < group->sos_count; sosindex++) {\n    SETMAX(group->maxorder, abs(group->sos_list[sosindex]->type));\n  }\n\n  return(TRUE);\n}\n\n\nSTATIC void free_SOSrec(SOSrec *SOS)\n{\n  if(SOS->name != NULL)\n    FREE(SOS->name);\n  if(SOS->size > 0) {\n    FREE(SOS->members);\n    FREE(SOS->weights);\n    FREE(SOS->membersSorted);\n    FREE(SOS->membersMapped);\n  }\n  FREE(SOS);\n}\n\n\nSTATIC MYBOOL SOS_member_sortlist(SOSgroup *group, int sosindex)\n/* Routine to (re-)sort SOS member arrays for faster access to large SOSes */\n{\n  int    i, n;\n  int    *list;\n  lprec  *lp = group->lp;\n  SOSrec *SOS;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_member_sortlist: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if((sosindex == 0) && (group->sos_count == 1))\n    sosindex = 1;\n\n  if(sosindex == 0) {\n    for(i = 1; i <= group->sos_count; i++) {\n      if(!SOS_member_sortlist(group, i))\n        return(FALSE);\n    }\n  }\n  else {\n    SOS = group->sos_list[sosindex-1];\n    list = SOS->members;\n    n = list[0];\n    /* Make sure that the arrays are properly allocated and sized */\n    if(n != group->sos_list[sosindex-1]->size) {\n      allocINT(lp, &SOS->membersSorted, n, AUTOMATIC);\n      allocINT(lp, &SOS->membersMapped, n, AUTOMATIC);\n      group->sos_list[sosindex-1]->size = n;\n    }\n    /* Reload the arrays and do the sorting */\n    for(i = 1; i <= n; i++) {\n      SOS->membersSorted[i - 1] = list[i];\n      SOS->membersMapped[i - 1] = i;\n    }\n    sortByINT(SOS->membersMapped, SOS->membersSorted, n, 0, TRUE);\n  }\n  return( TRUE );\n}\n\nSTATIC int SOS_member_updatemap(SOSgroup *group)\n{\n  int      i, j, k, n, nvars = 0,\n           *list, *tally = NULL;\n  SOSrec   *rec;\n  lprec    *lp = group->lp;\n\n  /* (Re)-initialize usage arrays */\n  allocINT(lp, &group->memberpos, lp->columns+1, AUTOMATIC);\n  allocINT(lp, &tally, lp->columns+1, TRUE);\n\n  /* Get each variable's SOS membership count */\n  for(i = 0; i < group->sos_count; i++) {\n    rec = group->sos_list[i];\n    n = rec->size;\n    list = rec->members;\n    for(j = 1; j <= n; j++) {\n      k = list[j];\n#ifdef Paranoia\n      if((k < 1) || (k > lp->columns))\n        report(lp, SEVERE, \"SOS_member_updatemap: Member %j of SOS number %d is out of column range (%d)\\n\",\n                            j, i+1, k);\n#endif\n      tally[k]++;\n    }\n\n  }\n\n  /* Compute pointer into column-sorted array */\n  group->memberpos[0] = 0;\n  for(i = 1; i <= lp->columns; i++) {\n    n = tally[i];\n    if(n > 0)\n      nvars++;\n    group->memberpos[i] = group->memberpos[i-1] + n;\n  }\n  n = group->memberpos[lp->columns];\n  MEMCOPY(tally+1, group->memberpos, lp->columns);\n\n  /* Load the column-sorted SOS indeces / pointers */\n  allocINT(lp, &group->membership, n+1, AUTOMATIC);\n  for(i = 0; i < group->sos_count; i++) {\n    rec = group->sos_list[i];\n    n = rec->size;\n    list = rec->members;\n    for(j = 1; j <= n; j++) {\n      k = tally[list[j]]++;\n#ifdef Paranoia\n      if(k > group->memberpos[lp->columns])\n        report(lp, SEVERE, \"SOS_member_updatemap: Member mapping for variable %j of SOS number %d is invalid\\n\",\n                            list[j], i+1);\n#endif\n      group->membership[k] = i+1;\n    }\n  }\n  FREE(tally);\n\n  return( nvars );\n}\n\n\nSTATIC MYBOOL SOS_shift_col(SOSgroup *group, int sosindex, int column, int delta, LLrec *usedmap, MYBOOL forceresort)\n/* Routine to adjust SOS indeces for variable insertions or deletions;\n   Note: SOS_shift_col must be called before make_SOSchain! */\n{\n  int    i, ii, n, nn, nr;\n  int    changed;\n  int    *list;\n  REAL   *weights;\n\n#ifdef Paranoia\n  lprec  *lp = group->lp;\n\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_shift_col: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n  else if((column < 1) || (delta == 0)) {\n    report(lp, IMPORTANT, \"SOS_shift_col: Invalid column %d specified with delta %d\\n\",\n                          column, delta);\n    return(FALSE);\n  }\n#endif\n\n  if((sosindex == 0) && (group->sos_count == 1))\n    sosindex = 1;\n\n  if(sosindex == 0) {\n    for(i = 1; i <= group->sos_count; i++) {\n      if(!SOS_shift_col(group, i, column, delta, usedmap, forceresort))\n        return(FALSE);\n    }\n  }\n  else {\n    list = group->sos_list[sosindex-1]->members;\n    weights = group->sos_list[sosindex-1]->weights;\n    n = list[0];\n    nn = list[n+1];\n\n    /* Case where variable indeces are to be incremented */\n    if(delta > 0) {\n      for(i = 1; i <= n; i++) {\n        if(list[i] >= column)\n          list[i] += delta;\n      }\n    }\n    /* Case where variables are to be deleted/indeces decremented */\n    else {\n      changed = 0;\n      if(usedmap != NULL) {\n        int *newidx = NULL;\n        /* Defer creation of index mapper until we are sure that a\n           member of this SOS is actually targeted for deletion */\n        if(newidx == NULL) {\n          allocINT(group->lp, &newidx, group->lp->columns+1, TRUE);\n          for(i = firstActiveLink(usedmap), ii = 1; i != 0;\n              i = nextActiveLink(usedmap, i), ii++)\n            newidx[i] = ii;\n        }\n        for(i = 1, ii = 0; i <= n; i++) {\n          nr = list[i];\n          /* Check if this SOS variable should be deleted */\n          if(!isActiveLink(usedmap, nr))\n            continue;\n\n          /* If the index is \"high\" then make adjustment and shift */\n          changed++;\n          ii++;\n          list[ii] = newidx[nr];\n          weights[ii] = weights[i];\n        }\n        FREE(newidx);\n      }\n      else\n        for(i = 1, ii = 0; i <= n; i++) {\n          nr = list[i];\n          /* Check if this SOS variable should be deleted */\n          if((nr >= column) && (nr < column-delta))\n            continue;\n          /* If the index is \"high\" then decrement */\n          if(nr > column) {\n            changed++;\n            nr += delta;\n          }\n          ii++;\n          list[ii] = nr;\n          weights[ii] = weights[i];\n        }\n      /* Update the SOS length / type indicators */\n      if(ii < n) {\n        list[0] = ii;\n        list[ii+1] = nn;\n      }\n\n     /* Update mapping arrays to search large SOS's faster */\n      if(forceresort && ((ii < n) || (changed > 0)))\n        SOS_member_sortlist(group, sosindex);\n    }\n\n  }\n  return(TRUE);\n\n}\n\nint SOS_member_count(SOSgroup *group, int sosindex)\n{\n  SOSrec *SOS;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(group->lp, IMPORTANT, \"SOS_member_count: Invalid SOS index %d\\n\", sosindex);\n    return( -1 );\n  }\n#endif\n  SOS = group->sos_list[sosindex-1];\n  return( SOS->members[0] );\n}\n\nint SOS_member_delete(SOSgroup *group, int sosindex, int member)\n{\n  int   *list, i, i2, k, n, nn = 0;\n  SOSrec *SOS;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(group->lp, IMPORTANT, \"SOS_member_delete: Invalid SOS index %d\\n\", sosindex);\n    return( -1 );\n  }\n#endif\n\n  if(sosindex == 0) {\n    for(i = group->memberpos[member-1]; i < group->memberpos[member]; i++) {\n      k = group->membership[i];\n      n = SOS_member_delete(group, k, member);\n      if(n >= 0)\n        nn += n;\n      else\n        return( n );\n    }\n    /* We must update the mapper */\n    k = group->memberpos[member];\n    i = group->memberpos[member-1];\n    n = group->memberpos[lp->columns] - k;\n    if(n > 0)\n      MEMCOPY(group->membership + i, group->membership + k, n);\n    for(i = member; i <= lp->columns; i++)\n      group->memberpos[i] = group->memberpos[i-1];\n  }\n  else {\n    SOS = group->sos_list[sosindex-1];\n    list = SOS->members;\n    n = list[0];\n\n    /* Find the offset of the member */\n    i = 1;\n    while((i <= n) && (abs(list[i]) != member))\n      i++;\n    if(i > n)\n      return( -1 );\n    nn++;\n\n    /* Shift remaining members *and* the active count one position left */\n    while(i <= n) {\n      list[i] = list[i+1];\n      i++;\n    }\n    list[0]--;\n    SOS->size--;\n\n    /* Do the same with the active list one position left */\n    i = n + 1;\n    i2 = i + list[n];\n    k = i + 1;\n    while(i < i2) {\n      if(abs(list[k]) == member)\n        k++;\n      list[i] = list[k];\n      i++;\n      k++;\n    }\n  }\n\n  return( nn );\n}\n\nint SOS_get_type(SOSgroup *group, int sosindex)\n{\n#ifdef Paranoia\n  if((sosindex < 1) || (sosindex > group->sos_count)) {\n    report(group->lp, IMPORTANT, \"SOS_get_type: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  return(group->sos_list[sosindex-1]->type);\n}\n\n\nint SOS_infeasible(SOSgroup *group, int sosindex)\n{\n  int    i, n, nn, varnr, failindex, *list;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_infeasible: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if(sosindex == 0 && group->sos_count == 1)\n    sosindex = 1;\n\n  failindex = 0;\n  if(sosindex == 0) {\n    for(i = 1; i <= group->sos_count; i++) {\n      failindex = SOS_infeasible(group, i);\n      if(failindex > 0) break;\n    }\n  }\n  else {\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0];\n    nn = list[n+1];\n   /* Find index of next lower-bounded variable */\n    for(i = 1; i <= n; i++) {\n      varnr = abs(list[i]);\n      if((lp->orig_lowbo[lp->rows + varnr] > 0) &&\n         !((lp->sc_vars > 0) && is_semicont(lp, varnr)))\n        break;\n    }\n\n   /* Find if there is another lower-bounded variable beyond the type window */\n    i = i+nn;\n    while(i <= n) {\n      varnr = abs(list[i]);\n      if((lp->orig_lowbo[lp->rows + varnr] > 0) &&\n         !((lp->sc_vars > 0) && is_semicont(lp, varnr)))\n        break;\n      i++;\n    }\n    if(i <= n)\n      failindex = abs(list[i]);\n  }\n  return(failindex);\n}\n\n\nint SOS_member_index(SOSgroup *group, int sosindex, int member)\n{\n  int    n;\n  SOSrec *SOS;\n\n  SOS = group->sos_list[sosindex-1];\n  n = SOS->members[0];\n\n  n = searchFor(member, SOS->membersSorted, n, 0, FALSE);\n  if(n >= 0)\n    n = SOS->membersMapped[n];\n\n  return(n);\n}\n\n\nint SOS_memberships(SOSgroup *group, int varnr)\n{\n  int   i, n = 0;\n  lprec *lp;\n\n  /* Check if there is anything to do */\n  if((group == NULL) || (SOS_count(lp = group->lp) == 0))\n    return( n );\n\n#ifdef Paranoia\n  if((varnr < 0) || (varnr > lp->columns)) {\n    report(lp, IMPORTANT, \"SOS_memberships: Invalid variable index %d given\\n\", varnr);\n    return( n );\n  }\n#endif\n\n  if(varnr == 0) {\n    for(i = 1; i <= lp->columns; i++)\n      if(group->memberpos[i] > group->memberpos[i-1])\n        n++;\n  }\n  else\n    n = group->memberpos[varnr] - group->memberpos[varnr-1];\n\n  return( n );\n}\n\n\nint SOS_is_member(SOSgroup *group, int sosindex, int column)\n{\n  int    i, n = FALSE, *list;\n  lprec  *lp;\n\n  if(group == NULL)\n    return( FALSE );\n  lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_is_member: Invalid SOS index %d\\n\", sosindex);\n    return(n);\n  }\n#endif\n\n  if(sosindex == 0) {\n    if(lp->var_type[column] & (ISSOS | ISGUB))\n      n = (MYBOOL) (SOS_memberships(group, column) > 0);\n  }\n  else if(lp->var_type[column] & (ISSOS | ISGUB)) {\n\n   /* Search for the variable */\n    i = SOS_member_index(group, sosindex, column);\n\n   /* Signal active status if found, otherwise return FALSE */\n    if(i > 0) {\n      list = group->sos_list[sosindex-1]->members;\n      if(list[i] < 0)\n        n = -TRUE;\n      else\n      n = TRUE;\n    }\n  }\n  return(n);\n}\n\n\nMYBOOL SOS_is_member_of_type(SOSgroup *group, int column, int sostype)\n{\n  int i, k, n;\n\n  if(group != NULL)\n  for(i = group->memberpos[column-1]; i < group->memberpos[column]; i++) {\n    k = group->membership[i];\n    n = SOS_get_type(group, k);\n    if(((n == sostype) ||\n        ((sostype == SOSn) && (n > 2))) && SOS_is_member(group, k, column))\n      return(TRUE);\n  }\n  return(FALSE);\n}\n\n\nMYBOOL SOS_set_GUB(SOSgroup *group, int sosindex, MYBOOL state)\n{\n  int i;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(group->lp, IMPORTANT, \"SOS_set_GUB: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n  if((sosindex == 0) && (group->sos_count == 1))\n    sosindex = 1;\n\n  if(sosindex == 0) {\n    for(i = 1; i <= group->sos_count; i++)\n      SOS_set_GUB(group, i, state);\n  }\n  else\n    group->sos_list[sosindex-1]->isGUB = state;\n  return(TRUE);\n}\n\n\nMYBOOL SOS_is_GUB(SOSgroup *group, int sosindex)\n{\n  int    i;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(group->lp, IMPORTANT, \"SOS_is_GUB: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if((sosindex == 0) && (group->sos_count == 1))\n    sosindex = 1;\n\n  if(sosindex == 0) {\n    for(i = 1; i <= group->sos_count; i++) {\n      if(SOS_is_GUB(group, i))\n        return(TRUE);\n    }\n    return(FALSE);\n  }\n  else\n    return( group->sos_list[sosindex-1]->isGUB );\n}\n\n\nMYBOOL SOS_is_marked(SOSgroup *group, int sosindex, int column)\n{\n  int    i, k, n, *list;\n  lprec  *lp;\n\n  if(group == NULL)\n    return( FALSE );\n  lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_is_marked: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if(!(lp->var_type[column] & (ISSOS | ISGUB)))\n    return(FALSE);\n\n  if(sosindex == 0) {\n    for(i = group->memberpos[column-1]; i < group->memberpos[column]; i++) {\n      k = group->membership[i];\n      n = SOS_is_marked(group, k, column);\n      if(n)\n        return(TRUE);\n    }\n  }\n  else  {\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0];\n\n   /* Search for the variable (normally always faster to do linear search here) */\n    column = -column;\n    for(i = 1; i <= n; i++)\n      if(list[i] == column)\n        return(TRUE);\n  }\n  return(FALSE);\n}\n\n\nMYBOOL SOS_is_active(SOSgroup *group, int sosindex, int column)\n{\n  int    i, n, nn, *list;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_is_active: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if(!(lp->var_type[column] & (ISSOS | ISGUB)))\n    return(FALSE);\n\n  if(sosindex == 0) {\n    for(i = group->memberpos[column-1]; i < group->memberpos[column]; i++) {\n      nn = group->membership[i];\n      n = SOS_is_active(group, nn, column);\n      if(n)\n        return(TRUE);\n    }\n  }\n  else {\n\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0]+1;\n    nn = list[n];\n\n    /* Scan the active (non-zero) SOS index list */\n    for(i = 1; (i <= nn) && (list[n+i] != 0); i++)\n      if(list[n+i] == column)\n        return(TRUE);\n  }\n  return(FALSE);\n}\n\n\nMYBOOL SOS_is_full(SOSgroup *group, int sosindex, int column, MYBOOL activeonly)\n{\n  int    i, nn, n, *list;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_is_full: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if(!(lp->var_type[column] & (ISSOS | ISGUB)))\n    return(FALSE);\n\n  if(sosindex == 0) {\n    for(i = group->memberpos[column-1]; i < group->memberpos[column]; i++) {\n      nn = group->membership[i];\n      if(SOS_is_full(group, nn, column, activeonly))\n        return(TRUE);\n    }\n  }\n  else if(SOS_is_member(group, sosindex, column)) {\n\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0]+1;\n    nn = list[n];\n\n   /* Info: Last item in the active list is non-zero if the current SOS is full */\n    if(list[n+nn] != 0)\n      return(TRUE);\n\n    if(!activeonly) {\n      /* Spool to last active variable */\n      for(i = nn-1; (i > 0) && (list[n+i] == 0); i--);\n      /* Having found it, check if subsequent variables are set (via bounds) as inactive */\n      if(i > 0) {\n        nn -= i;  /* Compute unused active slots */\n        i = SOS_member_index(group, sosindex, list[n+i]);\n        for(; (nn > 0) && (list[i] < 0); i++, nn--);\n        if(nn == 0)\n          return(TRUE);\n      }\n    }\n  }\n\n  return(FALSE);\n}\n\n\nMYBOOL SOS_can_activate(SOSgroup *group, int sosindex, int column)\n{\n  int    i, n, nn, nz, *list;\n  lprec  *lp;\n\n  if(group == NULL)\n    return( FALSE );\n  lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_can_activate: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if(!(lp->var_type[column] & (ISSOS | ISGUB)))\n    return(FALSE);\n\n  if(sosindex == 0) {\n    for(i = group->memberpos[column-1]; i < group->memberpos[column]; i++) {\n      nn = group->membership[i];\n      n = SOS_can_activate(group, nn, column);\n      if(n == FALSE)\n        return(FALSE);\n    }\n  }\n  else if(SOS_is_member(group, sosindex, column)) {\n\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0]+1;\n    nn = list[n];\n\n#if 0\n    /* Accept if the SOS is empty */\n    if(list[n+1] == 0)\n      return(TRUE);\n#endif\n\n    /* Cannot activate a variable if the SOS is full */\n    if(list[n+nn] != 0)\n      return(FALSE);\n\n    /* Check if there are variables quasi-active via non-zero lower bounds */\n    nz = 0;\n    for(i = 1; i < n; i++)\n      if(lp->bb_bounds->lowbo[lp->rows+abs(list[i])] > 0) {\n        nz++;\n        /* Reject outright if selected column has a non-zero lower bound */\n        if(list[i] == column)\n          return(FALSE);\n      }\n#ifdef Paranoia\n    if(nz > nn)\n      report(lp, SEVERE, \"SOS_can_activate: Found too many non-zero member variables for SOS index %d\\n\", sosindex);\n#endif\n    for(i = 1; i <= nn; i++) {\n      if(list[n+i] == 0)\n        break;\n      if(lp->bb_bounds->lowbo[lp->rows+list[n+i]] == 0)\n        nz++;\n    }\n    if(nz == nn)\n      return(FALSE);\n\n    /* Accept if the SOS is empty */\n    if(list[n+1] == 0)\n      return(TRUE);\n\n    /* Check if we can set variable active in SOS2..SOSn\n      (must check left and right neighbours if one variable is already active) */\n    if(nn > 1) {\n\n     /* Find the variable that was last activated;\n       Also check that the candidate variable is not already active */\n      for(i = 1; i <= nn; i++) {\n        if(list[n+i] == 0)\n          break;\n        if(list[n+i] == column)\n          return(FALSE);\n      }\n      i--;\n      nn = list[n+i];\n\n      /* SOS accepts an additional variable; confirm neighbourness of candidate;\n         Search for the SOS set index of the last activated variable */\n      n = list[0];\n      for(i = 1; i <= n; i++)\n        if(abs(list[i]) == nn)\n          break;\n      if(i > n) {\n        report(lp, CRITICAL, \"SOS_can_activate: Internal index error at SOS %d\\n\", sosindex);\n        return(FALSE);\n      }\n\n      /* SOS accepts an additional variable; confirm neighbourness of candidate */\n\n      /* Check left neighbour */\n      if((i > 1) && (list[i-1] == column))\n        return(TRUE);\n      /* Check right neighbour */\n      if((i < n) && (list[i+1] == column))\n        return(TRUE);\n\n      /* It is not the right neighbour; return false */\n      return(FALSE);\n    }\n  }\n  return(TRUE);\n}\n\n\nMYBOOL SOS_set_marked(SOSgroup *group, int sosindex, int column, MYBOOL asactive)\n{\n  int    i, n, nn, *list;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_set_marked: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if(!(lp->var_type[column] & (ISSOS | ISGUB)))\n    return(FALSE);\n\n  if(sosindex == 0) {\n\n   /* Define an IBM-\"SOS3\" member variable temporarily as integer, if it is\n      not already a permanent integer; is reset in SOS_unmark */\n    if(asactive && !is_int(lp, column) && SOS_is_member_of_type(group, column, SOS3)) {\n      lp->var_type[column] |= ISSOSTEMPINT;\n      set_int(lp, column, TRUE);\n    }\n\n    nn = 0;\n    for(i = group->memberpos[column-1]; i < group->memberpos[column]; i++) {\n      n = group->membership[i];\n      if(SOS_set_marked(group, n, column, asactive))\n        nn++;\n    }\n    return((MYBOOL) (nn == group->sos_count));\n  }\n  else {\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0]+1;\n    nn = list[n];\n\n   /* Search for the variable */\n    i = SOS_member_index(group, sosindex, column);\n\n   /* First mark active in the set member list as used */\n    if((i > 0) && (list[i] > 0))\n      list[i] *= -1;\n    else\n      return(TRUE);\n\n   /* Then move the variable to the live list */\n    if(asactive) {\n      for(i = 1; i <= nn; i++) {\n        if(list[n+i] == column)\n          return(FALSE);\n        else if(list[n+i] == 0) {\n          list[n+i] = column;\n          return(FALSE);\n        }\n      }\n    }\n    return(TRUE);\n  }\n}\n\n\nMYBOOL SOS_unmark(SOSgroup *group, int sosindex, int column)\n{\n  int    i, n, nn, *list;\n  MYBOOL isactive;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_unmark: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if(!(lp->var_type[column] & (ISSOS | ISGUB)))\n    return(FALSE);\n\n\n  if(sosindex == 0) {\n\n    /* Undefine a SOS3 member variable that has temporarily been set as integer */\n    if(lp->var_type[column] & ISSOSTEMPINT) {\n      lp->var_type[column] &= !ISSOSTEMPINT;\n      set_int(lp, column, FALSE);\n    }\n\n    nn = 0;\n    for(i = group->memberpos[column-1]; i < group->memberpos[column]; i++) {\n      n = group->membership[i];\n      if(SOS_unmark(group, n, column))\n        nn++;\n    }\n    return((MYBOOL) (nn == group->sos_count));\n  }\n  else {\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0]+1;\n    nn = list[n];\n\n   /* Search for the variable */\n    i = SOS_member_index(group, sosindex, column);\n\n   /* Restore sign in main list */\n    if((i > 0) && (list[i] < 0))\n      list[i] *= -1;\n    else\n      return(TRUE);\n\n   /* Find the variable in the active list... */\n    isactive = SOS_is_active(group, sosindex, column);\n    if(isactive) {\n      for(i = 1; i <= nn; i++)\n        if(list[n+i] == column)\n          break;\n     /* ...shrink the list if found, otherwise return error */\n      if(i <= nn) {\n        for(; i<nn; i++)\n        list[n+i] = list[n+i+1];\n        list[n+nn] = 0;\n        return(TRUE);\n      }\n      return(FALSE);\n    }\n    else\n      return(TRUE);\n  }\n}\n\n\nint SOS_fix_unmarked(SOSgroup *group, int sosindex, int variable, REAL *bound, REAL value, MYBOOL isupper,\n                     int *diffcount, DeltaVrec *changelog)\n{\n  int    i, ii, count, n, nn, nLeft, nRight, *list;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_fix_unmarked: Invalid SOS index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  count = 0;\n  if(sosindex == 0) {\n    for(i = group->memberpos[variable-1]; i < group->memberpos[variable]; i++) {\n      n = group->membership[i];\n      count += SOS_fix_unmarked(group, n, variable, bound, value, isupper, diffcount, changelog);\n    }\n  }\n  else {\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0]+1;\n\n   /* Count the number of active and free SOS variables */\n    nn = list[n];\n    for(i = 1; i <= nn; i++) {\n      if(list[n+i] == 0)\n      break;\n    }\n    i--;\n    i = nn - i;  /* Establish the number of unused slots */\n\n   /* Determine the free SOS variable window */\n    if(i == nn) {\n      nLeft = 0;\n      nRight = SOS_member_index(group, sosindex, variable);\n    }\n    else {\n      nLeft  = SOS_member_index(group, sosindex, list[n+1]);\n      if(variable == list[n+1])\n        nRight = nLeft;\n      else\n        nRight = SOS_member_index(group, sosindex, variable);\n    }\n\n    nRight += i;  /* Loop (nRight+1)..n */\n\n   /* Fix variables outside of the free SOS variable window */\n    for(i = 1; i < n; i++)  {\n     /* Skip the SOS variable window */\n      if((i >= nLeft) && (i <= nRight))\n        continue;\n     /* Otherwise proceed to set bound */\n      ii = list[i];\n      if(ii > 0) {\n        ii += lp->rows;\n        if(bound[ii] != value) {\n         /* Verify that we don't violate original bounds */\n          if(isupper && (value < lp->orig_lowbo[ii]))\n            return(-ii);\n          else if(!isupper && (value > lp->orig_upbo[ii]))\n            return(-ii);\n         /* OK, set the new bound */\n          count++;\n          if(changelog == NULL)\n            bound[ii] = value;\n          else\n            modifyUndoLadder(changelog, ii, bound, value);\n\n        }\n        if((diffcount != NULL) && (lp->solution[ii] != value))\n          (*diffcount)++;\n      }\n    }\n  }\n  return(count);\n}\n\nint *SOS_get_candidates(SOSgroup *group, int sosindex, int column, MYBOOL excludetarget,\n                        REAL *upbound, REAL *lobound)\n{\n  int    i, ii, j, n, nn = 0, *list, *candidates = NULL;\n  lprec  *lp = group->lp;\n\n  if(group == NULL)\n    return( candidates );\n\n#ifdef Paranoia\n  if(sosindex > group->sos_count) {\n    report(lp, IMPORTANT, \"SOS_get_candidates: Invalid index %d\\n\", sosindex);\n    return( candidates );\n  }\n#endif\n\n  /* Determine SOS target(s); note that if \"sosindex\" is negative, only\n     the first non-empty SOS where \"column\" is a member is processed */\n  if(sosindex <= 0) {\n    i = 0;\n    ii = group->sos_count;\n  }\n  else {\n    i = sosindex - 1;\n    ii = sosindex;\n  }\n\n  /* Tally candidate usage */\n  allocINT(lp, &candidates, lp->columns+1, TRUE);\n  for(; i < ii; i++) {\n    if(!SOS_is_member(group, i+1, column))\n      continue;\n    list = group->sos_list[i]->members;\n    n = list[0];\n    while(n > 0) {\n      j = list[n];\n      if((j > 0) && (upbound[lp->rows+j] > 0)) {\n        if(lobound[lp->rows+j] > 0) {\n          report(lp, IMPORTANT, \"SOS_get_candidates: Invalid non-zero lower bound setting\\n\");\n          n = 0;\n          goto Finish;\n        }\n        if(candidates[j] == 0)\n          nn++;\n        candidates[j]++;\n      }\n      n--;\n    }\n    if((sosindex < 0) && (nn > 1))\n      break;\n  }\n\n  /* Condense the list into indeces */\n  n = 0;\n  for(i = 1; i <= lp->columns; i++) {\n    if((candidates[i] > 0) && (!excludetarget || (i != column))) {\n      n++;\n      candidates[n] = i;\n    }\n  }\n\n  /* Finalize */\nFinish:\n  candidates[0] = n;\n  if(n == 0)\n    FREE(candidates);\n\n  return( candidates);\n\n}\n\nint SOS_fix_list(SOSgroup *group, int sosindex, int variable, REAL *bound,\n                 int *varlist, MYBOOL isleft, DeltaVrec *changelog)\n{\n  int    i, ii, jj, count = 0;\n  REAL   value = 0;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_fix_list: Invalid index %d\\n\", sosindex);\n    return(FALSE);\n  }\n#endif\n\n  if(sosindex == 0) {\n    for(i = group->memberpos[variable-1]; i < group->memberpos[variable]; i++) {\n      ii = group->membership[i];\n      count += SOS_fix_list(group, ii, variable, bound, varlist, isleft, changelog);\n    }\n  }\n  else {\n\n    /* Establish the number of unmarked variables in the left window\n       (note that \"variable\" should have been marked previously) */\n    ii = varlist[0] / 2;\n    if(isleft) {\n      i = 1;\n      if(isleft == AUTOMATIC)\n        ii = varlist[0];\n    }\n    else {\n      i = ii + 1;\n      ii = varlist[0];\n    }\n\n    /* Loop over members to fix values at the new bound (zero) */\n    while(i <= ii) {\n      if(SOS_is_member(group, sosindex, varlist[i])) {\n        jj = lp->rows + varlist[i];\n\n        /* Verify that we don't violate original bounds */\n        if(value < lp->orig_lowbo[jj])\n          return( -jj );\n        /* OK, set the new bound */\n        count++;\n        if(changelog == NULL)\n          bound[jj] = value;\n        else\n          modifyUndoLadder(changelog, jj, bound, value);\n      }\n      i++;\n    }\n\n  }\n  return( count );\n}\n\nint SOS_is_satisfied(SOSgroup *group, int sosindex, REAL *solution)\n/* Determine if the SOS is satisfied for the current solution vector;\n   The return code is in the range [-2..+2], depending on the type of\n   satisfaction.  Positive return value means too many non-zero values,\n   negative value means set incomplete:\n\n              -2: Set member count not full (SOS3)\n              -1: Set member count not full\n               0: Set is full (also returned if the SOS index is invalid)\n               1: Too many non-zero sequential variables\n               2: Set consistency error\n\n*/\n{\n  int    i, n, nn, count, *list;\n  int    type, status = 0;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_is_satisfied: Invalid index %d\\n\", sosindex);\n    return( SOS_COMPLETE );\n  }\n#endif\n\n  if((sosindex == 0) && (group->sos_count == 1))\n    sosindex = 1;\n\n  if(sosindex == 0) {\n    for(i = 1; i <= group->sos_count; i++) {\n      status = SOS_is_satisfied(group, i, solution);\n      if((status != SOS_COMPLETE) && (status != SOS_INCOMPLETE))\n        break;\n    }\n  }\n  else {\n    type = SOS_get_type(group, sosindex);\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0]+1;\n    nn = list[n];\n\n   /* Count the number of active SOS variables */\n    for(i = 1; i <= nn; i++) {\n      if(list[n+i] == 0)\n        break;\n    }\n    count = i-1;\n    if(count == nn)\n      status = SOS_COMPLETE;    /* Set is full    */\n    else\n      status = SOS_INCOMPLETE;  /* Set is partial */\n\n   /* Find index of the first active variable; fail if some are non-zero */\n    if(count > 0) {\n      nn = list[n+1];\n      for(i = 1; i < n; i++) {\n        if((abs(list[i]) == nn) || (solution[lp->rows + abs(list[i])] != 0))\n          break;\n      }\n      if(abs(list[i]) != nn)\n        status = SOS_INTERNALERROR;  /* Set consistency error (leading set variables are non-zero) */\n      else {\n       /* Scan active SOS variables until we find a non-zero value */\n        while(count > 0) {\n          if(solution[lp->rows + abs(list[i])] != 0)\n            break;\n          i++;\n          count--;\n        }\n       /* Scan active non-zero SOS variables; break at first non-zero (rest required to be zero) */\n        while(count > 0) {\n          if(solution[lp->rows + abs(list[i])] == 0)\n            break;\n          i++;\n          count--;\n        }\n        if(count > 0)\n          status = SOS_INTERNALERROR; /* Set consistency error (active set variables are zero) */\n      }\n    }\n    else {\n      i = 1;\n      /* There are no active variables; see if we have happened to find a valid header */\n      while((i < n) && (solution[lp->rows + abs(list[i])] == 0))\n        i++;\n      count = 0;\n      while((i < n) && (count <= nn) && (solution[lp->rows + abs(list[i])] != 0)) {\n        count++;\n        i++;\n      }\n      if(count > nn)\n        status = SOS_INFEASIBLE;   /* Too-many sequential non-zero variables */\n    }\n\n    /* Scan the trailing set of SOS variables; fail if some are non-zero */\n    if(status <= 0) {\n      n--;\n      while(i <= n) {\n        if(solution[lp->rows + abs(list[i])] != 0)\n          break;\n        i++;\n      }\n      if(i <= n)\n        status = SOS_INFEASIBLE;  /* Too-many sequential non-zero variables */\n\n      /* Code member deficiency for SOS3 separately */\n      else if((status == -1) && (type <= SOS3))\n        status = SOS3_INCOMPLETE;\n    }\n\n  }\n  return( status );\n}\n\nMYBOOL SOS_is_feasible(SOSgroup *group, int sosindex, REAL *solution)\n/* Determine if the SOS is feasible up to the current SOS variable */\n{\n  int    i, n, nn, *list;\n  MYBOOL status = TRUE;\n  lprec  *lp = group->lp;\n\n#ifdef Paranoia\n  if((sosindex < 0) || (sosindex > group->sos_count)) {\n    report(lp, IMPORTANT, \"SOS_is_feasible: Invalid SOS index %d\\n\", sosindex);\n    return( 0 );\n  }\n#endif\n\n  if((sosindex == 0) && (group->sos_count == 1))\n    sosindex = 1;\n\n  if(sosindex == 0) {\n    for(i = 1; status && (i <= group->sos_count); i++) {\n      status = SOS_is_feasible(group, i, solution);\n    }\n  }\n  else {\n    list = group->sos_list[sosindex-1]->members;\n    n = list[0]+1;\n    nn = list[n];\n    if(nn <= 2)\n      return(status);\n\n   /* Find if we have a gap in the non-zero solution values */\n    i = 1;\n    sosindex = 0;\n    while((i <= nn) && (list[n+i] != 0)) {\n      while((i <= nn) && (list[n+i] != 0) && (solution[lp->rows+list[n+i]] == 0))\n        i++;\n      if((i <= nn) && (list[n+i] != 0)) {\n        i++;  /* Step to next */\n        while((i <= nn) && (list[n+i] != 0) && (solution[lp->rows+list[n+i]] != 0))\n          i++;\n        sosindex++;\n      }\n      i++;    /* Step to next */\n    }\n    status = (MYBOOL) (sosindex <= 1);\n  }\n  return(status);\n}\n"
  },
  {
    "path": "utilities/lp_solve/lp_SOS.h",
    "content": "#ifndef HEADER_lp_SOS\n#define HEADER_lp_SOS\n\n/* Specially Ordered Sets (SOS) prototypes and settings                      */\n/* ------------------------------------------------------------------------- */\n\n#include \"lp_types.h\"\n#include \"lp_utils.h\"\n#include \"lp_matrix.h\"\n\n\n/* SOS constraint defines                                                    */\n/* ------------------------------------------------------------------------- */\n#define SOS1                     1\n#define SOS2                     2\n#define SOS3                    -1\n#define SOSn                      MAXINT32\n#define SOS_START_SIZE          10  /* Start size of SOS_list array; realloced if needed */\n\n/* Define SOS_is_feasible() return values                                    */\n/* ------------------------------------------------------------------------- */\n#define SOS3_INCOMPLETE         -2\n#define SOS_INCOMPLETE          -1\n#define SOS_COMPLETE             0\n#define SOS_INFEASIBLE           1\n#define SOS_INTERNALERROR        2\n\n\ntypedef struct _SOSgroup SOSgroup;\n\ntypedef struct _SOSrec\n{\n  SOSgroup  *parent;\n  int       tagorder;\n  char      *name;\n  int       type;\n  MYBOOL    isGUB;\n  int       size;\n  int       priority;\n  int       *members;\n  REAL      *weights;\n  int       *membersSorted;\n  int       *membersMapped;\n} SOSrec;\n\n/* typedef */ struct _SOSgroup\n{\n  lprec     *lp;                /* Pointer to owner */\n  SOSrec    **sos_list;         /* Array of pointers to SOS lists */\n  int       sos_alloc;          /* Size allocated to specially ordered sets (SOS1, SOS2...) */\n  int       sos_count;          /* Number of specially ordered sets (SOS1, SOS2...) */\n  int       maxorder;           /* The highest-order SOS in the group */\n  int       sos1_count;         /* Number of the lowest order SOS in the group */\n  int       *membership;        /* Array of variable-sorted indeces to SOSes that the variable is member of */\n  int       *memberpos;         /* Starting positions of the each column's membership list */\n} /* SOSgroup */;\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* SOS storage structure */\nSTATIC SOSgroup *create_SOSgroup(lprec *lp);\nSTATIC void resize_SOSgroup(SOSgroup *group);\nSTATIC int append_SOSgroup(SOSgroup *group, SOSrec *SOS);\nSTATIC int clean_SOSgroup(SOSgroup *group, MYBOOL forceupdatemap);\nSTATIC void free_SOSgroup(SOSgroup **group);\n\nSTATIC SOSrec *create_SOSrec(SOSgroup *group, const char *name, int type, int priority, int size, int *variables, REAL *weights);\nSTATIC MYBOOL delete_SOSrec(SOSgroup *group, int sosindex);\nSTATIC int append_SOSrec(SOSrec *SOS, int size, int *variables, REAL *weights);\nSTATIC void free_SOSrec(SOSrec *SOS);\n\n/* SOS utilities */\nSTATIC int make_SOSchain(lprec *lp, MYBOOL forceresort);\nSTATIC int SOS_member_updatemap(SOSgroup *group);\nSTATIC MYBOOL SOS_member_sortlist(SOSgroup *group, int sosindex);\nSTATIC MYBOOL SOS_shift_col(SOSgroup *group, int sosindex, int column, int delta, LLrec *usedmap, MYBOOL forceresort);\nint SOS_member_delete(SOSgroup *group, int sosindex, int member);\nint SOS_get_type(SOSgroup *group, int sosindex);\nint SOS_infeasible(SOSgroup *group, int sosindex);\nint SOS_member_index(SOSgroup *group, int sosindex, int member);\nint SOS_member_count(SOSgroup *group, int sosindex);\nint SOS_memberships(SOSgroup *group, int column);\nint *SOS_get_candidates(SOSgroup *group, int sosindex, int column, MYBOOL excludetarget, REAL *upbound, REAL *lobound);\nint SOS_is_member(SOSgroup *group, int sosindex, int column);\nMYBOOL SOS_is_member_of_type(SOSgroup *group, int column, int sostype);\nMYBOOL SOS_set_GUB(SOSgroup *group, int sosindex, MYBOOL state);\nMYBOOL SOS_is_GUB(SOSgroup *group, int sosindex);\nMYBOOL SOS_is_marked(SOSgroup *group, int sosindex, int column);\nMYBOOL SOS_is_active(SOSgroup *group, int sosindex, int column);\nMYBOOL SOS_is_full(SOSgroup *group, int sosindex, int column, MYBOOL activeonly);\nMYBOOL SOS_can_activate(SOSgroup *group, int sosindex, int column);\nMYBOOL SOS_set_marked(SOSgroup *group, int sosindex, int column, MYBOOL asactive);\nMYBOOL SOS_unmark(SOSgroup *group, int sosindex, int column);\nint SOS_fix_unmarked(SOSgroup *group, int sosindex, int variable, REAL *bound, REAL value,\n                     MYBOOL isupper, int *diffcount, DeltaVrec *changelog);\nint SOS_fix_list(SOSgroup *group, int sosindex, int variable, REAL *bound,\n                  int *varlist, MYBOOL isleft, DeltaVrec *changelog);\nint SOS_is_satisfied(SOSgroup *group, int sosindex, REAL *solution);\nMYBOOL SOS_is_feasible(SOSgroup *group, int sosindex, REAL *solution);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_SOS */\n"
  },
  {
    "path": "utilities/lp_solve/lp_bit.h",
    "content": "#include \"lp_types.h\"\n\n#if defined INLINE\n# define MYINLINE INLINE\n#else\n# define MYINLINE static\n#endif\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\nMYINLINE void set_biton(MYBOOL *bitarray, int item)\n{\n  bitarray[item / 8] |= (1 << (item % 8));\n}\n\n/*\nMYINLINE void set_bitoff(MYBOOL *bitarray, int item)\n{\n  bitarray[item / 8] &= ~(1 << (item % 8));\n}\n*/\n\nMYINLINE MYBOOL is_biton(MYBOOL *bitarray, int item)\n{\n  return( (MYBOOL) ((bitarray[item / 8] & (1 << (item % 8))) != 0) );\n}\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n"
  },
  {
    "path": "utilities/lp_solve/lp_crash.c",
    "content": "\n/*\n   ----------------------------------------------------------------------------------\n   Crash management routines in lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      lp_lib.h, lp_utils.h, lp_matrix.h\n\n    Release notes:\n    v1.0.0  1 April   2004      First version.\n    v1.1.0  20 July 2004        Reworked with flexible matrix storage model.\n\n   ----------------------------------------------------------------------------------\n*/\n\n#include <string.h>\n\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_scale.h\"\n#include \"lp_utils.h\"\n#include \"lp_report.h\"\n#include \"lp_matrix.h\"\n#include \"lp_crash.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\nMYBOOL crash_basis(lprec *lp)\n{\n  int     i;\n  MATrec  *mat = lp->matA;\n  MYBOOL  ok = TRUE;\n\n  /* Initialize basis indicators */\n  if(lp->basis_valid)\n    lp->var_basic[0] = FALSE;\n  else\n    default_basis(lp);\n\n  /* Set initial partial pricing blocks */\n  if(lp->rowblocks != NULL)\n    lp->rowblocks->blocknow = 1;\n  if(lp->colblocks != NULL)\n    lp->colblocks->blocknow = ((lp->crashmode == CRASH_NONE) || (lp->colblocks->blockcount == 1) ? 1 : 2);\n\n  /* Construct a basis that is in some measure the \"most feasible\" */\n  if((lp->crashmode == CRASH_MOSTFEASIBLE) && mat_validate(mat)) {\n    /* The logic here follows Maros */\n    LLrec   *rowLL = NULL, *colLL = NULL;\n    int     ii, rx, cx, ix, nz;\n    REAL    wx, tx, *rowMAX = NULL, *colMAX = NULL;\n    int     *rowNZ = NULL, *colNZ = NULL, *rowWT = NULL, *colWT = NULL;\n    REAL    *value;\n    int     *rownr, *colnr;\n\n    report(lp, NORMAL, \"crash_basis: 'Most feasible' basis crashing selected\\n\");\n\n    /* Tally row and column non-zero counts */\n    ok = allocINT(lp,  &rowNZ, lp->rows+1,     TRUE) &&\n         allocINT(lp,  &colNZ, lp->columns+1,  TRUE) &&\n         allocREAL(lp, &rowMAX, lp->rows+1,    FALSE) &&\n         allocREAL(lp, &colMAX, lp->columns+1, FALSE);\n    if(!ok)\n      goto Finish;\n\n    nz = mat_nonzeros(mat);\n    rownr = &COL_MAT_ROWNR(0);\n    colnr = &COL_MAT_COLNR(0);\n    value = &COL_MAT_VALUE(0);\n    for(i = 0; i < nz;\n        i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) {\n      rx = *rownr;\n      cx = *colnr;\n      wx = fabs(*value);\n      rowNZ[rx]++;\n      colNZ[cx]++;\n      if(i == 0) {\n        rowMAX[rx] = wx;\n        colMAX[cx] = wx;\n        colMAX[0]  = wx;\n      }\n      else {\n        SETMAX(rowMAX[rx], wx);\n        SETMAX(colMAX[cx], wx);\n        SETMAX(colMAX[0],  wx);\n      }\n    }\n    /* Reduce counts for small magnitude to preserve stability */\n    rownr = &COL_MAT_ROWNR(0);\n    colnr = &COL_MAT_COLNR(0);\n    value = &COL_MAT_VALUE(0);\n    for(i = 0; i < nz;\n        i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) {\n      rx = *rownr;\n      cx = *colnr;\n      wx = fabs(*value);\n#ifdef CRASH_SIMPLESCALE\n      if(wx < CRASH_THRESHOLD * colMAX[0]) {\n        rowNZ[rx]--;\n        colNZ[cx]--;\n      }\n#else\n      if(wx < CRASH_THRESHOLD * rowMAX[rx])\n        rowNZ[rx]--;\n      if(wx < CRASH_THRESHOLD * colMAX[cx])\n        colNZ[cx]--;\n#endif\n    }\n\n    /* Set up priority tables */\n    ok = allocINT(lp, &rowWT, lp->rows+1, TRUE);\n    createLink(lp->rows,    &rowLL, NULL);\n    ok &= (rowLL != NULL);\n    if(!ok)\n      goto Finish;\n    for(i = 1; i <= lp->rows; i++) {\n      if(get_constr_type(lp, i)==EQ)\n        ii = 3;\n      else if(lp->upbo[i] < lp->infinite)\n        ii = 2;\n      else if(fabs(lp->rhs[i]) < lp->infinite)\n        ii = 1;\n      else\n        ii = 0;\n      rowWT[i] = ii;\n      if(ii > 0)\n        appendLink(rowLL, i);\n    }\n    ok = allocINT(lp, &colWT, lp->columns+1, TRUE);\n    createLink(lp->columns, &colLL, NULL);\n    ok &= (colLL != NULL);\n    if(!ok)\n      goto Finish;\n    for(i = 1; i <= lp->columns; i++) {\n      ix = lp->rows+i;\n      if(is_unbounded(lp, i))\n        ii = 3;\n      else if(lp->upbo[ix] >= lp->infinite)\n        ii = 2;\n      else if(fabs(lp->upbo[ix]-lp->lowbo[ix]) > lp->epsmachine)\n        ii = 1;\n      else\n        ii = 0;\n      colWT[i] = ii;\n      if(ii > 0)\n        appendLink(colLL, i);\n    }\n\n    /* Loop over all basis variables */\n    for(i = 1; i <= lp->rows; i++) {\n\n      /* Select row */\n      rx = 0;\n      wx = -lp->infinite;\n      for(ii = firstActiveLink(rowLL); ii > 0; ii = nextActiveLink(rowLL, ii)) {\n        tx = rowWT[ii] - CRASH_SPACER*rowNZ[ii];\n        if(tx > wx) {\n          rx = ii;\n          wx = tx;\n        }\n      }\n      if(rx == 0)\n        break;\n      removeLink(rowLL, rx);\n\n      /* Select column */\n      cx = 0;\n      wx = -lp->infinite;\n      for(ii = mat->row_end[rx-1]; ii < mat->row_end[rx]; ii++) {\n\n        /* Update NZ column counts for row selected above */\n        tx = fabs(ROW_MAT_VALUE(ii));\n        ix = ROW_MAT_COLNR(ii);\n#ifdef CRASH_SIMPLESCALE\n        if(tx >= CRASH_THRESHOLD * colMAX[0])\n#else\n        if(tx >= CRASH_THRESHOLD * colMAX[ix])\n#endif\n          colNZ[ix]--;\n        if(!isActiveLink(colLL, ix) || (tx < CRASH_THRESHOLD * rowMAX[rx]))\n          continue;\n\n        /* Now do the test for best pivot */\n        tx = my_sign(lp->orig_obj[ix]) - my_sign(ROW_MAT_VALUE(ii));\n        tx = colWT[ix] + CRASH_WEIGHT*tx - CRASH_SPACER*colNZ[ix];\n        if(tx > wx) {\n          cx = ix;\n          wx = tx;\n        }\n      }\n      if(cx == 0)\n        break;\n      removeLink(colLL, cx);\n\n      /* Update row NZ counts */\n      ii = mat->col_end[cx-1];\n      rownr = &COL_MAT_ROWNR(ii);\n      value = &COL_MAT_VALUE(ii);\n      for(; ii < mat->col_end[cx];\n          ii++, rownr += matRowColStep, value += matValueStep) {\n        wx = fabs(*value);\n        ix = *rownr;\n#ifdef CRASH_SIMPLESCALE\n        if(wx >= CRASH_THRESHOLD * colMAX[0])\n#else\n        if(wx >= CRASH_THRESHOLD * rowMAX[ix])\n#endif\n          rowNZ[ix]--;\n      }\n\n      /* Set new basis variable */\n      set_basisvar(lp, rx, lp->rows+cx);\n    }\n\n    /* Clean up */\nFinish:\n    FREE(rowNZ);\n    FREE(colNZ);\n    FREE(rowMAX);\n    FREE(colMAX);\n    FREE(rowWT);\n    FREE(colWT);\n    freeLink(&rowLL);\n    freeLink(&colLL);\n  }\n\n  /* Construct a basis that is in some measure the \"least degenerate\" */\n  else if((lp->crashmode == CRASH_LEASTDEGENERATE) && mat_validate(mat)) {\n    /* The logic here follows Maros */\n    LLrec   *rowLL = NULL, *colLL = NULL;\n    int     ii, rx, cx, ix, nz, *merit = NULL;\n    REAL    *value, wx, hold, *rhs = NULL, *eta = NULL;\n    int     *rownr, *colnr;\n\n    report(lp, NORMAL, \"crash_basis: 'Least degenerate' basis crashing selected\\n\");\n\n    /* Create temporary arrays */\n    ok = allocINT(lp,  &merit, lp->columns + 1, FALSE) &&\n         allocREAL(lp, &eta, lp->rows + 1, FALSE) &&\n         allocREAL(lp, &rhs, lp->rows + 1, FALSE);\n    createLink(lp->columns, &colLL, NULL);\n    createLink(lp->rows, &rowLL, NULL);\n    ok &= (colLL != NULL) && (rowLL != NULL);\n    if(!ok)\n      goto FinishLD;\n    MEMCOPY(rhs, lp->orig_rhs, lp->rows + 1);\n    for(i = 1; i <= lp->columns; i++)\n      appendLink(colLL, i);\n    for(i = 1; i <= lp->rows; i++)\n      appendLink(rowLL, i);\n\n    /* Loop until we have found enough new bases */\n    while(colLL->count > 0) {\n\n      /* Tally non-zeros matching in RHS and each active column */\n      nz = mat_nonzeros(mat);\n      rownr = &COL_MAT_ROWNR(0);\n      colnr = &COL_MAT_COLNR(0);\n      ii = 0;\n      MEMCLEAR(merit, lp->columns + 1);\n      for(i = 0; i < nz;\n          i++, rownr += matRowColStep, colnr += matRowColStep) {\n        rx = *rownr;\n        cx = *colnr;\n        if(isActiveLink(colLL, cx) && (rhs[rx] != 0)) {\n          merit[cx]++;\n          ii++;\n        }\n      }\n      if(ii == 0)\n        break;\n\n      /* Find maximal match; break ties with column length */\n      i = firstActiveLink(colLL);\n      cx = i;\n      for(i = nextActiveLink(colLL, i); i != 0; i = nextActiveLink(colLL, i)) {\n        if(merit[i] >= merit[cx]) {\n          if((merit[i] > merit[cx]) || (mat_collength(mat, i) > mat_collength(mat, cx)))\n            cx = i;\n        }\n      }\n\n      /* Determine the best pivot row */\n      i = mat->col_end[cx-1];\n      nz = mat->col_end[cx];\n      rownr = &COL_MAT_ROWNR(i);\n      value = &COL_MAT_VALUE(i);\n      rx = 0;\n      wx = 0;\n      MEMCLEAR(eta, lp->rows + 1);\n      for(; i < nz;\n          i++, rownr += matRowColStep, value += matValueStep) {\n        ix = *rownr;\n        hold = *value;\n        eta[ix] = rhs[ix] / hold;\n        hold = fabs(hold);\n        if(isActiveLink(rowLL, ix) && (hold > wx)) {\n          wx = hold;\n          rx = ix;\n        }\n      }\n\n      /* Set new basis variable */\n      if(rx > 0) {\n\n        /* We have to update the rhs vector for the implied transformation\n          in order to be able to find the new RHS non-zero pattern */\n        for(i = 1; i <= lp->rows; i++)\n           rhs[i] -= wx * eta[i];\n        rhs[rx] = wx;\n\n        /* Do the exchange */\n        set_basisvar(lp, rx, lp->rows+cx);\n        removeLink(rowLL, rx);\n      }\n      removeLink(colLL, cx);\n\n    }\n\n    /* Clean up */\nFinishLD:\n    FREE(merit);\n    FREE(rhs);\n    freeLink(&rowLL);\n    freeLink(&colLL);\n\n  }\n  return( ok );\n}\n\n#if 0\nMYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector)\n{\n  MYBOOL status = FALSE;\n  REAL   *values = NULL, *violation = NULL,\n         *value, error, upB, loB, sortorder = 1.0;\n  int    i, n, *rownr, *colnr;\n  MATrec *mat = lp->matA;\n\n  if(!mat_validate(lp->matA))\n    return( status );\n\n  /* Create helper arrays */\n  if(!allocREAL(lp, &values, lp->sum+1, TRUE) ||\n     !allocREAL(lp, &violation, lp->sum+1, TRUE))\n    goto Finish;\n\n  /* Compute values of slack variables for given guess vector */\n  i = 0;\n  n = get_nonzeros(lp);\n  rownr = &COL_MAT_ROWNR(i);\n  colnr = &COL_MAT_COLNR(i);\n  value = &COL_MAT_VALUE(i);\n  for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep)\n    values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) *\n                      guessvector[*colnr];\n  MEMMOVE(values+lp->rows+1, guessvector+1, lp->columns);\n\n  /* Initialize constraint bound violation measures */\n  for(i = 1; i <= lp->rows; i++) {\n    upB = get_rh_upper(lp, i);\n    loB = get_rh_lower(lp, i);\n    error = values[i] - upB;\n    if(error > lp->epsprimal)\n      violation[i] = sortorder*error;\n    else {\n      error = loB - values[i];\n      if(error > lp->epsprimal)\n        violation[i] = sortorder*error;\n      else if(is_infinite(lp, loB) && is_infinite(lp, upB))\n        ;\n      else if(is_infinite(lp, upB))\n        violation[i] = sortorder*(loB - values[i]);\n      else if(is_infinite(lp, loB))\n        violation[i] = sortorder*(values[i] - upB);\n      else\n        violation[i] = - sortorder*MAX(upB - values[i], values[i] - loB);\n    }\n    basisvector[i] = i;\n  }\n\n  /* Initialize user variable bound violation measures */\n  for(i = 1; i <= lp->columns; i++) {\n    n = lp->rows+i;\n    upB = get_upbo(lp, i);\n    loB = get_lowbo(lp, i);\n    error = guessvector[i] - upB;\n    if(error > lp->epsprimal)\n      violation[n] = sortorder*error;\n    else {\n      error = loB - values[n];\n      if(error > lp->epsprimal)\n        violation[n] = sortorder*error;\n      else if(is_infinite(lp, loB) && is_infinite(lp, upB))\n        ;\n      else if(is_infinite(lp, upB))\n        violation[n] = sortorder*(loB - values[n]);\n      else if(is_infinite(lp, loB))\n        violation[n] = sortorder*(values[n] - upB);\n      else\n        violation[n] = - sortorder*MAX(upB - values[n], values[n] - loB);\n    }\n    basisvector[n] = n;\n  }\n\n  /* Sort decending by violation; this means that variables with\n     the largest violations will be designated as basic */\n  sortByREAL(basisvector, violation, lp->sum, 1, FALSE);\n\n  /* Adjust the non-basic indeces for the (proximal) bound state */\n  error = lp->epsprimal;\n  for(i = lp->rows+1, rownr = basisvector+i; i <= lp->sum; i++, rownr++) {\n    if(*rownr <= lp->rows) {\n      if(values[*rownr] <= get_rh_lower(lp, *rownr)+error)\n        *rownr = -(*rownr);\n    }\n    else\n      if(values[i] <= get_lowbo(lp, (*rownr)-lp->rows)+error)\n        *rownr = -(*rownr);\n  }\n\n  /* Clean up and return status */\n  status = (MYBOOL) (violation[1] == 0);\nFinish:\n  FREE(values);\n  FREE(violation);\n\n\n  return( status );\n}\n#endif\n\n#if 0\nMYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector)\n{\n  MYBOOL *isnz, status = FALSE;\n  REAL   *values = NULL, *violation = NULL,\n         eps = lp->epsprimal,\n         *value, error, upB, loB, sortorder = 1.0;\n  int    i, j, n, *rownr, *colnr, *slkpos,\n         nrows = lp->rows, ncols = lp->columns;\n  MATrec *mat = lp->matA;\n\n  if(!mat_validate(mat))\n    return( status );\n\n  /* Create helper arrays */\n  if(!allocREAL(lp, &values, lp->sum+1, TRUE) ||\n     !allocREAL(lp, &violation, lp->sum+1, TRUE))\n    goto Finish;\n\n  /* Compute values of slack variables for given guess vector */\n  i = 0;\n  n = get_nonzeros(lp);\n  rownr = &COL_MAT_ROWNR(i);\n  colnr = &COL_MAT_COLNR(i);\n  value = &COL_MAT_VALUE(i);\n  for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep)\n    values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) *\n                      guessvector[*colnr];\n  MEMMOVE(values+nrows+1, guessvector+1, ncols);\n\n  /* Initialize constraint bound violation measures (expressed as positive values) */\n  for(i = 1; i <= nrows; i++) {\n    upB = get_rh_upper(lp, i);\n    loB = get_rh_lower(lp, i);\n    error = values[i] - upB;\n    if(error > eps)\n      violation[i] = sortorder*error;\n    else {\n      error = loB - values[i];\n      if(error > eps)\n        violation[i] = sortorder*error;\n      else if(my_infinite(lp, loB) && my_infinite(lp, upB))\n        ;\n      else if(my_infinite(lp, upB))\n        violation[i] = sortorder*(loB - values[i]);\n      else if(my_infinite(lp, loB))\n        violation[i] = sortorder*(values[i] - upB);\n      else\n        violation[i] = -sortorder*MAX(upB - values[i], values[i] - loB);\n    }\n    basisvector[i] = i;\n  }\n\n  /* Initialize user variable bound violation measures (expressed as positive values) */\n  for(i = 1; i <= ncols; i++) {\n    n = nrows+i;\n    upB = get_upbo(lp, i);\n    loB = get_lowbo(lp, i);\n    error = guessvector[i] - upB;\n    if(error > eps)\n      violation[n] = sortorder*error;\n    else {\n      error = loB - values[n];\n      if(error > eps)\n        violation[n] = sortorder*error;\n      else if(my_infinite(lp, loB) && my_infinite(lp, upB))\n        ;\n      else if(my_infinite(lp, upB))\n        violation[n] = sortorder*(loB - values[n]);\n      else if(my_infinite(lp, loB))\n        violation[n] = sortorder*(values[n] - upB);\n      else\n        violation[n] = -sortorder*MAX(upB - values[n], values[n] - loB);\n    }\n    basisvector[n] = n;\n  }\n\n  /* Sort decending by violation; this means that variables with\n     the largest violations will be designated as basic */\n  sortByREAL(basisvector, violation, lp->sum, 1, FALSE);\n  error = violation[1];\n\n  /* Adjust the non-basic indeces for the (proximal) bound state */\n  for(i = nrows+1, rownr = basisvector+i; i <= lp->sum; i++, rownr++) {\n    if(*rownr <= nrows) {\n      if(values[*rownr] <= get_rh_lower(lp, *rownr)+eps)\n        *rownr = -(*rownr);\n    }\n    else\n      if(values[i] <= get_lowbo(lp, (*rownr)-nrows)+eps)\n        *rownr = -(*rownr);\n  }\n\n#if 1\n  /* Let us check for obvious row singularities and try to fix these;\n     First assemble necessary basis statistics... */\n  isnz = (MYBOOL *) values;\n  MEMCLEAR(isnz, nrows+1);\n  slkpos = (int *) violation;\n  MEMCLEAR(slkpos, nrows+1);\n  for(i = 1; i <= nrows; i++) {\n    j = abs(basisvector[i]);\n    if(j <= nrows) {\n      isnz[j] = TRUE;\n      slkpos[j] = i;\n    }\n    else {\n      j-= nrows;\n      j = mat->col_end[j-1];\n      isnz[COL_MAT_ROWNR(j)] = TRUE;\n      /*isnz[COL_MAT_ROWNR(j+1)] = TRUE;*/\n    }\n  }\n  for(; i <= lp->sum; i++) {\n    j = abs(basisvector[i]);\n    if(j <= nrows)\n      slkpos[j] = i;\n  }\n\n  /* ...then set the corresponding slacks basic for row rank deficient positions */\n  for(j = 1; j <= nrows; j++) {\n#ifdef Paranoia\n    if(slkpos[j] == 0)\n      report(lp, SEVERE, \"guess_basis: Internal error\");\n#endif\n    if(!isnz[j]) {\n      isnz[j] = TRUE;\n      i = slkpos[j];\n      swapINT(&basisvector[i], &basisvector[j]);\n      basisvector[j] = abs(basisvector[j]);\n    }\n  }\n#endif\n\n  /* Clean up and return status */\n  status = (MYBOOL) (error <= eps);\nFinish:\n  FREE(values);\n  FREE(violation);\n\n  return( status );\n}\n#endif\n\n#if 0\nMYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector)\n{\n  MYBOOL *isnz, status = FALSE;\n  REAL   *values = NULL, *violation = NULL,\n         eps = lp->epsprimal,\n         *value, error, upB, loB, sortorder = 1.0;\n  int    i, j, jj, n, *rownr, *colnr, *slkpos,\n         nrows = lp->rows, ncols = lp->columns;\n  MATrec *mat = lp->matA;\n\n  if(!mat_validate(mat))\n    return( status );\n\n  /* Create helper arrays */\n  if(!allocREAL(lp, &values, lp->sum+1, TRUE) ||\n     !allocREAL(lp, &violation, lp->sum+1, TRUE))\n    goto Finish;\n\n  /* Compute values of slack variables for given guess vector */\n  i = 0;\n  n = get_nonzeros(lp);\n  rownr = &COL_MAT_ROWNR(i);\n  colnr = &COL_MAT_COLNR(i);\n  value = &COL_MAT_VALUE(i);\n  for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep)\n    values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) *\n                      guessvector[*colnr];\n  MEMMOVE(values+nrows+1, guessvector+1, ncols);\n\n  /* Initialize constraint bound violation measures (expressed as positive values) */\n  for(i = 1; i <= nrows; i++) {\n    upB = get_rh_upper(lp, i);\n    loB = get_rh_lower(lp, i);\n    error = values[i] - upB;\n    if(error > -eps)\n      violation[i] = sortorder*MAX(0,error);\n    else {\n      error = loB - values[i];\n      if(error > -eps)\n        violation[i] = sortorder*MAX(0,error);\n      else if(my_infinite(lp, loB) && my_infinite(lp, upB))\n        ;\n      else if(my_infinite(lp, upB))\n        violation[i] = sortorder*(loB - values[i]);\n      else if(my_infinite(lp, loB))\n        violation[i] = sortorder*(values[i] - upB);\n      else\n        violation[i] = -sortorder*MAX(upB - values[i], values[i] - loB);\n    }\n    basisvector[i] = i;\n  }\n\n  /* Initialize user variable bound violation measures (expressed as positive values) */\n  for(i = 1; i <= ncols; i++) {\n    n = nrows+i;\n    upB = get_upbo(lp, i);\n    loB = get_lowbo(lp, i);\n    error = guessvector[i] - upB;\n    if(error > -eps)\n      violation[n] = sortorder*MAX(0,error);\n    else {\n      error = loB - values[n];\n      if(error > -eps)\n        violation[n] = sortorder*MAX(0,error);\n      else if(my_infinite(lp, loB) && my_infinite(lp, upB))\n        ;\n      else if(my_infinite(lp, upB))\n        violation[n] = sortorder*(loB - values[n]);\n      else if(my_infinite(lp, loB))\n        violation[n] = sortorder*(values[n] - upB);\n      else\n        violation[n] = -sortorder*MAX(upB - values[n], values[n] - loB);\n    }\n    basisvector[n] = n;\n  }\n\n  /* Sort decending by violation; this means that variables with\n     the largest violations will be designated as basic */\n  sortByREAL(basisvector, violation, lp->sum, 1, FALSE);\n  error = violation[1];\n\n  /* Adjust the non-basic indeces for the (proximal) bound state */\n  for(i = nrows+1, rownr = basisvector+i; i <= lp->sum; i++, rownr++) {\n    if(*rownr <= nrows) {\n      values[*rownr] -= lp->orig_rhs[*rownr];\n      if(values[*rownr] <= eps)\n        *rownr = -(*rownr);\n    }\n    else\n      if(values[i] <= get_lowbo(lp, (*rownr)-nrows)+eps)\n        *rownr = -(*rownr);\n  }\n\n  /* Let us check for obvious row singularities and try to fix these;\n     First assemble necessary basis statistics... */\n  isnz = (MYBOOL *) values;\n  MEMCLEAR(isnz, nrows+1);\n  slkpos = (int *) violation;\n  MEMCLEAR(slkpos, nrows+1);\n  for(i = 1; i <= nrows; i++) {\n    j = abs(basisvector[i]);\n    if(j <= nrows) {\n      isnz[j] = TRUE;\n      slkpos[j] = i;\n    }\n    else {\n      j-= nrows;\n      jj = mat->col_end[j-1];\n      isnz[COL_MAT_ROWNR(jj)] = TRUE;\n/*      if(++jj < mat->col_end[j])\n        isnz[COL_MAT_ROWNR(jj)] = TRUE; */\n    }\n  }\n  for(; i <= lp->sum; i++) {\n    j = abs(basisvector[i]);\n    if(j <= nrows)\n      slkpos[j] = i;\n  }\n\n  /* ...then set the corresponding slacks basic for row rank deficient positions */\n  for(j = 1; j <= nrows; j++) {\n#ifdef Paranoia\n    if(slkpos[j] == 0)\n      report(lp, SEVERE, \"guess_basis: Internal error\");\n#endif\n    if(!isnz[j]) {\n      isnz[j] = TRUE;\n      i = slkpos[j];\n      swapINT(&basisvector[i], &basisvector[j]);\n      basisvector[j] = abs(basisvector[j]);\n    }\n  }\n\n  /* Lastly normalize all basic variables to be coded as lower-bounded */\n  for(i = 1; i <= nrows; i++)\n    basisvector[i] = -abs(basisvector[i]);\n\n  /* Clean up and return status */\n  status = (MYBOOL) (error <= eps);\nFinish:\n  FREE(values);\n  FREE(violation);\n\n  return( status );\n}\n#endif\n\nMYBOOL __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector)\n{\n  MYBOOL *isnz = NULL, status = FALSE;\n  REAL   *values = NULL, *violation = NULL,\n         eps = lp->epsprimal,\n         *value, error, upB, loB, sortorder = -1.0;\n  int    i, j, jj, n, *rownr, *colnr, *slkpos = NULL,\n         nrows = lp->rows, ncols = lp->columns, nsum = lp->sum;\n  int    *basisnr;\n  MATrec *mat = lp->matA;\n\n  if(!mat_validate(mat))\n    return( status );\n\n  /* Create helper arrays, providing for multiple use of the violation array */\n  if(!allocREAL(lp, &values, nsum+1, TRUE) ||\n     !allocREAL(lp, &violation, nsum+1, TRUE))\n    goto Finish;\n\n  /* Compute the values of the constraints for the given guess vector */\n  i = 0;\n  n = get_nonzeros(lp);\n  rownr = &COL_MAT_ROWNR(i);\n  colnr = &COL_MAT_COLNR(i);\n  value = &COL_MAT_VALUE(i);\n  for(; i < n; i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep)\n    values[*rownr] += unscaled_mat(lp, my_chsign(is_chsign(lp, *rownr), *value), *rownr, *colnr) *\n                      guessvector[*colnr];\n  MEMMOVE(values+nrows+1, guessvector+1, ncols);\n\n  /* Initialize bound \"violation\" or primal non-degeneracy measures, expressed\n     as the absolute value of the differences from the closest bound. */\n  for(i = 1; i <= nsum; i++) {\n    if(i <= nrows) {\n      loB = get_rh_lower(lp, i);\n      upB = get_rh_upper(lp, i);\n    }\n    else {\n      loB = get_lowbo(lp, i-nrows);\n      upB = get_upbo(lp, i-nrows);\n    }\n\n    /* Free constraints/variables */\n    if(my_infinite(lp, loB) && my_infinite(lp, upB))\n      error = 0;\n    /* Violated constraints/variable bounds */\n    else if(values[i]+eps < loB)\n      error = loB-values[i];\n    else if(values[i]-eps > upB)\n      error = values[i]-upB;\n    /* Non-violated constraints/variables bounds */\n    else if(my_infinite(lp, upB))\n      error = MAX(0, values[i]-loB);\n    else if(my_infinite(lp, loB))\n      error = MAX(0, upB-values[i]);\n    else\n      error = MIN(upB-values[i], values[i]-loB); /* MAX(upB-values[i], values[i]-loB); */\n    if(error != 0)\n      violation[i] = sortorder*error;\n    basisvector[i] = i;\n  }\n\n  /* Sort decending , meaning that variables with the largest\n     \"violations\" will be designated basic. Effectively, we are performing a\n     greedy type algorithm, but start at the \"least interesting\" end. */\n  sortByREAL(basisvector, violation, nsum, 1, FALSE);\n  error = violation[1]; /* Used for setting the return value */\n\n  /* Let us check for obvious row singularities and try to fix these.\n     Note that we reuse the memory allocated to the violation array.\n     First assemble necessary basis statistics... */\n  slkpos = (int *) violation;\n  n = nrows+1;\n  MEMCLEAR(slkpos, n);\n  isnz = (MYBOOL *) (slkpos+n+1);\n  MEMCLEAR(isnz, n);\n  for(i = 1; i <= nrows; i++) {\n    j = abs(basisvector[i]);\n    if(j <= nrows) {\n      isnz[j] = TRUE;\n      slkpos[j] = i;\n    }\n    else {\n      j-= nrows;\n      jj = mat->col_end[j-1];\n      jj = COL_MAT_ROWNR(jj);\n      isnz[jj] = TRUE;\n    }\n  }\n  for(; i <= nsum; i++) {\n    j = abs(basisvector[i]);\n    if(j <= nrows)\n      slkpos[j] = i;\n  }\n\n  /* ...then set the corresponding slacks basic for row rank deficient positions */\n  for(j = 1; j <= nrows; j++) {\n    if(slkpos[j] == 0)\n      report(lp, SEVERE, \"guess_basis: Internal error\");\n    if(!isnz[j]) {\n      isnz[j] = TRUE;\n      i = slkpos[j];\n      swapINT(&basisvector[i], &basisvector[j]);\n      basisvector[j] = abs(basisvector[j]);\n    }\n  }\n\n  /* Adjust the non-basic indeces for the (proximal) bound state */\n  for(i = nrows+1, basisnr = basisvector+i; i <= nsum; i++, basisnr++) {\n    n = *basisnr;\n    if(n <= nrows) {\n      values[n] -= get_rh_lower(lp, n);\n      if(values[n] <= eps)\n        *basisnr = -(*basisnr);\n    }\n    else\n      if(values[n]-eps <= get_lowbo(lp, n-nrows))\n        *basisnr = -(*basisnr);\n  }\n\n/* Lastly normalize all basic variables to be coded as lower-bounded,\n   or effectively zero-based in the case of free variables. */\n  for(i = 1; i <= nrows; i++)\n    basisvector[i] = -abs(basisvector[i]);\n\n  /* Clean up and return status */\n  status = (MYBOOL) (error <= eps);\nFinish:\n  FREE(values);\n  FREE(violation);\n\n  return( status );\n}\n"
  },
  {
    "path": "utilities/lp_solve/lp_crash.h",
    "content": "\n#ifndef HEADER_lp_crash\n#define HEADER_lp_crash\n\n\n#include \"lp_types.h\"\n\n#define CRASH_SIMPLESCALE       /* Specify if we should use a simple absolute scaling threshold */\n\n#define CRASH_THRESHOLD  0.167\n#define CRASH_SPACER        10\n#define CRASH_WEIGHT     0.500\n\n\n\n#ifdef __cplusplus\n__EXTERN_C {\n#endif\n\nSTATIC MYBOOL crash_basis(lprec *lp);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* HEADER_lp_crash */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_explicit.h",
    "content": "#define HEADER_lp_report\n\n#include \"lp_lib.h\"\n\n#if defined LPSOLVEAPIFROMLPRECDEF\n# define LPSOLVEAPIFROMLPREC\n# define LPSOLVEAPIDEF\n#endif\n\n#if defined LPSOLVEAPIFROMLIBDEF\n# define LPSOLVEAPIFROMLIB\n# define LPSOLVEAPIDEF\n#endif\n\n#if !defined LPSOLVEAPIDEF\n# define LPSOLVEAPIDEF extern\n#endif\n\n/* entries for lp structure */\nLPSOLVEAPIDEF add_column_func               *_add_column;\nLPSOLVEAPIDEF add_columnex_func             *_add_columnex;\nLPSOLVEAPIDEF add_constraint_func           *_add_constraint;\nLPSOLVEAPIDEF add_constraintex_func         *_add_constraintex;\nLPSOLVEAPIDEF add_lag_con_func              *_add_lag_con;\nLPSOLVEAPIDEF add_SOS_func                  *_add_SOS;\nLPSOLVEAPIDEF column_in_lp_func             *_column_in_lp;\nLPSOLVEAPIDEF copy_lp_func                  *_copy_lp;\nLPSOLVEAPIDEF default_basis_func            *_default_basis;\nLPSOLVEAPIDEF del_column_func               *_del_column;\nLPSOLVEAPIDEF del_constraint_func           *_del_constraint;\nLPSOLVEAPIDEF delete_lp_func                *_delete_lp;\nLPSOLVEAPIDEF dualize_lp_func               *_dualize_lp;\nLPSOLVEAPIDEF free_lp_func                  *_free_lp;\n/*LPSOLVEAPIDEF get_accuracy_func             *_get_accuracy;*/\nLPSOLVEAPIDEF get_anti_degen_func           *_get_anti_degen;\nLPSOLVEAPIDEF get_basis_func                *_get_basis;\nLPSOLVEAPIDEF get_basiscrash_func           *_get_basiscrash;\nLPSOLVEAPIDEF get_bb_depthlimit_func        *_get_bb_depthlimit;\nLPSOLVEAPIDEF get_bb_floorfirst_func        *_get_bb_floorfirst;\nLPSOLVEAPIDEF get_bb_rule_func              *_get_bb_rule;\nLPSOLVEAPIDEF get_bounds_tighter_func       *_get_bounds_tighter;\nLPSOLVEAPIDEF get_break_at_value_func       *_get_break_at_value;\n/*LPSOLVEAPIDEF get_break_numeric_accuracy_func *_get_break_numeric_accuracy;*/\nLPSOLVEAPIDEF get_col_name_func             *_get_col_name;\nLPSOLVEAPIDEF get_column_func               *_get_column;\nLPSOLVEAPIDEF get_columnex_func             *_get_columnex;\nLPSOLVEAPIDEF get_constr_type_func          *_get_constr_type;\nLPSOLVEAPIDEF get_constr_value_func         *_get_constr_value;\nLPSOLVEAPIDEF get_constraints_func          *_get_constraints;\nLPSOLVEAPIDEF get_dual_solution_func        *_get_dual_solution;\nLPSOLVEAPIDEF get_epsb_func                 *_get_epsb;\nLPSOLVEAPIDEF get_epsd_func                 *_get_epsd;\nLPSOLVEAPIDEF get_epsel_func                *_get_epsel;\nLPSOLVEAPIDEF get_epsint_func               *_get_epsint;\nLPSOLVEAPIDEF get_epsperturb_func           *_get_epsperturb;\nLPSOLVEAPIDEF get_epspivot_func             *_get_epspivot;\nLPSOLVEAPIDEF get_improve_func              *_get_improve;\nLPSOLVEAPIDEF get_infinite_func             *_get_infinite;\nLPSOLVEAPIDEF get_lambda_func               *_get_lambda;\nLPSOLVEAPIDEF get_lowbo_func                *_get_lowbo;\nLPSOLVEAPIDEF get_lp_index_func             *_get_lp_index;\nLPSOLVEAPIDEF get_lp_name_func              *_get_lp_name;\nLPSOLVEAPIDEF get_Lrows_func                *_get_Lrows;\nLPSOLVEAPIDEF get_mat_func                  *_get_mat;\nLPSOLVEAPIDEF get_mat_byindex_func          *_get_mat_byindex;\nLPSOLVEAPIDEF get_max_level_func            *_get_max_level;\nLPSOLVEAPIDEF get_maxpivot_func             *_get_maxpivot;\nLPSOLVEAPIDEF get_mip_gap_func              *_get_mip_gap;\nLPSOLVEAPIDEF get_multiprice_func           *_get_multiprice;\nLPSOLVEAPIDEF get_nameindex_func            *_get_nameindex;\nLPSOLVEAPIDEF get_Ncolumns_func             *_get_Ncolumns;\nLPSOLVEAPIDEF get_negrange_func             *_get_negrange;\nLPSOLVEAPIDEF get_nz_func                   *_get_nonzeros;\nLPSOLVEAPIDEF get_Norig_columns_func        *_get_Norig_columns;\nLPSOLVEAPIDEF get_Norig_rows_func           *_get_Norig_rows;\nLPSOLVEAPIDEF get_Nrows_func                *_get_Nrows;\nLPSOLVEAPIDEF get_obj_bound_func            *_get_obj_bound;\nLPSOLVEAPIDEF get_objective_func            *_get_objective;\nLPSOLVEAPIDEF get_orig_index_func           *_get_orig_index;\nLPSOLVEAPIDEF get_origcol_name_func         *_get_origcol_name;\nLPSOLVEAPIDEF get_origrow_name_func         *_get_origrow_name;\nLPSOLVEAPIDEF get_partialprice_func         *_get_partialprice;\nLPSOLVEAPIDEF get_pivoting_func             *_get_pivoting;\nLPSOLVEAPIDEF get_presolve_func             *_get_presolve;\nLPSOLVEAPIDEF get_presolveloops_func        *_get_presolveloops;\nLPSOLVEAPIDEF get_primal_solution_func      *_get_primal_solution;\nLPSOLVEAPIDEF get_print_sol_func            *_get_print_sol;\nLPSOLVEAPIDEF get_pseudocosts_func          *_get_pseudocosts;\nLPSOLVEAPIDEF get_ptr_constraints_func      *_get_ptr_constraints;\nLPSOLVEAPIDEF get_ptr_dual_solution_func    *_get_ptr_dual_solution;\nLPSOLVEAPIDEF get_ptr_lambda_func           *_get_ptr_lambda;\nLPSOLVEAPIDEF get_ptr_primal_solution_func  *_get_ptr_primal_solution;\nLPSOLVEAPIDEF get_ptr_sensitivity_obj_func  *_get_ptr_sensitivity_obj;\nLPSOLVEAPIDEF get_ptr_sensitivity_objex_func *_get_ptr_sensitivity_objex;\nLPSOLVEAPIDEF get_ptr_sensitivity_rhs_func  *_get_ptr_sensitivity_rhs;\nLPSOLVEAPIDEF get_ptr_variables_func        *_get_ptr_variables;\nLPSOLVEAPIDEF get_rh_func                   *_get_rh;\nLPSOLVEAPIDEF get_rh_range_func             *_get_rh_range;\nLPSOLVEAPIDEF get_row_func                  *_get_row;\nLPSOLVEAPIDEF get_rowex_func                *_get_rowex;\nLPSOLVEAPIDEF get_row_name_func             *_get_row_name;\nLPSOLVEAPIDEF get_scalelimit_func           *_get_scalelimit;\nLPSOLVEAPIDEF get_scaling_func              *_get_scaling;\nLPSOLVEAPIDEF get_sensitivity_obj_func      *_get_sensitivity_obj;\nLPSOLVEAPIDEF get_sensitivity_objex_func    *_get_sensitivity_objex;\nLPSOLVEAPIDEF get_sensitivity_rhs_func      *_get_sensitivity_rhs;\nLPSOLVEAPIDEF get_simplextype_func          *_get_simplextype;\nLPSOLVEAPIDEF get_solutioncount_func        *_get_solutioncount;\nLPSOLVEAPIDEF get_solutionlimit_func        *_get_solutionlimit;\nLPSOLVEAPIDEF get_status_func               *_get_status;\nLPSOLVEAPIDEF get_statustext_func           *_get_statustext;\nLPSOLVEAPIDEF get_timeout_func              *_get_timeout;\nLPSOLVEAPIDEF get_total_iter_func           *_get_total_iter;\nLPSOLVEAPIDEF get_total_nodes_func          *_get_total_nodes;\nLPSOLVEAPIDEF get_upbo_func                 *_get_upbo;\nLPSOLVEAPIDEF get_var_branch_func           *_get_var_branch;\nLPSOLVEAPIDEF get_var_dualresult_func       *_get_var_dualresult;\nLPSOLVEAPIDEF get_var_primalresult_func     *_get_var_primalresult;\nLPSOLVEAPIDEF get_var_priority_func         *_get_var_priority;\nLPSOLVEAPIDEF get_variables_func            *_get_variables;\nLPSOLVEAPIDEF get_verbose_func              *_get_verbose;\nLPSOLVEAPIDEF get_working_objective_func    *_get_working_objective;\nLPSOLVEAPIDEF guess_basis_func              *_guess_basis;\nLPSOLVEAPIDEF has_BFP_func                  *_has_BFP;\nLPSOLVEAPIDEF has_XLI_func                  *_has_XLI;\nLPSOLVEAPIDEF is_add_rowmode_func           *_is_add_rowmode;\nLPSOLVEAPIDEF is_anti_degen_func            *_is_anti_degen;\nLPSOLVEAPIDEF is_binary_func                *_is_binary;\nLPSOLVEAPIDEF is_break_at_first_func        *_is_break_at_first;\nLPSOLVEAPIDEF is_constr_type_func           *_is_constr_type;\nLPSOLVEAPIDEF is_debug_func                 *_is_debug;\nLPSOLVEAPIDEF is_feasible_func              *_is_feasible;\nLPSOLVEAPIDEF is_unbounded_func             *_is_unbounded;\nLPSOLVEAPIDEF is_infinite_func              *_is_infinite;\nLPSOLVEAPIDEF is_int_func                   *_is_int;\nLPSOLVEAPIDEF is_integerscaling_func        *_is_integerscaling;\nLPSOLVEAPIDEF is_lag_trace_func             *_is_lag_trace;\nLPSOLVEAPIDEF is_maxim_func                 *_is_maxim;\nLPSOLVEAPIDEF is_nativeBFP_func             *_is_nativeBFP;\nLPSOLVEAPIDEF is_nativeXLI_func             *_is_nativeXLI;\nLPSOLVEAPIDEF is_negative_func              *_is_negative;\nLPSOLVEAPIDEF is_piv_mode_func              *_is_piv_mode;\nLPSOLVEAPIDEF is_piv_rule_func              *_is_piv_rule;\nLPSOLVEAPIDEF is_presolve_func              *_is_presolve;\nLPSOLVEAPIDEF is_scalemode_func             *_is_scalemode;\nLPSOLVEAPIDEF is_scaletype_func             *_is_scaletype;\nLPSOLVEAPIDEF is_semicont_func              *_is_semicont;\nLPSOLVEAPIDEF is_SOS_var_func               *_is_SOS_var;\nLPSOLVEAPIDEF is_trace_func                 *_is_trace;\nLPSOLVEAPIDEF is_use_names_func             *_is_use_names;\nLPSOLVEAPIDEF lp_solve_version_func         *_lp_solve_version;\nLPSOLVEAPIDEF make_lp_func                  *_make_lp;\nLPSOLVEAPIDEF print_constraints_func        *_print_constraints;\nLPSOLVEAPIDEF print_debugdump_func          *_print_debugdump;\nLPSOLVEAPIDEF print_duals_func              *_print_duals;\nLPSOLVEAPIDEF print_lp_func                 *_print_lp;\nLPSOLVEAPIDEF print_objective_func          *_print_objective;\nLPSOLVEAPIDEF print_scales_func             *_print_scales;\nLPSOLVEAPIDEF print_solution_func           *_print_solution;\nLPSOLVEAPIDEF print_str_func                *_print_str;\nLPSOLVEAPIDEF print_tableau_func            *_print_tableau;\nLPSOLVEAPIDEF put_abortfunc_func            *_put_abortfunc;\nLPSOLVEAPIDEF put_bb_nodefunc_func          *_put_bb_nodefunc;\nLPSOLVEAPIDEF put_bb_branchfunc_func        *_put_bb_branchfunc;\nLPSOLVEAPIDEF put_logfunc_func              *_put_logfunc;\nLPSOLVEAPIDEF put_msgfunc_func              *_put_msgfunc;\nLPSOLVEAPIDEF read_LP_func                  *_read_LP;\nLPSOLVEAPIDEF read_MPS_func                 *_read_MPS;\nLPSOLVEAPIDEF read_XLI_func                 *_read_XLI;\nLPSOLVEAPIDEF read_params_func              *_read_params;\nLPSOLVEAPIDEF read_basis_func               *_read_basis;\nLPSOLVEAPIDEF reset_basis_func              *_reset_basis;\nLPSOLVEAPIDEF reset_params_func             *_reset_params;\nLPSOLVEAPIDEF reportfunc                    *_report;\nLPSOLVEAPIDEF resize_lp_func                *_resize_lp;\nLPSOLVEAPIDEF set_add_rowmode_func          *_set_add_rowmode;\nLPSOLVEAPIDEF set_anti_degen_func           *_set_anti_degen;\nLPSOLVEAPIDEF set_basisvar_func             *_set_basisvar;\nLPSOLVEAPIDEF set_basis_func                *_set_basis;\nLPSOLVEAPIDEF set_basiscrash_func           *_set_basiscrash;\nLPSOLVEAPIDEF set_bb_depthlimit_func        *_set_bb_depthlimit;\nLPSOLVEAPIDEF set_bb_floorfirst_func        *_set_bb_floorfirst;\nLPSOLVEAPIDEF set_bb_rule_func              *_set_bb_rule;\nLPSOLVEAPIDEF set_BFP_func                  *_set_BFP;\nLPSOLVEAPIDEF set_binary_func               *_set_binary;\nLPSOLVEAPIDEF set_bounds_func               *_set_bounds;\nLPSOLVEAPIDEF set_bounds_tighter_func       *_set_bounds_tighter;\nLPSOLVEAPIDEF set_break_at_first_func       *_set_break_at_first;\nLPSOLVEAPIDEF set_break_at_value_func       *_set_break_at_value;\n/*LPSOLVEAPIDEF set_break_numeric_accuracy_func *_set_break_numeric_accuracy;*/\nLPSOLVEAPIDEF set_column_func               *_set_column;\nLPSOLVEAPIDEF set_columnex_func             *_set_columnex;\nLPSOLVEAPIDEF set_col_name_func             *_set_col_name;\nLPSOLVEAPIDEF set_constr_type_func          *_set_constr_type;\nLPSOLVEAPIDEF set_debug_func                *_set_debug;\nLPSOLVEAPIDEF set_epsb_func                 *_set_epsb;\nLPSOLVEAPIDEF set_epsd_func                 *_set_epsd;\nLPSOLVEAPIDEF set_epsel_func                *_set_epsel;\nLPSOLVEAPIDEF set_epsint_func               *_set_epsint;\nLPSOLVEAPIDEF set_epslevel_func             *_set_epslevel;\nLPSOLVEAPIDEF set_epsperturb_func           *_set_epsperturb;\nLPSOLVEAPIDEF set_epspivot_func             *_set_epspivot;\nLPSOLVEAPIDEF set_unbounded_func            *_set_unbounded;\nLPSOLVEAPIDEF set_improve_func              *_set_improve;\nLPSOLVEAPIDEF set_infinite_func             *_set_infinite;\nLPSOLVEAPIDEF set_int_func                  *_set_int;\nLPSOLVEAPIDEF set_lag_trace_func            *_set_lag_trace;\nLPSOLVEAPIDEF set_lowbo_func                *_set_lowbo;\nLPSOLVEAPIDEF set_lp_name_func              *_set_lp_name;\nLPSOLVEAPIDEF set_mat_func                  *_set_mat;\nLPSOLVEAPIDEF set_maxim_func                *_set_maxim;\nLPSOLVEAPIDEF set_maxpivot_func             *_set_maxpivot;\nLPSOLVEAPIDEF set_minim_func                *_set_minim;\nLPSOLVEAPIDEF set_mip_gap_func              *_set_mip_gap;\nLPSOLVEAPIDEF set_multiprice_func           *_set_multiprice;\nLPSOLVEAPIDEF set_negrange_func             *_set_negrange;\nLPSOLVEAPIDEF set_obj_bound_func            *_set_obj_bound;\nLPSOLVEAPIDEF set_obj_fn_func               *_set_obj_fn;\nLPSOLVEAPIDEF set_obj_fnex_func             *_set_obj_fnex;\nLPSOLVEAPIDEF set_obj_func                  *_set_obj;\nLPSOLVEAPIDEF set_outputfile_func           *_set_outputfile;\nLPSOLVEAPIDEF set_outputstream_func         *_set_outputstream;\nLPSOLVEAPIDEF set_partialprice_func         *_set_partialprice;\nLPSOLVEAPIDEF set_pivoting_func             *_set_pivoting;\nLPSOLVEAPIDEF set_preferdual_func           *_set_preferdual;\nLPSOLVEAPIDEF set_presolve_func             *_set_presolve;\nLPSOLVEAPIDEF set_print_sol_func            *_set_print_sol;\nLPSOLVEAPIDEF set_pseudocosts_func          *_set_pseudocosts;\nLPSOLVEAPIDEF set_rh_func                   *_set_rh;\nLPSOLVEAPIDEF set_rh_range_func             *_set_rh_range;\nLPSOLVEAPIDEF set_rh_vec_func               *_set_rh_vec;\nLPSOLVEAPIDEF set_row_func                  *_set_row;\nLPSOLVEAPIDEF set_rowex_func                *_set_rowex;\nLPSOLVEAPIDEF set_row_name_func             *_set_row_name;\nLPSOLVEAPIDEF set_scalelimit_func           *_set_scalelimit;\nLPSOLVEAPIDEF set_scaling_func              *_set_scaling;\nLPSOLVEAPIDEF set_semicont_func             *_set_semicont;\nLPSOLVEAPIDEF set_sense_func                *_set_sense;\nLPSOLVEAPIDEF set_simplextype_func          *_set_simplextype;\nLPSOLVEAPIDEF set_solutionlimit_func        *_set_solutionlimit;\nLPSOLVEAPIDEF set_timeout_func              *_set_timeout;\nLPSOLVEAPIDEF set_trace_func                *_set_trace;\nLPSOLVEAPIDEF set_upbo_func                 *_set_upbo;\nLPSOLVEAPIDEF set_var_branch_func           *_set_var_branch;\nLPSOLVEAPIDEF set_var_weights_func          *_set_var_weights;\nLPSOLVEAPIDEF set_verbose_func              *_set_verbose;\nLPSOLVEAPIDEF set_XLI_func                  *_set_XLI;\nLPSOLVEAPIDEF solve_func                    *_solve;\nLPSOLVEAPIDEF str_add_column_func           *_str_add_column;\nLPSOLVEAPIDEF str_add_constraint_func       *_str_add_constraint;\nLPSOLVEAPIDEF str_add_lag_con_func          *_str_add_lag_con;\nLPSOLVEAPIDEF str_set_obj_fn_func           *_str_set_obj_fn;\nLPSOLVEAPIDEF str_set_rh_vec_func           *_str_set_rh_vec;\nLPSOLVEAPIDEF time_elapsed_func             *_time_elapsed;\nLPSOLVEAPIDEF unscale_func                  *_unscale;\nLPSOLVEAPIDEF write_lp_func                 *_write_lp;\nLPSOLVEAPIDEF write_LP_func                 *_write_LP;\nLPSOLVEAPIDEF write_mps_func                *_write_mps;\nLPSOLVEAPIDEF write_MPS_func                *_write_MPS;\nLPSOLVEAPIDEF write_freemps_func            *_write_freemps;\nLPSOLVEAPIDEF write_freeMPS_func            *_write_freeMPS;\nLPSOLVEAPIDEF write_XLI_func                *_write_XLI;\nLPSOLVEAPIDEF write_basis_func              *_write_basis;\nLPSOLVEAPIDEF write_params_func             *_write_params;\n\n#if defined LPSOLVEAPIFROMLPREC\n\nstatic int init_lpsolve(lprec *lp)\n{\n  _add_column = lp->add_column;\n  _add_columnex = lp->add_columnex;\n  _add_constraint = lp->add_constraint;\n  _add_constraintex = lp->add_constraintex;\n  _add_lag_con = lp->add_lag_con;\n  _add_SOS = lp->add_SOS;\n  _column_in_lp = lp->column_in_lp;\n  _copy_lp = lp->copy_lp;\n  _default_basis = lp->default_basis;\n  _del_column = lp->del_column;\n  _del_constraint = lp->del_constraint;\n  _delete_lp = lp->delete_lp;\n  _dualize_lp = lp->dualize_lp;\n  _free_lp = lp->free_lp;\n  /*_get_accuracy = lp->get_accuracy;*/\n  _get_anti_degen = lp->get_anti_degen;\n  _get_basis = lp->get_basis;\n  _get_basiscrash = lp->get_basiscrash;\n  _get_bb_depthlimit = lp->get_bb_depthlimit;\n  _get_bb_floorfirst = lp->get_bb_floorfirst;\n  _get_bb_rule = lp->get_bb_rule;\n  _get_bounds_tighter = lp->get_bounds_tighter;\n  _get_break_at_value = lp->get_break_at_value;\n/*  _get_break_numeric_accuracy = lp->get_break_numeric_accuracy;*/\n  _get_col_name = lp->get_col_name;\n  _get_columnex = lp->get_columnex;\n  _get_constr_type = lp->get_constr_type;\n  _get_constr_value = lp->get_constr_value;\n  _get_constraints = lp->get_constraints;\n  _get_dual_solution = lp->get_dual_solution;\n  _get_epsb = lp->get_epsb;\n  _get_epsd = lp->get_epsd;\n  _get_epsel = lp->get_epsel;\n  _get_epsint = lp->get_epsint;\n  _get_epsperturb = lp->get_epsperturb;\n  _get_epspivot = lp->get_epspivot;\n  _get_improve = lp->get_improve;\n  _get_infinite = lp->get_infinite;\n  _get_lambda = lp->get_lambda;\n  _get_lowbo = lp->get_lowbo;\n  _get_lp_index = lp->get_lp_index;\n  _get_lp_name = lp->get_lp_name;\n  _get_Lrows = lp->get_Lrows;\n  _get_mat = lp->get_mat;\n  _get_mat_byindex = lp->get_mat_byindex;\n  _get_max_level = lp->get_max_level;\n  _get_maxpivot = lp->get_maxpivot;\n  _get_mip_gap = lp->get_mip_gap;\n  _get_multiprice = lp->get_multiprice;\n  _get_nameindex = lp->get_nameindex;\n  _get_Ncolumns = lp->get_Ncolumns;\n  _get_negrange = lp->get_negrange;\n  _get_nonzeros = lp->get_nonzeros;\n  _get_Norig_columns = lp->get_Norig_columns;\n  _get_Norig_rows = lp->get_Norig_rows;\n  _get_Nrows = lp->get_Nrows;\n  _get_obj_bound = lp->get_obj_bound;\n  _get_objective = lp->get_objective;\n  _get_orig_index = lp->get_orig_index;\n  _get_origcol_name = lp->get_origcol_name;\n  _get_origrow_name = lp->get_origrow_name;\n  _get_partialprice = lp->get_partialprice;\n  _get_pivoting = lp->get_pivoting;\n  _get_presolve = lp->get_presolve;\n  _get_presolveloops = lp->get_presolveloops;\n  _get_primal_solution = lp->get_primal_solution;\n  _get_print_sol = lp->get_print_sol;\n  _get_pseudocosts = lp->get_pseudocosts;\n  _get_ptr_constraints = lp->get_ptr_constraints;\n  _get_ptr_dual_solution = lp->get_ptr_dual_solution;\n  _get_ptr_lambda = lp->get_ptr_lambda;\n  _get_ptr_primal_solution = lp->get_ptr_primal_solution;\n  _get_ptr_sensitivity_obj = lp->get_ptr_sensitivity_obj;\n  _get_ptr_sensitivity_objex = lp->get_ptr_sensitivity_objex;\n  _get_ptr_sensitivity_rhs = lp->get_ptr_sensitivity_rhs;\n  _get_ptr_variables = lp->get_ptr_variables;\n  _get_rh = lp->get_rh;\n  _get_rh_range = lp->get_rh_range;\n  _get_row = lp->get_row;\n  _get_rowex = lp->get_rowex;\n  _get_row_name = lp->get_row_name;\n  _get_scalelimit = lp->get_scalelimit;\n  _get_scaling = lp->get_scaling;\n  _get_sensitivity_obj = lp->get_sensitivity_obj;\n  _get_sensitivity_objex = lp->get_sensitivity_objex;\n  _get_sensitivity_rhs = lp->get_sensitivity_rhs;\n  _get_simplextype = lp->get_simplextype;\n  _get_solutioncount = lp->get_solutioncount;\n  _get_solutionlimit = lp->get_solutionlimit;\n  _get_status = lp->get_status;\n  _get_statustext = lp->get_statustext;\n  _get_timeout = lp->get_timeout;\n  _get_total_iter = lp->get_total_iter;\n  _get_total_nodes = lp->get_total_nodes;\n  _get_upbo = lp->get_upbo;\n  _get_var_branch = lp->get_var_branch;\n  _get_var_dualresult = lp->get_var_dualresult;\n  _get_var_primalresult = lp->get_var_primalresult;\n  _get_var_priority = lp->get_var_priority;\n  _get_variables = lp->get_variables;\n  _get_verbose = lp->get_verbose;\n  _get_working_objective = lp->get_working_objective;\n  _has_BFP = lp->has_BFP;\n  _has_XLI = lp->has_XLI;\n  _is_add_rowmode = lp->is_add_rowmode;\n  _is_anti_degen = lp->is_anti_degen;\n  _is_binary = lp->is_binary;\n  _is_break_at_first = lp->is_break_at_first;\n  _is_constr_type = lp->is_constr_type;\n  _is_debug = lp->is_debug;\n  _is_feasible = lp->is_feasible;\n  _is_unbounded = lp->is_unbounded;\n  _is_infinite = lp->is_infinite;\n  _is_int = lp->is_int;\n  _is_integerscaling = lp->is_integerscaling;\n  _is_lag_trace = lp->is_lag_trace;\n  _is_maxim = lp->is_maxim;\n  _is_nativeBFP = lp->is_nativeBFP;\n  _is_nativeXLI = lp->is_nativeXLI;\n  _is_negative = lp->is_negative;\n  _is_piv_mode = lp->is_piv_mode;\n  _is_piv_rule = lp->is_piv_rule;\n  _is_presolve = lp->is_presolve;\n  _is_scalemode = lp->is_scalemode;\n  _is_scaletype = lp->is_scaletype;\n  _is_semicont = lp->is_semicont;\n  _is_SOS_var = lp->is_SOS_var;\n  _is_trace = lp->is_trace;\n  _is_use_names = lp->is_use_names;\n  _lp_solve_version = lp->lp_solve_version;\n  _make_lp = lp->make_lp;\n  _print_constraints = lp->print_constraints;\n  _print_debugdump = lp->print_debugdump;\n  _print_duals = lp->print_duals;\n  _print_lp = lp->print_lp;\n  _print_objective = lp->print_objective;\n  _print_scales = lp->print_scales;\n  _print_solution = lp->print_solution;\n  _print_str = lp->print_str;\n  _print_tableau = lp->print_tableau;\n  _put_abortfunc = lp->put_abortfunc;\n  _put_bb_nodefunc = lp->put_bb_nodefunc;\n  _put_bb_branchfunc = lp->put_bb_branchfunc;\n  _put_logfunc = lp->put_logfunc;\n  _put_msgfunc = lp->put_msgfunc;\n  _read_LP = lp->read_LP;\n  _read_MPS = lp->read_MPS;\n  _read_XLI = lp->read_XLI;\n  _read_params = lp->read_params;\n  _read_basis = lp->read_basis;\n  _reset_basis = lp->reset_basis;\n  _reset_params = lp->reset_params;\n  _report = lp->report;\n  _resize_lp = lp->resize_lp;\n  _set_add_rowmode = lp->set_add_rowmode;\n  _set_anti_degen = lp->set_anti_degen;\n  _set_basisvar = lp->set_basisvar;\n  _set_basis = lp->set_basis;\n  _set_basiscrash = lp->set_basiscrash;\n  _set_bb_depthlimit = lp->set_bb_depthlimit;\n  _set_bb_floorfirst = lp->set_bb_floorfirst;\n  _set_bb_rule = lp->set_bb_rule;\n  _set_BFP = lp->set_BFP;\n  _set_binary = lp->set_binary;\n  _set_bounds = lp->set_bounds;\n  _set_bounds_tighter = lp->set_bounds_tighter;\n  _set_break_at_first = lp->set_break_at_first;\n  _set_break_at_value = lp->set_break_at_value;\n/*  _set_break_numeric_accuracy = lp->set_break_numeric_accuracy;*/\n  _set_column = lp->set_column;\n  _set_columnex = lp->set_columnex;\n  _set_col_name = lp->set_col_name;\n  _set_constr_type = lp->set_constr_type;\n  _set_debug = lp->set_debug;\n  _set_epsb = lp->set_epsb;\n  _set_epsd = lp->set_epsd;\n  _set_epsel = lp->set_epsel;\n  _set_epsint = lp->set_epsint;\n  _set_epslevel = lp->set_epslevel;\n  _set_epsperturb = lp->set_epsperturb;\n  _set_epspivot = lp->set_epspivot;\n  _set_unbounded = lp->set_unbounded;\n  _set_improve = lp->set_improve;\n  _set_infinite = lp->set_infinite;\n  _set_int = lp->set_int;\n  _set_lag_trace = lp->set_lag_trace;\n  _set_lowbo = lp->set_lowbo;\n  _set_lp_name = lp->set_lp_name;\n  _set_mat = lp->set_mat;\n  _set_maxim = lp->set_maxim;\n  _set_maxpivot = lp->set_maxpivot;\n  _set_minim = lp->set_minim;\n  _set_mip_gap = lp->set_mip_gap;\n  _set_multiprice = lp->set_multiprice;\n  _set_negrange = lp->set_negrange;\n  _set_obj_bound = lp->set_obj_bound;\n  _set_obj_fn = lp->set_obj_fn;\n  _set_obj_fnex = lp->set_obj_fnex;\n  _set_obj = lp->set_obj;\n  _set_outputfile = lp->set_outputfile;\n  _set_outputstream = lp->set_outputstream;\n  _set_partialprice = lp->set_partialprice;\n  _set_pivoting = lp->set_pivoting;\n  _set_preferdual = lp->set_preferdual;\n  _set_presolve = lp->set_presolve;\n  _set_print_sol = lp->set_print_sol;\n  _set_pseudocosts = lp->set_pseudocosts;\n  _set_rh = lp->set_rh;\n  _set_rh_range = lp->set_rh_range;\n  _set_rh_vec = lp->set_rh_vec;\n  _set_row = lp->set_row;\n  _set_rowex = lp->set_rowex;\n  _set_row_name = lp->set_row_name;\n  _set_scalelimit = lp->set_scalelimit;\n  _set_scaling = lp->set_scaling;\n  _set_semicont = lp->set_semicont;\n  _set_sense = lp->set_sense;\n  _set_simplextype = lp->set_simplextype;\n  _set_solutionlimit = lp->set_solutionlimit;\n  _set_timeout = lp->set_timeout;\n  _set_trace = lp->set_trace;\n  _set_upbo = lp->set_upbo;\n  _set_var_branch = lp->set_var_branch;\n  _set_var_weights = lp->set_var_weights;\n  _set_verbose = lp->set_verbose;\n  _set_XLI = lp->set_XLI;\n  _solve = lp->solve;\n  _str_add_column = lp->str_add_column;\n  _str_add_constraint = lp->str_add_constraint;\n  _str_add_lag_con = lp->str_add_lag_con;\n  _str_set_obj_fn = lp->str_set_obj_fn;\n  _str_set_rh_vec = lp->str_set_rh_vec;\n  _time_elapsed = lp->time_elapsed;\n  _unscale = lp->unscale;\n  _write_lp = lp->write_lp;\n  _write_LP = lp->write_LP;\n  _write_mps = lp->write_mps;\n  _write_MPS = lp->write_MPS;\n  _write_freemps = lp->write_freemps;\n  _write_freeMPS = lp->write_freeMPS;\n  _write_XLI = lp->write_XLI;\n  _write_basis = lp->write_basis;\n  _write_params = lp->write_params;\n\n  return(TRUE);\n}\n\n#elif defined LPSOLVEAPIFROMLIB\n\n#ifdef WIN32\n#  include <windows.h>\n#else\n#  include <dlfcn.h>\n#endif\n\n#if defined WIN32\n# define hlpsolve HINSTANCE\n#else\n# define hlpsolve void *\n#endif\n\nstatic hlpsolve open_lpsolve_lib(char *filename)\n{\n  hlpsolve lpsolve;\n\n# if defined WIN32\n  /* Get a handle to the Windows DLL module. */\n  lpsolve = LoadLibrary(\"lpsolve55.dll\");\n# else\n  lpsolve = dlopen(\"liblpsolve55.so\", RTLD_LAZY);;\n# endif\n  return(lpsolve);\n}\n\nstatic int close_lpsolve_lib(hlpsolve lpsolve)\n{\n#ifdef WIN32\n  FreeLibrary(lpsolve);\n#else\n  dlclose(lpsolve);\n#endif\n\n  return(TRUE);\n}\n\nstatic int init_lpsolve(hlpsolve lpsolve)\n{\n# if defined WIN32\n#   define AddressOf GetProcAddress\n# else\n#   define AddressOf dlsym\n# endif\n\n  /* assign API functions to lp structure */\n  _add_column = (add_column_func *) AddressOf(lpsolve, \"add_column\");\n  _add_columnex = (add_columnex_func *) AddressOf(lpsolve, \"add_columnex\");\n  _add_constraint = (add_constraint_func *) AddressOf(lpsolve, \"add_constraint\");\n  _add_constraintex = (add_constraintex_func *) AddressOf(lpsolve, \"add_constraintex\");\n  _add_lag_con = (add_lag_con_func *) AddressOf(lpsolve, \"add_lag_con\");\n  _add_SOS = (add_SOS_func *) AddressOf(lpsolve, \"add_SOS\");\n  _column_in_lp = (column_in_lp_func *) AddressOf(lpsolve, \"column_in_lp\");\n  _copy_lp = (copy_lp_func *) AddressOf(lpsolve, \"copy_lp\");\n  _default_basis = (default_basis_func *) AddressOf(lpsolve, \"default_basis\");\n  _del_column = (del_column_func *) AddressOf(lpsolve, \"del_column\");\n  _del_constraint = (del_constraint_func *) AddressOf(lpsolve, \"del_constraint\");\n  _delete_lp = (delete_lp_func *) AddressOf(lpsolve, \"delete_lp\");\n  _dualize_lp = (dualize_lp_func *) AddressOf(lpsolve, \"dualize_lp\");\n  _free_lp = (free_lp_func *) AddressOf(lpsolve, \"free_lp\");\n  /*_get_accuracy = (get_accuracy_func *) AddressOf(lpsolve, \"get_accuracy\");*/\n  _get_anti_degen = (get_anti_degen_func *) AddressOf(lpsolve, \"get_anti_degen\");\n  _get_basis = (get_basis_func *) AddressOf(lpsolve, \"get_basis\");\n  _get_basiscrash = (get_basiscrash_func *) AddressOf(lpsolve, \"get_basiscrash\");\n  _get_bb_depthlimit = (get_bb_depthlimit_func *) AddressOf(lpsolve, \"get_bb_depthlimit\");\n  _get_bb_floorfirst = (get_bb_floorfirst_func *) AddressOf(lpsolve, \"get_bb_floorfirst\");\n  _get_bb_rule = (get_bb_rule_func *) AddressOf(lpsolve, \"get_bb_rule\");\n  _get_bounds_tighter = (get_bounds_tighter_func *) AddressOf(lpsolve, \"get_bounds_tighter\");\n  _get_break_at_value = (get_break_at_value_func *) AddressOf(lpsolve, \"get_break_at_value\");\n/*  _get_break_numeric_accuracy = (get_break_numeric_accuracy_func *) AddressOf(lpsolve, \"get_break_numeric_accuracy\");*/\n  _get_col_name = (get_col_name_func *) AddressOf(lpsolve, \"get_col_name\");\n  _get_column = (get_column_func *) AddressOf(lpsolve, \"get_column\");\n  _get_columnex = (get_columnex_func *) AddressOf(lpsolve, \"get_columnex\");\n  _get_constr_type = (get_constr_type_func *) AddressOf(lpsolve, \"get_constr_type\");\n  _get_constr_value = (get_constr_value_func *) AddressOf(lpsolve, \"get_constr_value\");\n  _get_constraints = (get_constraints_func *) AddressOf(lpsolve, \"get_constraints\");\n  _get_dual_solution = (get_dual_solution_func *) AddressOf(lpsolve, \"get_dual_solution\");\n  _get_epsb = (get_epsb_func *) AddressOf(lpsolve, \"get_epsb\");\n  _get_epsd = (get_epsd_func *) AddressOf(lpsolve, \"get_epsd\");\n  _get_epsel = (get_epsel_func *) AddressOf(lpsolve, \"get_epsel\");\n  _get_epsint = (get_epsint_func *) AddressOf(lpsolve, \"get_epsint\");\n  _get_epsperturb = (get_epsperturb_func *) AddressOf(lpsolve, \"get_epsperturb\");\n  _get_epspivot = (get_epspivot_func *) AddressOf(lpsolve, \"get_epspivot\");\n  _get_improve = (get_improve_func *) AddressOf(lpsolve, \"get_improve\");\n  _get_infinite = (get_infinite_func *) AddressOf(lpsolve, \"get_infinite\");\n  _get_lambda = (get_lambda_func *) AddressOf(lpsolve, \"get_lambda\");\n  _get_lowbo = (get_lowbo_func *) AddressOf(lpsolve, \"get_lowbo\");\n  _get_lp_index = (get_lp_index_func *) AddressOf(lpsolve, \"get_lp_index\");\n  _get_lp_name = (get_lp_name_func *) AddressOf(lpsolve, \"get_lp_name\");\n  _get_Lrows = (get_Lrows_func *) AddressOf(lpsolve, \"get_Lrows\");\n  _get_mat = (get_mat_func *) AddressOf(lpsolve, \"get_mat\");\n  _get_mat_byindex = (get_mat_byindex_func *) AddressOf(lpsolve, \"get_mat_byindex\");\n  _get_max_level = (get_max_level_func *) AddressOf(lpsolve, \"get_max_level\");\n  _get_maxpivot = (get_maxpivot_func *) AddressOf(lpsolve, \"get_maxpivot\");\n  _get_mip_gap = (get_mip_gap_func *) AddressOf(lpsolve, \"get_mip_gap\");\n  _get_multiprice = (get_multiprice_func *) AddressOf(lpsolve, \"get_multiprice\");\n  _get_nameindex = (get_nameindex_func *) AddressOf(lpsolve, \"get_nameindex\");\n  _get_Ncolumns = (get_Ncolumns_func *) AddressOf(lpsolve, \"get_Ncolumns\");\n  _get_negrange = (get_negrange_func *) AddressOf(lpsolve, \"get_negrange\");\n  _get_nonzeros = (get_nz_func *) AddressOf(lpsolve, \"get_nonzeros\");\n  _get_Norig_columns = (get_Norig_columns_func *) AddressOf(lpsolve, \"get_Norig_columns\");\n  _get_Norig_rows = (get_Norig_rows_func *) AddressOf(lpsolve, \"get_Norig_rows\");\n  _get_Nrows = (get_Nrows_func *) AddressOf(lpsolve, \"get_Nrows\");\n  _get_obj_bound = (get_obj_bound_func *) AddressOf(lpsolve, \"get_obj_bound\");\n  _get_objective = (get_objective_func *) AddressOf(lpsolve, \"get_objective\");\n  _get_orig_index = (get_orig_index_func *) AddressOf(lpsolve, \"get_orig_index\");\n  _get_origcol_name = (get_origcol_name_func *) AddressOf(lpsolve, \"get_origcol_name\");\n  _get_origrow_name = (get_origrow_name_func *) AddressOf(lpsolve, \"get_origrow_name\");\n  _get_partialprice = (get_partialprice_func *) AddressOf(lpsolve, \"get_partialprice\");\n  _get_pivoting = (get_pivoting_func *) AddressOf(lpsolve, \"get_pivoting\");\n  _get_presolve = (get_presolve_func *) AddressOf(lpsolve, \"get_presolve\");\n  _get_presolveloops = (get_presolveloops_func *) AddressOf(lpsolve, \"get_presolveloops\");\n  _get_primal_solution = (get_primal_solution_func *) AddressOf(lpsolve, \"get_primal_solution\");\n  _get_print_sol = (get_print_sol_func *) AddressOf(lpsolve, \"get_print_sol\");\n  _get_pseudocosts = (get_pseudocosts_func *) AddressOf(lpsolve, \"get_pseudocosts\");\n  _get_ptr_constraints = (get_ptr_constraints_func *) AddressOf(lpsolve, \"get_ptr_constraints\");\n  _get_ptr_dual_solution = (get_ptr_dual_solution_func *) AddressOf(lpsolve, \"get_ptr_dual_solution\");\n  _get_ptr_lambda = (get_ptr_lambda_func *) AddressOf(lpsolve, \"get_ptr_lambda\");\n  _get_ptr_primal_solution = (get_ptr_primal_solution_func *) AddressOf(lpsolve, \"get_ptr_primal_solution\");\n  _get_ptr_sensitivity_obj = (get_ptr_sensitivity_obj_func *) AddressOf(lpsolve, \"get_ptr_sensitivity_obj\");\n  _get_ptr_sensitivity_objex = (get_ptr_sensitivity_objex_func *) AddressOf(lpsolve, \"get_ptr_sensitivity_objex\");\n  _get_ptr_sensitivity_rhs = (get_ptr_sensitivity_rhs_func *) AddressOf(lpsolve, \"get_ptr_sensitivity_rhs\");\n  _get_ptr_variables = (get_ptr_variables_func *) AddressOf(lpsolve, \"get_ptr_variables\");\n  _get_rh = (get_rh_func *) AddressOf(lpsolve, \"get_rh\");\n  _get_rh_range = (get_rh_range_func *) AddressOf(lpsolve, \"get_rh_range\");\n  _get_row = (get_row_func *) AddressOf(lpsolve, \"get_row\");\n  _get_rowex = (get_rowex_func *) AddressOf(lpsolve, \"get_rowex\");\n  _get_row_name = (get_row_name_func *) AddressOf(lpsolve, \"get_row_name\");\n  _get_scalelimit = (get_scalelimit_func *) AddressOf(lpsolve, \"get_scalelimit\");\n  _get_scaling = (get_scaling_func *) AddressOf(lpsolve, \"get_scaling\");\n  _get_sensitivity_obj = (get_sensitivity_obj_func *) AddressOf(lpsolve, \"get_sensitivity_obj\");\n  _get_sensitivity_objex = (get_sensitivity_objex_func *) AddressOf(lpsolve, \"get_sensitivity_objex\");\n  _get_sensitivity_rhs = (get_sensitivity_rhs_func *) AddressOf(lpsolve, \"get_sensitivity_rhs\");\n  _get_simplextype = (get_simplextype_func *) AddressOf(lpsolve, \"get_simplextype\");\n  _get_solutioncount = (get_solutioncount_func *) AddressOf(lpsolve, \"get_solutioncount\");\n  _get_solutionlimit = (get_solutionlimit_func *) AddressOf(lpsolve, \"get_solutionlimit\");\n  _get_status = (get_status_func *) AddressOf(lpsolve, \"get_status\");\n  _get_statustext = (get_statustext_func *) AddressOf(lpsolve, \"get_statustext\");\n  _get_timeout = (get_timeout_func *) AddressOf(lpsolve, \"get_timeout\");\n  _get_total_iter = (get_total_iter_func *) AddressOf(lpsolve, \"get_total_iter\");\n  _get_total_nodes = (get_total_nodes_func *) AddressOf(lpsolve, \"get_total_nodes\");\n  _get_upbo = (get_upbo_func *) AddressOf(lpsolve, \"get_upbo\");\n  _get_var_branch = (get_var_branch_func *) AddressOf(lpsolve, \"get_var_branch\");\n  _get_var_dualresult = (get_var_dualresult_func *) AddressOf(lpsolve, \"get_var_dualresult\");\n  _get_var_primalresult = (get_var_primalresult_func *) AddressOf(lpsolve, \"get_var_primalresult\");\n  _get_var_priority = (get_var_priority_func *) AddressOf(lpsolve, \"get_var_priority\");\n  _get_variables = (get_variables_func *) AddressOf(lpsolve, \"get_variables\");\n  _get_verbose = (get_verbose_func *) AddressOf(lpsolve, \"get_verbose\");\n  _get_working_objective = (get_working_objective_func *) AddressOf(lpsolve, \"get_working_objective\");\n  _guess_basis = (guess_basis_func *) AddressOf(lpsolve, \"guess_basis\");\n  _has_BFP = (has_BFP_func *) AddressOf(lpsolve, \"has_BFP\");\n  _has_XLI = (has_XLI_func *) AddressOf(lpsolve, \"has_XLI\");\n  _is_add_rowmode = (is_add_rowmode_func *) AddressOf(lpsolve, \"is_add_rowmode\");\n  _is_anti_degen = (is_anti_degen_func *) AddressOf(lpsolve, \"is_anti_degen\");\n  _is_binary = (is_binary_func *) AddressOf(lpsolve, \"is_binary\");\n  _is_break_at_first = (is_break_at_first_func *) AddressOf(lpsolve, \"is_break_at_first\");\n  _is_constr_type = (is_constr_type_func *) AddressOf(lpsolve, \"is_constr_type\");\n  _is_debug = (is_debug_func *) AddressOf(lpsolve, \"is_debug\");\n  _is_feasible = (is_feasible_func *) AddressOf(lpsolve, \"is_feasible\");\n  _is_unbounded = (is_unbounded_func *) AddressOf(lpsolve, \"is_unbounded\");\n  _is_infinite = (is_infinite_func *) AddressOf(lpsolve, \"is_infinite\");\n  _is_int = (is_int_func *) AddressOf(lpsolve, \"is_int\");\n  _is_integerscaling = (is_integerscaling_func *) AddressOf(lpsolve, \"is_integerscaling\");\n  _is_lag_trace = (is_lag_trace_func *) AddressOf(lpsolve, \"is_lag_trace\");\n  _is_maxim = (is_maxim_func *) AddressOf(lpsolve, \"is_maxim\");\n  _is_nativeBFP = (is_nativeBFP_func *) AddressOf(lpsolve, \"is_nativeBFP\");\n  _is_nativeXLI = (is_nativeXLI_func *) AddressOf(lpsolve, \"is_nativeXLI\");\n  _is_negative = (is_negative_func *) AddressOf(lpsolve, \"is_negative\");\n  _is_piv_mode = (is_piv_mode_func *) AddressOf(lpsolve, \"is_piv_mode\");\n  _is_piv_rule = (is_piv_rule_func *) AddressOf(lpsolve, \"is_piv_rule\");\n  _is_presolve = (is_presolve_func *) AddressOf(lpsolve, \"is_presolve\");\n  _is_scalemode = (is_scalemode_func *) AddressOf(lpsolve, \"is_scalemode\");\n  _is_scaletype = (is_scaletype_func *) AddressOf(lpsolve, \"is_scaletype\");\n  _is_semicont = (is_semicont_func *) AddressOf(lpsolve, \"is_semicont\");\n  _is_SOS_var = (is_SOS_var_func *) AddressOf(lpsolve, \"is_SOS_var\");\n  _is_trace = (is_trace_func *) AddressOf(lpsolve, \"is_trace\");\n  _is_use_names = (is_use_names_func *) AddressOf(lpsolve, \"is_use_names\");\n  _lp_solve_version = (lp_solve_version_func *) AddressOf(lpsolve, \"lp_solve_version\");\n  _make_lp = (make_lp_func *) AddressOf(lpsolve, \"make_lp\");\n  _print_constraints = (print_constraints_func *) AddressOf(lpsolve, \"print_constraints\");\n  _print_debugdump = (print_debugdump_func *) AddressOf(lpsolve, \"print_debugdump\");\n  _print_duals = (print_duals_func *) AddressOf(lpsolve, \"print_duals\");\n  _print_lp = (print_lp_func *) AddressOf(lpsolve, \"print_lp\");\n  _print_objective = (print_objective_func *) AddressOf(lpsolve, \"print_objective\");\n  _print_scales = (print_scales_func *) AddressOf(lpsolve, \"print_scales\");\n  _print_solution = (print_solution_func *) AddressOf(lpsolve, \"print_solution\");\n  _print_str = (print_str_func *) AddressOf(lpsolve, \"print_str\");\n  _print_tableau = (print_tableau_func *) AddressOf(lpsolve, \"print_tableau\");\n  _put_abortfunc = (put_abortfunc_func *) AddressOf(lpsolve, \"put_abortfunc\");\n  _put_bb_nodefunc = (put_bb_nodefunc_func *) AddressOf(lpsolve, \"put_bb_nodefunc\");\n  _put_bb_branchfunc = (put_bb_branchfunc_func *) AddressOf(lpsolve, \"put_bb_branchfunc\");\n  _put_logfunc = (put_logfunc_func *) AddressOf(lpsolve, \"put_logfunc\");\n  _put_msgfunc = (put_msgfunc_func *) AddressOf(lpsolve, \"put_msgfunc\");\n  _read_LP = (read_LP_func *) AddressOf(lpsolve, \"read_LP\");\n  _read_MPS = (read_MPS_func *) AddressOf(lpsolve, \"read_MPS\");\n  _read_XLI = (read_XLI_func *) AddressOf(lpsolve, \"read_XLI\");\n  _read_params = (read_params_func *) AddressOf(lpsolve, \"read_params\");\n  _read_basis = (read_basis_func *) AddressOf(lpsolve, \"read_basis\");\n  _reset_basis = (reset_basis_func *) AddressOf(lpsolve, \"reset_basis\");\n  _reset_params = (reset_params_func *) AddressOf(lpsolve, \"reset_params\");\n  _report = (reportfunc *) AddressOf(lpsolve, \"report\");\n  _resize_lp = (resize_lp_func *) AddressOf(lpsolve, \"resize_lp\");\n  _set_add_rowmode = (set_add_rowmode_func *) AddressOf(lpsolve, \"set_add_rowmode\");\n  _set_anti_degen = (set_anti_degen_func *) AddressOf(lpsolve, \"set_anti_degen\");\n  _set_basisvar = (set_basisvar_func *) AddressOf(lpsolve, \"set_basisvar\");\n  _set_basis = (set_basis_func *) AddressOf(lpsolve, \"set_basis\");\n  _set_basiscrash = (set_basiscrash_func *) AddressOf(lpsolve, \"set_basiscrash\");\n  _set_bb_depthlimit = (set_bb_depthlimit_func *) AddressOf(lpsolve, \"set_bb_depthlimit\");\n  _set_bb_floorfirst = (set_bb_floorfirst_func *) AddressOf(lpsolve, \"set_bb_floorfirst\");\n  _set_bb_rule = (set_bb_rule_func *) AddressOf(lpsolve, \"set_bb_rule\");\n  _set_BFP = (set_BFP_func *) AddressOf(lpsolve, \"set_BFP\");\n  _set_binary = (set_binary_func *) AddressOf(lpsolve, \"set_binary\");\n  _set_bounds = (set_bounds_func *) AddressOf(lpsolve, \"set_bounds\");\n  _set_bounds_tighter = (set_bounds_tighter_func *) AddressOf(lpsolve, \"set_bounds_tighter\");\n  _set_break_at_first = (set_break_at_first_func *) AddressOf(lpsolve, \"set_break_at_first\");\n  _set_break_at_value = (set_break_at_value_func *) AddressOf(lpsolve, \"set_break_at_value\");\n/*  _set_break_numeric_accuracy = (set_break_numeric_accuracy_func *) AddressOf(lpsolve, \"set_break_numeric_accuracy\");*/\n  _set_column = (set_column_func *) AddressOf(lpsolve, \"set_column\");\n  _set_columnex = (set_columnex_func *) AddressOf(lpsolve, \"set_columnex\");\n  _set_col_name = (set_col_name_func *) AddressOf(lpsolve, \"set_col_name\");\n  _set_constr_type = (set_constr_type_func *) AddressOf(lpsolve, \"set_constr_type\");\n  _set_debug = (set_debug_func *) AddressOf(lpsolve, \"set_debug\");\n  _set_epsb = (set_epsb_func *) AddressOf(lpsolve, \"set_epsb\");\n  _set_epsd = (set_epsd_func *) AddressOf(lpsolve, \"set_epsd\");\n  _set_epsel = (set_epsel_func *) AddressOf(lpsolve, \"set_epsel\");\n  _set_epsint = (set_epsint_func *) AddressOf(lpsolve, \"set_epsint\");\n  _set_epslevel = (set_epslevel_func *) AddressOf(lpsolve, \"set_epslevel\");\n  _set_epsperturb = (set_epsperturb_func *) AddressOf(lpsolve, \"set_epsperturb\");\n  _set_epspivot = (set_epspivot_func *) AddressOf(lpsolve, \"set_epspivot\");\n  _set_unbounded = (set_unbounded_func *) AddressOf(lpsolve, \"set_unbounded\");\n  _set_improve = (set_improve_func *) AddressOf(lpsolve, \"set_improve\");\n  _set_infinite = (set_infinite_func *) AddressOf(lpsolve, \"set_infinite\");\n  _set_int = (set_int_func *) AddressOf(lpsolve, \"set_int\");\n  _set_lag_trace = (set_lag_trace_func *) AddressOf(lpsolve, \"set_lag_trace\");\n  _set_lowbo = (set_lowbo_func *) AddressOf(lpsolve, \"set_lowbo\");\n  _set_lp_name = (set_lp_name_func *) AddressOf(lpsolve, \"set_lp_name\");\n  _set_mat = (set_mat_func *) AddressOf(lpsolve, \"set_mat\");\n  _set_maxim = (set_maxim_func *) AddressOf(lpsolve, \"set_maxim\");\n  _set_maxpivot = (set_maxpivot_func *) AddressOf(lpsolve, \"set_maxpivot\");\n  _set_minim = (set_minim_func *) AddressOf(lpsolve, \"set_minim\");\n  _set_mip_gap = (set_mip_gap_func *) AddressOf(lpsolve, \"set_mip_gap\");\n  _set_multiprice = (set_multiprice_func *) AddressOf(lpsolve, \"set_multiprice\");\n  _set_negrange = (set_negrange_func *) AddressOf(lpsolve, \"set_negrange\");\n  _set_obj_bound = (set_obj_bound_func *) AddressOf(lpsolve, \"set_obj_bound\");\n  _set_obj_fn = (set_obj_fn_func *) AddressOf(lpsolve, \"set_obj_fn\");\n  _set_obj_fnex = (set_obj_fnex_func *) AddressOf(lpsolve, \"set_obj_fnex\");\n  _set_obj = (set_obj_func *) AddressOf(lpsolve, \"set_obj\");\n  _set_outputfile = (set_outputfile_func *) AddressOf(lpsolve, \"set_outputfile\");\n  _set_outputstream = (set_outputstream_func *) AddressOf(lpsolve, \"set_outputstream\");\n  _set_partialprice = (set_partialprice_func *) AddressOf(lpsolve, \"set_partialprice\");\n  _set_pivoting = (set_pivoting_func *) AddressOf(lpsolve, \"set_pivoting\");\n  _set_preferdual = (set_preferdual_func *) AddressOf(lpsolve, \"set_preferdual\");\n  _set_presolve = (set_presolve_func *) AddressOf(lpsolve, \"set_presolve\");\n  _set_print_sol = (set_print_sol_func *) AddressOf(lpsolve, \"set_print_sol\");\n  _set_pseudocosts = (set_pseudocosts_func *) AddressOf(lpsolve, \"set_pseudocosts\");\n  _set_rh = (set_rh_func *) AddressOf(lpsolve, \"set_rh\");\n  _set_rh_range = (set_rh_range_func *) AddressOf(lpsolve, \"set_rh_range\");\n  _set_rh_vec = (set_rh_vec_func *) AddressOf(lpsolve, \"set_rh_vec\");\n  _set_row = (set_row_func *) AddressOf(lpsolve, \"set_row\");\n  _set_rowex = (set_rowex_func *) AddressOf(lpsolve, \"set_rowex\");\n  _set_row_name = (set_row_name_func *) AddressOf(lpsolve, \"set_row_name\");\n  _set_scalelimit = (set_scalelimit_func *) AddressOf(lpsolve, \"set_scalelimit\");\n  _set_scaling = (set_scaling_func *) AddressOf(lpsolve, \"set_scaling\");\n  _set_semicont = (set_semicont_func *) AddressOf(lpsolve, \"set_semicont\");\n  _set_sense = (set_sense_func *) AddressOf(lpsolve, \"set_sense\");\n  _set_simplextype = (set_simplextype_func *) AddressOf(lpsolve, \"set_simplextype\");\n  _set_solutionlimit = (set_solutionlimit_func *) AddressOf(lpsolve, \"set_solutionlimit\");\n  _set_timeout = (set_timeout_func *) AddressOf(lpsolve, \"set_timeout\");\n  _set_trace = (set_trace_func *) AddressOf(lpsolve, \"set_trace\");\n  _set_upbo = (set_upbo_func *) AddressOf(lpsolve, \"set_upbo\");\n  _set_var_branch = (set_var_branch_func *) AddressOf(lpsolve, \"set_var_branch\");\n  _set_var_weights = (set_var_weights_func *) AddressOf(lpsolve, \"set_var_weights\");\n  _set_verbose = (set_verbose_func *) AddressOf(lpsolve, \"set_verbose\");\n  _set_XLI = (set_XLI_func *) AddressOf(lpsolve, \"set_XLI\");\n  _solve = (solve_func *) AddressOf(lpsolve, \"solve\");\n  _str_add_column = (str_add_column_func *) AddressOf(lpsolve, \"str_add_column\");\n  _str_add_constraint = (str_add_constraint_func *) AddressOf(lpsolve, \"str_add_constraint\");\n  _str_add_lag_con = (str_add_lag_con_func *) AddressOf(lpsolve, \"str_add_lag_con\");\n  _str_set_obj_fn = (str_set_obj_fn_func *) AddressOf(lpsolve, \"str_set_obj_fn\");\n  _str_set_rh_vec = (str_set_rh_vec_func *) AddressOf(lpsolve, \"str_set_rh_vec\");\n  _time_elapsed = (time_elapsed_func *) AddressOf(lpsolve, \"time_elapsed\");\n  _unscale = (unscale_func *) AddressOf(lpsolve, \"unscale\");\n  _write_lp = (write_lp_func *) AddressOf(lpsolve, \"write_lp\");\n  _write_LP = (write_LP_func *) AddressOf(lpsolve, \"write_LP\");\n  _write_mps = (write_mps_func *) AddressOf(lpsolve, \"write_mps\");\n  _write_MPS = (write_MPS_func *) AddressOf(lpsolve, \"write_MPS\");\n  _write_freemps = (write_freemps_func *) AddressOf(lpsolve, \"write_freemps\");\n  _write_freeMPS = (write_freeMPS_func *) AddressOf(lpsolve, \"write_freeMPS\");\n  _write_XLI = (write_XLI_func *) AddressOf(lpsolve, \"write_XLI\");\n  _write_basis = (write_basis_func *) AddressOf(lpsolve, \"write_basis\");\n  _write_params = (write_params_func *) AddressOf(lpsolve, \"write_params\");\n\n  return(TRUE);\n# undef AddressOf\n}\n\n#else\n#  error Either LPSOLVEAPIFROMLPREC or LPSOLVEAPIFROMLIB must be defined\n#endif\n\n#define add_column _add_column\n#define add_columnex _add_columnex\n#define add_constraint _add_constraint\n#define add_constraintex _add_constraintex\n#define add_lag_con _add_lag_con\n#define add_SOS _add_SOS\n#define column_in_lp _column_in_lp\n#define copy_lp _copy_lp\n#define default_basis _default_basis\n#define del_column _del_column\n#define del_constraint _del_constraint\n#define delete_lp _delete_lp\n#define dualize_lp _dualize_lp\n#define free_lp _free_lp\n/*#define get_accuracy _get_accuracy*/\n#define get_anti_degen _get_anti_degen\n#define get_basis _get_basis\n#define get_basiscrash _get_basiscrash\n#define get_bb_depthlimit _get_bb_depthlimit\n#define get_bb_floorfirst _get_bb_floorfirst\n#define get_bb_rule _get_bb_rule\n#define get_bounds_tighter _get_bounds_tighter\n#define get_break_at_value _get_break_at_value\n/*#define get_break_numeric_accuracy _get_break_numeric_accuracy*/\n#define get_col_name _get_col_name\n#define get_column _get_column\n#define get_columnex _get_columnex\n#define get_constr_type _get_constr_type\n#define get_constr_value _get_constr_value\n#define get_constraints _get_constraints\n#define get_dual_solution _get_dual_solution\n#define get_epsb _get_epsb\n#define get_epsd _get_epsd\n#define get_epsel _get_epsel\n#define get_epsint _get_epsint\n#define get_epsperturb _get_epsperturb\n#define get_epspivot _get_epspivot\n#define get_improve _get_improve\n#define get_infinite _get_infinite\n#define get_lambda _get_lambda\n#define get_lowbo _get_lowbo\n#define get_lp_index _get_lp_index\n#define get_lp_name _get_lp_name\n#define get_Lrows _get_Lrows\n#define get_mat _get_mat\n#define get_mat_byindex _get_mat_byindex\n#define get_max_level _get_max_level\n#define get_maxpivot _get_maxpivot\n#define get_mip_gap _get_mip_gap\n#define get_multiprice _get_multiprice\n#define get_nameindex _get_nameindex\n#define get_Ncolumns _get_Ncolumns\n#define get_negrange _get_negrange\n#define get_nonzeros _get_nonzeros\n#define get_Norig_columns _get_Norig_columns\n#define get_Norig_rows _get_Norig_rows\n#define get_Nrows _get_Nrows\n#define get_obj_bound _get_obj_bound\n#define get_objective _get_objective\n#define get_orig_index _get_orig_index\n#define get_origcol_name _get_origcol_name\n#define get_origrow_name _get_origrow_name\n#define get_partialprice _get_partialprice\n#define get_pivoting _get_pivoting\n#define get_presolve _get_presolve\n#define get_presolveloops _get_presolveloops\n#define get_primal_solution _get_primal_solution\n#define get_print_sol _get_print_sol\n#define get_pseudocosts _get_pseudocosts\n#define get_ptr_constraints _get_ptr_constraints\n#define get_ptr_dual_solution _get_ptr_dual_solution\n#define get_ptr_lambda _get_ptr_lambda\n#define get_ptr_primal_solution _get_ptr_primal_solution\n#define get_ptr_sensitivity_obj _get_ptr_sensitivity_obj\n#define get_ptr_sensitivity_objex _get_ptr_sensitivity_objex\n#define get_ptr_sensitivity_rhs _get_ptr_sensitivity_rhs\n#define get_ptr_variables _get_ptr_variables\n#define get_rh _get_rh\n#define get_rh_range _get_rh_range\n#define get_row _get_row\n#define get_rowex _get_rowex\n#define get_row_name _get_row_name\n#define get_scalelimit _get_scalelimit\n#define get_scaling _get_scaling\n#define get_sensitivity_obj _get_sensitivity_obj\n#define get_sensitivity_objex _get_sensitivity_objex\n#define get_sensitivity_rhs _get_sensitivity_rhs\n#define get_simplextype _get_simplextype\n#define get_solutioncount _get_solutioncount\n#define get_solutionlimit _get_solutionlimit\n#define get_status _get_status\n#define get_statustext _get_statustext\n#define get_timeout _get_timeout\n#define get_total_iter _get_total_iter\n#define get_total_nodes _get_total_nodes\n#define get_upbo _get_upbo\n#define get_var_branch _get_var_branch\n#define get_var_dualresult _get_var_dualresult\n#define get_var_primalresult _get_var_primalresult\n#define get_var_priority _get_var_priority\n#define get_variables _get_variables\n#define get_verbose _get_verbose\n#define get_working_objective _get_working_objective\n#define guess_basis _guess_basis\n#define has_BFP _has_BFP\n#define has_XLI _has_XLI\n#define is_add_rowmode _is_add_rowmode\n#define is_anti_degen _is_anti_degen\n#define is_binary _is_binary\n#define is_break_at_first _is_break_at_first\n#define is_constr_type _is_constr_type\n#define is_debug _is_debug\n#define is_feasible _is_feasible\n#define is_unbounded _is_unbounded\n#define is_infinite _is_infinite\n#define is_int _is_int\n#define is_integerscaling _is_integerscaling\n#define is_lag_trace _is_lag_trace\n#define is_maxim _is_maxim\n#define is_nativeBFP _is_nativeBFP\n#define is_nativeXLI _is_nativeXLI\n#define is_negative _is_negative\n#define is_piv_mode _is_piv_mode\n#define is_piv_rule _is_piv_rule\n#define is_presolve _is_presolve\n#define is_scalemode _is_scalemode\n#define is_scaletype _is_scaletype\n#define is_semicont _is_semicont\n#define is_SOS_var _is_SOS_var\n#define is_trace _is_trace\n#define is_use_names _is_use_names\n#define lp_solve_version _lp_solve_version\n#define make_lp _make_lp\n#define print_constraints _print_constraints\n#define print_debugdump _print_debugdump\n#define print_duals _print_duals\n#define print_lp _print_lp\n#define print_objective _print_objective\n#define print_scales _print_scales\n#define print_solution _print_solution\n#define print_str _print_str\n#define print_tableau _print_tableau\n#define put_abortfunc _put_abortfunc\n#define put_bb_nodefunc _put_bb_nodefunc\n#define put_bb_branchfunc _put_bb_branchfunc\n#define put_logfunc _put_logfunc\n#define put_msgfunc _put_msgfunc\n#define read_LP _read_LP\n#define read_MPS _read_MPS\n#define read_XLI _read_XLI\n#define read_params _read_params\n#define read_basis _read_basis\n#define reset_basis _reset_basis\n#define reset_params _reset_params\n#define report _report\n#define resize_lp _resize_lp\n#define set_add_rowmode _set_add_rowmode\n#define set_anti_degen _set_anti_degen\n#define set_basisvar _set_basisvar\n#define set_basis _set_basis\n#define set_basiscrash _set_basiscrash\n#define set_bb_depthlimit _set_bb_depthlimit\n#define set_bb_floorfirst _set_bb_floorfirst\n#define set_bb_rule _set_bb_rule\n#define set_BFP _set_BFP\n#define set_binary _set_binary\n#define set_bounds _set_bounds\n#define set_bounds_tighter _set_bounds_tighter\n#define set_break_at_first _set_break_at_first\n#define set_break_at_value _set_break_at_value\n/*#define set_break_numeric_accuracy _set_break_numeric_accuracy*/\n#define set_column _set_column\n#define set_columnex _set_columnex\n#define set_col_name _set_col_name\n#define set_constr_type _set_constr_type\n#define set_debug _set_debug\n#define set_epsb _set_epsb\n#define set_epsd _set_epsd\n#define set_epsel _set_epsel\n#define set_epsint _set_epsint\n#define set_epslevel _set_epslevel\n#define set_epsperturb _set_epsperturb\n#define set_epspivot _set_epspivot\n#define set_unbounded _set_unbounded\n#define set_improve _set_improve\n#define set_infinite _set_infinite\n#define set_int _set_int\n#define set_lag_trace _set_lag_trace\n#define set_lowbo _set_lowbo\n#define set_lp_name _set_lp_name\n#define set_mat _set_mat\n#define set_maxim _set_maxim\n#define set_maxpivot _set_maxpivot\n#define set_minim _set_minim\n#define set_mip_gap _set_mip_gap\n#define set_multiprice _set_multiprice\n#define set_negrange _set_negrange\n#define set_obj_bound _set_obj_bound\n#define set_obj_fn _set_obj_fn\n#define set_obj_fnex _set_obj_fnex\n#define set_obj _set_obj\n#define set_outputfile _set_outputfile\n#define set_outputstream _set_outputstream\n#define set_partialprice _set_partialprice\n#define set_pivoting _set_pivoting\n#define set_preferdual _set_preferdual\n#define set_presolve _set_presolve\n#define set_print_sol _set_print_sol\n#define set_pseudocosts _set_pseudocosts\n#define set_rh _set_rh\n#define set_rh_range _set_rh_range\n#define set_rh_vec _set_rh_vec\n#define set_row _set_row\n#define set_rowex _set_rowex\n#define set_row_name _set_row_name\n#define set_scalelimit _set_scalelimit\n#define set_scaling _set_scaling\n#define set_semicont _set_semicont\n#define set_sense _set_sense\n#define set_simplextype _set_simplextype\n#define set_solutionlimit _set_solutionlimit\n#define set_timeout _set_timeout\n#define set_trace _set_trace\n#define set_upbo _set_upbo\n#define set_var_branch _set_var_branch\n#define set_var_weights _set_var_weights\n#define set_verbose _set_verbose\n#define set_XLI _set_XLI\n#define solve _solve\n#define str_add_column _str_add_column\n#define str_add_constraint _str_add_constraint\n#define str_add_lag_con _str_add_lag_con\n#define str_set_obj_fn _str_set_obj_fn\n#define str_set_rh_vec _str_set_rh_vec\n#define time_elapsed _time_elapsed\n#define unscale _unscale\n#define write_lp _write_lp\n#define write_LP _write_LP\n#define write_mps _write_mps\n#define write_MPS _write_MPS\n#define write_freemps _write_freemps\n#define write_freeMPS _write_freeMPS\n#define write_XLI _write_XLI\n#define write_basis _write_basis\n#define write_params _write_params\n"
  },
  {
    "path": "utilities/lp_solve/lp_fortify.h",
    "content": "#ifdef FORTIFY\n\n#include \"fortify.h\"\n\n#endif\n"
  },
  {
    "path": "utilities/lp_solve/lp_lib.c",
    "content": "\n/* ----------------------------------------------------------------------------------\n   Main library of routines for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Michel Berkelaar (to v3.2)\n                   Kjell Eikland    (v4.0 and forward)\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      (see below)\n\n    Release notes:\n    v5.0.0  1 January 2004      First integrated and repackaged version.\n    v5.0.1  8 May 2004          Cumulative update since initial release;\n                                overall functionality scope maintained.\n    v5.1.0  20 July 2004        Reworked lp_solve throughout to fit new\n                                flexible matrix storage model.\n\n   ---------------------------------------------------------------------------------- */\n\n/* ---------------------------------------------------------------------------------- */\n/* Main library of routines for lp_solve                                              */\n/*----------------------------------------------------------------------------------- */\n#include <signal.h>\n#include <string.h>\n#include <float.h>\n#include <math.h>\n\n#if LoadInverseLib == TRUE\n  #ifdef WIN32\n    #include <windows.h>\n  #else\n    #include <dlfcn.h>\n  #endif\n#endif\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Include core and support modules via headers                                       */\n/* ---------------------------------------------------------------------------------- */\n#include \"lp_lib.h\"\n#include \"commonlib.h\"\n#include \"lp_utils.h\"\n#include \"lp_matrix.h\"\n#include \"lp_SOS.h\"\n#include \"lp_Hash.h\"\n#include \"lp_MPS.h\"\n#include \"lp_wlp.h\"\n#include \"lp_presolve.h\"\n#include \"lp_scale.h\"\n#include \"lp_simplex.h\"\n#include \"lp_mipbb.h\"\n#include \"lp_report.h\"\n#include \"lp_MDO.h\"\n#include \"lp_bit.h\"\n\n#if INVERSE_ACTIVE==INVERSE_LUMOD\n  #include \"lp_LUMOD.h\"\n#elif INVERSE_ACTIVE==INVERSE_LUSOL\n  #include \"lp_LUSOL.h\"\n#elif INVERSE_ACTIVE==INVERSE_GLPKLU\n  #include \"lp_glpkLU.h\"\n#elif INVERSE_ACTIVE==INVERSE_ETAPFI\n  #include \"lp_etaPFI.h\"\n#elif INVERSE_ACTIVE==INVERSE_LEGACY\n  #include \"lp_etaPFI.h\"\n#endif\n\n#if libBLAS > 0\n  #include \"myblas.h\"\n#endif\n\n#ifdef __BORLANDC__\n  #pragma hdrstop\n  #pragma package(smart_init)\n#endif\n\n/* ---------------------------------------------------------------------------------- */\n/* Include selected basis inverse routines and price norm scalars                     */\n/* ---------------------------------------------------------------------------------- */\n\n#include \"lp_price.h\"\n#include \"lp_pricePSE.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n#define sensrejvar TRUE\n\n/* Return lp_solve version information */\nvoid __WINAPI lp_solve_version(int *majorversion, int *minorversion, int *release, int *build)\n{\n  if(majorversion != NULL)\n    (*majorversion) = MAJORVERSION;\n  if(minorversion != NULL)\n    (*minorversion) = MINORVERSION;\n  if(release != NULL)\n    (*release) = RELEASE;\n  if(build != NULL)\n    (*build) = BUILD;\n}\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Various interaction elements                                                       */\n/* ---------------------------------------------------------------------------------- */\n\nMYBOOL __WINAPI userabort(lprec *lp, int message)\n{\n  MYBOOL abort;\n  int spx_save;\n\n  spx_save = lp->spx_status;\n  lp->spx_status = RUNNING;\n  if(yieldformessages(lp) != 0) {\n    lp->spx_status = USERABORT;\n    if(lp->bb_level > 0)\n      lp->bb_break = TRUE;\n  }\n  if((message > 0) && (lp->usermessage != NULL) && (lp->msgmask & message))\n    lp->usermessage(lp, lp->msghandle, message);\n  abort = (MYBOOL) (lp->spx_status != RUNNING);\n  if(!abort)\n    lp->spx_status = spx_save;\n  return( abort );\n}\n\nSTATIC int yieldformessages(lprec *lp)\n{\n  if((lp->sectimeout > 0) &&\n     ((timeNow()-lp->timestart)-(REAL)lp->sectimeout>0))\n    lp->spx_status = TIMEOUT;\n\n  if(lp->ctrlc != NULL) {\n    int retcode = lp->ctrlc(lp, lp->ctrlchandle);\n    /* Check for command to restart the B&B */\n    if((retcode == ACTION_RESTART) && (lp->bb_level > 1)) {\n      lp->bb_break = AUTOMATIC;\n      retcode = 0;\n    }\n    return(retcode);\n  }\n  else\n    return(0);\n}\n\nvoid __WINAPI set_outputstream(lprec *lp, FILE *stream)\n{\n  if((lp->outstream != NULL) && (lp->outstream != stdout)) {\n    if(lp->streamowned)\n      fclose(lp->outstream);\n    else\n      fflush(lp->outstream);\n  }\n  if(stream == NULL)\n    lp->outstream = stdout;\n  else\n    lp->outstream = stream;\n  lp->streamowned = FALSE;\n}\n\nMYBOOL __WINAPI set_outputfile(lprec *lp, const char *filename)\n{\n  MYBOOL ok;\n  FILE   *output = stdout;\n\n  ok = (MYBOOL) ((filename == NULL) || (*filename == 0) || ((output = fopen(filename,\"w\")) != NULL));\n  if(ok) {\n    set_outputstream(lp, output);\n    lp->streamowned = (MYBOOL) ((filename != NULL) && (*filename != 0));\n#if 1\n    if((filename != NULL) && (*filename == 0))\n      lp->outstream = NULL;\n#endif\n  }\n  return(ok);\n}\n\nREAL __WINAPI time_elapsed(lprec *lp)\n{\n  if(lp->timeend > 0)\n    return(lp->timeend - lp->timestart);\n  else\n    return(timeNow() - lp->timestart);\n}\n\nvoid __WINAPI put_bb_nodefunc(lprec *lp, lphandleint_intfunc newnode, void *bbnodehandle)\n{\n  lp->bb_usenode = newnode;\n  lp->bb_nodehandle = bbnodehandle;         /* User-specified \"owner process ID\" */\n}\nvoid __WINAPI put_bb_branchfunc(lprec *lp, lphandleint_intfunc newbranch, void *bbbranchhandle)\n{\n  lp->bb_usebranch = newbranch;\n  lp->bb_branchhandle = bbbranchhandle;     /* User-specified \"owner process ID\" */\n}\nvoid __WINAPI put_abortfunc(lprec *lp, lphandle_intfunc newctrlc, void *ctrlchandle)\n{\n  lp->ctrlc = newctrlc;\n  lp->ctrlchandle = ctrlchandle;            /* User-specified \"owner process ID\" */\n}\nvoid __WINAPI put_logfunc(lprec *lp, lphandlestr_func newlog, void *loghandle)\n{\n  lp->writelog = newlog;\n  lp->loghandle = loghandle;                /* User-specified \"owner process ID\" */\n}\nvoid __WINAPI put_msgfunc(lprec *lp, lphandleint_func newmsg, void *msghandle, int mask)\n{\n  lp->usermessage = newmsg;\n  lp->msghandle = msghandle;                /* User-specified \"owner process ID\" */\n  lp->msgmask = mask;\n}\n\n\n/* ---------------------------------------------------------------------------------- */\n/* DLL exported function                                                              */\n/* ---------------------------------------------------------------------------------- */\nlprec * __WINAPI read_MPS(char *filename, int options)\n{\n  lprec *lp = NULL;\n  int typeMPS;\n\n  typeMPS = (options & ~0x07) >> 2;\n  if ((typeMPS & (MPSFIXED|MPSFREE)) == 0)\n    typeMPS |= MPSFIXED;\n  if(MPS_readfile(&lp, filename, typeMPS, options & 0x07))\n    return( lp );\n  else\n    return( NULL );\n}\nlprec * __WINAPI read_mps(FILE *filename, int options)\n{\n  lprec *lp = NULL;\n  int typeMPS;\n\n  typeMPS = (options & ~0x07) >> 2;\n  if ((typeMPS & (MPSFIXED|MPSFREE)) == 0)\n    typeMPS |= MPSFIXED;\n  if(MPS_readhandle(&lp, filename, typeMPS, options & 0x07))\n    return( lp );\n  else\n    return( NULL );\n}\n/* #if defined develop */\nlprec * __WINAPI read_mpsex(void *userhandle, read_modeldata_func read_modeldata, int options)\n{\n  lprec *lp = NULL;\n  int typeMPS;\n\n  typeMPS = (options & ~0x07) >> 2;\n  if ((typeMPS & (MPSFIXED|MPSFREE)) == 0)\n    typeMPS |= MPSFIXED;\n  if(MPS_readex(&lp, userhandle, read_modeldata, typeMPS, options & 0x07))\n    return( lp );\n  else\n    return( NULL );\n}\n/* #endif */\nlprec * __WINAPI read_freeMPS(char *filename, int options)\n{\n  lprec *lp = NULL;\n  int typeMPS;\n\n  typeMPS = (options & ~0x07) >> 2;\n  typeMPS &= ~MPSFIXED;\n  typeMPS |= MPSFREE;\n  if(MPS_readfile(&lp, filename, typeMPS, options & 0x07))\n    return( lp );\n  else\n    return( NULL );\n}\nlprec * __WINAPI read_freemps(FILE *filename, int options)\n{\n  lprec *lp = NULL;\n  int typeMPS;\n\n  typeMPS = (options & ~0x07) >> 2;\n  typeMPS &= ~MPSFIXED;\n  typeMPS |= MPSFREE;\n  if(MPS_readhandle(&lp, filename, typeMPS, options & 0x07))\n    return( lp );\n  else\n    return( NULL );\n}\n/* #if defined develop */\nlprec * __WINAPI read_freempsex(void *userhandle, read_modeldata_func read_modeldata, int options)\n{\n  lprec *lp = NULL;\n  int typeMPS;\n\n  typeMPS = (options & ~0x07) >> 2;\n  typeMPS &= ~MPSFIXED;\n  typeMPS |= MPSFREE;\n  if(MPS_readex(&lp, userhandle, read_modeldata, typeMPS, options & 0x07))\n    return( lp );\n  else\n    return( NULL );\n}\n/* #endif */\nMYBOOL __WINAPI write_mps(lprec *lp, const char *filename)\n{\n  return(MPS_writefile(lp, MPSFIXED, filename));\n}\nMYBOOL __WINAPI write_MPS(lprec *lp, FILE *output)\n{\n  return(MPS_writehandle(lp, MPSFIXED, output));\n}\n\nMYBOOL __WINAPI write_freemps(lprec *lp, const char *filename)\n{\n  return(MPS_writefile(lp, MPSFREE, filename));\n}\nMYBOOL __WINAPI write_freeMPS(lprec *lp, FILE *output)\n{\n  return(MPS_writehandle(lp, MPSFREE, output));\n}\n\nMYBOOL __WINAPI write_lp(lprec *lp, const char *filename)\n{\n  return(LP_writefile(lp, filename));\n}\nMYBOOL __WINAPI write_LP(lprec *lp, FILE *output)\n{\n  return(LP_writehandle(lp, output));\n}\n#ifndef PARSER_LP\nMYBOOL __WINAPI LP_readhandle(lprec **lp, FILE *filename, int verbose, const char *lp_name)\n{\n  return(FALSE);\n}\nlprec * __WINAPI read_lp(FILE *filename, int verbose, const char *lp_name)\n{\n  return(NULL);\n}\nlprec * __WINAPI read_LP(char *filename, int verbose, const char *lp_name)\n{\n  return(NULL);\n}\n#endif\n\nMYBOOL __WINAPI write_basis(lprec *lp, const char *filename)\n{\n  int typeMPS = MPSFIXED;\n  return( MPS_writeBAS(lp, typeMPS, filename) );\n}\nMYBOOL __WINAPI read_basis(lprec *lp, const char *filename, char *info)\n{\n  int typeMPS = MPSFIXED;\n\n  typeMPS = MPS_readBAS(lp, typeMPS, filename, info);\n\n  /* Code basis */\n  if(typeMPS) {\n    set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n    lp->basis_valid = TRUE;   /* Do not re-initialize basis on entering Solve */\n    lp->var_basic[0] = FALSE; /* Set to signal that this is a non-default basis */\n  }\n  return( (MYBOOL) typeMPS );\n}\n\n/* Write and read lp_solve parameters (placeholders) - see lp_params.c */\nvoid __WINAPI reset_params(lprec *lp)\n{\n  int mode;\n\n  lp->epsmachine        = DEF_EPSMACHINE;\n  lp->epsperturb        = DEF_PERTURB;\n  /* lp->lag_accept        = DEF_LAGACCEPT; */\n  set_epslevel(lp, EPS_DEFAULT);\n\n  lp->tighten_on_set    = FALSE;\n  lp->negrange          = DEF_NEGRANGE;\n\n#if 0\n  lp->do_presolve       = PRESOLVE_ROWS | PRESOLVE_COLS | PRESOLVE_MERGEROWS |\n                          PRESOLVE_REDUCEGCD |\n                          PRESOLVE_ROWDOMINATE;\n#else\n  lp->do_presolve       = PRESOLVE_NONE;\n#endif\n  lp->presolveloops     = DEF_MAXPRESOLVELOOPS;\n\n  lp->scalelimit        = DEF_SCALINGLIMIT;\n  lp->scalemode         = SCALE_INTEGERS |\n#if 0\n                          SCALE_POWER2 |\n                          SCALE_LOGARITHMIC | SCALE_MEAN;\n#else\n                          SCALE_LINEAR | SCALE_GEOMETRIC |\n                          SCALE_EQUILIBRATE;\n#endif\n\n  lp->crashmode         = CRASH_NONE;\n\n  lp->max_pivots        = 0;\n  lp->simplex_strategy  = SIMPLEX_DUAL_PRIMAL;\n#define PricerDefaultOpt 1\n#if PricerDefaultOpt == 1\n  mode = PRICER_DEVEX;\n#elif PricerDefaultOpt == 2\n  mode = PRICER_STEEPESTEDGE;\n  mode |= PRICE_TRUENORMINIT;\n#else\n  mode = PRICER_STEEPESTEDGE | PRICE_PRIMALFALLBACK;\n#endif\n  mode |= PRICE_ADAPTIVE;\n#ifdef EnableRandomizedPricing\n  mode |= PRICE_RANDOMIZE;\n#endif\n  set_pivoting(lp, mode);\n\n  lp->improve           = IMPROVE_DEFAULT;\n  lp->anti_degen        = ANTIDEGEN_DEFAULT;\n\n  lp->bb_floorfirst     = BRANCH_AUTOMATIC;\n  lp->bb_rule           = NODE_DYNAMICMODE | NODE_GREEDYMODE | NODE_GAPSELECT |\n#if 1\n                          NODE_PSEUDOCOSTSELECT |\n#else\n                          NODE_PSEUDOFEASSELECT |\n#endif\n                          NODE_RCOSTFIXING;\n  lp->bb_limitlevel     = DEF_BB_LIMITLEVEL;\n  lp->bb_PseudoUpdates  = DEF_PSEUDOCOSTUPDATES;\n\n  lp->bb_heuristicOF    = my_chsign(is_maxim(lp), MAX(DEF_INFINITE, lp->infinite));\n  lp->bb_breakOF        = -lp->bb_heuristicOF;\n\n  lp->sectimeout        = 0;\n  lp->solutionlimit     = 1;\n\n  set_outputstream(lp, NULL);          /* Set to default output stream */\n  lp->verbose           = NORMAL;\n  lp->print_sol         = FALSE;       /* Can be FALSE, TRUE, AUTOMATIC (only non-zeros printed) */\n  lp->spx_trace         = FALSE;\n  lp->lag_trace         = FALSE;\n  lp->bb_trace          = FALSE;\n}\n\nvoid __WINAPI unscale(lprec *lp)\n{\n  undoscale(lp);\n}\nint __WINAPI solve(lprec *lp)\n{\n#if defined FPUexception\n  catchFPU(_EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW);\n#endif\n\n  if(has_BFP(lp)) {\n    lp->solvecount++;\n    if(is_add_rowmode(lp))\n      set_add_rowmode(lp, FALSE);\n    return(lin_solve(lp));\n  }\n  else\n    return( NOBFP );\n}\nvoid __WINAPI print_lp(lprec *lp)\n{\n  REPORT_lp(lp);\n}\nvoid __WINAPI print_tableau(lprec *lp)\n{\n  REPORT_tableau(lp);\n}\nvoid __WINAPI print_objective(lprec *lp)\n{\n  REPORT_objective(lp);\n}\nvoid __WINAPI print_solution(lprec *lp, int columns)\n{\n  REPORT_solution(lp, columns);\n}\nvoid __WINAPI print_constraints(lprec *lp, int columns)\n{\n  REPORT_constraints(lp, columns);\n}\nvoid __WINAPI print_duals(lprec *lp)\n{\n  REPORT_duals(lp);\n}\nvoid __WINAPI print_scales(lprec *lp)\n{\n  REPORT_scales(lp);\n}\nMYBOOL __WINAPI print_debugdump(lprec *lp, const char *filename)\n{\n  return(REPORT_debugdump(lp, filename, (MYBOOL) (get_total_iter(lp) > 0)));\n}\nvoid __WINAPI print_str(lprec *lp, const char *str)\n{\n  report(lp, lp->verbose, \"%s\", str);\n}\n\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Parameter setting and retrieval functions                                          */\n/* ---------------------------------------------------------------------------------- */\n\nvoid __WINAPI set_timeout(lprec *lp, long sectimeout)\n{\n  lp->sectimeout = sectimeout;\n}\n\nlong __WINAPI get_timeout(lprec *lp)\n{\n  return(lp->sectimeout);\n}\n\nvoid __WINAPI set_verbose(lprec *lp, int verbose)\n{\n  lp->verbose = verbose;\n}\n\nint __WINAPI get_verbose(lprec *lp)\n{\n  return(lp->verbose);\n}\n\nvoid __WINAPI set_print_sol(lprec *lp, int print_sol)\n{\n  lp->print_sol = print_sol;\n}\n\nint __WINAPI get_print_sol(lprec *lp)\n{\n  return(lp->print_sol);\n}\n\nvoid __WINAPI set_debug(lprec *lp, MYBOOL debug)\n{\n  lp->bb_trace = debug;\n}\n\nMYBOOL __WINAPI is_debug(lprec *lp)\n{\n  return(lp->bb_trace);\n}\n\nvoid __WINAPI set_trace(lprec *lp, MYBOOL trace)\n{\n  lp->spx_trace = trace;\n}\n\nMYBOOL __WINAPI is_trace(lprec *lp)\n{\n  return(lp->spx_trace);\n}\n\nvoid __WINAPI set_anti_degen(lprec *lp, int anti_degen)\n{\n  lp->anti_degen = anti_degen;\n}\n\nint __WINAPI get_anti_degen(lprec *lp)\n{\n  return(lp->anti_degen);\n}\n\nMYBOOL __WINAPI is_anti_degen(lprec *lp, int testmask)\n{\n  return((MYBOOL) ((lp->anti_degen == testmask) || ((lp->anti_degen & testmask) != 0)));\n}\n\nvoid __WINAPI set_presolve(lprec *lp, int presolvemode, int maxloops)\n{\n  presolvemode &= ~PRESOLVE_REDUCEMIP; /* disable PRESOLVE_REDUCEMIP since it is very rare that this is effective, and also that it adds code complications and delayed presolve effects that are not captured properly. */\n  lp->do_presolve = presolvemode;\n  lp->presolveloops = maxloops;\n}\n\nint __WINAPI get_presolve(lprec *lp)\n{\n  return(lp->do_presolve);\n}\n\nint __WINAPI get_presolveloops(lprec *lp)\n{\n  if(lp->presolveloops < 0)\n    return(DEF_MAXPRESOLVELOOPS);\n  else if(lp->presolveloops == 0)\n    return(MAXINT32);\n  else\n    return(lp->presolveloops);\n}\n\nMYBOOL __WINAPI is_presolve(lprec *lp, int testmask)\n{\n  return((MYBOOL) ((lp->do_presolve == testmask) || ((lp->do_presolve & testmask) != 0)));\n}\n\nvoid __WINAPI set_maxpivot(lprec *lp, int maxpivot)\n{\n  lp->max_pivots = maxpivot;\n}\n\nint __WINAPI get_maxpivot(lprec *lp)\n{\n  return( lp->bfp_pivotmax(lp) );\n}\n\nvoid __WINAPI set_bb_rule(lprec *lp, int bb_rule)\n{\n  lp->bb_rule = bb_rule;\n}\n\nint __WINAPI get_bb_rule(lprec *lp)\n{\n  return(lp->bb_rule);\n}\n\n/* INLINE */ MYBOOL is_bb_rule(lprec *lp, int bb_rule)\n{\n  return( (MYBOOL) ((lp->bb_rule & NODE_STRATEGYMASK) == bb_rule) );\n}\n\n/* INLINE */ MYBOOL is_bb_mode(lprec *lp, int bb_mask)\n{\n  return( (MYBOOL) ((lp->bb_rule & bb_mask) > 0) );\n}\n\nvoid __WINAPI set_action(int *actionvar, int actionmask)\n{\n  *actionvar |= actionmask;\n}\n\nvoid __WINAPI clear_action(int *actionvar, int actionmask)\n{\n  *actionvar &= ~actionmask;\n}\n\nMYBOOL __WINAPI is_action(int actionvar, int testmask)\n{\n  return( (MYBOOL) ((actionvar & testmask) != 0) );\n}\n\nvoid __WINAPI set_bb_depthlimit(lprec *lp, int bb_maxlevel)\n{\n  lp->bb_limitlevel = bb_maxlevel;\n}\n\nint __WINAPI get_bb_depthlimit(lprec *lp)\n{\n  return(lp->bb_limitlevel);\n}\n\nvoid __WINAPI set_obj_bound(lprec *lp, REAL bb_heuristicOF)\n{\n  lp->bb_heuristicOF = bb_heuristicOF;\n}\n\nREAL __WINAPI get_obj_bound(lprec *lp)\n{\n  return(lp->bb_heuristicOF);\n}\n\nvoid __WINAPI set_mip_gap(lprec *lp, MYBOOL absolute, REAL mip_gap)\n{\n  if(absolute)\n    lp->mip_absgap = mip_gap;\n  else\n    lp->mip_relgap = mip_gap;\n}\n\nREAL __WINAPI get_mip_gap(lprec *lp, MYBOOL absolute)\n{\n  if(absolute)\n    return(lp->mip_absgap);\n  else\n    return(lp->mip_relgap);\n}\n\nMYBOOL __WINAPI set_var_branch(lprec *lp, int colnr, int branch_mode)\n{\n  if(colnr > lp->columns || colnr < 1) {\n    report(lp, IMPORTANT, \"set_var_branch: Column %d out of range\\n\", colnr);\n    return( FALSE );\n  }\n\n  if(lp->bb_varbranch == NULL) {\n    int i;\n    if(branch_mode == BRANCH_DEFAULT)\n      return( TRUE );\n    allocMYBOOL(lp, &lp->bb_varbranch, lp->columns_alloc, FALSE);\n    for(i = 0; i < lp->columns; i++)\n      lp->bb_varbranch[i] = BRANCH_DEFAULT;\n  }\n  lp->bb_varbranch[colnr - 1] = (MYBOOL) branch_mode;\n  return( TRUE );\n}\n\nint __WINAPI get_var_branch(lprec *lp, int colnr)\n{\n  if(colnr > lp->columns || colnr < 1) {\n    report(lp, IMPORTANT, \"get_var_branch: Column %d out of range\\n\", colnr);\n    return(lp->bb_floorfirst);\n  }\n\n  if(lp->bb_varbranch == NULL)\n    return(lp->bb_floorfirst);\n  if(lp->bb_varbranch[colnr - 1] == BRANCH_DEFAULT)\n    return(lp->bb_floorfirst);\n  else\n    return(lp->bb_varbranch[colnr - 1]);\n}\n\nstatic void set_infiniteex(lprec *lp, REAL infinite, MYBOOL init)\n{\n  int i;\n\n  infinite = fabs(infinite);\n  if((init) || is_infinite(lp, lp->bb_heuristicOF))\n    lp->bb_heuristicOF = my_chsign(is_maxim(lp), infinite);\n  if((init) || is_infinite(lp, lp->bb_breakOF))\n    lp->bb_breakOF = my_chsign(is_maxim(lp), -infinite);\n  for(i = 0; i <= lp->sum; i++) {\n    if((!init) && is_infinite(lp, lp->orig_lowbo[i]))\n      lp->orig_lowbo[i] = -infinite;\n    if((init) || is_infinite(lp, lp->orig_upbo[i]))\n      lp->orig_upbo[i] = infinite;\n  }\n  lp->infinite = infinite;\n}\n\n\nMYBOOL __WINAPI is_infinite(lprec *lp, REAL value)\n{\n#if 1\n  return( (MYBOOL) (fabs(value) >= lp->infinite) );\n#else\n  if(fabs(value) >= lp->infinite)\n    return( TRUE );\n  else\n    return( FALSE );\n#endif\n}\n\nvoid __WINAPI set_infinite(lprec *lp, REAL infinite)\n{\n  set_infiniteex(lp, infinite, FALSE);\n}\n\nREAL __WINAPI get_infinite(lprec *lp)\n{\n  return(lp->infinite);\n}\n\nvoid __WINAPI set_epsperturb(lprec *lp, REAL epsperturb)\n{\n  lp->epsperturb = epsperturb;\n}\n\nREAL __WINAPI get_epsperturb(lprec *lp)\n{\n  return(lp->epsperturb);\n}\n\nvoid __WINAPI set_epspivot(lprec *lp, REAL epspivot)\n{\n  lp->epspivot = epspivot;\n}\n\nREAL __WINAPI get_epspivot(lprec *lp)\n{\n  return(lp->epspivot);\n}\n\nvoid __WINAPI set_epsint(lprec *lp, REAL epsint)\n{\n  lp->epsint = epsint;\n}\n\nREAL __WINAPI get_epsint(lprec *lp)\n{\n  return(lp->epsint);\n}\n\nvoid __WINAPI set_epsb(lprec *lp, REAL epsb)\n{\n  lp->epsprimal = MAX(epsb, lp->epsmachine);\n}\n\nREAL __WINAPI get_epsb(lprec *lp)\n{\n  return(lp->epsprimal);\n}\n\nvoid __WINAPI set_epsd(lprec *lp, REAL epsd)\n{\n  lp->epsdual = MAX(epsd, lp->epsmachine); /* Mainly used as tolerance for reduced cost */\n}\n\nREAL __WINAPI get_epsd(lprec *lp)\n{\n  return(lp->epsdual);\n}\n\nvoid __WINAPI set_epsel(lprec *lp, REAL epsel)\n{\n  lp->epsvalue = MAX(epsel, lp->epsmachine);\n}\n\nREAL __WINAPI get_epsel(lprec *lp)\n{\n  return(lp->epsvalue);\n}\n\nMYBOOL __WINAPI set_epslevel(lprec *lp, int epslevel)\n{\n  REAL SPX_RELAX, MIP_RELAX;\n\n  switch(epslevel) {\n    case EPS_TIGHT:  SPX_RELAX = 1;\n                      MIP_RELAX = 1;\n                      break;\n    case EPS_MEDIUM: SPX_RELAX = 10;\n                      MIP_RELAX = 1;\n                      break;\n    case EPS_LOOSE:  SPX_RELAX = 100;\n                      MIP_RELAX = 10;\n                      break;\n    case EPS_BAGGY:  SPX_RELAX = 1000;\n                      MIP_RELAX = 100;\n                      break;\n    default:        return( FALSE );\n  }\n  lp->epsvalue   = SPX_RELAX*DEF_EPSVALUE;\n  lp->epsprimal  = SPX_RELAX*DEF_EPSPRIMAL;\n  lp->epsdual    = SPX_RELAX*DEF_EPSDUAL;\n  lp->epspivot   = SPX_RELAX*DEF_EPSPIVOT;\n  lp->epssolution= MIP_RELAX*DEF_EPSSOLUTION;\n  lp->epsint     = MIP_RELAX*DEF_EPSINT;\n  lp->mip_absgap = MIP_RELAX*DEF_MIP_GAP;\n  lp->mip_relgap = MIP_RELAX*DEF_MIP_GAP;\n\n  return( TRUE );\n}\n\nvoid __WINAPI set_scaling(lprec *lp, int scalemode)\n{\n  lp->scalemode = scalemode;\n}\n\nint __WINAPI get_scaling(lprec *lp)\n{\n  return(lp->scalemode);\n}\n\nMYBOOL __WINAPI is_scalemode(lprec *lp, int testmask)\n{\n  return((MYBOOL) ((lp->scalemode & testmask) != 0));\n}\n\nMYBOOL __WINAPI is_scaletype(lprec *lp, int scaletype)\n{\n  int testtype;\n\n  testtype = lp->scalemode & SCALE_MAXTYPE;\n  return((MYBOOL) (scaletype == testtype));\n}\n\nvoid __WINAPI set_scalelimit(lprec *lp, REAL scalelimit)\n/* Set the relative scaling convergence criterion for the active scaling mode;\n   the integer part specifies the maximum number of iterations (default = 5). */\n{\n  lp->scalelimit = fabs(scalelimit);\n}\n\nREAL __WINAPI get_scalelimit(lprec *lp)\n{\n  return(lp->scalelimit);\n}\n\nMYBOOL __WINAPI is_integerscaling(lprec *lp)\n{\n  return(is_scalemode(lp, SCALE_INTEGERS));\n}\n\nvoid __WINAPI set_improve(lprec *lp, int improve)\n{\n  lp->improve = improve;\n}\n\nint __WINAPI get_improve(lprec *lp)\n{\n  return(lp->improve);\n}\n\nvoid __WINAPI set_lag_trace(lprec *lp, MYBOOL lag_trace)\n{\n  lp->lag_trace = lag_trace;\n}\n\nMYBOOL __WINAPI is_lag_trace(lprec *lp)\n{\n  return(lp->lag_trace);\n}\n\nvoid __WINAPI set_pivoting(lprec *lp, int pivoting)\n{\n  /* Set new pivoting strategy */\n  lp->piv_strategy = pivoting;\n  report(lp, DETAILED, \"set_pivoting: Pricing strategy set to '%s'\\n\",\n                       get_str_piv_rule(get_piv_rule(lp)));\n}\n\nint __WINAPI get_pivoting(lprec *lp)\n{\n  return( lp->piv_strategy );\n}\n\n/* INLINE */ int get_piv_rule(lprec *lp)\n{\n  return( (lp->piv_strategy | PRICE_STRATEGYMASK) ^ PRICE_STRATEGYMASK );\n}\n\nSTATIC const char *get_str_piv_rule(int rule)\n{\n  static const char * const pivotText[PRICER_LASTOPTION+1] =\n  {\"Bland first index\", \"Dantzig\", \"Devex\", \"Steepest Edge\"};\n\n  return( pivotText[rule] );\n}\n\nMYBOOL __WINAPI is_piv_rule(lprec *lp, int rule)\n{\n  return( (MYBOOL) (get_piv_rule(lp) == rule) );\n}\n\nMYBOOL __WINAPI is_piv_mode(lprec *lp, int testmask)\n{\n  return((MYBOOL) (((testmask & PRICE_STRATEGYMASK) != 0) &&\n                   ((lp->piv_strategy & testmask) != 0)));\n}\n\nvoid __WINAPI set_break_at_first(lprec *lp, MYBOOL break_at_first)\n{\n  lp->bb_breakfirst = break_at_first;\n}\n\nMYBOOL __WINAPI is_break_at_first(lprec *lp)\n{\n  return(lp->bb_breakfirst);\n}\n\nvoid __WINAPI set_bb_floorfirst(lprec *lp, int bb_floorfirst)\n{\n  lp->bb_floorfirst = (MYBOOL) bb_floorfirst;\n}\n\nint __WINAPI get_bb_floorfirst(lprec *lp)\n{\n  return(lp->bb_floorfirst);\n}\n\nvoid __WINAPI set_break_at_value(lprec *lp, REAL break_at_value)\n{\n  lp->bb_breakOF = break_at_value;\n}\n\nREAL __WINAPI get_break_at_value(lprec *lp)\n{\n  return(lp->bb_breakOF);\n}\n\nvoid __WINAPI set_negrange(lprec *lp, REAL negrange)\n{\n  if(negrange <= 0)\n    lp->negrange = negrange;\n  else\n    lp->negrange = 0.0;\n}\n\nREAL __WINAPI get_negrange(lprec *lp)\n{\n  return(lp->negrange);\n}\n\nint __WINAPI get_max_level(lprec *lp)\n{\n  return(lp->bb_maxlevel);\n}\n\nCOUNTER __WINAPI get_total_nodes(lprec *lp)\n{\n  return(lp->bb_totalnodes);\n}\n\nCOUNTER __WINAPI get_total_iter(lprec *lp)\n{\n  return(lp->total_iter + lp->current_iter);\n}\n\nREAL __WINAPI get_objective(lprec *lp)\n{\n  if(lp->spx_status == OPTIMAL)\n    ;\n  else if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_objective: Not a valid basis\\n\");\n    return(0.0);\n  }\n\n  return( lp->best_solution[0] );\n}\n\nint __WINAPI get_nonzeros(lprec *lp)\n{\n  return( mat_nonzeros(lp->matA) );\n}\n\nMYBOOL __WINAPI set_mat(lprec *lp, int rownr, int colnr, REAL value)\n{\n  if((rownr < 0) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"set_mat: Row %d out of range\\n\", rownr);\n    return( FALSE );\n  }\n  if((colnr < 1) || (colnr > lp->columns)) {\n    report(lp, IMPORTANT, \"set_mat: Column %d out of range\\n\", colnr);\n    return( FALSE );\n  }\n\n#ifdef DoMatrixRounding\n  if(rownr == 0)\n    value = roundToPrecision(value, lp->matA->epsvalue);\n#endif\n  value = scaled_mat(lp, value, rownr, colnr);\n  if(rownr == 0) {\n    lp->orig_obj[colnr] = my_chsign(is_chsign(lp, rownr), value);\n    return( TRUE );\n  }\n  else\n    return( mat_setvalue(lp->matA, rownr, colnr, value, FALSE) );\n}\n\nREAL __WINAPI get_working_objective(lprec *lp)\n{\n  REAL value = 0.0;\n\n  if(!lp->basis_valid)\n    report(lp, CRITICAL, \"get_working_objective: Not a valid basis\\n\");\n  else if((lp->spx_status == RUNNING) && (lp->solutioncount == 0))\n    value = my_chsign(!is_maxim(lp), lp->rhs[0]);\n  else\n    value = lp->solution[0];\n\n  return(value);\n}\n\nREAL __WINAPI get_var_primalresult(lprec *lp, int index)\n{\n  if((index < 0) || (index > lp->presolve_undo->orig_sum)) {\n    report(lp, IMPORTANT, \"get_var_primalresult: Index %d out of range\\n\", index);\n    return( 0.0 );\n  }\n  if((lp->do_presolve & PRESOLVE_LASTMASKMODE) != PRESOLVE_NONE)\n    return( lp->full_solution[index] );\n  else\n    return( lp->best_solution[index] );\n}\n\nREAL __WINAPI get_var_dualresult(lprec *lp, int index)\n{\n  REAL *duals;\n\n  if((index < 0) || (index > lp->presolve_undo->orig_sum)) {\n    report(lp, IMPORTANT, \"get_var_dualresult: Index %d out of range\\n\", index);\n    return( 0.0 );\n  }\n\n  if(index == 0)\n    return( lp->best_solution[0] );\n\n  /* Make sure we actually have dual information available */\n  if(!get_ptr_sensitivity_rhs(lp, &duals, NULL, NULL))\n    return( 0.0 );\n  else\n    duals = ((lp->full_duals == NULL) ? lp->duals : lp->full_duals);\n  return( duals[index] );\n}\n\nMYBOOL __WINAPI get_variables(lprec *lp, REAL *var)\n{\n  if(lp->spx_status == OPTIMAL)\n    ;\n  else if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_variables: Not a valid basis\\n\");\n    return(FALSE);\n  }\n\n  MEMCOPY(var, lp->best_solution + (1 + lp->rows), lp->columns);\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_ptr_variables(lprec *lp, REAL **var)\n{\n  if(lp->spx_status == OPTIMAL)\n    ;\n  else if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_ptr_variables: Not a valid basis\\n\");\n    return(FALSE);\n  }\n\n  if(var != NULL)\n   *var = lp->best_solution + (1 + lp->rows);\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_constraints(lprec *lp, REAL *constr)\n{\n  if(lp->spx_status == OPTIMAL)\n    ;\n  else if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_constraints: Not a valid basis\\n\");\n    return(FALSE);\n  }\n\n  MEMCOPY(constr, lp->best_solution + 1, lp->rows);\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_ptr_constraints(lprec *lp, REAL **constr)\n{\n  if(lp->spx_status == OPTIMAL)\n    ;\n  else if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_ptr_constraints: Not a valid basis\\n\");\n    return(FALSE);\n  }\n\n  if(constr != NULL)\n   *constr = lp->best_solution + 1;\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_sensitivity_rhs(lprec *lp, REAL *duals, REAL *dualsfrom, REAL *dualstill)\n{\n  REAL *duals0, *dualsfrom0, *dualstill0;\n\n  if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_sensitivity_rhs: Not a valid basis\\n\");\n    return(FALSE);\n  }\n\n  if(!get_ptr_sensitivity_rhs(lp,\n                              (duals != NULL) ? &duals0 : NULL,\n                              (dualsfrom != NULL) ? &dualsfrom0 : NULL,\n                              (dualstill != NULL) ? &dualstill0 : NULL))\n    return(FALSE);\n\n  if(duals != NULL)\n    MEMCOPY(duals, duals0, lp->sum);\n  if(dualsfrom != NULL)\n    MEMCOPY(dualsfrom, dualsfrom0, lp->sum);\n  if(dualstill != NULL)\n    MEMCOPY(dualstill, dualstill0, lp->sum);\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_ptr_sensitivity_rhs(lprec *lp, REAL **duals, REAL **dualsfrom, REAL **dualstill)\n{\n  if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_ptr_sensitivity_rhs: Not a valid basis\\n\");\n    return(FALSE);\n  }\n\n  if(duals != NULL) {\n    if(lp->duals == NULL) {\n      if((MIP_count(lp) > 0) && (lp->bb_totalnodes > 0)) {\n        report(lp, CRITICAL, \"get_ptr_sensitivity_rhs: Sensitivity unknown\\n\");\n        return(FALSE);\n      }\n      if(!construct_duals(lp))\n        return(FALSE);\n    }\n    *duals = lp->duals + 1;\n  }\n\n  if((dualsfrom != NULL) || (dualstill != NULL)) {\n    if((lp->dualsfrom == NULL) || (lp->dualstill == NULL)) {\n      if((MIP_count(lp) > 0) && (lp->bb_totalnodes > 0)) {\n        report(lp, CRITICAL, \"get_ptr_sensitivity_rhs: Sensitivity unknown\\n\");\n        return(FALSE);\n      }\n      construct_sensitivity_duals(lp);\n      if((lp->dualsfrom == NULL) || (lp->dualstill == NULL))\n        return(FALSE);\n    }\n    if(dualsfrom != NULL)\n      *dualsfrom = lp->dualsfrom + 1;\n    if(dualstill != NULL)\n      *dualstill = lp->dualstill + 1;\n  }\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_sensitivity_objex(lprec *lp, REAL *objfrom, REAL *objtill, REAL *objfromvalue, REAL *objtillvalue)\n{\n  REAL *objfrom0, *objtill0, *objfromvalue0, *objtillvalue0;\n\n  if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_sensitivity_objex: Not a valid basis\\n\");\n    return(FALSE);\n  }\n\n  if(!get_ptr_sensitivity_objex(lp, (objfrom != NULL) ? &objfrom0 : NULL,\n                                    (objtill != NULL) ? &objtill0 : NULL,\n                                    (objfromvalue != NULL) ? &objfromvalue0 : NULL,\n                                    (objtillvalue != NULL) ? &objtillvalue0 : NULL))\n    return(FALSE);\n\n  if((objfrom != NULL) && (objfrom0 != NULL))\n    MEMCOPY(objfrom, objfrom0, lp->columns);\n  if((objtill != NULL) && (objtill0 != NULL))\n    MEMCOPY(objtill, objtill0, lp->columns);\n  if((objfromvalue != NULL) && (objfromvalue0 != NULL))\n    MEMCOPY(objfromvalue, objfromvalue0, lp->columns);\n  if((objtillvalue != NULL) && (objtillvalue0 != NULL))\n    MEMCOPY(objtillvalue, objtillvalue0, lp->columns);\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_sensitivity_obj(lprec *lp, REAL *objfrom, REAL *objtill)\n{\n  return(get_sensitivity_objex(lp, objfrom, objtill, NULL, NULL));\n}\n\nMYBOOL __WINAPI get_ptr_sensitivity_objex(lprec *lp, REAL **objfrom, REAL **objtill, REAL **objfromvalue, REAL **objtillvalue)\n{\n  if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_ptr_sensitivity_objex: Not a valid basis\\n\");\n    return(FALSE);\n  }\n\n  if((objfrom != NULL) || (objtill != NULL)) {\n    if((lp->objfrom == NULL) || (lp->objtill == NULL)) {\n      if((MIP_count(lp) > 0) && (lp->bb_totalnodes > 0)) {\n        report(lp, CRITICAL, \"get_ptr_sensitivity_objex: Sensitivity unknown\\n\");\n        return(FALSE);\n      }\n      construct_sensitivity_obj(lp);\n      if((lp->objfrom == NULL) || (lp->objtill == NULL))\n        return(FALSE);\n    }\n    if(objfrom != NULL)\n      *objfrom = lp->objfrom + 1;\n    if(objtill != NULL)\n      *objtill = lp->objtill + 1;\n  }\n\n  if((objfromvalue != NULL) /* || (objtillvalue != NULL) */) {\n    if(lp->objfromvalue == NULL /* || (lp->objtillvalue == NULL) */) {\n      if((MIP_count(lp) > 0) && (lp->bb_totalnodes > 0)) {\n        report(lp, CRITICAL, \"get_ptr_sensitivity_objex: Sensitivity unknown\\n\");\n        return(FALSE);\n      }\n      construct_sensitivity_duals(lp);\n      if(lp->objfromvalue == NULL /* || (lp->objtillvalue == NULL) */)\n        return(FALSE);\n    }\n  }\n\n  if(objfromvalue != NULL)\n    *objfromvalue = lp->objfromvalue + 1;\n\n  if(objtillvalue != NULL)\n    *objtillvalue = NULL /* lp->objtillvalue + 1 */;\n\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_ptr_sensitivity_obj(lprec *lp, REAL **objfrom, REAL **objtill)\n{\n  return(get_ptr_sensitivity_objex(lp, objfrom, objtill, NULL, NULL));\n}\n\nvoid __WINAPI set_solutionlimit(lprec *lp, int limit)\n{\n  lp->solutionlimit = limit;\n}\nint __WINAPI get_solutionlimit(lprec *lp)\n{\n  return(lp->solutionlimit);\n}\nint __WINAPI get_solutioncount(lprec *lp)\n{\n  return(lp->solutioncount);\n}\n\nint __WINAPI get_Nrows(lprec *lp)\n{\n  return(lp->rows);\n}\n\nint __WINAPI get_Norig_rows(lprec *lp)\n{\n  if(lp->varmap_locked)\n    return(lp->presolve_undo->orig_rows);\n  else\n    return(lp->rows);\n}\n\nint __WINAPI get_Lrows(lprec *lp)\n{\n  if(lp->matL == NULL)\n    return( 0 );\n  else\n    return( lp->matL->rows );\n}\n\nint __WINAPI get_Ncolumns(lprec *lp)\n{\n  return(lp->columns);\n}\n\nint __WINAPI get_Norig_columns(lprec *lp)\n{\n  if(lp->varmap_locked)\n    return(lp->presolve_undo->orig_columns);\n  else\n    return(lp->columns);\n}\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Core routines for lp_solve                                                         */\n/* ---------------------------------------------------------------------------------- */\nint __WINAPI get_status(lprec *lp)\n{\n  return(lp->spx_status);\n}\n\nconst char * __WINAPI get_statustext(lprec *lp, int statuscode)\n{\n  (void)lp;\n  if (statuscode == NOBFP)             return(\"No basis factorization package\");\n  else if (statuscode == DATAIGNORED)  return(\"Invalid input data provided\");\n  else if (statuscode == NOMEMORY)     return(\"Not enough memory available\");\n  else if (statuscode == NOTRUN)       return(\"Model has not been optimized\");\n  else if (statuscode == OPTIMAL)      return(\"OPTIMAL solution\");\n  else if (statuscode == SUBOPTIMAL)   return(\"SUB-OPTIMAL solution\");\n  else if (statuscode == INFEASIBLE)   return(\"Model is primal INFEASIBLE\");\n  else if (statuscode == UNBOUNDED)    return(\"Model is primal UNBOUNDED\");\n  else if (statuscode == RUNNING)      return(\"lp_solve is currently running\");\n  else if (statuscode == NUMFAILURE)   return(\"NUMERIC FAILURE encountered\");\n  else if (statuscode == DEGENERATE)   return(\"DEGENERATE situation\");\n  else if (statuscode == USERABORT)    return(\"User-requested termination\");\n  else if (statuscode == TIMEOUT)      return(\"Termination due to timeout\");\n  else if (statuscode == PRESOLVED)    return(\"Model solved by presolve\");\n  else if (statuscode == PROCFAIL)     return(\"B&B routine failed\");\n  else if (statuscode == PROCBREAK)    return(\"B&B routine terminated\");\n  else if (statuscode == FEASFOUND)    return(\"Feasible B&B solution found\");\n  else if (statuscode == NOFEASFOUND)  return(\"No feasible B&B solution found\");\n  else if (statuscode == FATHOMED)     return(\"Fathomed/pruned branch\");\n  else                                 return(\"Undefined internal error\");\n}\n\nMYBOOL __WINAPI is_obj_in_basis(lprec *lp)\n{\n  return( lp->obj_in_basis );\n}\n\nvoid __WINAPI set_obj_in_basis(lprec *lp, MYBOOL obj_in_basis)\n{\n  lp->obj_in_basis = (MYBOOL) (obj_in_basis == TRUE);\n}\n\nlprec * __WINAPI make_lp(int rows, int columns)\n{\n  lprec *lp;\n\n# if defined FORTIFY\n   /* Fortify_EnterScope(); */\n# endif\n\n  if(rows < 0 || columns < 0)\n    return(NULL);\n\n  lp = (lprec*) calloc(1, sizeof(*lp));\n  if(!lp)\n    return(NULL);\n\n  set_lp_name(lp, NULL);\n  lp->names_used    = FALSE;\n  lp->use_row_names = TRUE;\n  lp->use_col_names = TRUE;\n  lp->rowcol_name   = NULL;\n\n  /* Do standard initializations ------------------------------------------------------------ */\n#if 1\n  lp->obj_in_basis  = DEF_OBJINBASIS;\n#else\n  lp->obj_in_basis  = FALSE;\n#endif\n  lp->verbose       = NORMAL;\n  set_callbacks(lp);\n  set_BFP(lp, NULL);\n  set_XLI(lp, NULL);\n#if libBLAS > 0\n  init_BLAS();\n#if libBLAS > 1\n  if(is_nativeBLAS() && !load_BLAS(libnameBLAS))\n    /*report(lp, \"make_lp: Could not load external BLAS library '%s'.\\n\", libnameBLAS)*/;\n#endif\n#endif\n\n  /* Define the defaults for key user-settable values --------------------------------------- */\n  reset_params(lp);\n\n  /* Do other initializations --------------------------------------------------------------- */\n  lp->source_is_file    = FALSE;\n  lp->model_is_pure     = TRUE;\n  lp->model_is_valid    = FALSE;\n  lp->spx_status        = NOTRUN;\n  lp->lag_status        = NOTRUN;\n\n  lp->workarrays = mempool_create(lp);\n  lp->wasPreprocessed   = FALSE;\n  lp->wasPresolved      = FALSE;\n  presolve_createUndo(lp);\n\n  lp->bb_varactive      = NULL;\n  lp->bb_varbranch      = NULL;\n  lp->var_priority      = NULL;\n\n  lp->rhsmax            = 0.0;\n  lp->bigM              = 0.0;\n  lp->bb_deltaOF        = 0.0;\n\n  lp->equalities        = 0;\n  lp->fixedvars         = 0;\n  lp->int_vars          = 0;\n  lp->sc_vars           = 0;\n\n  lp->sos_ints          = 0;\n  lp->sos_vars          = 0;\n  lp->sos_priority      = NULL;\n\n  lp->rows_alloc        = 0;\n  lp->columns_alloc     = 0;\n  lp->sum_alloc         = 0;\n\n  lp->rows              = rows;\n  lp->columns           = columns;\n  lp->sum               = rows + columns;\n  varmap_clear(lp);\n\n  lp->matA = mat_create(lp, rows, columns, lp->epsvalue);\n  lp->matL = NULL;\n  lp->invB = NULL;\n  lp->duals = NULL;\n  lp->dualsfrom = NULL;\n  lp->dualstill = NULL;\n  lp->objfromvalue = NULL;\n  lp->objfrom = NULL;\n  lp->objtill = NULL;\n\n  inc_col_space(lp, columns + 1);\n  inc_row_space(lp, rows + 1);\n\n  /* Avoid bound-checker uninitialized variable error */\n  lp->orig_lowbo[0] = 0;\n\n  lp->rootbounds = NULL;\n  lp->bb_bounds = NULL;\n  lp->bb_basis = NULL;\n\n  lp->basis_valid       = FALSE;\n  lp->simplex_mode      = SIMPLEX_DYNAMIC;\n  lp->scaling_used      = FALSE;\n  lp->columns_scaled    = FALSE;\n  lp->P1extraDim        = 0;\n  lp->P1extraVal        = 0.0;\n  lp->bb_strongbranches = 0;\n  lp->current_iter      = 0;\n  lp->total_iter        = 0;\n  lp->current_bswap     = 0;\n  lp->total_bswap       = 0;\n  lp->solutioncount     = 0;\n  lp->solvecount        = 0;\n\n  allocINT(lp, &lp->rejectpivot, DEF_MAXPIVOTRETRY + 1, TRUE);\n\n  set_minim(lp);\n  set_infiniteex(lp, DEF_INFINITE, TRUE);\n  /* set_break_numeric_accuracy(lp, DEF_INFINITE); */\n  /* set_break_numeric_accuracy(lp, 1e-5); */\n  /* set_break_numeric_accuracy(lp, 5e-5); */\n  /* set_break_numeric_accuracy(lp, 1e-6); */\n  /* set_break_numeric_accuracy(lp, 5e-6); */\n  set_break_numeric_accuracy(lp, 5e-7);\n\n  initPricer(lp);\n\n  /* Call-back routines by KE */\n  lp->ctrlc = NULL;\n  lp->ctrlchandle = NULL;\n  lp->writelog = NULL;\n  lp->loghandle = NULL;\n  lp->debuginfo = NULL;\n  lp->usermessage = NULL;\n  lp->msgmask = MSG_NONE;\n  lp->msghandle = NULL;\n\n  lp->timecreate = timeNow();\n\n  return(lp);\n}\n\nMYBOOL __WINAPI resize_lp(lprec *lp, int rows, int columns)\n{\n  MYBOOL status = TRUE;\n\n  if(columns > lp->columns)\n    status = inc_col_space(lp, columns - lp->columns);\n  else\n    while(status && (lp->columns > columns)) {\n      status = del_column(lp, lp->columns);\n    }\n  if(status && (rows > lp->rows))\n    status = inc_row_space(lp, rows - lp->rows);\n  else\n    while(status && (lp->rows > rows)) {\n      status = del_constraint(lp, lp->rows);\n    }\n  return( status );\n}\n\nvoid __WINAPI free_lp(lprec **plp)\n{\n  if(plp != NULL) {\n    lprec *lp = *plp;\n    if(lp != NULL)\n      delete_lp(lp);\n    *plp = NULL;\n  }\n}\n\nvoid __WINAPI delete_lp(lprec *lp)\n{\n  if(lp == NULL)\n    return;\n\n  FREE(lp->rowcol_name);\n  FREE(lp->lp_name);\n  FREE(lp->ex_status);\n  if(lp->names_used) {\n    FREE(lp->row_name);\n    FREE(lp->col_name);\n    free_hash_table(lp->rowname_hashtab);\n    free_hash_table(lp->colname_hashtab);\n  }\n\n  mat_free(&lp->matA);\n  lp->bfp_free(lp);\n#if LoadInverseLib == TRUE\n  if(lp->hBFP != NULL)\n    set_BFP(lp, NULL);\n#endif\n#if LoadLanguageLib == TRUE\n  if(lp->hXLI != NULL)\n    set_XLI(lp, NULL);\n#endif\n\n  unset_OF_p1extra(lp);\n  FREE(lp->orig_obj);\n  FREE(lp->orig_rhs);\n  FREE(lp->rhs);\n  FREE(lp->var_type);\n  set_var_weights(lp, NULL);\n  FREE(lp->bb_varbranch);\n  FREE(lp->sc_lobound);\n  FREE(lp->var_is_free);\n  FREE(lp->orig_upbo);\n  FREE(lp->orig_lowbo);\n  FREE(lp->upbo);\n  FREE(lp->lowbo);\n  FREE(lp->var_basic);\n  FREE(lp->is_basic);\n  FREE(lp->is_lower);\n  if(lp->bb_PseudoCost != NULL) {\n/*    report(lp, SEVERE, \"delete_lp: The B&B pseudo-cost array was not cleared on delete\\n\"); */\n    free_pseudocost(lp);\n  }\n  if(lp->bb_bounds != NULL) {\n    report(lp, SEVERE, \"delete_lp: The stack of B&B levels was not empty (failed at %.0f nodes)\\n\",\n                       (double) lp->bb_totalnodes);\n    unload_BB(lp);\n  }\n  if(lp->bb_basis != NULL) {\n/*    report(lp, SEVERE, \"delete_lp: The stack of saved bases was not empty on delete\\n\"); */\n    unload_basis(lp, FALSE);\n  }\n\n  FREE(lp->rejectpivot);\n  partial_freeBlocks(&(lp->rowblocks));\n  partial_freeBlocks(&(lp->colblocks));\n  multi_free(&(lp->multivars));\n  multi_free(&(lp->longsteps));\n\n  FREE(lp->solution);\n  FREE(lp->best_solution);\n  FREE(lp->full_solution);\n\n  presolve_freeUndo(lp);\n  mempool_free(&(lp->workarrays));\n\n  freePricer(lp);\n\n  FREE(lp->drow);\n  FREE(lp->nzdrow);\n\n  FREE(lp->duals);\n  FREE(lp->full_duals);\n  FREE(lp->dualsfrom);\n  FREE(lp->dualstill);\n  FREE(lp->objfromvalue);\n  FREE(lp->objfrom);\n  FREE(lp->objtill);\n  FREE(lp->row_type);\n\n  if(lp->sos_vars > 0)\n    FREE(lp->sos_priority);\n  free_SOSgroup(&(lp->SOS));\n  free_SOSgroup(&(lp->GUB));\n  freecuts_BB(lp);\n\n  if(lp->scaling_used)\n    FREE(lp->scalars);\n  if(lp->matL != NULL) {\n    FREE(lp->lag_rhs);\n    FREE(lp->lambda);\n    FREE(lp->lag_con_type);\n    mat_free(&lp->matL);\n  }\n  if(lp->streamowned)\n    set_outputstream(lp, NULL);\n\n#if libBLAS > 0\n  if(!is_nativeBLAS())\n    unload_BLAS();\n#endif\n\n  FREE(lp);\n\n# if defined FORTIFY\n    /* Fortify_LeaveScope(); */\n# endif\n}\n\nstatic MYBOOL get_SOS(lprec *lp, int index, char *name, int *sostype, int *priority, int *count, int *sosvars, REAL *weights)\n{\n  SOSrec *SOS;\n\n  if((index < 1) || (index > SOS_count(lp)))\n    return( FALSE );\n  SOS = lp->SOS->sos_list[index-1];\n  if(name != NULL)\n    strcpy(name, SOS->name);\n  if(sostype != NULL)\n    *sostype = SOS->type;\n  if(priority != NULL)\n    *priority = SOS->priority;\n  if(count != NULL) {\n    *count = SOS->size;\n    if(sosvars != NULL) {\n      int i;\n      for(i = 1; i <= *count; i++) {\n        sosvars[i-1] = SOS->members[i];\n        if(weights != NULL)\n          weights[i-1] = SOS->weights[i];\n      }\n    }\n  }\n  return( TRUE );\n}\n\n/* Make a copy of the existing model using (mostly) high-level\n   construction routines to simplify future maintainance. */\nlprec* __WINAPI copy_lp(lprec *lp)\n{\n  int   i, n, *idx = NULL;\n  REAL  hold, *val = NULL, infinite;\n  lprec *newlp = NULL;\n  char buf[256], ok = FALSE;\n  int sostype, priority, count, *sosvars, rows, columns;\n  REAL *weights = NULL;\n\n#if 0\n  if(lp->wasPresolved)\n    return( newlp );\n#endif\n\n  rows = get_Nrows(lp);\n  columns = get_Ncolumns(lp);\n\n  if(!allocINT(lp, &idx, rows+1, FALSE) ||\n     !allocREAL(lp, &val, rows+1, FALSE))\n    goto Finish;\n\n  /* Create the new object */\n  newlp = make_lp(rows, 0);\n  if(newlp == NULL)\n    goto Finish;\n  if(!resize_lp(newlp, rows, columns))\n    goto Finish;\n  set_sense(newlp, is_maxim(lp));\n  set_use_names(newlp, FALSE, is_use_names(lp, FALSE));\n  set_use_names(newlp, TRUE, is_use_names(lp, TRUE));\n  if(!set_lp_name(newlp, get_lp_name(lp)))\n    goto Finish;\n  /* set_algopt(newlp, get_algopt(lp)); */ /* v6 */\n  set_verbose(newlp, get_verbose(lp));\n\n  /* Transfer standard simplex parameters */\n  set_epspivot(newlp, get_epspivot(lp));\n  set_epsel(newlp, get_epsel(lp));\n  set_epsb(newlp, get_epsb(lp));\n  set_epsd(newlp, get_epsd(lp));\n  set_pivoting(newlp, get_pivoting(lp));\n  set_negrange(newlp, lp->negrange);\n  set_infinite(newlp, get_infinite(lp));\n  set_presolve(newlp, get_presolve(lp), get_presolveloops(lp));\n  set_scaling(newlp, get_scaling(lp));\n  set_scalelimit(newlp, get_scalelimit(lp));\n  set_simplextype(newlp, get_simplextype(lp));\n  set_epsperturb(newlp, get_epsperturb(lp));\n  set_anti_degen(newlp, get_anti_degen(lp));\n  set_improve(newlp, get_improve(lp));\n  set_basiscrash(newlp, get_basiscrash(lp));\n  set_maxpivot(newlp, get_maxpivot(lp));\n  set_timeout(newlp, get_timeout(lp));\n\n  /* Transfer MILP parameters */\n  set_epsint(newlp, get_epsint(lp));\n  set_bb_rule(newlp, get_bb_rule(lp));\n  set_bb_depthlimit(newlp, get_bb_depthlimit(lp));\n  set_bb_floorfirst(newlp, get_bb_floorfirst(lp));\n  set_mip_gap(newlp, TRUE, get_mip_gap(lp, TRUE));\n  set_mip_gap(newlp, FALSE, get_mip_gap(lp, FALSE));\n  set_break_at_first(newlp, is_break_at_first(lp));\n  set_break_at_value(newlp, get_break_at_value(lp));\n\n  /* Set RHS and range */\n  infinite = get_infinite(lp);\n  for(i = 0; i <= rows; i++) {\n    if(i > 0)\n      if(!set_constr_type(newlp, i, get_constr_type(lp, i)))\n        goto Finish;\n    if(!set_rh(newlp, i, get_rh(lp, i)))\n      goto Finish;\n    if((i > 0) && ((hold = get_rh_range(lp, i)) < infinite))\n      if(!set_rh_range(newlp, i, hold))\n        goto Finish;\n    if(lp->names_used && lp->use_row_names && (lp->row_name[i] != NULL) && (lp->row_name[i]->name != NULL))\n      if(!set_row_name(newlp, i, get_row_name(lp, i)))\n        goto Finish;\n  }\n\n  /* Load the constraint matrix and variable definitions */\n  for(i = 1; i <= columns; i++) {\n    n = get_columnex(lp, i, val, idx);\n    if ((n < 0) || (!add_columnex(newlp, n, val, idx)))\n      goto Finish;\n    if(is_binary(lp, i)) {\n      if (!set_binary(newlp, i, TRUE))\n        goto Finish;\n    }\n    else {\n      if(is_int(lp, i))\n        if(!set_int(newlp, i, TRUE))\n          goto Finish;\n      if((hold = get_lowbo(lp, i)) != 0)\n        if(!set_lowbo(newlp, i, hold))\n          goto Finish;\n      if((hold = get_upbo(lp, i)) < infinite)\n        if(!set_upbo(newlp, i, hold))\n          goto Finish;\n    }\n    if(is_semicont(lp, i))\n      if(!set_semicont(newlp, i, TRUE))\n        goto Finish;\n    if(lp->names_used && lp->use_col_names && (lp->col_name[i] != NULL) && (lp->col_name[i]->name != NULL))\n      if(!set_col_name(newlp, i, get_col_name(lp, i)))\n        goto Finish;\n  }\n\n  /* copy SOS data */\n  for(i = 1; get_SOS(lp, i, buf, &sostype, &priority, &count, NULL, NULL); i++)\n    if (count) {\n      if(!allocINT(lp, &sosvars, count, FALSE) ||\n         !allocREAL(lp, &weights, count, FALSE))\n        n = 0;\n      else {\n        get_SOS(lp, i, buf, &sostype, &priority, &count, sosvars, weights);\n        n = add_SOS(newlp, buf, sostype, priority, count, sosvars, weights);\n      }\n      FREE(weights);\n      FREE(sosvars);\n      if(n == 0)\n        goto Finish;\n    }\n\n#if 0\n  /* Other parameters set if the source model was previously solved */\n  if(lp->solvecount > 0) {\n    MEMCOPY(newlp->scalars, lp->scalars, lp->sum+1);\n    MEMCOPY(newlp->var_basic, lp->var_basic, rows+1);\n    MEMCOPY(newlp->is_basic, lp->is_basic, lp->sum+1);\n    MEMCOPY(newlp->is_lower, lp->is_lower, lp->sum+1);\n    MEMCOPY(newlp->solution, lp->solution, lp->sum+1);\n    if(lp->duals != NULL) {\n      allocREAL(newlp, &newlp->duals, newlp->sum_alloc+1, FALSE);\n      MEMCOPY(newlp->duals, lp->duals, lp->sum+1);\n    }\n    newlp->solutioncount = lp->solutioncount;\n    newlp->solvecount = lp->solvecount;\n  }\n#endif\n\n  ok = TRUE;\n\n  /* Clean up before returning */\nFinish:\n  if(!ok)\n    free_lp(&newlp);\n  FREE(val);\n  FREE(idx);\n\n  return( newlp );\n}\nMYBOOL __WINAPI dualize_lp(lprec *lp)\n{\n  int     i, n;\n  MATrec  *mat = lp->matA;\n  REAL    *item;\n\n  /* Are we allowed to perform the operation? */\n  if((MIP_count(lp) > 0) || (lp->solvecount > 0))\n    return( FALSE );\n\n  /* Modify sense */\n  set_sense(lp, (MYBOOL) !is_maxim(lp));\n\n  /* Transpose matrix and reverse signs */\n  n = mat_nonzeros(mat);\n  mat_transpose(mat);\n  item = &COL_MAT_VALUE(0);\n  for(i = 0; i < n; i++, item += matValueStep)\n    *item *= -1;\n\n  /* Row-column swap other vectors */\n  swapINT(&lp->rows, &lp->columns);\n  swapINT(&lp->rows_alloc, &lp->columns_alloc);\n  swapREAL(lp->orig_rhs, lp->orig_obj);\n  if ((lp->rhs != NULL) && (lp->obj != NULL))\n    swapREAL(lp->rhs, lp->obj);\n\n  /* Reallocate storage */\n/*\nvar_type\nsc_bound\nsolution\nbest_solution\nfull_solution\nduals\n*/\n\n  /* Shift variable bounds */\n/*\nis_basic\norig_upbo\norig_lowbo\nscalars\n*/\n\n  return( TRUE );\n}\n\n/* Optimize memory usage */\nSTATIC MYBOOL memopt_lp(lprec *lp, int rowextra, int colextra, int nzextra)\n{\n  MYBOOL status = FALSE;\n\n  if(lp == NULL)\n    return( status );\n\n  status = mat_memopt(lp->matA, rowextra, colextra, nzextra) &&\n           (++rowextra > 0) && (++colextra > 0) && (++nzextra > 0);\n\n#if 0 /* inc_ routines not well-tested for reduction in size allocation */\n  if(status) {\n    int colalloc = lp->columns_alloc - MIN(lp->columns_alloc, lp->columns + colextra),\n        rowalloc = lp->rows_alloc    - MIN(lp->rows_alloc,    lp->rows + rowextra);\n\n    status = inc_lag_space(lp, rowalloc, FALSE) &&\n             inc_row_space(lp, rowalloc) &&\n             inc_col_space(lp, colalloc);\n  }\n#endif\n\n  return( status );\n}\n\n\n/* Utility routine group for constraint and column deletion/insertion\n   mapping in relation to the original set of constraints and columns */\nSTATIC void varmap_lock(lprec *lp)\n{\n  presolve_fillUndo(lp, lp->rows, lp->columns, TRUE);\n  lp->varmap_locked = TRUE;\n}\nSTATIC void varmap_clear(lprec *lp)\n{\n  presolve_setOrig(lp, 0, 0);\n  lp->varmap_locked = FALSE;\n}\nSTATIC MYBOOL varmap_canunlock(lprec *lp)\n{\n  /* Don't do anything if variables aren't locked yet */\n  if(lp->varmap_locked) {\n    int i;\n    presolveundorec *psundo = lp->presolve_undo;\n\n    /* Check for the obvious */\n    if(/*lp->names_used ||\n       (psundo->orig_columns != lp->columns) || (psundo->orig_rows != lp->rows)) */\n       (psundo->orig_columns > lp->columns) || (psundo->orig_rows > lp->rows))\n      return( FALSE );\n\n    /* Check for deletions */\n    for(i = psundo->orig_rows + psundo->orig_columns; i > 0; i--)\n      if(psundo->orig_to_var[i] == 0)\n        return( FALSE );\n\n    /* Check for insertions */\n    for(i = lp->sum; i > 0; i--)\n      if(psundo->var_to_orig[i] == 0)\n        return( FALSE );\n  }\n  return( TRUE );\n}\nSTATIC void varmap_add(lprec *lp, int base, int delta)\n{\n  int i, ii;\n  presolveundorec *psundo = lp->presolve_undo;\n\n  /* Don't do anything if variables aren't locked yet */\n  if(!lp->varmap_locked)\n    return;\n\n  /* Set new constraints/columns to have an \"undefined\" mapping to original\n     constraints/columns (assumes that counters have NOT yet been updated) */\n  for(i = lp->sum; i >= base; i--) {\n    ii = i + delta;\n    psundo->var_to_orig[ii] = psundo->var_to_orig[i];\n  }\n\n  /* Initialize map of added rows/columns */\n  for(i = 0; i < delta; i++) {\n    ii = base + i;\n    psundo->var_to_orig[ii] = 0;\n  }\n}\n\nSTATIC void varmap_delete(lprec *lp, int base, int delta, LLrec *varmap)\n{\n  int             i, ii, j;\n  MYBOOL          preparecompact = (MYBOOL) (varmap != NULL);\n  presolveundorec *psundo = lp->presolve_undo;\n\n  /* Set the model \"dirty\" if we are deleting row of constraint */\n  lp->model_is_pure &= (MYBOOL) ((lp->solutioncount == 0) && !preparecompact);\n\n  /* Don't do anything if\n     1) variables aren't locked yet, or\n     2) the constraint was added after the variables were locked */\n  if(!lp->varmap_locked) {\n#if 0\n   if(lp->names_used)\n     varmap_lock(lp);\n   else\n     return;\n#else\n    if(!lp->model_is_pure && lp->names_used)\n      varmap_lock(lp);\n#endif\n  }\n\n  /* Do mass deletion via a linked list */\n  preparecompact = (MYBOOL) (varmap != NULL);\n  if(preparecompact) {\n    preparecompact = (MYBOOL) (base > lp->rows);  /* Set TRUE for columns */\n    for(j = firstInactiveLink(varmap); j != 0; j = nextInactiveLink(varmap, j)) {\n      i = j;\n      if(preparecompact) {\n#ifdef Paranoia\n        if(SOS_is_member(lp->SOS, 0, j))\n          report(lp, SEVERE, \"varmap_delete: Deleting variable %d, which is in a SOS!\\n\", j);\n#endif\n        i += lp->rows;\n      }\n      ii = psundo->var_to_orig[i];\n      if(ii > 0)  /* It was an original variable; reverse sign of index to flag deletion */\n        psundo->var_to_orig[i] = -ii;\n      else        /* It was a non-original variable; add special code for deletion */\n        psundo->var_to_orig[i] = -(psundo->orig_rows+psundo->orig_columns+i);\n    }\n    return;\n  }\n\n  /* Do legacy simplified version if we are doing batch delete operations */\n  preparecompact = (MYBOOL) (base < 0);\n  if(preparecompact) {\n    base = -base;\n    if(base > lp->rows)\n      base += (psundo->orig_rows - lp->rows);\n    for(i = base; i < base-delta; i++) {\n      ii = psundo->var_to_orig[i];\n      if(ii > 0)  /* It was an original variable; reverse sign of index to flag deletion */\n        psundo->var_to_orig[i] = -ii;\n      else       /* It was a non-original variable; add special code for deletion */\n        psundo->var_to_orig[i] = -(psundo->orig_rows+psundo->orig_columns+i);\n    }\n    return;\n  }\n\n  /* We are deleting an original constraint/column;\n     1) clear mapping of original to deleted\n     2) shift the deleted variable to original mappings left\n     3) decrement all subsequent original-to-current pointers\n  */\n  if(varmap_canunlock(lp))    lp->varmap_locked = FALSE;\n  for(i = base; i < base-delta; i++) {\n    ii = psundo->var_to_orig[i];\n    if(ii > 0)\n      psundo->orig_to_var[ii] = 0;\n  }\n  for(i = base; i <= lp->sum+delta; i++) {\n    ii = i - delta;\n    psundo->var_to_orig[i] = psundo->var_to_orig[ii];\n  }\n\n  i = 1;\n  j = psundo->orig_rows;\n  if(base > lp->rows) {\n    i += j;\n    j += psundo->orig_columns;\n  }\n  ii = base-delta;\n  for(; i <= j; i++) {\n    if(psundo->orig_to_var[i] >= ii)\n      psundo->orig_to_var[i] += delta;\n  }\n\n}\n\nSTATIC MYBOOL varmap_validate(lprec *lp, int varno)\n{\n  MYBOOL success = TRUE;\n  int i, ii, ix, ie,\n       n_rows = lp->rows,\n       orig_sum = lp->presolve_undo->orig_sum,\n       orig_rows = lp->presolve_undo->orig_rows;\n\n  if(varno <= 0) {\n    varno = 1;\n    ie = orig_sum;\n  }\n  else\n    ie = varno;\n  for(i = varno; success && (i <= ie); i++) {\n    ix = lp->presolve_undo->orig_to_var[i];\n    if((ix > 0) && (i > orig_rows))\n      ix += n_rows;\n\n    /* Check for index out of range due to presolve */\n    success = (MYBOOL) (ix <= orig_sum);\n    if(!success)\n      report(lp, SEVERE, \"varmap_validate: Invalid new mapping found for variable %d\\n\",\n                           i);\n    else if(ix != 0) {\n      ii = lp->presolve_undo->var_to_orig[ix];\n      if(ix > n_rows)\n        ii += orig_rows;\n      success = (MYBOOL) (ii == i);\n      if(!success)\n        report(lp, SEVERE, \"varmap_validate: Invalid old mapping found for variable %d (%d)\\n\",\n                           i, ii);\n    }\n  }\n  return( success );\n}\n\nSTATIC void varmap_compact(lprec *lp, int prev_rows, int prev_cols)\n{\n  presolveundorec *psundo = lp->presolve_undo;\n  int             i, ii, n_sum, n_rows,\n                  orig_rows = psundo->orig_rows,\n                  prev_sum = prev_rows + prev_cols;\n\n  /* Nothing to do if the model is not \"dirty\" or the variable map is not locked */\n  if(lp->model_is_pure || !lp->varmap_locked)\n    return;\n\n  /* We are deleting an original constraint/column;\n     1) clear mapping of original to deleted\n     2) shift the deleted variable to original mappings left\n     3) decrement all subsequent original-to-current pointers\n  */\n  n_sum = 0;\n  n_rows = 0;\n  for(i = 1; i <= prev_sum; i++) {\n    ii = psundo->var_to_orig[i];\n\n    /* Process variable if it was deleted in the previous round */\n    if(ii < 0) {\n      ii = -ii;\n      /* Update map back if we have an original variable, otherwise just skip */\n      if(i <= prev_rows)\n        psundo->orig_to_var[ii] = 0;\n      else\n        psundo->orig_to_var[orig_rows+ii] = 0;\n    }\n    /* Otherwise shift and update map back */\n    else {\n      n_sum++;\n      /* Shift only if necessary */\n      if(n_sum < i)\n        psundo->var_to_orig[n_sum] = ii;\n      /* Update map back if we have an original variable */\n      if(ii > 0) {\n        if(i <= prev_rows) {\n          psundo->orig_to_var[ii] = n_sum;\n          n_rows = n_sum;\n        }\n        else\n          psundo->orig_to_var[orig_rows+ii] = n_sum-n_rows;\n      }\n    }\n  }\n#ifdef xxParanoia\n  if(!varmap_validate(lp, 0))\n    report(lp, SEVERE, \"varmap_compact: Internal presolve mapping error at exit\\n\");\n#endif\n\n}\n\n/* Utility group for shifting row and column data */\nSTATIC MYBOOL shift_rowcoldata(lprec *lp, int base, int delta, LLrec *usedmap, MYBOOL isrow)\n/* Note: Assumes that \"lp->sum\" and \"lp->rows\" HAVE NOT been updated to the new counts */\n{\n  int  i, ii;\n  REAL lodefault;\n\n  /* Shift data right/down (insert), and set default values in positive delta-gap */\n  if(delta > 0) {\n\n    /* Determine if we can take the easy way out */\n    MYBOOL easyout = (MYBOOL) ((lp->solvecount == 0) && (base > lp->rows));\n\n    /* Shift the row/column data */\n\n    MEMMOVE(lp->orig_upbo + base + delta, lp->orig_upbo + base, lp->sum - base + 1);\n    MEMMOVE(lp->orig_lowbo + base + delta, lp->orig_lowbo + base, lp->sum - base + 1);\n\n    if(!easyout) {\n      MEMMOVE(lp->upbo + base + delta, lp->upbo + base, lp->sum - base + 1);\n      MEMMOVE(lp->lowbo + base + delta, lp->lowbo + base, lp->sum - base + 1);\n      if(lp->model_is_valid) {\n        MEMMOVE(lp->solution + base + delta, lp->solution + base, lp->sum - base + 1);\n        MEMMOVE(lp->best_solution + base + delta, lp->best_solution + base, lp->sum - base + 1);\n      }\n      MEMMOVE(lp->is_lower + base + delta, lp->is_lower + base, lp->sum - base + 1);\n    }\n\n    /* Deal with scalars; the vector can be NULL */\n    if(lp->scalars != NULL) {\n      if(!easyout)\n        for(ii = lp->sum; ii >= base; ii--) {\n          i = ii + delta;\n          lp->scalars[i] = lp->scalars[ii];\n        }\n      for(ii = base; ii < base + delta; ii++)\n        lp->scalars[ii] = 1;\n    }\n\n    /* Set defaults */\n#ifdef SlackInitMinusInf\n    if(isrow)\n      lodefault = -lp->infinite;\n    else\n#endif\n      lodefault = 0;\n\n    for(i = 0; i < delta; i++) {\n      ii = base + i;\n      lp->orig_upbo[ii] = lp->infinite;\n      lp->orig_lowbo[ii] = lodefault;\n      if(!easyout) {\n        lp->upbo[ii] = lp->orig_upbo[ii];\n        lp->lowbo[ii] = lp->orig_lowbo[ii];\n        lp->is_lower[ii] = TRUE;\n      }\n    }\n  }\n\n  /* Shift data left/up (delete) */\n  else if(usedmap != NULL) {\n    int k, offset = 0;\n    if(!isrow)\n      offset += lp->rows;\n    i = offset + 1;\n    for(k = firstActiveLink(usedmap); k != 0;\n        i++, k = nextActiveLink(usedmap, k)) {\n      ii = k + offset;\n      if(ii == i)\n        continue;\n      lp->upbo[i] = lp->upbo[ii];\n      lp->orig_upbo[i] = lp->orig_upbo[ii];\n      lp->lowbo[i] = lp->lowbo[ii];\n      lp->orig_lowbo[i] = lp->orig_lowbo[ii];\n      lp->solution[i] = lp->solution[ii];\n      lp->best_solution[i] = lp->best_solution[ii];\n      lp->is_lower[i] = lp->is_lower[ii];\n      if(lp->scalars != NULL)\n        lp->scalars[i] = lp->scalars[ii];\n    }\n    if(isrow) {\n      base = lp->rows + 1;\n      MEMMOVE(lp->upbo + i, lp->upbo + base, lp->columns);\n      MEMMOVE(lp->orig_upbo + i, lp->orig_upbo + base, lp->columns);\n      MEMMOVE(lp->lowbo + i, lp->lowbo + base, lp->columns);\n      MEMMOVE(lp->orig_lowbo + i, lp->orig_lowbo + base, lp->columns);\n      if(lp->model_is_valid) {\n        MEMMOVE(lp->solution + i, lp->solution + base, lp->columns);\n        MEMMOVE(lp->best_solution + i, lp->best_solution + base, lp->columns);\n      }\n      MEMMOVE(lp->is_lower + i, lp->is_lower + base, lp->columns);\n      if(lp->scalars != NULL)\n        MEMMOVE(lp->scalars + i, lp->scalars + base, lp->columns);\n    }\n  }\n\n  else if(delta < 0) {\n\n    /* First make sure we don't cross the sum count border */\n    if(base-delta-1 > lp->sum)\n      delta = base - lp->sum - 1;\n\n    /* Shift the data*/\n    for(i = base; i <= lp->sum + delta; i++) {\n      ii = i - delta;\n      lp->upbo[i] = lp->upbo[ii];\n      lp->orig_upbo[i] = lp->orig_upbo[ii];\n      lp->lowbo[i] = lp->lowbo[ii];\n      lp->orig_lowbo[i] = lp->orig_lowbo[ii];\n      lp->solution[i] = lp->solution[ii];\n      lp->best_solution[i] = lp->best_solution[ii];\n      lp->is_lower[i] = lp->is_lower[ii];\n      if(lp->scalars != NULL)\n        lp->scalars[i] = lp->scalars[ii];\n    }\n\n  }\n\n  lp->sum += delta;\n\n  lp->matA->row_end_valid = FALSE;\n\n  return(TRUE);\n}\n\nSTATIC MYBOOL shift_basis(lprec *lp, int base, int delta, LLrec *usedmap, MYBOOL isrow)\n/* Note: Assumes that \"lp->sum\" and \"lp->rows\" HAVE NOT been updated to the new counts */\n{\n  (void)usedmap;\n  int i, ii;\n  MYBOOL Ok = TRUE;\n  (void)usedmap;\n\n  /* Don't bother to shift the basis if it is not yet ready */\n  if(!is_BasisReady(lp))\n    return( Ok );\n\n  /* Basis adjustments due to insertions (after actual row/column insertions) */\n  if(delta > 0) {\n\n    /* Determine if the basis becomes invalidated */\n    if(isrow)\n      set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT);\n\n    /* Shift and fix invalid basis references (increment higher order basic variable index) */\n    if(base <= lp->sum)\n      MEMMOVE(lp->is_basic + base + delta, lp->is_basic + base, lp->sum - base + 1);\n\n    /* Prevent CPU-expensive basis updating if this is the initial model creation */\n    if(!lp->model_is_pure || (lp->solvecount > 0))\n      for(i = 1; i <= lp->rows; i++) {\n        ii = lp->var_basic[i];\n        if(ii >= base)\n          lp->var_basic[i] += delta;\n      }\n\n    /* Update the basis (shift and extend) */\n    for(i = 0; i < delta; i++) {\n      ii = base + i;\n      lp->is_basic[ii] = isrow;\n      if(isrow)\n        lp->var_basic[lp->rows+1+i] = ii;\n    }\n\n  }\n  /* Basis adjustments due to deletions (after actual row/column deletions) */\n  else {\n    int j,k;\n\n    /* Fix invalid basis references (decrement high basic slack variable indexes),\n       but reset the entire basis if a deleted variable is found in the basis */\n    k = 0;\n    for(i = 1; i <= lp->rows; i++) {\n      ii = lp->var_basic[i];\n      lp->is_basic[ii] = FALSE;\n      if(ii >= base) {\n       /* Skip to next basis variable if this one is to be deleted */\n        if(ii < base-delta) {\n          set_action(&lp->spx_action, ACTION_REBASE);\n          continue;\n        }\n       /* Otherwise, update the index of the basic variable for deleted variables */\n        ii += delta;\n      }\n      k++;\n      lp->var_basic[k] = ii;\n    }\n\n    /* Set the new basis indicators */\n    i = k;\n    if(isrow)\n      i = MIN(k, lp->rows+delta);\n    for(; i > 0; i--) {\n      j = lp->var_basic[i];\n      lp->is_basic[j] = TRUE;\n    }\n\n    /* If a column was deleted from the basis then simply add back a non-basic\n       slack variable; do two scans, if necessary to avoid adding equality slacks */\n    if(!isrow && (k < lp->rows)) {\n      for(j = 0; j <= 1; j++)\n      for(i = 1; (i <= lp->rows) && (k < lp->rows); i++)\n        if(!lp->is_basic[i]) {\n          if(!is_constr_type(lp, i, EQ) || (j == 1)) {\n            k++;\n            lp->var_basic[k] = i;\n            lp->is_basic[i] = TRUE;\n          }\n        }\n      k = 0;\n    }\n\n    /* We are left with \"k\" indexes; if no basis variable was deleted, k=rows and the\n       inverse is still valid, if k+delta < 0 we do not have a valid\n       basis and must create one (in most usage modes this should not happen,\n       unless there is a bug) */\n    if(k+delta < 0)\n      Ok = FALSE;\n    if(isrow || (k != lp->rows))\n      set_action(&lp->spx_action, ACTION_REINVERT);\n\n  }\n  return(Ok);\n\n}\n\nSTATIC MYBOOL shift_rowdata(lprec *lp, int base, int delta, LLrec *usedmap)\n/* Note: Assumes that \"lp->rows\" HAS NOT been updated to the new count */\n{\n  int i, ii;\n\n  /* Shift sparse matrix row data */\n  if(lp->matA->is_roworder)\n    mat_shiftcols(lp->matA, &base, delta, usedmap);\n  else\n    mat_shiftrows(lp->matA, &base, delta, usedmap);\n\n  /* Shift data down (insert row), and set default values in positive delta-gap */\n  if(delta > 0) {\n\n    /* Shift row data */\n    for(ii = lp->rows; ii >= base; ii--) {\n      i = ii + delta;\n      lp->orig_rhs[i] = lp->orig_rhs[ii];\n      lp->rhs[i] = lp->rhs[ii];\n      lp->row_type[i] = lp->row_type[ii];\n    }\n\n    /* Set defaults (actual basis set in separate procedure) */\n    for(i = 0; i < delta; i++) {\n      ii = base + i;\n      lp->orig_rhs[ii] = 0;\n      lp->rhs[ii] = 0;\n      lp->row_type[ii] = ROWTYPE_EMPTY;\n    }\n  }\n\n  /* Shift data up (delete row) */\n  else if(usedmap != NULL) {\n    for(i = 1, ii = firstActiveLink(usedmap); ii != 0;\n        i++, ii = nextActiveLink(usedmap, ii)) {\n      if(i == ii)\n        continue;\n      lp->orig_rhs[i] = lp->orig_rhs[ii];\n      lp->rhs[i] = lp->rhs[ii];\n      lp->row_type[i] = lp->row_type[ii];\n    }\n    delta = i - lp->rows - 1;\n  }\n  else if(delta < 0) {\n\n    /* First make sure we don't cross the row count border */\n    if(base-delta-1 > lp->rows)\n      delta = base - lp->rows - 1;\n\n    /* Shift row data (don't shift basis indexes here; done in next step) */\n    for(i = base; i <= lp->rows + delta; i++) {\n      ii = i - delta;\n      lp->orig_rhs[i] = lp->orig_rhs[ii];\n      lp->rhs[i] = lp->rhs[ii];\n      lp->row_type[i] = lp->row_type[ii];\n    }\n  }\n\n  shift_basis(lp, base, delta, usedmap, TRUE);\n  shift_rowcoldata(lp, base, delta, usedmap, TRUE);\n  inc_rows(lp, delta);\n\n  return(TRUE);\n}\n\nSTATIC MYBOOL shift_coldata(lprec *lp, int base, int delta, LLrec *usedmap)\n/* Note: Assumes that \"lp->columns\" has NOT been updated to the new count */\n{\n  int i, ii;\n\n  if(lp->bb_totalnodes == 0)\n    free_duals(lp);\n\n  /* Shift A matrix data */\n  if(lp->matA->is_roworder)\n    mat_shiftrows(lp->matA, &base, delta, usedmap);\n  else\n    mat_shiftcols(lp->matA, &base, delta, usedmap);\n\n  /* Shift data right (insert), and set default values in positive delta-gap */\n  if(delta > 0) {\n\n    /* Fix variable priority data */\n    if((lp->var_priority != NULL) && (base <= lp->columns)) {\n      for(i = 0; i < lp->columns; i++)\n        if(lp->var_priority[i] >= base)\n          lp->var_priority[i] += delta;\n    }\n    if((lp->sos_priority != NULL) && (base <= lp->columns)) {\n      for(i = 0; i < lp->sos_vars; i++)\n        if(lp->sos_priority[i] >= base)\n          lp->sos_priority[i] += delta;\n    }\n\n    /* Fix invalid split variable data */\n    if((lp->var_is_free != NULL) && (base <= lp->columns)) {\n      for(i = 1; i <= lp->columns; i++)\n        if(abs(lp->var_is_free[i]) >= base)\n          lp->var_is_free[i] += my_chsign(lp->var_is_free[i] < 0, delta);\n    }\n\n    /* Shift column data right */\n    for(ii = lp->columns; ii >= base; ii--) {\n      i = ii + delta;\n      lp->var_type[i] = lp->var_type[ii];\n      lp->sc_lobound[i] = lp->sc_lobound[ii];\n      lp->orig_obj[i] = lp->orig_obj[ii];\n      if(lp->obj != NULL)\n        lp->obj[i] = lp->obj[ii];\n/*\n      if(lp->objfromvalue != NULL)\n        lp->objfromvalue[i] = lp->objfromvalue[ii];\n      if(lp->objfrom != NULL)\n        lp->objfrom[i] = lp->objfrom[ii];\n      if(lp->objtill != NULL)\n        lp->objtill[i] = lp->objtill[ii];\n*/\n      if(lp->var_priority != NULL)\n        lp->var_priority[i-1] = lp->var_priority[ii-1];\n      if(lp->bb_varbranch != NULL)\n        lp->bb_varbranch[i-1] = lp->bb_varbranch[ii-1];\n      if(lp->var_is_free != NULL)\n        lp->var_is_free[i] = lp->var_is_free[ii];\n      if(lp->best_solution != NULL)\n        lp->best_solution[lp->rows + i] = lp->best_solution[lp->rows + ii];\n    }\n\n    /* Set defaults */\n    for(i = 0; i < delta; i++) {\n      ii = base + i;\n      lp->var_type[ii] = ISREAL;\n      lp->sc_lobound[ii] = 0;\n      lp->orig_obj[ii] = 0;\n      if(lp->obj != NULL)\n        lp->obj[ii] = 0;\n/*\n      if(lp->objfromvalue != NULL)\n        lp->objfromvalue[ii] = 0;\n      if(lp->objfrom != NULL)\n        lp->objfrom[ii] = 0;\n      if(lp->objtill != NULL)\n        lp->objtill[ii] = 0;\n*/\n      if(lp->var_priority != NULL)\n        lp->var_priority[ii-1] = ii;\n      if(lp->bb_varbranch != NULL)\n        lp->bb_varbranch[ii-1] = BRANCH_DEFAULT;\n      if(lp->var_is_free != NULL)\n        lp->var_is_free[ii] = 0;\n      if(lp->best_solution != NULL)\n        lp->best_solution[lp->rows + ii] = 0;\n    }\n  }\n\n  /* Shift data left (delete) */\n  else if(usedmap != NULL) {\n    /* Assume there is no need to handle split columns, since we are doing\n       this only from presolve, which comes before splitting of columns. */\n\n    /* First update counts */\n    if(lp->int_vars + lp->sc_vars > 0)\n    for(ii = firstInactiveLink(usedmap); ii != 0; ii = nextInactiveLink(usedmap, ii)) {\n      if(is_int(lp, ii)) {\n        lp->int_vars--;\n        if(SOS_is_member(lp->SOS, 0, ii))\n          lp->sos_ints--;\n      }\n      if(is_semicont(lp, ii))\n        lp->sc_vars--;\n    }\n    /* Shift array members */\n    for(i = 1, ii = firstActiveLink(usedmap); ii != 0;\n        i++, ii = nextActiveLink(usedmap, ii)) {\n      if(i == ii)\n        continue;\n      lp->var_type[i] = lp->var_type[ii];\n      lp->sc_lobound[i] = lp->sc_lobound[ii];\n      lp->orig_obj[i] = lp->orig_obj[ii];\n      if(lp->obj != NULL)\n        lp->obj[i] = lp->obj[ii];\n/*\n      if(lp->objfromvalue != NULL)\n        lp->objfromvalue[i] = lp->objfromvalue[ii];\n      if(lp->objfrom != NULL)\n        lp->objfrom[i] = lp->objfrom[ii];\n      if(lp->objtill != NULL)\n        lp->objtill[i] = lp->objtill[ii];\n*/\n      if(lp->bb_varbranch != NULL)\n        lp->bb_varbranch[i-1] = lp->bb_varbranch[ii-1];\n      if(lp->var_is_free != NULL)\n        lp->var_is_free[i] = lp->var_is_free[ii];\n      if(lp->best_solution != NULL)\n        lp->best_solution[lp->rows + i] = lp->best_solution[lp->rows + ii];\n    }\n    /* Shift variable priority data */\n    if((lp->var_priority != NULL) || (lp->sos_priority != NULL)) {\n      int *colmap = NULL, k;\n      allocINT(lp, &colmap, lp->columns + 1, TRUE);\n      for(i = 1, ii = 0; i <= lp->columns; i++) {\n        if(isActiveLink(usedmap, i)) {\n          ii++;\n          colmap[i] = ii;\n        }\n      }\n      if(lp->var_priority != NULL) {\n        for(i = 0, ii = 0; i < lp->columns; i++) {\n          k = colmap[lp->var_priority[i]];\n          if(k > 0) {\n            lp->var_priority[ii] = k;\n            ii++;\n          }\n        }\n      }\n      if(lp->sos_priority != NULL) {\n        for(i = 0, ii = 0; i < lp->sos_vars; i++) {\n          k = colmap[lp->sos_priority[i]];\n          if(k > 0) {\n            lp->sos_priority[ii] = k;\n            ii++;\n          }\n        }\n        lp->sos_vars = ii;\n      }\n      FREE(colmap);\n    }\n\n    delta = i - lp->columns - 1;\n  }\n  else if(delta < 0) {\n\n    /* Fix invalid split variable data */\n    if(lp->var_is_free != NULL) {\n      for(i = 1; i <= lp->columns; i++)\n        if(abs(lp->var_is_free[i]) >= base)\n          lp->var_is_free[i] -= my_chsign(lp->var_is_free[i] < 0, delta);\n    }\n\n    /* Shift column data (excluding the basis) */\n    for(i = base; i < base-delta; i++) {\n      if(is_int(lp, i)) {\n        lp->int_vars--;\n        if(SOS_is_member(lp->SOS, 0, i))\n          lp->sos_ints--;\n      }\n      if(is_semicont(lp, i))\n        lp->sc_vars--;\n    }\n    for(i = base; i <= lp->columns + delta; i++) {\n      ii = i - delta;\n      lp->var_type[i] = lp->var_type[ii];\n      lp->sc_lobound[i] = lp->sc_lobound[ii];\n      lp->orig_obj[i] = lp->orig_obj[ii];\n      if(lp->obj != NULL)\n        lp->obj[i] = lp->obj[ii];\n/*\n      if(lp->objfromvalue != NULL)\n        lp->objfromvalue[i] = lp->objfromvalue[ii];\n      if(lp->objfrom != NULL)\n        lp->objfrom[i] = lp->objfrom[ii];\n      if(lp->objtill != NULL)\n        lp->objtill[i] = lp->objtill[ii];\n*/\n      if(lp->var_priority != NULL)\n        lp->var_priority[i-1] = lp->var_priority[ii-1];\n      if(lp->bb_varbranch != NULL)\n        lp->bb_varbranch[i-1] = lp->bb_varbranch[ii-1];\n      if(lp->var_is_free != NULL)\n        lp->var_is_free[i] = lp->var_is_free[ii];\n      if(lp->best_solution != NULL)\n        lp->best_solution[lp->rows + i] = lp->best_solution[lp->rows + ii];\n    }\n\n    /* Fix invalid variable priority data */\n    if(lp->var_priority != NULL) {\n      for(i = 0, ii = 0; i < lp->columns; i++)\n        if(lp->var_priority[i] > base - delta)\n          lp->var_priority[ii++] = lp->var_priority[i] + delta;\n        else if(lp->var_priority[i] < base)\n          lp->var_priority[ii++] = lp->var_priority[i];\n    }\n    if(lp->sos_priority != NULL) {\n      for(i = 0, ii = 0; i < lp->sos_vars; i++) {\n        if(lp->sos_priority[i] > base - delta)\n          lp->sos_priority[ii++] = lp->sos_priority[i] + delta;\n        else if(lp->sos_priority[i] < base)\n          lp->sos_priority[ii++] = lp->sos_priority[i];\n      }\n      lp->sos_vars = ii;\n    }\n\n  }\n\n  shift_basis(lp, lp->rows+base, delta, usedmap, FALSE);\n  if(SOS_count(lp) > 0)\n    SOS_shift_col(lp->SOS, 0, base, delta, usedmap, FALSE);\n  shift_rowcoldata(lp, lp->rows+base, delta, usedmap, FALSE);\n  inc_columns(lp, delta);\n\n  return( TRUE );\n}\n\n/* Utility group for incrementing row and column vector storage space */\nSTATIC void inc_rows(lprec *lp, int delta)\n{\n  int i;\n\n  if(lp->names_used && (lp->row_name != NULL))\n    for(i = lp->rows + delta; i > lp->rows; i--)\n      lp->row_name[i] = NULL;\n\n  lp->rows += delta;\n  if(lp->matA->is_roworder)\n    lp->matA->columns += delta;\n  else\n    lp->matA->rows += delta;\n}\n\nSTATIC void inc_columns(lprec *lp, int delta)\n{\n  int i;\n\n  if(lp->names_used && (lp->col_name != NULL))\n    for(i = lp->columns + delta; i > lp->columns; i--)\n      lp->col_name[i] = NULL;\n\n  lp->columns += delta;\n  if(lp->matA->is_roworder)\n    lp->matA->rows += delta;\n  else\n    lp->matA->columns += delta;\n  if(get_Lrows(lp) > 0)\n    lp->matL->columns += delta;\n}\n\nSTATIC MYBOOL inc_rowcol_space(lprec *lp, int delta, MYBOOL isrows)\n{\n  int i, oldrowcolalloc, rowcolsum;\n\n  /* Get rid of dual arrays */\n  if(lp->solvecount > 0)\n    free_duals(lp);\n\n  /* Set constants */\n  oldrowcolalloc = lp->sum_alloc;\n  lp->sum_alloc += delta;\n  rowcolsum = lp->sum_alloc + 1;\n\n  /* Reallocate lp memory */\n  if(!allocREAL(lp, &lp->upbo, rowcolsum, AUTOMATIC) ||\n     !allocREAL(lp, &lp->orig_upbo, rowcolsum, AUTOMATIC) ||\n     !allocREAL(lp, &lp->lowbo, rowcolsum, AUTOMATIC) ||\n     !allocREAL(lp, &lp->orig_lowbo, rowcolsum, AUTOMATIC) ||\n     !allocREAL(lp, &lp->solution, rowcolsum, AUTOMATIC) ||\n     !allocREAL(lp, &lp->best_solution, rowcolsum, AUTOMATIC) ||\n     !allocMYBOOL(lp, &lp->is_basic, rowcolsum, AUTOMATIC) ||\n     !allocMYBOOL(lp, &lp->is_lower, rowcolsum, AUTOMATIC) ||\n     ((lp->scalars != NULL) && !allocREAL(lp, &lp->scalars, rowcolsum, AUTOMATIC)))\n    return( FALSE );\n\n  /* Fill in default values, where appropriate */\n  for(i = oldrowcolalloc+1; i < rowcolsum; i++) {\n    lp->upbo[i] = lp->infinite;\n    lp->orig_upbo[i] = lp->upbo[i];\n    lp->lowbo[i] = 0;\n    lp->orig_lowbo[i] = lp->lowbo[i];\n    lp->is_basic[i] = FALSE;\n    lp->is_lower[i] = TRUE;\n  }\n\n  /* Deal with scalars; the vector can be NULL and also contains Lagrangean information */\n  if(lp->scalars != NULL) {\n    for(i = oldrowcolalloc+1; i < rowcolsum; i++)\n      lp->scalars[i] = 1;\n    if(oldrowcolalloc == 0)\n      lp->scalars[0] = 1;\n  }\n\n  return( inc_presolve_space(lp, delta, isrows) &&\n           resizePricer(lp) );\n}\n\nSTATIC MYBOOL inc_lag_space(lprec *lp, int deltarows, MYBOOL ignoreMAT)\n{\n  int newsize;\n\n  if(deltarows > 0) {\n\n    newsize = get_Lrows(lp) + deltarows;\n\n    /* Reallocate arrays */\n    if(!allocREAL(lp, &lp->lag_rhs, newsize+1, AUTOMATIC) ||\n       !allocREAL(lp, &lp->lambda, newsize+1, AUTOMATIC) ||\n       !allocINT(lp, &lp->lag_con_type, newsize+1, AUTOMATIC))\n      return( FALSE );\n\n    /* Reallocate the matrix (note that the row scalars are stored at index 0) */\n    if(!ignoreMAT) {\n      if(lp->matL == NULL)\n        lp->matL = mat_create(lp, newsize, lp->columns, lp->epsvalue);\n      else\n        inc_matrow_space(lp->matL, deltarows);\n    }\n    lp->matL->rows += deltarows;\n\n  }\n  /* Handle column count expansion as special case */\n  else if(!ignoreMAT) {\n    inc_matcol_space(lp->matL, lp->columns_alloc-lp->matL->columns_alloc+1);\n  }\n\n\n  return( TRUE );\n}\n\nSTATIC MYBOOL inc_row_space(lprec *lp, int deltarows)\n{\n  int    i, rowsum, oldrowsalloc;\n  MYBOOL ok = TRUE;\n\n  /* Adjust lp row structures */\n  i = lp->rows_alloc+deltarows;\n  if(lp->matA->is_roworder) {\n    i -= lp->matA->columns_alloc;\n    SETMIN(i, deltarows);\n    if(i > 0)\n      inc_matcol_space(lp->matA, i);\n    rowsum = lp->matA->columns_alloc;\n  }\n  else {\n#if 0\n    if((lp->rows_alloc > 0) && (lp->rows + deltarows > lp->rows_alloc))\n      i = deltarows; /* peno 25/12/06 */\n    else\n#endif\n      i -= lp->matA->rows_alloc;\n    SETMIN(i, deltarows);\n    if(i > 0)\n      inc_matrow_space(lp->matA, i);\n    rowsum = lp->matA->rows_alloc;\n  }\n  if(lp->rows+deltarows > lp->rows_alloc) {\n\n    rowsum++;\n    oldrowsalloc = lp->rows_alloc;\n    lp->rows_alloc = rowsum;\n    deltarows = rowsum - oldrowsalloc;\n    rowsum++;\n\n    if(!allocREAL(lp, &lp->orig_rhs, rowsum, AUTOMATIC) ||\n       !allocLREAL(lp, &lp->rhs, rowsum, AUTOMATIC) ||\n       !allocINT(lp, &lp->row_type, rowsum, AUTOMATIC) ||\n       !allocINT(lp, &lp->var_basic, rowsum, AUTOMATIC))\n      return( FALSE );\n\n    if(oldrowsalloc == 0) {\n      lp->var_basic[0] = AUTOMATIC; /*TRUE;*/  /* Indicates default basis */\n      lp->orig_rhs[0] = 0;\n      lp->row_type[0] = ROWTYPE_OFMIN;\n    }\n    for(i = oldrowsalloc+1; i < rowsum; i++) {\n      lp->orig_rhs[i] = 0;\n      lp->rhs[i] = 0;\n      lp->row_type[i] = ROWTYPE_EMPTY;\n      lp->var_basic[i] = i;\n    }\n\n    /* Adjust hash name structures */\n    if(lp->names_used && (lp->row_name != NULL)) {\n\n      /* First check the hash table */\n      if(lp->rowname_hashtab->size < lp->rows_alloc) {\n        hashtable *ht;\n\n        ht = copy_hash_table(lp->rowname_hashtab, lp->row_name, lp->rows_alloc + 1);\n        if(ht == NULL) {\n          lp->spx_status = NOMEMORY;\n          return( FALSE );\n        }\n        free_hash_table(lp->rowname_hashtab);\n        lp->rowname_hashtab = ht;\n      }\n\n      /* Then the string storage (i.e. pointer to the item's hash structure) */\n      lp->row_name = (hashelem **) realloc(lp->row_name, (rowsum) * sizeof(*lp->row_name));\n      if(lp->row_name == NULL) {\n        lp->spx_status = NOMEMORY;\n        return( FALSE );\n      }\n      for(i = oldrowsalloc + 1; i < rowsum; i++)\n        lp->row_name[i] = NULL;\n    }\n\n    ok = inc_rowcol_space(lp, deltarows, TRUE);\n\n  }\n  return(ok);\n}\n\nSTATIC MYBOOL inc_col_space(lprec *lp, int deltacols)\n{\n  int i,colsum, oldcolsalloc;\n\n  i = lp->columns_alloc+deltacols;\n  if(lp->matA->is_roworder) {\n    i -= lp->matA->rows_alloc;\n    SETMIN(i, deltacols);\n    if(i > 0)\n      inc_matrow_space(lp->matA, i);\n    colsum = lp->matA->rows_alloc;\n  }\n  else {\n    i -= lp->matA->columns_alloc;\n    SETMIN(i, deltacols);\n    if(i > 0)\n      inc_matcol_space(lp->matA, i);\n    colsum = lp->matA->columns_alloc;\n  }\n\n  if(lp->columns+deltacols >= lp->columns_alloc) {\n\n    colsum++;\n    oldcolsalloc = lp->columns_alloc;\n    lp->columns_alloc = colsum;\n    deltacols = colsum - oldcolsalloc;\n    colsum++;\n\n    /* Adjust hash name structures */\n    if(lp->names_used && (lp->col_name != NULL)) {\n\n      /* First check the hash table */\n      if(lp->colname_hashtab->size < lp->columns_alloc) {\n        hashtable *ht;\n\n        ht = copy_hash_table(lp->colname_hashtab, lp->col_name, lp->columns_alloc + 1);\n        if(ht != NULL) {\n          free_hash_table(lp->colname_hashtab);\n          lp->colname_hashtab = ht;\n        }\n      }\n\n      /* Then the string storage (i.e. pointer to the item's hash structure) */\n      lp->col_name = (hashelem **) realloc(lp->col_name, (colsum) * sizeof(*lp->col_name));\n      for(i = oldcolsalloc+1; i < colsum; i++)\n        lp->col_name[i] = NULL;\n    }\n\n    if(!allocREAL(lp, &lp->orig_obj, colsum, AUTOMATIC) ||\n       !allocMYBOOL(lp, &lp->var_type, colsum, AUTOMATIC) ||\n       !allocREAL(lp, &lp->sc_lobound, colsum, AUTOMATIC) ||\n       ((lp->obj != NULL) && !allocREAL(lp, &lp->obj, colsum, AUTOMATIC)) ||\n       ((lp->var_priority != NULL) && !allocINT(lp, &lp->var_priority, colsum-1, AUTOMATIC)) ||\n       ((lp->var_is_free != NULL) && !allocINT(lp, &lp->var_is_free, colsum, AUTOMATIC)) ||\n       ((lp->bb_varbranch != NULL) && !allocMYBOOL(lp, &lp->bb_varbranch, colsum-1, AUTOMATIC)))\n      return( FALSE );\n\n    /* Make sure that Lagrangean constraints have the same number of columns */\n    if(get_Lrows(lp) > 0)\n      inc_lag_space(lp, 0, FALSE);\n\n    /* Update column pointers */\n    for(i = MIN(oldcolsalloc, lp->columns) + 1; i < colsum; i++) {\n      lp->orig_obj[i] = 0;\n      if(lp->obj != NULL)\n        lp->obj[i] = 0;\n      lp->var_type[i] = ISREAL;\n      lp->sc_lobound[i] = 0;\n      if(lp->var_priority != NULL)\n        lp->var_priority[i-1] = i;\n    }\n\n    if(lp->var_is_free != NULL) {\n      for(i = oldcolsalloc+1; i < colsum; i++)\n        lp->var_is_free[i] = 0;\n    }\n\n    if(lp->bb_varbranch != NULL) {\n      for(i = oldcolsalloc; i < colsum-1; i++)\n        lp->bb_varbranch[i] = BRANCH_DEFAULT;\n    }\n\n    inc_rowcol_space(lp, deltacols, FALSE);\n\n  }\n  return(TRUE);\n}\n\n/* Problem manipulation routines */\n\nMYBOOL __WINAPI set_obj(lprec *lp, int colnr, REAL value)\n{\n  if(colnr <= 0)\n    colnr = set_rh(lp, 0, value);\n  else\n    colnr = set_mat(lp, 0, colnr, value);\n  return((MYBOOL) colnr);\n}\n\nMYBOOL __WINAPI set_obj_fnex(lprec *lp, int count, REAL *row, int *colno)\n{\n  MYBOOL chsgn = is_maxim(lp);\n  int    i, ix;\n  REAL   value;\n\n  if(row == NULL)\n    return( FALSE );\n\n  else if(colno == NULL) {\n    if(count <= 0)\n      count = lp->columns;\n    for(i = 1; i <= count; i++) {\n      value = row[i];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, lp->matA->epsvalue);\n#endif\n      lp->orig_obj[i] = my_chsign(chsgn, scaled_mat(lp, value, 0, i));\n    }\n  }\n  else {\n    MEMCLEAR(lp->orig_obj, lp->columns+1);\n    for(i = 0; i < count; i++) {\n      ix = colno[i];\n      value = row[i];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, lp->matA->epsvalue);\n#endif\n      lp->orig_obj[ix] = my_chsign(chsgn, scaled_mat(lp, value, 0, ix));\n    }\n  }\n\n  return(TRUE);\n}\n\nMYBOOL __WINAPI set_obj_fn(lprec *lp, REAL *row)\n{\n  return( set_obj_fnex(lp, 0, row, NULL) );\n}\n\nMYBOOL __WINAPI str_set_obj_fn(lprec *lp, const char *row_string)\n{\n  int    i;\n  MYBOOL ret = TRUE;\n  REAL   *arow;\n  const char   *p;\n  char *newp;\n\n  allocREAL(lp, &arow, lp->columns + 1, FALSE);\n  p = row_string;\n  for(i = 1; i <= lp->columns; i++) {\n    arow[i] = (REAL) strtod(p, &newp);\n    if(p == newp) {\n      report(lp, IMPORTANT, \"str_set_obj_fn: Bad string %s\\n\", p);\n      lp->spx_status = DATAIGNORED;\n      ret = FALSE;\n      break;\n    }\n    else\n      p = newp;\n  }\n  if(lp->spx_status != DATAIGNORED)\n    ret = set_obj_fn(lp, arow);\n  FREE(arow);\n  return( ret );\n}\n\nSTATIC MYBOOL append_columns(lprec *lp, int deltacolumns)\n{\n  if(!inc_col_space(lp, deltacolumns))\n    return( FALSE );\n  varmap_add(lp, lp->sum+1, deltacolumns);\n  shift_coldata(lp, lp->columns+1, deltacolumns, NULL);\n  return( TRUE );\n}\n\nSTATIC MYBOOL append_rows(lprec *lp, int deltarows)\n{\n  if(!inc_row_space(lp, deltarows))\n    return( FALSE );\n  varmap_add(lp, lp->rows+1, deltarows);\n  shift_rowdata(lp, lp->rows+1, deltarows, NULL);\n\n  return( TRUE );\n}\n\nMYBOOL __WINAPI set_add_rowmode(lprec *lp, MYBOOL turnon)\n{\n  if((lp->solvecount == 0) && (turnon ^ lp->matA->is_roworder))\n    return( mat_transpose(lp->matA) );\n  else\n    return( FALSE );\n}\n\nMYBOOL __WINAPI is_add_rowmode(lprec *lp)\n{\n  return(lp->matA->is_roworder);\n}\n\nMYBOOL __WINAPI set_row(lprec *lp, int rownr, REAL *row)\n{\n  if((rownr < 0) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"set_row: Row %d out of range\\n\", rownr);\n    return( FALSE );\n  }\n  if(rownr == 0)\n    return( set_obj_fn(lp, row) );\n  else\n    return( mat_setrow(lp->matA, rownr, lp->columns, row, NULL, TRUE, TRUE) );\n}\n\nMYBOOL __WINAPI set_rowex(lprec *lp, int rownr, int count, REAL *row, int *colno)\n{\n  if((rownr < 0) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"set_rowex: Row %d out of range\\n\", rownr);\n    return( FALSE );\n  }\n  if(rownr == 0)\n    return( set_obj_fnex(lp, count, row, colno) );\n  else\n    return( mat_setrow(lp->matA, rownr, count, row, colno, TRUE, TRUE) );\n}\n\nMYBOOL __WINAPI add_constraintex(lprec *lp, int count, REAL *row, int *colno, int constr_type, REAL rh)\n{\n  int    n;\n  MYBOOL status = FALSE;\n\n  if(!(constr_type == LE || constr_type == GE || constr_type == EQ)) {\n    report(lp, IMPORTANT, \"add_constraintex: Invalid %d constraint type\\n\", constr_type);\n    return( status );\n  }\n\n  /* Prepare for a new row */\n  if(!append_rows(lp, 1))\n    return( status );\n\n  /* Set constraint parameters, fix the slack */\n  if((constr_type & ROWTYPE_CONSTRAINT) == EQ) {\n    lp->equalities++;\n    lp->orig_upbo[lp->rows] = 0;\n    lp->upbo[lp->rows] = 0;\n  }\n  lp->row_type[lp->rows] = constr_type;\n\n  if(is_chsign(lp, lp->rows) && (rh != 0))\n    lp->orig_rhs[lp->rows] = -rh;\n  else\n    lp->orig_rhs[lp->rows] = rh;\n\n  /* Insert the non-zero constraint values */\n  if(colno == NULL && row != NULL)\n    n = lp->columns;\n  else\n    n = count;\n  mat_appendrow(lp->matA, n, row, colno, my_chsign(is_chsign(lp, lp->rows), 1.0), TRUE);\n  if(!lp->varmap_locked)\n    presolve_setOrig(lp, lp->rows, lp->columns);\n\n#ifdef Paranoia\n  if(lp->matA->is_roworder)\n    n = lp->matA->columns;\n  else\n    n = lp->matA->rows;\n  if(lp->rows != n) {\n    report(lp, SEVERE, \"add_constraintex: Row count mismatch %d vs %d\\n\",\n                       lp->rows, n);\n  }\n  else if(is_BasisReady(lp) && !verify_basis(lp))\n    report(lp, SEVERE, \"add_constraintex: Invalid basis detected for row %d\\n\", lp->rows);\n  else\n#endif\n  status = TRUE;\n\n  return( status );\n}\n\nMYBOOL __WINAPI add_constraint(lprec *lp, REAL *row, int constr_type, REAL rh)\n{\n  return( add_constraintex(lp, 0, row, NULL, constr_type, rh) );\n}\n\nMYBOOL __WINAPI str_add_constraint(lprec *lp, const char *row_string, int constr_type, REAL rh)\n{\n  int    i;\n  const char   *p;\n  char *newp;\n  REAL   *aRow;\n  MYBOOL status = FALSE;\n\n  allocREAL(lp, &aRow, lp->columns + 1, FALSE);\n  p = row_string;\n\n  for(i = 1; i <= lp->columns; i++) {\n    aRow[i] = (REAL) strtod(p, &newp);\n    if(p == newp) {\n      report(lp, IMPORTANT, \"str_add_constraint: Bad string '%s'\\n\", p);\n      lp->spx_status = DATAIGNORED;\n      break;\n    }\n    else\n      p = newp;\n  }\n  if(lp->spx_status != DATAIGNORED)\n    status = add_constraint(lp, aRow, constr_type, rh);\n  FREE(aRow);\n\n  return(status);\n}\n\nSTATIC MYBOOL del_constraintex(lprec *lp, LLrec *rowmap)\n{\n  int i;\n\n  if(lp->equalities > 0)\n  for(i = firstInactiveLink(rowmap); i != 0; i = nextInactiveLink(rowmap, i)) {\n    if(is_constr_type(lp, i, EQ)) {\n#ifdef Paranoia\n      if(lp->equalities == 0)\n        report(lp, SEVERE, \"del_constraintex: Invalid count of equality constraints\\n\");\n#endif\n       lp->equalities--;\n    }\n  }\n\n  varmap_delete(lp, 1, -1, rowmap);\n  shift_rowdata(lp, 1, -1, rowmap);\n  if(!lp->varmap_locked) {\n    presolve_setOrig(lp, lp->rows, lp->columns);\n    if(lp->names_used)\n      del_varnameex(lp, lp->row_name, lp->rows, lp->rowname_hashtab, 0, rowmap);\n  }\n\n#ifdef Paranoia\n  if(is_BasisReady(lp) && !verify_basis(lp))\n    report(lp, SEVERE, \"del_constraintex: Invalid basis detected\\n\");\n#endif\n\n  return(TRUE);\n}\nMYBOOL __WINAPI del_constraint(lprec *lp, int rownr)\n{\n  MYBOOL preparecompact = (MYBOOL) (rownr < 0);\n\n  if(preparecompact)\n    rownr = -rownr;\n  if((rownr < 1) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"del_constraint: Attempt to delete non-existing constraint %d\\n\", rownr);\n    return(FALSE);\n  }\n  /*\n  if(lp->matA->is_roworder) {\n    report(lp, IMPORTANT, \"del_constraint: Cannot delete constraint while in row entry mode.\\n\");\n    return(FALSE);\n  }\n  */\n\n  if(is_constr_type(lp, rownr, EQ) && (lp->equalities > 0))\n    lp->equalities--;\n\n  varmap_delete(lp, my_chsign(preparecompact, rownr), -1, NULL);\n  shift_rowdata(lp, my_chsign(preparecompact, rownr), -1, NULL);\n\n/*\n   peno 04.10.07\n   Fixes a problem with del_constraint.\n   Constraints names were not shifted and reported variable result was incorrect.\n   See UnitTest1, UnitTest2\n\n   min: -2 x3;\n\n   c1: +x2 -x1 <= 10;\n   c: 0 x3 <= 0;\n   c2: +x3 +x2 +x1 <= 20;\n\n   2 <= x3 <= 3;\n   x1 <= 30;\n\n   // del_constraint(lp, 2);\n\n   // See write_LP and print_solution result\n\n   // To fix, commented if(!lp->varmap_locked)\n\n*/\n  if(!lp->varmap_locked)\n  {\n    presolve_setOrig(lp, lp->rows, lp->columns);\n    if(lp->names_used)\n      del_varnameex(lp, lp->row_name, lp->rows, lp->rowname_hashtab, rownr, NULL);\n  }\n\n#ifdef Paranoia\n  if(is_BasisReady(lp) && !verify_basis(lp))\n    report(lp, SEVERE, \"del_constraint: Invalid basis detected at row %d\\n\", rownr);\n#endif\n\n  return(TRUE);\n}\n\nMYBOOL __WINAPI add_lag_con(lprec *lp, REAL *row, int con_type, REAL rhs)\n{\n  int  k;\n  REAL sign;\n\n  if(con_type == LE || con_type == EQ)\n    sign = 1;\n  else if(con_type == GE)\n    sign = -1;\n  else {\n    report(lp, IMPORTANT, \"add_lag_con: Constraint type %d not implemented\\n\", con_type);\n    return(FALSE);\n  }\n\n  inc_lag_space(lp, 1, FALSE);\n\n  k = get_Lrows(lp);\n  lp->lag_rhs[k] = rhs * sign;\n  mat_appendrow(lp->matL, lp->columns, row, NULL, sign, TRUE);\n  lp->lambda[k] = 0;\n  lp->lag_con_type[k] = con_type;\n\n  return(TRUE);\n}\n\nMYBOOL __WINAPI str_add_lag_con(lprec *lp, const char *row_string, int con_type, REAL rhs)\n{\n  int    i;\n  MYBOOL ret = TRUE;\n  REAL   *a_row;\n  const char   *p;\n  char *new_p;\n\n  allocREAL(lp, &a_row, lp->columns + 1, FALSE);\n  p = row_string;\n\n  for(i = 1; i <= lp->columns; i++) {\n    a_row[i] = (REAL) strtod(p, &new_p);\n    if(p == new_p) {\n      report(lp, IMPORTANT, \"str_add_lag_con: Bad string '%s'\\n\", p);\n      lp->spx_status = DATAIGNORED;\n      ret = FALSE;\n      break;\n    }\n    else\n      p = new_p;\n  }\n  if(lp->spx_status != DATAIGNORED)\n    ret = add_lag_con(lp, a_row, con_type, rhs);\n  FREE(a_row);\n  return( ret );\n}\n\n/* INLINE */ MYBOOL is_splitvar(lprec *lp, int colnr)\n/* Two cases handled by var_is_free:\n\n   1) LB:-Inf / UB:<Inf variables\n      No helper column created, sign of var_is_free set negative with index to itself.\n   2) LB:-Inf / UB: Inf (free) variables\n      Sign of var_is_free set positive with index to new helper column,\n      helper column created with negative var_is_free with index to the original column.\n\n   This function helps identify the helper column in 2).\n*/\n{\n   return((MYBOOL) ((lp->var_is_free != NULL) &&\n                    (lp->var_is_free[colnr] < 0) && (-lp->var_is_free[colnr] != colnr)));\n}\n\nvoid del_splitvars(lprec *lp)\n{\n  int j, jj, i;\n\n  if(lp->var_is_free != NULL) {\n    for(j = lp->columns; j >= 1; j--)\n      if(is_splitvar(lp, j)) {\n        /* Check if we need to modify the basis */\n        jj = lp->rows+abs(lp->var_is_free[j]);\n        i = lp->rows+j;\n        if(lp->is_basic[i] && !lp->is_basic[jj]) {\n          i = findBasisPos(lp, i, NULL);\n          set_basisvar(lp, i, jj);\n        }\n        /* Delete the helper column */\n        del_column(lp, j);\n      }\n    FREE(lp->var_is_free);\n  }\n}\n\nMYBOOL __WINAPI set_column(lprec *lp, int colnr, REAL *column)\n{\n  return( mat_setcol(lp->matA, colnr, lp->rows, column, NULL, TRUE, TRUE) );\n}\n\nMYBOOL __WINAPI set_columnex(lprec *lp, int colnr, int count, REAL *column, int *rowno)\n{\n  return( mat_setcol(lp->matA, colnr, count, column, rowno, TRUE, TRUE) );\n}\n\nMYBOOL __WINAPI add_columnex(lprec *lp, int count, REAL *column, int *rowno)\n/* This function adds a data column to the current model; three cases handled:\n\n    1: Prepare for column data by setting column = NULL\n    2: Dense vector indicated by (rowno == NULL) over 0..count+get_Lrows() elements\n    3: Sparse vector set over row vectors rowno, over 0..count-1 elements.\n\n   NB! If the column has only one entry, this should be handled as\n       a bound, but this currently is not the case  */\n{\n  MYBOOL status = FALSE;\n\n /* Prepare and shift column vectors */\n  if(!append_columns(lp, 1))\n    return( status );\n\n /* Append sparse regular constraint values */\n  if(mat_appendcol(lp->matA, count, column, rowno, 1.0, TRUE) < 0)\n    report(lp, SEVERE, \"add_columnex: Data column %d supplied in non-ascending row index order.\\n\",\n                       lp->columns);\n  else\n#ifdef Paranoia\n  if(lp->columns != (lp->matA->is_roworder ? lp->matA->rows : lp->matA->columns)) {\n    report(lp, SEVERE, \"add_columnex: Column count mismatch %d vs %d\\n\",\n                       lp->columns, (lp->matA->is_roworder ? lp->matA->rows : lp->matA->columns));\n  }\n  else if(is_BasisReady(lp) && (lp->P1extraDim == 0) && !verify_basis(lp))\n    report(lp, SEVERE, \"add_columnex: Invalid basis detected for column %d\\n\",\n                       lp->columns);\n  else\n#endif\n    status = TRUE;\n\n  if(!lp->varmap_locked)\n    presolve_setOrig(lp, lp->rows, lp->columns);\n\n  return( status );\n}\n\nMYBOOL __WINAPI add_column(lprec *lp, REAL *column)\n{\n  del_splitvars(lp);\n  return(add_columnex(lp, lp->rows, column, NULL));\n}\n\nMYBOOL __WINAPI str_add_column(lprec *lp, const char *col_string)\n{\n  int  i;\n  MYBOOL ret = TRUE;\n  REAL *aCol;\n  const char *p;\n  char *newp;\n\n  allocREAL(lp, &aCol, lp->rows + 1, FALSE);\n  p = col_string;\n\n  for(i = 0; i <= lp->rows; i++) {\n    aCol[i] = (REAL) strtod(p, &newp);\n    if(p == newp) {\n      report(lp, IMPORTANT, \"str_add_column: Bad string '%s'\\n\", p);\n      lp->spx_status = DATAIGNORED;\n      ret = FALSE;\n      break;\n    }\n    else\n      p = newp;\n  }\n  if(lp->spx_status != DATAIGNORED)\n    ret = add_column(lp, aCol);\n  FREE(aCol);\n  return( ret );\n}\n\nSTATIC MYBOOL del_varnameex(lprec *lp, hashelem **namelist, int items, hashtable *ht, int varnr, LLrec *varmap)\n{\n  (void)lp;\n  int i, n;\n  (void)lp;\n\n  /* First drop hash table entries of the deleted variables */\n  if(varmap != NULL)\n    i = firstInactiveLink(varmap);\n  else\n    i = varnr;\n  while(i > 0) {\n    if(namelist[i] != NULL) {\n      if(namelist[i]->name != NULL)\n        drophash(namelist[i]->name, namelist, ht);\n    }\n    if(varmap != NULL)\n      i = nextInactiveLink(varmap, i);\n    else\n      i = 0;\n  }\n\n  /* Then compress the name list */\n  if(varmap != NULL) {\n    i = firstInactiveLink(varmap);\n    n = nextActiveLink(varmap, i);\n    varnr = i;\n  }\n  else {\n    i = varnr;\n    n = i + 1;\n  }\n  while(n != 0) {\n    namelist[i] = namelist[n];\n    if((namelist[i] != NULL) && (namelist[i]->index > varnr))\n      namelist[i]->index -= n - i;\n    i++;\n    if(varmap != NULL)\n      n = nextActiveLink(varmap, i);\n    else if(n <= items) /* items has been updated for the new count */\n      n++;\n    else\n      n = 0;\n  }\n\n  return( TRUE );\n}\nSTATIC MYBOOL del_columnex(lprec *lp, LLrec *colmap)\n{\n  varmap_delete(lp, lp->rows+1, -1, colmap);\n  shift_coldata(lp, 1, -1, colmap);\n  if(!lp->varmap_locked) {\n    presolve_setOrig(lp, lp->rows, lp->columns);\n    if(lp->names_used)\n      del_varnameex(lp, lp->col_name, lp->columns, lp->colname_hashtab, 0, colmap);\n  }\n#ifdef Paranoia\n  if(is_BasisReady(lp) && (lp->P1extraDim == 0) && !verify_basis(lp))\n    report(lp, SEVERE, \"del_columnex: Invalid basis detected\\n\");\n#endif\n\n  return(TRUE);\n}\nMYBOOL __WINAPI del_column(lprec *lp, int colnr)\n{\n  MYBOOL preparecompact = (MYBOOL) (colnr < 0);\n\n  if(preparecompact)\n    colnr = -colnr;\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"del_column: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n  /*\n  if(lp->matA->is_roworder) {\n    report(lp, IMPORTANT, \"del_column: Cannot delete column while in row entry mode.\\n\");\n    return(FALSE);\n  }\n  */\n\n  if((lp->var_is_free != NULL) && (lp->var_is_free[colnr] > 0))\n    del_column(lp, lp->var_is_free[colnr]); /* delete corresponding split column (is always after this column) */\n\n  varmap_delete(lp, my_chsign(preparecompact, lp->rows+colnr), -1, NULL);\n  shift_coldata(lp, my_chsign(preparecompact, colnr), -1, NULL);\n  if(!lp->varmap_locked) {\n    presolve_setOrig(lp, lp->rows, lp->columns);\n    if(lp->names_used)\n      del_varnameex(lp, lp->col_name, lp->columns, lp->colname_hashtab, colnr, NULL);\n  }\n#ifdef Paranoia\n  if(is_BasisReady(lp) && (lp->P1extraDim == 0) && !verify_basis(lp))\n    report(lp, SEVERE, \"del_column: Invalid basis detected at column %d (%d)\\n\", colnr, lp->columns);\n#endif\n\n  return(TRUE);\n}\n\nvoid __WINAPI set_simplextype(lprec *lp, int simplextype)\n{\n  lp->simplex_strategy = simplextype;\n}\n\nint __WINAPI get_simplextype(lprec *lp)\n{\n  return(lp->simplex_strategy);\n}\n\nvoid __WINAPI set_preferdual(lprec *lp, MYBOOL dodual)\n{\n  if(dodual & TRUE)\n    lp->simplex_strategy = SIMPLEX_DUAL_DUAL;\n  else\n    lp->simplex_strategy = SIMPLEX_PRIMAL_PRIMAL;\n}\n\nvoid __WINAPI set_bounds_tighter(lprec *lp, MYBOOL tighten)\n{\n  lp->tighten_on_set = tighten;\n}\nMYBOOL __WINAPI get_bounds_tighter(lprec *lp)\n{\n  return(lp->tighten_on_set);\n}\n\nMYBOOL __WINAPI set_upbo(lprec *lp, int colnr, REAL value)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"set_upbo: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n#ifdef DoBorderRounding\n  if(fabs(value) < lp->infinite)\n    value = my_avoidtiny(value, lp->matA->epsvalue);\n#endif\n  value = scaled_value(lp, value, lp->rows + colnr);\n  if(lp->tighten_on_set) {\n    if(value < lp->orig_lowbo[lp->rows + colnr]) {\n      report(lp, IMPORTANT, \"set_upbo: Upperbound must be >= lowerbound\\n\");\n      return(FALSE);\n    }\n    if(value < lp->orig_upbo[lp->rows + colnr]) {\n      set_action(&lp->spx_action, ACTION_REBASE);\n      lp->orig_upbo[lp->rows + colnr] = value;\n    }\n  }\n  else\n  {\n    set_action(&lp->spx_action, ACTION_REBASE);\n    if(value > lp->infinite)\n      value = lp->infinite;\n    if (value < lp->infinite && lp->orig_lowbo[lp->rows + colnr] > -lp->infinite && value != lp->orig_lowbo[lp->rows + colnr] && fabs(value - lp->orig_lowbo[lp->rows + colnr]) < lp->epsvalue)\n      value = lp->orig_lowbo[lp->rows + colnr];\n    lp->orig_upbo[lp->rows + colnr] = value;\n  }\n  return(TRUE);\n}\n\nREAL __WINAPI get_upbo(lprec *lp, int colnr)\n{\n  REAL value;\n\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"get_upbo: Column %d out of range\\n\", colnr);\n    return(0);\n  }\n\n  value = lp->orig_upbo[lp->rows + colnr];\n  value = unscaled_value(lp, value, lp->rows + colnr);\n  return(value);\n}\n\nMYBOOL __WINAPI set_lowbo(lprec *lp, int colnr, REAL value)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"set_lowbo: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n#ifdef DoBorderRounding\n  if(fabs(value) < lp->infinite)\n    value = my_avoidtiny(value, lp->matA->epsvalue);\n#endif\n  value = scaled_value(lp, value, lp->rows + colnr);\n  if(lp->tighten_on_set) {\n    if(value > lp->orig_upbo[lp->rows + colnr]) {\n      report(lp, IMPORTANT, \"set_lowbo: Upper bound must be >= lower bound\\n\");\n      return(FALSE);\n    }\n    if((value < 0) || (value > lp->orig_lowbo[lp->rows + colnr])) {\n      set_action(&lp->spx_action, ACTION_REBASE);\n      lp->orig_lowbo[lp->rows + colnr] = value;\n    }\n  }\n  else\n  {\n    set_action(&lp->spx_action, ACTION_REBASE);\n    if(value < -lp->infinite)\n      value = -lp->infinite;\n    if (value > -lp->infinite && lp->orig_upbo[lp->rows + colnr] < lp->infinite && value != lp->orig_upbo[lp->rows + colnr] && fabs(value - lp->orig_upbo[lp->rows + colnr]) < lp->epsvalue)\n      value = lp->orig_upbo[lp->rows + colnr];\n    lp->orig_lowbo[lp->rows + colnr] = value;\n  }\n  return(TRUE);\n}\n\nREAL __WINAPI get_lowbo(lprec *lp, int colnr)\n{\n  REAL value;\n\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"get_lowbo: Column %d out of range\\n\", colnr);\n    return(0);\n  }\n\n  value = lp->orig_lowbo[lp->rows + colnr];\n  value = unscaled_value(lp, value, lp->rows + colnr);\n  return(value);\n}\n\nMYBOOL __WINAPI set_bounds(lprec *lp, int colnr, REAL lower, REAL upper)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"set_bounds: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n  if(fabs(upper - lower) < lp->epsvalue) {\n    if(lower < 0)\n      lower = upper;\n    else\n      upper = lower;\n  }\n  else if(lower > upper) {\n    report(lp, IMPORTANT, \"set_bounds: Column %d upper bound must be >= lower bound\\n\",\n                          colnr);\n    return( FALSE );\n  }\n\n  colnr += lp->rows;\n\n  if(lower < -lp->infinite)\n    lower = -lp->infinite;\n  else if(lp->scaling_used) {\n    lower = scaled_value(lp, lower, colnr);\n#ifdef DoBorderRounding\n    lower = my_avoidtiny(lower, lp->matA->epsvalue);\n#endif\n  }\n\n  if(upper > lp->infinite)\n    upper = lp->infinite;\n  else if(lp->scaling_used) {\n    upper = scaled_value(lp, upper, colnr);\n#ifdef DoBorderRounding\n    upper = my_avoidtiny(upper, lp->matA->epsvalue);\n#endif\n  }\n\n  lp->orig_lowbo[colnr] = lower;\n  lp->orig_upbo[colnr]  = upper;\n  set_action(&lp->spx_action, ACTION_REBASE);\n\n  return(TRUE);\n}\n\nMYBOOL get_bounds(lprec *lp, int column, REAL *lower, REAL *upper)\n{\n  if((column > lp->columns) || (column < 1)) {\n    report(lp, IMPORTANT, \"get_bounds: Column %d out of range\", column);\n    return(FALSE);\n  }\n\n  if(lower != NULL)\n    *lower = get_lowbo(lp, column);\n  if(upper != NULL)\n    *upper = get_upbo(lp, column);\n\n  return(TRUE);\n}\n\nMYBOOL __WINAPI set_int(lprec *lp, int colnr, MYBOOL var_type)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"set_int: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n  if((lp->var_type[colnr] & ISINTEGER) != 0) {\n    lp->int_vars--;\n    lp->var_type[colnr] &= ~ISINTEGER;\n  }\n  if(var_type) {\n    lp->var_type[colnr] |= ISINTEGER;\n    lp->int_vars++;\n    if(lp->columns_scaled && !is_integerscaling(lp))\n      unscale_columns(lp);\n  }\n  return(TRUE);\n}\n\nMYBOOL __WINAPI is_int(lprec *lp, int colnr)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"is_int: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n  return((lp->var_type[colnr] & ISINTEGER) != 0);\n}\n\nMYBOOL __WINAPI is_SOS_var(lprec *lp, int colnr)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"is_SOS_var: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n  return((lp->var_type[colnr] & ISSOS) != 0);\n}\n\nint __WINAPI add_SOS(lprec *lp, const char *name, int sostype, int priority, int count, int *sosvars, REAL *weights)\n{\n  SOSrec *SOS;\n  int    k;\n\n  if((sostype < 1) || (count < 0)) {\n    report(lp, IMPORTANT, \"add_SOS: Invalid SOS type definition %d\\n\", sostype);\n    return( 0 );\n  }\n\n  /* Make sure SOSes of order 3 and higher are properly defined */\n  if(sostype > 2) {\n    int j;\n    for(k = 0; k < count; k++) {\n      j = sosvars[k];\n      if(!is_int(lp, j) || !is_semicont(lp, j)) {\n        report(lp, IMPORTANT, \"add_SOS: SOS3+ members all have to be integer or semi-continuous.\\n\");\n        return( 0 );\n      }\n    }\n  }\n\n  /* Make size in the list to handle another SOS record */\n  if(lp->SOS == NULL)\n    lp->SOS = create_SOSgroup(lp);\n\n  /* Create and append SOS to list */\n  SOS = create_SOSrec(lp->SOS, name, sostype, priority, count, sosvars, weights);\n  k = append_SOSgroup(lp->SOS, SOS);\n\n  return(k);\n}\n\nSTATIC int add_GUB(lprec *lp, const char *name, int priority, int count, int *gubvars)\n{\n  SOSrec *GUB;\n  int    k;\n\n#ifdef Paranoia\n  if(count < 0) {\n    report(lp, IMPORTANT, \"add_GUB: Invalid GUB member count %d\\n\", count);\n    return(FALSE);\n  }\n#endif\n\n  /* Make size in the list to handle another GUB record */\n  if(lp->GUB == NULL)\n    lp->GUB = create_SOSgroup(lp);\n\n  /* Create and append GUB to list */\n  GUB = create_SOSrec(lp->GUB, name, 1, priority, count, gubvars, NULL);\n  GUB->isGUB = TRUE;\n  k = append_SOSgroup(lp->GUB, GUB);\n\n  return(k);\n}\n\nMYBOOL __WINAPI set_binary(lprec *lp, int colnr, MYBOOL must_be_bin)\n{\n  MYBOOL status = FALSE;\n\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"set_binary: Column %d out of range\\n\", colnr);\n    return( status );\n  }\n\n  status = set_int(lp, colnr, must_be_bin);\n  if(status && must_be_bin)\n    status = set_bounds(lp, colnr, 0, 1);\n  return( status );\n}\n\nMYBOOL __WINAPI is_binary(lprec *lp, int colnr)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"is_binary: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n  return((MYBOOL) (((lp->var_type[colnr] & ISINTEGER) != 0) &&\n                    (get_lowbo(lp, colnr) == 0) &&\n                    (fabs(get_upbo(lp, colnr) - 1) < lp->epsprimal)));\n}\n\nMYBOOL __WINAPI set_unbounded(lprec *lp, int colnr)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"set_unbounded: Column %d out of range\\n\", colnr);\n    return( FALSE );\n  }\n\n  return( set_bounds(lp, colnr, -lp->infinite, lp->infinite) );\n}\n\nMYBOOL __WINAPI is_unbounded(lprec *lp, int colnr)\n{\n  MYBOOL test;\n\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"is_unbounded: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n  test = is_splitvar(lp, colnr);\n  if(!test) {\n    colnr += lp->rows;\n    test = (MYBOOL) ((lp->orig_lowbo[colnr] <= -lp->infinite) &&\n                     (lp->orig_upbo[colnr] >= lp->infinite));\n  }\n  return( test );\n}\n\nMYBOOL __WINAPI is_negative(lprec *lp, int colnr)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"is_negative: Column %d out of range\\n\", colnr);\n    return( FALSE );\n  }\n\n  colnr += lp->rows;\n  return( (MYBOOL) ((lp->orig_upbo[colnr] <= 0) &&\n                    (lp->orig_lowbo[colnr] < 0)) );\n}\n\nMYBOOL __WINAPI set_var_weights(lprec *lp, REAL *weights)\n{\n  if(lp->var_priority != NULL) {\n    FREE(lp->var_priority);\n  }\n  if(weights != NULL) {\n    int n;\n    allocINT(lp, &lp->var_priority, lp->columns_alloc, FALSE);\n    for(n = 0; n < lp->columns; n++) {\n      lp->var_priority[n] = n+1;\n    }\n    n = sortByREAL(lp->var_priority, weights, lp->columns, 0, FALSE);\n  }\n  return(TRUE);\n}\n\nMYBOOL __WINAPI set_var_priority(lprec *lp)\n/* Experimental automatic variable ordering/priority setting */\n{\n  MYBOOL status = FALSE;\n\n  if(is_bb_mode(lp, NODE_AUTOORDER) &&\n     (lp->var_priority == NULL) &&\n     (SOS_count(lp) == 0)) {\n\n    REAL *rcost = NULL;\n    int  i, j, *colorder = NULL;\n\n    allocINT(lp, &colorder, lp->columns+1, FALSE);\n\n    /* Create an \"optimal\" B&B variable ordering; this MDO-based routine\n       returns column indeces in an increasing order of co-dependency.\n       It can be argued that arranging the columns in right-to-left\n       MDO order should tend to minimize the consequences of choosing the\n       wrong variable by reducing the average B&B depth. */\n    colorder[0] = lp->columns;\n    for(j = 1; j <= lp->columns; j++)\n      colorder[j] = lp->rows+j;\n    i = getMDO(lp, NULL, colorder, NULL, FALSE);\n\n    /* Map to variable weight */\n    allocREAL(lp, &rcost, lp->columns+1, FALSE);\n    for(j = lp->columns; j > 0; j--) {\n      i = colorder[j]-lp->rows;\n      rcost[i] = -j;\n    }\n\n   /* Establish the MIP variable priorities */\n    set_var_weights(lp, rcost+1);\n\n    FREE(rcost);\n    FREE(colorder);\n    status = TRUE;\n  }\n\n  return( status );\n}\n\nint __WINAPI get_var_priority(lprec *lp, int colnr)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"get_var_priority: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n  if(lp->var_priority == NULL)\n    return(colnr);\n  else\n    return(lp->var_priority[colnr - 1]);\n}\n\nMYBOOL __WINAPI set_semicont(lprec *lp, int colnr, MYBOOL must_be_sc)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"set_semicont: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n  if(lp->sc_lobound[colnr] != 0) {\n    lp->sc_vars--;\n    lp->var_type[colnr] &= ~ISSEMI;\n  }\n  lp->sc_lobound[colnr] = must_be_sc;\n  if(must_be_sc) {\n    lp->var_type[colnr] |= ISSEMI;\n    lp->sc_vars++;\n  }\n  return(TRUE);\n}\n\nMYBOOL __WINAPI is_semicont(lprec *lp, int colnr)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"is_semicont: Column %d out of range\\n\", colnr);\n    return(FALSE);\n  }\n\n  return((lp->var_type[colnr] & ISSEMI) != 0);\n}\n\nMYBOOL __WINAPI set_rh(lprec *lp, int rownr, REAL value)\n{\n  if((rownr > lp->rows) || (rownr < 0)) {\n    report(lp, IMPORTANT, \"set_rh: Row %d out of range\\n\", rownr);\n    return(FALSE);\n  }\n\n  if(((rownr == 0) && (!is_maxim(lp))) ||\n     ((rownr > 0) && is_chsign(lp, rownr)))    /* setting of RHS of OF IS meaningful */\n    value = my_flipsign(value);\n  if(fabs(value) > lp->infinite) {\n    if(value < 0)\n      value = -lp->infinite;\n    else\n      value = lp->infinite;\n  }\n#ifdef DoBorderRounding\n  else\n    value = my_avoidtiny(value, lp->matA->epsvalue);\n#endif\n  value = scaled_value(lp, value, rownr);\n  lp->orig_rhs[rownr] = value;\n  set_action(&lp->spx_action, ACTION_RECOMPUTE);\n  return(TRUE);\n}\n\nREAL __WINAPI get_rh(lprec *lp, int rownr)\n{\n  REAL value;\n\n  if((rownr > lp->rows) || (rownr < 0)) {\n    report(lp, IMPORTANT, \"get_rh: Row %d out of range\", rownr);\n    return( 0.0 );\n  }\n\n  value = lp->orig_rhs[rownr];\n  if (((rownr == 0) && !is_maxim(lp)) ||\n      ((rownr > 0) && is_chsign(lp, rownr)))    /* setting of RHS of OF IS meaningful */\n    value = my_flipsign(value);\n  value = unscaled_value(lp, value, rownr);\n  return(value);\n}\n\nREAL get_rh_upper(lprec *lp, int rownr)\n{\n  REAL value, valueR;\n\n  value = lp->orig_rhs[rownr];\n  if(is_chsign(lp, rownr)) {\n    valueR = lp->orig_upbo[rownr];\n    if(is_infinite(lp, valueR))\n      return(lp->infinite);\n    value = my_flipsign(value);\n    value += valueR;\n  }\n  value = unscaled_value(lp, value, rownr);\n  return(value);\n}\n\nREAL get_rh_lower(lprec *lp, int rownr)\n{\n  REAL value, valueR;\n\n  value = lp->orig_rhs[rownr];\n  if(is_chsign(lp, rownr))\n    value = my_flipsign(value);\n  else {\n    valueR = lp->orig_upbo[rownr];\n    if(is_infinite(lp, valueR))\n      return(-lp->infinite);\n    value -= valueR;\n  }\n  value = unscaled_value(lp, value, rownr);\n  return(value);\n}\n\nMYBOOL set_rh_upper(lprec *lp, int rownr, REAL value)\n{\n  if(rownr > lp->rows || rownr < 1) {\n    report(lp, IMPORTANT, \"set_rh_upper: Row %d out of range\", rownr);\n    return(FALSE);\n  }\n\n /* First scale the value */\n  value = scaled_value(lp, value, rownr);\n\n /* orig_rhs stores the upper bound assuming a < constraint;\n    If we have a > constraint, we must adjust the range instead */\n  if(is_chsign(lp, rownr)) {\n    if(is_infinite(lp, value))\n      lp->orig_upbo[rownr] = lp->infinite;\n    else {\n#ifdef Paranoia\n      if(value + lp->orig_rhs[rownr] < 0) {\n        report(lp, SEVERE, \"set_rh_upper: Invalid negative range in row %d\\n\",\n                           rownr);\n        return(FALSE);\n      }\n#endif\n#ifdef DoBorderRounding\n      lp->orig_upbo[rownr] = my_avoidtiny(value + lp->orig_rhs[rownr], lp->epsvalue);\n#else\n      lp->orig_upbo[rownr] = value + lp->orig_rhs[rownr];\n#endif\n    }\n  }\n  else {\n    /* If there is a constraint range, then this has to be adjusted also */\n    if(!is_infinite(lp, lp->orig_upbo[rownr])) {\n      lp->orig_upbo[rownr] -= lp->orig_rhs[rownr] - value;\n      my_roundzero(lp->orig_upbo[rownr], lp->epsvalue);\n      if(lp->orig_upbo[rownr] < 0) {\n        report(lp, IMPORTANT, \"set_rh_upper: Negative bound set for constraint %d made 0\\n\", rownr);\n        lp->orig_upbo[rownr] = 0;\n      }\n    }\n    lp->orig_rhs[rownr] = value;\n  }\n  return(TRUE);\n}\n\nMYBOOL set_rh_lower(lprec *lp, int rownr, REAL value)\n{\n  if(rownr > lp->rows || rownr < 1) {\n    report(lp, IMPORTANT, \"set_rh_lower: Row %d out of range\", rownr);\n    return(FALSE);\n  }\n\n /* First scale the value */\n  value = scaled_value(lp, value, rownr);\n\n /* orig_rhs stores the upper bound assuming a < constraint;\n    If we have a < constraint, we must adjust the range instead */\n  if(!is_chsign(lp, rownr)) {\n    if(is_infinite(lp, value))\n      lp->orig_upbo[rownr] = lp->infinite;\n    else {\n#ifdef Paranoia\n      if(lp->orig_rhs[rownr] - value < 0) {\n        report(lp, SEVERE, \"set_rh_lower: Invalid negative range in row %d\\n\",\n                           rownr);\n        return(FALSE);\n      }\n#endif\n#ifdef DoBorderRounding\n      lp->orig_upbo[rownr] = my_avoidtiny(lp->orig_rhs[rownr] - value, lp->epsvalue);\n#else\n      lp->orig_upbo[rownr] = lp->orig_rhs[rownr] - value;\n#endif\n    }\n  }\n  else {\n    value = my_flipsign(value);\n    /* If there is a constraint range, then this has to be adjusted also */\n    if(!is_infinite(lp, lp->orig_upbo[rownr])) {\n      lp->orig_upbo[rownr] -= lp->orig_rhs[rownr] - value;\n      my_roundzero(lp->orig_upbo[rownr], lp->epsvalue);\n      if(lp->orig_upbo[rownr] < 0) {\n        report(lp, IMPORTANT, \"set_rh_lower: Negative bound set for constraint %d made 0\\n\", rownr);\n        lp->orig_upbo[rownr] = 0;\n      }\n    }\n    lp->orig_rhs[rownr] = value;\n  }\n  return(TRUE);\n}\n\nMYBOOL __WINAPI set_rh_range(lprec *lp, int rownr, REAL deltavalue)\n{\n  if((rownr > lp->rows) || (rownr < 1)) {\n    report(lp, IMPORTANT, \"set_rh_range: Row %d out of range\", rownr);\n    return(FALSE);\n  }\n\n  deltavalue = scaled_value(lp, deltavalue, rownr);\n  if(deltavalue > lp->infinite)\n    deltavalue = lp->infinite;\n  else if(deltavalue < -lp->infinite)\n    deltavalue = -lp->infinite;\n#ifdef DoBorderRounding\n  else\n    deltavalue = my_avoidtiny(deltavalue, lp->matA->epsvalue);\n#endif\n\n  if(fabs(deltavalue) < lp->epsprimal) {\n    /* Conversion to EQ */\n    set_constr_type(lp, rownr, EQ);\n  }\n  else if(is_constr_type(lp, rownr, EQ)) {\n    /* EQ with a non-zero range */\n    if(deltavalue > 0)\n      set_constr_type(lp, rownr, GE);\n    else\n      set_constr_type(lp, rownr, LE);\n    lp->orig_upbo[rownr] = fabs(deltavalue);\n  }\n  else {\n    /* Modify GE/LE ranges */\n    lp->orig_upbo[rownr] = fabs(deltavalue);\n  }\n\n  return(TRUE);\n}\n\nREAL __WINAPI get_rh_range(lprec *lp, int rownr)\n{\n  if((rownr > lp->rows) || (rownr < 0)) {\n    report(lp, IMPORTANT, \"get_rh_range: row %d out of range\\n\", rownr);\n    return(FALSE);\n  }\n\n  if(lp->orig_upbo[rownr] >= lp->infinite)\n    return(lp->orig_upbo[rownr]);\n  else\n    return(unscaled_value(lp, lp->orig_upbo[rownr], rownr));\n}\n\nvoid __WINAPI set_rh_vec(lprec *lp, REAL *rh)\n{\n  int  i;\n  REAL rhi;\n\n  for(i = 1; i <= lp->rows; i++) {\n    rhi = rh[i];\n#ifdef DoBorderRounding\n    rhi = my_avoidtiny(rhi, lp->matA->epsvalue);\n#endif\n    lp->orig_rhs[i] = my_chsign(is_chsign(lp, i), scaled_value(lp, rhi, i));\n  }\n  set_action(&lp->spx_action, ACTION_RECOMPUTE);\n}\n\nMYBOOL __WINAPI str_set_rh_vec(lprec *lp, const char *rh_string)\n{\n  int  i;\n  MYBOOL ret = TRUE;\n  REAL *newrh;\n  const char *p;\n  char *newp;\n\n  allocREAL(lp, &newrh, lp->rows + 1, TRUE);\n  p = rh_string;\n\n  for(i = 1; i <= lp->rows; i++) {\n    newrh[i] = (REAL) strtod(p, &newp);\n    if(p == newp) {\n      report(lp, IMPORTANT, \"str_set_rh_vec: Bad string %s\\n\", p);\n      lp->spx_status = DATAIGNORED;\n      ret = FALSE;\n      break;\n    }\n    else\n      p = newp;\n  }\n  if(!(lp->spx_status == DATAIGNORED))\n    set_rh_vec(lp, newrh);\n  FREE(newrh);\n  return( ret );\n}\n\nvoid __WINAPI set_sense(lprec *lp, MYBOOL maximize)\n{\n  maximize = (MYBOOL) (maximize != FALSE);\n  if(is_maxim(lp) != maximize) {\n    int i;\n    if(is_infinite(lp, lp->bb_heuristicOF))\n      lp->bb_heuristicOF = my_chsign(maximize, lp->infinite);\n    if(is_infinite(lp, lp->bb_breakOF))\n      lp->bb_breakOF = my_chsign(maximize, -lp->infinite);\n    lp->orig_rhs[0] = my_flipsign(lp->orig_rhs[0]);\n    for(i = 1; i <= lp->columns; i++)\n      lp->orig_obj[i] = my_flipsign(lp->orig_obj[i]);\n    set_action(&lp->spx_action, ACTION_REINVERT | ACTION_RECOMPUTE);\n  }\n  if(maximize)\n    lp->row_type[0] = ROWTYPE_OFMAX;\n  else\n    lp->row_type[0] = ROWTYPE_OFMIN;\n}\n\nvoid __WINAPI set_maxim(lprec *lp)\n{\n  set_sense(lp, TRUE);\n}\n\nvoid __WINAPI set_minim(lprec *lp)\n{\n  set_sense(lp, FALSE);\n}\n\nMYBOOL __WINAPI is_maxim(lprec *lp)\n{\n  return( (MYBOOL) ((lp->row_type != NULL) &&\n                     ((lp->row_type[0] & ROWTYPE_CHSIGN) == ROWTYPE_GE)) );\n}\n\nMYBOOL __WINAPI set_constr_type(lprec *lp, int rownr, int con_type)\n{\n  MYBOOL oldchsign;\n\n  if(rownr > lp->rows+1 || rownr < 1) {\n    report(lp, IMPORTANT, \"set_constr_type: Row %d out of range\\n\", rownr);\n    return( FALSE );\n  }\n\n  /* Prepare for a new row */\n  if((rownr > lp->rows) && !append_rows(lp, rownr-lp->rows))\n    return( FALSE );\n\n  /* Update the constraint type data */\n  if(is_constr_type(lp, rownr, EQ))\n    lp->equalities--;\n\n  if((con_type & ROWTYPE_CONSTRAINT) == EQ) {\n    lp->equalities++;\n    lp->orig_upbo[rownr] = 0;\n  }\n  else if(((con_type & LE) > 0) || ((con_type & GE) > 0) || (con_type == FR))\n    lp->orig_upbo[rownr] = lp->infinite;\n  else {\n    report(lp, IMPORTANT, \"set_constr_type: Constraint type %d not implemented (row %d)\\n\",\n                          con_type, rownr);\n    return( FALSE );\n  }\n\n  /* Change the signs of the row, if necessary */\n  oldchsign = is_chsign(lp, rownr);\n  if(con_type == FR)\n    lp->row_type[rownr] = LE;\n  else\n    lp->row_type[rownr] = con_type;\n  if(oldchsign != is_chsign(lp, rownr)) {\n    MATrec *mat = lp->matA;\n\n    if(mat->is_roworder)\n      mat_multcol(mat, rownr, -1, FALSE);\n    else\n      mat_multrow(mat, rownr, -1);\n    if(lp->orig_rhs[rownr] != 0)\n      lp->orig_rhs[rownr] *= -1;\n    set_action(&lp->spx_action, ACTION_RECOMPUTE);\n  }\n  if(con_type == FR)\n      lp->orig_rhs[rownr] = lp->infinite;\n\n  set_action(&lp->spx_action, ACTION_REINVERT);\n  lp->basis_valid = FALSE;\n\n  return( TRUE );\n}\n\n/* INLINE */ MYBOOL is_chsign(lprec *lp, int rownr)\n{\n  return( (MYBOOL) ((lp->row_type[rownr] & ROWTYPE_CONSTRAINT) == ROWTYPE_CHSIGN) );\n}\n\nMYBOOL __WINAPI is_constr_type(lprec *lp, int rownr, int mask)\n{\n  if((rownr < 0) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"is_constr_type: Row %d out of range\\n\", rownr);\n    return( FALSE );\n  }\n  return( (MYBOOL) ((lp->row_type[rownr] & ROWTYPE_CONSTRAINT) == mask));\n}\n\nint __WINAPI get_constr_type(lprec *lp, int rownr)\n{\n  if((rownr < 0) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"get_constr_type: Row %d out of range\\n\", rownr);\n    return(-1);\n  }\n  return( lp->row_type[rownr] );\n}\nREAL __WINAPI get_constr_value(lprec *lp, int rownr, int count, REAL *primsolution, int *nzindex)\n{\n  int    i;\n  REAL   value = 0.0;\n  MATrec *mat = lp->matA;\n\n  if((rownr < 0) || (rownr > get_Nrows(lp)))\n    return( value );\n\n  /* First do validation and initialization of applicable primal solution */\n  if(!mat_validate(mat) || ((primsolution == NULL) && (lp->solvecount == 0)))\n    return( value );\n  i = get_Ncolumns(lp);\n  if((primsolution != NULL) && (nzindex == NULL) &&\n     ((count <= 0) || (count > i)))\n    count = i;\n  if(primsolution == NULL) {\n    get_ptr_variables(lp, &primsolution);\n    primsolution--;\n    nzindex = NULL;\n    count = i;\n  }\n\n  /* Do objective or constraint, as specified */\n  if(rownr == 0) {\n    value += get_rh(lp, 0);\n    if(nzindex != NULL)\n      for(i = 0; i < count; i++)\n        value += get_mat(lp, 0, nzindex[i]) * primsolution[i];\n    else\n      for(i = 1; i <= count; i++)\n        value += get_mat(lp, 0, i) * primsolution[i];\n  }\n  else {\n    if(nzindex != NULL) {\n      for(i = 0; i < count; i++)\n        value += get_mat(lp, rownr, nzindex[i]) * primsolution[i];\n    }\n    else {\n      int j;\n\n      for(i = mat->row_end[rownr-1]; i < mat->row_end[rownr]; i++) {\n        j = ROW_MAT_COLNR(i);\n        value += unscaled_mat(lp, ROW_MAT_VALUE(i), rownr, j) * primsolution[j];\n      }\n      value = my_chsign(is_chsign(lp, rownr), value);\n    }\n  }\n  return( value );\n}\n\nSTATIC const char *get_str_constr_class(lprec *lp, int con_class)\n{\n  (void)lp;\n  switch(con_class) {\n    case ROWCLASS_Unknown:     return(\"Unknown\");\n    case ROWCLASS_Objective:   return(\"Objective\");\n    case ROWCLASS_GeneralREAL: return(\"General REAL\");\n    case ROWCLASS_GeneralMIP:  return(\"General MIP\");\n    case ROWCLASS_GeneralINT:  return(\"General INT\");\n    case ROWCLASS_GeneralBIN:  return(\"General BIN\");\n    case ROWCLASS_KnapsackINT: return(\"Knapsack INT\");\n    case ROWCLASS_KnapsackBIN: return(\"Knapsack BIN\");\n    case ROWCLASS_SetPacking:  return(\"Set packing\");\n    case ROWCLASS_SetCover:    return(\"Set cover\");\n    case ROWCLASS_GUB:         return(\"GUB\");\n    default:                   return(\"Error\");\n  }\n}\n\nSTATIC const char *get_str_constr_type(lprec *lp, int con_type)\n{\n  (void)lp;\n  switch(con_type) {\n    case FR: return(\"FR\");\n    case LE: return(\"LE\");\n    case GE: return(\"GE\");\n    case EQ: return(\"EQ\");\n    default: return(\"Error\");\n  }\n}\n\nSTATIC int get_constr_class(lprec *lp, int rownr)\n{\n  int    aBIN = 0, aINT = 0, aREAL = 0,\n         xBIN = 0, xINT = 0, xREAL = 0;\n  int    j, elmnr, elmend, nelm;\n  MYBOOL chsign;\n  REAL   a;\n  MATrec *mat = lp->matA;\n\n  if((rownr < 1) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"get_constr_class: Row %d out of range\\n\", rownr);\n    return( ROWCLASS_Unknown );\n  }\n  mat_validate(mat);\n\n  /* Tally counts of constraint variable types and coefficients */\n  if(rownr == 0) {\n    elmnr = 1;\n    elmend = lp->columns;\n    nelm = 0;\n  }\n  else {\n    elmnr  = mat->row_end[rownr - 1];\n    elmend = mat->row_end[rownr];\n    nelm = elmend - elmnr;\n  }\n  chsign = is_chsign(lp, rownr);\n  for(; elmnr < elmend; elmnr++) {\n    if(rownr == 0) {\n      a = lp->orig_obj[elmnr];\n      if(a == 0)\n        continue;\n      j = elmnr;\n    }\n    else {\n      j = ROW_MAT_COLNR(elmnr);\n      a = ROW_MAT_VALUE(elmnr);\n    }\n    a = unscaled_mat(lp, my_chsign(chsign, a), rownr, j);\n    if(is_binary(lp, j))\n      xBIN++;\n    else if((get_lowbo(lp, j) >= 0) && is_int(lp, j))\n      xINT++;\n    else\n      xREAL++;  /* Includes integer variables with negative lower bound */\n\n    if(fabs(a-1.0) < lp->epsvalue)\n      aBIN++;\n    else if((a > 0) && (fabs(floor(a+lp->epsvalue)-a) < lp->epsvalue))\n      aINT++;\n    else\n      aREAL++;  /* Includes negative integer-valued coefficients */\n  }\n\n  /* Get the constraint type and the RHS */\n  if(rownr == 0)\n    return( ROWCLASS_Objective );\n  j = get_constr_type(lp, rownr);\n  a = get_rh(lp, rownr);\n\n  /* Determine the constraint class */\n  if((aBIN == nelm) && (xBIN == nelm) && (a >= 1)) {\n    if(a > 1)\n      j = ROWCLASS_KnapsackBIN;\n    else if(j == EQ)\n      j = ROWCLASS_GUB;\n    else if(j == LE)\n      j = ROWCLASS_SetCover;\n    else\n      j = ROWCLASS_SetPacking;\n  }\n  else if((aINT == nelm) && (xINT == nelm) && (a >= 1))\n    j = ROWCLASS_KnapsackINT;\n  else if(xBIN == nelm)\n    j = ROWCLASS_GeneralBIN;\n  else if(xINT == nelm)\n    j = ROWCLASS_GeneralINT;\n  else if((xREAL > 0) && (xINT+xBIN > 0))\n    j = ROWCLASS_GeneralMIP;\n  else\n    j = ROWCLASS_GeneralREAL;\n\n  return( j );\n}\n\nREAL __WINAPI get_mat(lprec *lp, int rownr, int colnr)\n{\n  REAL value;\n  int  elmnr;\n  int colnr1 = colnr, rownr1 = rownr;\n\n  if((rownr < 0) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"get_mat: Row %d out of range\", rownr);\n    return(0);\n  }\n  if((colnr < 1) || (colnr > lp->columns)) {\n    report(lp, IMPORTANT, \"get_mat: Column %d out of range\", colnr);\n    return(0);\n  }\n  if(rownr == 0) {\n    value = lp->orig_obj[colnr];\n    value = my_chsign(is_chsign(lp, rownr), value);\n    value = unscaled_mat(lp, value, rownr, colnr);\n  }\n  else {\n    if(lp->matA->is_roworder)\n      swapINT(&colnr1, &rownr1);\n    elmnr = mat_findelm(lp->matA, rownr1, colnr1);\n    if(elmnr >= 0) {\n      MATrec *mat = lp->matA;\n      value = my_chsign(is_chsign(lp, rownr), COL_MAT_VALUE(elmnr));\n      value = unscaled_mat(lp, value, rownr, colnr);\n    }\n    else\n      value = 0;\n  }\n  return(value);\n}\n\nREAL __WINAPI get_mat_byindex(lprec *lp, int matindex, MYBOOL isrow, MYBOOL adjustsign)\n/* Note that this function does not adjust for sign-changed GT constraints! */\n{\n  int  *rownr, *colnr;\n  REAL *value, result;\n\n  mat_get_data(lp, matindex, isrow, &rownr, &colnr, &value);\n  if(adjustsign)\n    result = (*value) * (is_chsign(lp, *rownr) ? -1 : 1);\n  else\n    result = *value;\n  if(lp->scaling_used)\n    return( unscaled_mat(lp, result, *rownr, *colnr) );\n  else\n    return( result );\n}\n\nstatic int mat_getrow(lprec *lp, int rownr, REAL *row, int *colno)\n{\n  MYBOOL isnz;\n  int    j, countnz = 0;\n  REAL   a;\n\n  if((rownr == 0) || !mat_validate(lp->matA)) {\n    for(j = 1; j <= lp->columns; j++) {\n      a = get_mat(lp,rownr,j);\n      isnz = (a != 0);\n      if(colno == NULL)\n        row[j] = a;\n      else if(isnz) {\n        row[countnz]   = a;\n        colno[countnz] = j;\n      }\n      if(isnz)\n        countnz++;\n    }\n  }\n  else {\n    MYBOOL chsign = FALSE;\n    int    ie, i;\n    MATrec *mat = lp->matA;\n\n    if(colno == NULL)\n      MEMCLEAR(row, lp->columns+1);\n    if(mat->is_roworder) {\n     /* Add the objective function */\n      a = get_mat(lp, 0, rownr);\n      if(colno == NULL) {\n        row[countnz] = a;\n        if(a != 0)\n          countnz++;\n      }\n      else if(a != 0) {\n        row[countnz] = a;\n        colno[countnz] = 0;\n        countnz++;\n      }\n    }\n    i = mat->row_end[rownr-1];\n    ie = mat->row_end[rownr];\n    if(!lp->matA->is_roworder)\n      chsign = is_chsign(lp, rownr);\n    for(; i < ie; i++) {\n      j = ROW_MAT_COLNR(i);\n      a = get_mat_byindex(lp, i, TRUE, FALSE);\n      if(lp->matA->is_roworder)\n        chsign = is_chsign(lp, j);\n      a = my_chsign(chsign, a);\n      if(colno == NULL)\n        row[j] = a;\n      else {\n        row[countnz]   = a;\n        colno[countnz] = j;\n      }\n      countnz++;\n    }\n  }\n  return( countnz );\n}\n\nstatic int mat_getcolumn(lprec *lp, int colnr, REAL *column, int *nzrow)\n{\n  int    n = 0, i, ii, ie, *rownr;\n  REAL   hold, *value;\n  MATrec *mat = lp->matA;\n\n  if(nzrow == NULL)\n    MEMCLEAR(column, lp->rows + 1);\n  if(!mat->is_roworder) {\n     /* Add the objective function */\n    hold = get_mat(lp, 0, colnr);\n    if(nzrow == NULL) {\n      column[n] = hold;\n      if(hold != 0)\n        n++;\n    }\n    else if(hold != 0) {\n      column[n] = hold;\n      nzrow[n] = 0;\n      n++;\n    }\n  }\n\n  i  = lp->matA->col_end[colnr - 1];\n  ie = lp->matA->col_end[colnr];\n  if(nzrow == NULL)\n    n += ie - i;\n  rownr = &COL_MAT_ROWNR(i);\n  value = &COL_MAT_VALUE(i);\n  for(; i < ie;\n      i++, rownr += matRowColStep, value += matValueStep) {\n    ii = *rownr;\n\n    hold = my_chsign(is_chsign(lp, (mat->is_roworder) ? colnr : ii), *value);\n    hold = unscaled_mat(lp, hold, ii, colnr);\n    if(nzrow == NULL)\n      column[ii] = hold;\n    else if(hold != 0) {\n      column[n] = hold;\n      nzrow[n] = ii;\n      n++;\n    }\n  }\n  return( n );\n}\n\nint __WINAPI get_columnex(lprec *lp, int colnr, REAL *column, int *nzrow)\n{\n  if((colnr > lp->columns) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"get_columnex: Column %d out of range\\n\", colnr);\n    return( -1 );\n  }\n\n  if(lp->matA->is_roworder)\n    return(mat_getrow(lp, colnr, column, nzrow));\n  else\n    return(mat_getcolumn(lp, colnr, column, nzrow));\n}\n\nMYBOOL __WINAPI get_column(lprec *lp, int colnr, REAL *column)\n{\n  return( (MYBOOL) (get_columnex(lp, colnr, column, NULL) >= 0) );\n}\n\nint __WINAPI get_rowex(lprec *lp, int rownr, REAL *row, int *colno)\n{\n  if((rownr < 0) || (rownr > lp->rows)) {\n    report(lp, IMPORTANT, \"get_rowex: Row %d out of range\\n\", rownr);\n    return( -1 );\n  }\n\n  if(rownr != 0 && lp->matA->is_roworder)\n    return(mat_getcolumn(lp, rownr, row, colno));\n  else\n    return(mat_getrow(lp, rownr, row, colno));\n}\n\nMYBOOL __WINAPI get_row(lprec *lp, int rownr, REAL *row)\n{\n  return((MYBOOL) (get_rowex(lp, rownr, row, NULL) >= 0) );\n}\n\nSTATIC void set_OF_override(lprec *lp, REAL *ofVector)\n/* The purpose of this function is to set, or clear if NULL, the\n   ofVector[0..columns] as the active objective function instead of\n   the one stored in the A-matrix. See also lag_solve().*/\n{\n  lp->obj = ofVector;\n}\n\nMYBOOL modifyOF1(lprec *lp, int index, REAL *ofValue, REAL mult)\n/* Adjust objective function values for primal/dual phase 1, if appropriate */\n{\n  MYBOOL accept = TRUE;\n\n  /* Primal simplex: Set user variables to zero or BigM-scaled */\n  if(((lp->simplex_mode & SIMPLEX_Phase1_PRIMAL) != 0) && (abs(lp->P1extraDim) > 0)) {\n#ifndef Phase1EliminateRedundant\n    if(lp->P1extraDim < 0) {\n      if(index > lp->sum + lp->P1extraDim)\n        accept = FALSE;\n    }\n    else\n#endif\n    if((index <= lp->sum - lp->P1extraDim) || (mult == 0)) {\n      if((mult == 0) || (lp->bigM == 0))\n        accept = FALSE;\n      else\n        (*ofValue) /= lp->bigM;\n    }\n  }\n\n  /* Dual simplex: Subtract P1extraVal from objective function values */\n  else if(((lp->simplex_mode & SIMPLEX_Phase1_DUAL) != 0) && (index > lp->rows)) {\n#if 1  /* This may help increase sparsity of the (extended) basis matrix;\n         Can it introduce degeneracy in some cases? */\n    if((lp->P1extraVal != 0) && (lp->orig_obj[index - lp->rows] > 0))\n      *ofValue = 0;\n    else\n#endif\n    {\n      *ofValue -= lp->P1extraVal;\n#if 0\n      if(is_action(lp->anti_degen, ANTIDEGEN_RHSPERTURB))\n        *ofValue -= rand_uniform(lp, lp->epsperturb);\n#endif\n    }\n  }\n\n  /* Do scaling and test for zero */\n  if(accept) {\n    (*ofValue) *= mult;\n    if(fabs(*ofValue) < lp->epsmachine) {\n      (*ofValue) = 0;\n      accept = FALSE;\n    }\n  }\n  else\n    (*ofValue) = 0;\n\n  return( accept );\n}\n\nSTATIC void set_OF_p1extra(lprec *lp, REAL p1extra)\n{\n  int  i;\n  REAL *value;\n\n  if(lp->spx_trace)\n    report(lp, DETAILED, \"set_OF_p1extra: Set dual objective offset to %g at iter %.0f.\\n\",\n                          p1extra, (double) get_total_iter(lp));\n  lp->P1extraVal = p1extra;\n  if(lp->obj == NULL)\n    allocREAL(lp, &lp->obj, lp->columns_alloc+1, TRUE);\n  for(i = 1, value = lp->obj+1; i <= lp->columns; i++, value++) {\n    *value = lp->orig_obj[i];\n    modifyOF1(lp, lp->rows + i, value, 1.0);\n  }\n}\n\nSTATIC void unset_OF_p1extra(lprec *lp)\n{\n  lp->P1extraVal = 0;\n  FREE(lp->obj);\n}\n\nREAL __WINAPI get_OF_active(lprec *lp, int varnr, REAL mult)\n{\n  int  colnr = varnr - lp->rows;\n  REAL holdOF = 0;\n\n#ifdef Paranoia\n  if((colnr <= 0) || (colnr > lp->columns)) {\n    report(lp, SEVERE, \"get_OF_active: Invalid column index %d supplied\\n\", colnr);\n  }\n  else\n#endif\n  if(lp->obj == NULL) {\n    if(colnr > 0)\n      holdOF = lp->orig_obj[colnr];\n    modifyOF1(lp, varnr, &holdOF, mult);\n  }\n  else if(colnr > 0)\n    holdOF = lp->obj[colnr] * mult;\n\n  return( holdOF );\n}\n\nSTATIC MYBOOL is_OF_nz(lprec *lp, int colnr)\n{\n  return( (MYBOOL) (lp->orig_obj[colnr] != 0) );\n}\n\nSTATIC int singleton_column(lprec *lp, int row_nr, REAL *column, int *nzlist, REAL value, int *maxabs)\n{\n  int nz = 1;\n\n  if(nzlist == NULL) {\n    MEMCLEAR(column, lp->rows + 1);\n    column[row_nr] = value;\n  }\n  else {\n    column[nz] = value;\n    nzlist[nz] = row_nr;\n  }\n\n  if(maxabs != NULL)\n    *maxabs = row_nr;\n  return( nz );\n}\n\nSTATIC int expand_column(lprec *lp, int col_nr, REAL *column, int *nzlist, REAL mult, int *maxabs)\n{\n  int     i, ie, j, maxidx, nzcount;\n  REAL    value, maxval;\n  MATrec  *mat = lp->matA;\n  REAL    *matValue;\n  int     *matRownr;\n\n  /* Retrieve a column from the user data matrix A */\n  maxval = 0;\n  maxidx = -1;\n  if(nzlist == NULL) {\n    MEMCLEAR(column, lp->rows + 1);\n    i  = mat->col_end[col_nr - 1];\n    ie = mat->col_end[col_nr];\n    matRownr = &COL_MAT_ROWNR(i);\n    matValue = &COL_MAT_VALUE(i);\n    nzcount = i;\n    for(; i < ie;\n        i++, matRownr += matRowColStep, matValue += matValueStep) {\n      j = *matRownr;\n      value = *matValue;\n      if(j > 0) {\n        value *= mult;\n        if(fabs(value) > maxval) {\n          maxval = fabs(value);\n          maxidx = j;\n        }\n      }\n      column[j] = value;\n    }\n    nzcount = i - nzcount;\n\n    /* Get the objective as row 0, optionally adjusting the objective for phase 1 */\n    if(lp->obj_in_basis) {\n      column[0] = get_OF_active(lp, lp->rows+col_nr, mult);\n      if(column[0] != 0)\n        nzcount++;\n    }\n  }\n  else {\n    nzcount = 0;\n\n    /* Get the objective as row 0, optionally adjusting the objective for phase 1 */\n    if(lp->obj_in_basis) {\n      value = get_OF_active(lp, lp->rows+col_nr, mult);\n      if(value != 0) {\n        nzcount++;\n        nzlist[nzcount] = 0;\n        column[nzcount] = value;\n      }\n    }\n\n    /* Loop over the non-zero column entries */\n    i  = mat->col_end[col_nr - 1];\n    ie = mat->col_end[col_nr];\n    matRownr = &COL_MAT_ROWNR(i);\n    matValue = &COL_MAT_VALUE(i);\n    for(; i < ie;\n        i++, matRownr += matRowColStep, matValue += matValueStep) {\n      j = *matRownr;\n      value = (*matValue) * mult;\n      nzcount++;\n      nzlist[nzcount] = j;\n      column[nzcount] = value;\n      if(fabs(value) > maxval) {\n        maxval = fabs(value);\n        maxidx = nzcount;\n      }\n    }\n  }\n\n  if(maxabs != NULL)\n    *maxabs = maxidx;\n  return( nzcount );\n}\n\n\n/* Retrieve a column vector from the data matrix [1..rows, rows+1..rows+columns];\n   needs __WINAPI call model since it may be called from BFPs */\nint __WINAPI obtain_column(lprec *lp, int varin, REAL *pcol, int *nzlist, int *maxabs)\n{\n  REAL value = my_chsign(lp->is_lower[varin], -1);\n  if(varin > lp->rows) {\n    varin -= lp->rows;\n    varin = expand_column(lp, varin, pcol, nzlist, value, maxabs);\n  }\n  else if(lp->obj_in_basis || (varin > 0))\n    varin = singleton_column(lp, varin, pcol, nzlist, value, maxabs);\n  else\n    varin = get_basisOF(lp, NULL, pcol, nzlist);\n\n  return(varin);\n}\n\n/* GENERAL INVARIANT CALLBACK FUNCTIONS */\nMYBOOL set_callbacks(lprec *lp)\n{\n  /* Assign API functions to lp structure (mainly for XLIs) */\n  lp->add_column              = add_column;\n  lp->add_columnex            = add_columnex;\n  lp->add_constraint          = add_constraint;\n  lp->add_constraintex        = add_constraintex;\n  lp->add_lag_con             = add_lag_con;\n  lp->add_SOS                 = add_SOS;\n  lp->column_in_lp            = column_in_lp;\n  lp->copy_lp                 = copy_lp;\n  lp->default_basis           = default_basis;\n  lp->del_column              = del_column;\n  lp->del_constraint          = del_constraint;\n  lp->delete_lp               = delete_lp;\n  lp->dualize_lp              = dualize_lp;\n  lp->free_lp                 = free_lp;\n  lp->get_anti_degen          = get_anti_degen;\n  lp->get_basis               = get_basis;\n  lp->get_basiscrash          = get_basiscrash;\n  lp->get_bb_depthlimit       = get_bb_depthlimit;\n  lp->get_bb_floorfirst       = get_bb_floorfirst;\n  lp->get_bb_rule             = get_bb_rule;\n  lp->get_bounds_tighter      = get_bounds_tighter;\n  lp->get_break_at_value      = get_break_at_value;\n  lp->get_col_name            = get_col_name;\n  lp->get_columnex            = get_columnex;\n  lp->get_constr_type         = get_constr_type;\n  lp->get_constr_value        = get_constr_value;\n  lp->get_constraints         = get_constraints;\n  lp->get_dual_solution       = get_dual_solution;\n  lp->get_epsb                = get_epsb;\n  lp->get_epsd                = get_epsd;\n  lp->get_epsel               = get_epsel;\n  lp->get_epsint              = get_epsint;\n  lp->get_epsperturb          = get_epsperturb;\n  lp->get_epspivot            = get_epspivot;\n  lp->get_improve             = get_improve;\n  lp->get_infinite            = get_infinite;\n  lp->get_lambda              = get_lambda;\n  lp->get_lowbo               = get_lowbo;\n  lp->get_lp_index            = get_lp_index;\n  lp->get_lp_name             = get_lp_name;\n  lp->get_Lrows               = get_Lrows;\n  lp->get_mat                 = get_mat;\n  lp->get_mat_byindex         = get_mat_byindex;\n  lp->get_max_level           = get_max_level;\n  lp->get_maxpivot            = get_maxpivot;\n  lp->get_mip_gap             = get_mip_gap;\n  lp->get_multiprice          = get_multiprice;\n  lp->get_nameindex           = get_nameindex;\n  lp->get_Ncolumns            = get_Ncolumns;\n  lp->get_negrange            = get_negrange;\n  lp->get_nonzeros            = get_nonzeros;\n  lp->get_Norig_columns       = get_Norig_columns;\n  lp->get_Norig_rows          = get_Norig_rows;\n  lp->get_Nrows               = get_Nrows;\n  lp->get_obj_bound           = get_obj_bound;\n  lp->get_objective           = get_objective;\n  lp->get_orig_index          = get_orig_index;\n  lp->get_origcol_name        = get_origcol_name;\n  lp->get_origrow_name        = get_origrow_name;\n  lp->get_partialprice        = get_partialprice;\n  lp->get_pivoting            = get_pivoting;\n  lp->get_presolve            = get_presolve;\n  lp->get_presolveloops       = get_presolveloops;\n  lp->get_primal_solution     = get_primal_solution;\n  lp->get_print_sol           = get_print_sol;\n  lp->get_pseudocosts         = get_pseudocosts;\n  lp->get_ptr_constraints     = get_ptr_constraints;\n  lp->get_ptr_dual_solution   = get_ptr_dual_solution;\n  lp->get_ptr_lambda          = get_ptr_lambda;\n  lp->get_ptr_primal_solution = get_ptr_primal_solution;\n  lp->get_ptr_sensitivity_obj = get_ptr_sensitivity_obj;\n  lp->get_ptr_sensitivity_objex = get_ptr_sensitivity_objex;\n  lp->get_ptr_sensitivity_rhs = get_ptr_sensitivity_rhs;\n  lp->get_ptr_variables       = get_ptr_variables;\n  lp->get_rh                  = get_rh;\n  lp->get_rh_range            = get_rh_range;\n  lp->get_row                 = get_row;\n  lp->get_rowex               = get_rowex;\n  lp->get_row_name            = get_row_name;\n  lp->get_scalelimit          = get_scalelimit;\n  lp->get_scaling             = get_scaling;\n  lp->get_sensitivity_obj     = get_sensitivity_obj;\n  lp->get_sensitivity_objex   = get_sensitivity_objex;\n  lp->get_sensitivity_rhs     = get_sensitivity_rhs;\n  lp->get_simplextype         = get_simplextype;\n  lp->get_solutioncount       = get_solutioncount;\n  lp->get_solutionlimit       = get_solutionlimit;\n  lp->get_status              = get_status;\n  lp->get_statustext          = get_statustext;\n  lp->get_timeout             = get_timeout;\n  lp->get_total_iter          = get_total_iter;\n  lp->get_total_nodes         = get_total_nodes;\n  lp->get_upbo                = get_upbo;\n  lp->get_var_branch          = get_var_branch;\n  lp->get_var_dualresult      = get_var_dualresult;\n  lp->get_var_primalresult    = get_var_primalresult;\n  lp->get_var_priority        = get_var_priority;\n  lp->get_variables           = get_variables;\n  lp->get_verbose             = get_verbose;\n  lp->get_working_objective   = get_working_objective;\n  lp->has_BFP                 = has_BFP;\n  lp->has_XLI                 = has_XLI;\n  lp->is_add_rowmode          = is_add_rowmode;\n  lp->is_anti_degen           = is_anti_degen;\n  lp->is_binary               = is_binary;\n  lp->is_break_at_first       = is_break_at_first;\n  lp->is_constr_type          = is_constr_type;\n  lp->is_debug                = is_debug;\n  lp->is_feasible             = is_feasible;\n  lp->is_unbounded            = is_unbounded;\n  lp->is_infinite             = is_infinite;\n  lp->is_int                  = is_int;\n  lp->is_integerscaling       = is_integerscaling;\n  lp->is_lag_trace            = is_lag_trace;\n  lp->is_maxim                = is_maxim;\n  lp->is_nativeBFP            = is_nativeBFP;\n  lp->is_nativeXLI            = is_nativeXLI;\n  lp->is_negative             = is_negative;\n  lp->is_obj_in_basis         = is_obj_in_basis;\n  lp->is_piv_mode             = is_piv_mode;\n  lp->is_piv_rule             = is_piv_rule;\n  lp->is_presolve             = is_presolve;\n  lp->is_scalemode            = is_scalemode;\n  lp->is_scaletype            = is_scaletype;\n  lp->is_semicont             = is_semicont;\n  lp->is_SOS_var              = is_SOS_var;\n  lp->is_trace                = is_trace;\n  lp->lp_solve_version        = lp_solve_version;\n  lp->make_lp                 = make_lp;\n  lp->print_constraints       = print_constraints;\n  lp->print_debugdump         = print_debugdump;\n  lp->print_duals             = print_duals;\n  lp->print_lp                = print_lp;\n  lp->print_objective         = print_objective;\n  lp->print_scales            = print_scales;\n  lp->print_solution          = print_solution;\n  lp->print_str               = print_str;\n  lp->print_tableau           = print_tableau;\n  lp->put_abortfunc           = put_abortfunc;\n  lp->put_bb_nodefunc         = put_bb_nodefunc;\n  lp->put_bb_branchfunc       = put_bb_branchfunc;\n  lp->put_logfunc             = put_logfunc;\n  lp->put_msgfunc             = put_msgfunc;\n  lp->read_LP                 = read_LP;\n  lp->read_MPS                = read_MPS;\n  lp->read_XLI                = read_XLI;\n  lp->read_basis              = read_basis;\n  lp->reset_basis             = reset_basis;\n  lp->read_params             = read_params;\n  lp->reset_params            = reset_params;\n  lp->resize_lp               = resize_lp;\n  lp->set_action              = set_action;\n  lp->set_add_rowmode         = set_add_rowmode;\n  lp->set_anti_degen          = set_anti_degen;\n  lp->set_basisvar            = set_basisvar;\n  lp->set_basis               = set_basis;\n  lp->set_basiscrash          = set_basiscrash;\n  lp->set_bb_depthlimit       = set_bb_depthlimit;\n  lp->set_bb_floorfirst       = set_bb_floorfirst;\n  lp->set_bb_rule             = set_bb_rule;\n  lp->set_BFP                 = set_BFP;\n  lp->set_binary              = set_binary;\n  lp->set_bounds              = set_bounds;\n  lp->set_bounds_tighter      = set_bounds_tighter;\n  lp->set_break_at_first      = set_break_at_first;\n  lp->set_break_at_value      = set_break_at_value;\n  lp->set_col_name            = set_col_name;\n  lp->set_constr_type         = set_constr_type;\n  lp->set_debug               = set_debug;\n  lp->set_epsb                = set_epsb;\n  lp->set_epsd                = set_epsd;\n  lp->set_epsel               = set_epsel;\n  lp->set_epsint              = set_epsint;\n  lp->set_epslevel            = set_epslevel;\n  lp->set_epsperturb          = set_epsperturb;\n  lp->set_epspivot            = set_epspivot;\n  lp->set_unbounded           = set_unbounded;\n  lp->set_improve             = set_improve;\n  lp->set_infinite            = set_infinite;\n  lp->set_int                 = set_int;\n  lp->set_lag_trace           = set_lag_trace;\n  lp->set_lowbo               = set_lowbo;\n  lp->set_lp_name             = set_lp_name;\n  lp->set_mat                 = set_mat;\n  lp->set_maxim               = set_maxim;\n  lp->set_maxpivot            = set_maxpivot;\n  lp->set_minim               = set_minim;\n  lp->set_mip_gap             = set_mip_gap;\n  lp->set_multiprice          = set_multiprice;\n  lp->set_negrange            = set_negrange;\n  lp->set_obj                 = set_obj;\n  lp->set_obj_bound           = set_obj_bound;\n  lp->set_obj_fn              = set_obj_fn;\n  lp->set_obj_fnex            = set_obj_fnex;\n  lp->set_obj_in_basis        = set_obj_in_basis;\n  lp->set_outputfile          = set_outputfile;\n  lp->set_outputstream        = set_outputstream;\n  lp->set_partialprice        = set_partialprice;\n  lp->set_pivoting            = set_pivoting;\n  lp->set_preferdual          = set_preferdual;\n  lp->set_presolve            = set_presolve;\n  lp->set_print_sol           = set_print_sol;\n  lp->set_pseudocosts         = set_pseudocosts;\n  lp->set_rh                  = set_rh;\n  lp->set_rh_range            = set_rh_range;\n  lp->set_rh_vec              = set_rh_vec;\n  lp->set_row                 = set_row;\n  lp->set_rowex               = set_rowex;\n  lp->set_row_name            = set_row_name;\n  lp->set_scalelimit          = set_scalelimit;\n  lp->set_scaling             = set_scaling;\n  lp->set_semicont            = set_semicont;\n  lp->set_sense               = set_sense;\n  lp->set_simplextype         = set_simplextype;\n  lp->set_solutionlimit       = set_solutionlimit;\n  lp->set_timeout             = set_timeout;\n  lp->set_trace               = set_trace;\n  lp->set_upbo                = set_upbo;\n  lp->set_var_branch          = set_var_branch;\n  lp->set_var_weights         = set_var_weights;\n  lp->set_verbose             = set_verbose;\n  lp->set_XLI                 = set_XLI;\n  lp->solve                   = solve;\n  lp->str_add_column          = str_add_column;\n  lp->str_add_constraint      = str_add_constraint;\n  lp->str_add_lag_con         = str_add_lag_con;\n  lp->str_set_obj_fn          = str_set_obj_fn;\n  lp->str_set_rh_vec          = str_set_rh_vec;\n  lp->time_elapsed            = time_elapsed;\n  lp->unscale                 = unscale;\n  lp->write_lp                = write_lp;\n  lp->write_LP                = write_LP;\n  lp->write_mps               = write_mps;\n  lp->write_freemps           = write_freemps;\n  lp->write_MPS               = write_MPS;\n  lp->write_freeMPS           = write_freeMPS;\n  lp->write_XLI               = write_XLI;\n  lp->write_basis             = write_basis;\n  lp->write_params            = write_params;\n\n  /* Utility functions (mainly for BFPs) */\n  lp->userabort               = userabort;\n  lp->report                  = report;\n  lp->explain                 = explain;\n  lp->set_basisvar            = set_basisvar;\n  lp->get_lpcolumn            = obtain_column;\n  lp->get_basiscolumn         = get_basiscolumn;\n  lp->get_OF_active           = get_OF_active;\n  lp->getMDO                  = getMDO;\n  lp->invert                  = invert;\n  lp->set_action              = set_action;\n  lp->clear_action            = clear_action;\n  lp->is_action               = is_action;\n\n  return( TRUE );\n}\n\n/* SUPPORT FUNCTION FOR BASIS FACTORIZATION PACKAGES */\nMYBOOL __WINAPI has_BFP(lprec *lp)\n{\n  return( is_nativeBFP(lp)\n#if LoadInverseLib == TRUE\n       || (MYBOOL) (lp->hBFP != NULL)\n#endif\n        );\n}\n\nMYBOOL __WINAPI is_nativeBFP(lprec *lp)\n{\n#ifdef ExcludeNativeInverse\n  return( FALSE );\n#elif LoadInverseLib == TRUE\n  return( (MYBOOL) (lp->hBFP == NULL) );\n#else\n  return( TRUE );\n#endif\n}\n\nMYBOOL __WINAPI set_BFP(lprec *lp, const char *filename)\n/* (Re)mapping of basis factorization variant methods is done here */\n{\n  int result = LIB_LOADED;\n\n  /* Release the BFP and basis if we are active */\n  if(lp->invB != NULL)\n    bfp_free(lp);\n\n#if LoadInverseLib == TRUE\n  if(lp->hBFP != NULL) {\n  #ifdef WIN32\n    FreeLibrary(lp->hBFP);\n  #else\n    dlclose(lp->hBFP);\n  #endif\n    lp->hBFP = NULL;\n  }\n#endif\n\n  if(filename == NULL) {\n    if(!is_nativeBFP(lp))\n      return( FALSE );\n#ifndef ExcludeNativeInverse\n    lp->bfp_name = bfp_name;\n    lp->bfp_compatible = bfp_compatible;\n    lp->bfp_free = bfp_free;\n    lp->bfp_resize = bfp_resize;\n    lp->bfp_nonzeros = bfp_nonzeros;\n    lp->bfp_memallocated = bfp_memallocated;\n    lp->bfp_restart = bfp_restart;\n    lp->bfp_mustrefactorize = bfp_mustrefactorize;\n    lp->bfp_preparefactorization = bfp_preparefactorization;\n    lp->bfp_factorize = bfp_factorize;\n    lp->bfp_finishupdate = bfp_finishupdate;\n    lp->bfp_ftran_normal = bfp_ftran_normal;\n    lp->bfp_ftran_prepare = bfp_ftran_prepare;\n    lp->bfp_btran_normal = bfp_btran_normal;\n    lp->bfp_status = bfp_status;\n    lp->bfp_implicitslack = bfp_implicitslack;\n    lp->bfp_indexbase = bfp_indexbase;\n    lp->bfp_rowoffset = bfp_rowoffset;\n    lp->bfp_pivotmax = bfp_pivotmax;\n    lp->bfp_init = bfp_init;\n    lp->bfp_pivotalloc = bfp_pivotalloc;\n    lp->bfp_colcount = bfp_colcount;\n    lp->bfp_canresetbasis = bfp_canresetbasis;\n    lp->bfp_finishfactorization = bfp_finishfactorization;\n    lp->bfp_updaterefactstats = bfp_updaterefactstats;\n    lp->bfp_prepareupdate = bfp_prepareupdate;\n    lp->bfp_pivotRHS = bfp_pivotRHS;\n    lp->bfp_btran_double = bfp_btran_double;\n    lp->bfp_efficiency = bfp_efficiency;\n    lp->bfp_pivotvector = bfp_pivotvector;\n    lp->bfp_pivotcount = bfp_pivotcount;\n    lp->bfp_refactcount = bfp_refactcount;\n    lp->bfp_isSetI = bfp_isSetI;\n    lp->bfp_findredundant = bfp_findredundant;\n#endif\n  }\n  else {\n#if LoadInverseLib == TRUE\n  #ifdef WIN32\n   /* Get a handle to the Windows DLL module. */\n    lp->hBFP = LoadLibrary(filename);\n\n   /* If the handle is valid, try to get the function addresses. */\n    if(lp->hBFP != NULL) {\n      lp->bfp_compatible           = (BFPbool_lpintintint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_compatible\");\n      if(lp->bfp_compatible == NULL)\n        result = LIB_NOINFO;\n      else if(lp->bfp_compatible(lp, BFPVERSION, MAJORVERSION, sizeof(REAL))) {\n\n      lp->bfp_name                 = (BFPchar *)\n                                      GetProcAddress(lp->hBFP, \"bfp_name\");\n      lp->bfp_free                 = (BFP_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_free\");\n      lp->bfp_resize               = (BFPbool_lpint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_resize\");\n      lp->bfp_nonzeros             = (BFPint_lpbool *)\n                                      GetProcAddress(lp->hBFP, \"bfp_nonzeros\");\n      lp->bfp_memallocated         = (BFPint_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_memallocated\");\n      lp->bfp_restart              = (BFPbool_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_restart\");\n      lp->bfp_mustrefactorize      = (BFPbool_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_mustrefactorize\");\n      lp->bfp_preparefactorization = (BFPint_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_preparefactorization\");\n      lp->bfp_factorize            = (BFPint_lpintintboolbool *)\n                                      GetProcAddress(lp->hBFP, \"bfp_factorize\");\n      lp->bfp_finishupdate         = (BFPbool_lpbool *)\n                                      GetProcAddress(lp->hBFP, \"bfp_finishupdate\");\n      lp->bfp_ftran_normal         = (BFP_lprealint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_ftran_normal\");\n      lp->bfp_ftran_prepare        = (BFP_lprealint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_ftran_prepare\");\n      lp->bfp_btran_normal         = (BFP_lprealint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_btran_normal\");\n      lp->bfp_status               = (BFPint_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_status\");\n      lp->bfp_implicitslack        = (BFPbool_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_implicitslack\");\n      lp->bfp_indexbase            = (BFPint_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_indexbase\");\n      lp->bfp_rowoffset            = (BFPint_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_rowoffset\");\n      lp->bfp_pivotmax             = (BFPint_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_pivotmax\");\n      lp->bfp_init                 = (BFPbool_lpintintchar *)\n                                      GetProcAddress(lp->hBFP, \"bfp_init\");\n      lp->bfp_pivotalloc           = (BFPbool_lpint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_pivotalloc\");\n      lp->bfp_colcount             = (BFPint_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_colcount\");\n      lp->bfp_canresetbasis        = (BFPbool_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_canresetbasis\");\n      lp->bfp_finishfactorization  = (BFP_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_finishfactorization\");\n      lp->bfp_updaterefactstats    = (BFP_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_updaterefactstats\");\n      lp->bfp_prepareupdate        = (BFPlreal_lpintintreal *)\n                                      GetProcAddress(lp->hBFP, \"bfp_prepareupdate\");\n      lp->bfp_pivotRHS             = (BFPreal_lplrealreal *)\n                                      GetProcAddress(lp->hBFP, \"bfp_pivotRHS\");\n      lp->bfp_btran_double         = (BFP_lprealintrealint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_btran_double\");\n      lp->bfp_efficiency           = (BFPreal_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_efficiency\");\n      lp->bfp_pivotvector          = (BFPrealp_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_pivotvector\");\n      lp->bfp_pivotcount           = (BFPint_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_pivotcount\");\n      lp->bfp_refactcount          = (BFPint_lpint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_refactcount\");\n      lp->bfp_isSetI               = (BFPbool_lp *)\n                                      GetProcAddress(lp->hBFP, \"bfp_isSetI\");\n      lp->bfp_findredundant        = (BFPint_lpintrealcbintint *)\n                                      GetProcAddress(lp->hBFP, \"bfp_findredundant\");\n      }\n      else\n        result = LIB_VERINVALID;\n    }\n  #else\n   /* First standardize UNIX .SO library name format. */\n    char bfpname[260];\n    const char *ptr;\n\n    strcpy(bfpname, filename);\n    if((ptr = strrchr(filename, '/')) == NULL)\n      ptr = filename;\n    else\n      ptr++;\n    bfpname[(int) (ptr - filename)] = 0;\n    if(strncmp(ptr, \"lib\", 3))\n      strcat(bfpname, \"lib\");\n    strcat(bfpname, ptr);\n    if(strcmp(bfpname + strlen(bfpname) - 3, \".so\"))\n      strcat(bfpname, \".so\");\n\n   /* Get a handle to the module. */\n    lp->hBFP = dlopen(bfpname, RTLD_LAZY);\n\n   /* If the handle is valid, try to get the function addresses. */\n    if(lp->hBFP != NULL) {\n      lp->bfp_compatible           = (BFPbool_lpintintint *)\n                                      dlsym(lp->hBFP, \"bfp_compatible\");\n      if(lp->bfp_compatible == NULL)\n        result = LIB_NOINFO;\n      else if(lp->bfp_compatible(lp, BFPVERSION, MAJORVERSION, sizeof(REAL))) {\n\n      lp->bfp_name                 = (BFPchar *)\n                                      dlsym(lp->hBFP, \"bfp_name\");\n      lp->bfp_free                 = (BFP_lp *)\n                                      dlsym(lp->hBFP, \"bfp_free\");\n      lp->bfp_resize               = (BFPbool_lpint *)\n                                      dlsym(lp->hBFP, \"bfp_resize\");\n      lp->bfp_nonzeros             = (BFPint_lpbool *)\n                                      dlsym(lp->hBFP, \"bfp_nonzeros\");\n      lp->bfp_memallocated         = (BFPint_lp *)\n                                      dlsym(lp->hBFP, \"bfp_memallocated\");\n      lp->bfp_restart              = (BFPbool_lp *)\n                                      dlsym(lp->hBFP, \"bfp_restart\");\n      lp->bfp_mustrefactorize      = (BFPbool_lp *)\n                                      dlsym(lp->hBFP, \"bfp_mustrefactorize\");\n      lp->bfp_preparefactorization = (BFPint_lp *)\n                                      dlsym(lp->hBFP, \"bfp_preparefactorization\");\n      lp->bfp_factorize            = (BFPint_lpintintboolbool *)\n                                      dlsym(lp->hBFP, \"bfp_factorize\");\n      lp->bfp_finishupdate         = (BFPbool_lpbool *)\n                                      dlsym(lp->hBFP, \"bfp_finishupdate\");\n      lp->bfp_ftran_normal         = (BFP_lprealint *)\n                                      dlsym(lp->hBFP, \"bfp_ftran_normal\");\n      lp->bfp_ftran_prepare        = (BFP_lprealint *)\n                                      dlsym(lp->hBFP, \"bfp_ftran_prepare\");\n      lp->bfp_btran_normal         = (BFP_lprealint *)\n                                      dlsym(lp->hBFP, \"bfp_btran_normal\");\n      lp->bfp_status               = (BFPint_lp *)\n                                      dlsym(lp->hBFP, \"bfp_status\");\n      lp->bfp_implicitslack        = (BFPbool_lp *)\n                                      dlsym(lp->hBFP, \"bfp_implicitslack\");\n      lp->bfp_indexbase            = (BFPint_lp *)\n                                      dlsym(lp->hBFP, \"bfp_indexbase\");\n      lp->bfp_rowoffset            = (BFPint_lp *)\n                                      dlsym(lp->hBFP, \"bfp_rowoffset\");\n      lp->bfp_pivotmax             = (BFPint_lp *)\n                                      dlsym(lp->hBFP, \"bfp_pivotmax\");\n      lp->bfp_init                 = (BFPbool_lpintintchar *)\n                                      dlsym(lp->hBFP, \"bfp_init\");\n      lp->bfp_pivotalloc           = (BFPbool_lpint *)\n                                      dlsym(lp->hBFP, \"bfp_pivotalloc\");\n      lp->bfp_colcount             = (BFPint_lp *)\n                                      dlsym(lp->hBFP, \"bfp_colcount\");\n      lp->bfp_canresetbasis        = (BFPbool_lp *)\n                                      dlsym(lp->hBFP, \"bfp_canresetbasis\");\n      lp->bfp_finishfactorization  = (BFP_lp *)\n                                      dlsym(lp->hBFP, \"bfp_finishfactorization\");\n      lp->bfp_updaterefactstats    = (BFP_lp *)\n                                      dlsym(lp->hBFP, \"bfp_updaterefactstats\");\n      lp->bfp_prepareupdate        = (BFPlreal_lpintintreal *)\n                                      dlsym(lp->hBFP, \"bfp_prepareupdate\");\n      lp->bfp_pivotRHS             = (BFPreal_lplrealreal *)\n                                      dlsym(lp->hBFP, \"bfp_pivotRHS\");\n      lp->bfp_btran_double         = (BFP_lprealintrealint *)\n                                      dlsym(lp->hBFP, \"bfp_btran_double\");\n      lp->bfp_efficiency           = (BFPreal_lp *)\n                                      dlsym(lp->hBFP, \"bfp_efficiency\");\n      lp->bfp_pivotvector          = (BFPrealp_lp *)\n                                      dlsym(lp->hBFP, \"bfp_pivotvector\");\n      lp->bfp_pivotcount           = (BFPint_lp *)\n                                      dlsym(lp->hBFP, \"bfp_pivotcount\");\n      lp->bfp_refactcount          = (BFPint_lpint *)\n                                      dlsym(lp->hBFP, \"bfp_refactcount\");\n      lp->bfp_isSetI               = (BFPbool_lp *)\n                                      dlsym(lp->hBFP, \"bfp_isSetI\");\n      lp->bfp_findredundant        = (BFPint_lpintrealcbintint *)\n                                      dlsym(lp->hBFP, \"bfp_findredundant\");\n      }\n      else\n        result = LIB_VERINVALID;\n    }\n  #endif\n    else\n      result = LIB_NOTFOUND;\n#endif\n    /* Do validation */\n    if((result != LIB_LOADED) ||\n       ((lp->bfp_name == NULL) ||\n        (lp->bfp_compatible == NULL) ||\n        (lp->bfp_free == NULL) ||\n        (lp->bfp_resize == NULL) ||\n        (lp->bfp_nonzeros == NULL) ||\n        (lp->bfp_memallocated == NULL) ||\n        (lp->bfp_restart == NULL) ||\n        (lp->bfp_mustrefactorize == NULL) ||\n        (lp->bfp_preparefactorization == NULL) ||\n        (lp->bfp_factorize == NULL) ||\n        (lp->bfp_finishupdate == NULL) ||\n        (lp->bfp_ftran_normal == NULL) ||\n        (lp->bfp_ftran_prepare == NULL) ||\n        (lp->bfp_btran_normal == NULL) ||\n        (lp->bfp_status == NULL) ||\n        (lp->bfp_implicitslack == NULL) ||\n        (lp->bfp_indexbase == NULL) ||\n        (lp->bfp_rowoffset == NULL) ||\n        (lp->bfp_pivotmax == NULL) ||\n        (lp->bfp_init == NULL) ||\n        (lp->bfp_pivotalloc == NULL) ||\n        (lp->bfp_colcount == NULL) ||\n        (lp->bfp_canresetbasis == NULL) ||\n        (lp->bfp_finishfactorization == NULL) ||\n        (lp->bfp_updaterefactstats == NULL) ||\n        (lp->bfp_prepareupdate == NULL) ||\n        (lp->bfp_pivotRHS == NULL) ||\n        (lp->bfp_btran_double == NULL) ||\n        (lp->bfp_efficiency == NULL) ||\n        (lp->bfp_pivotvector == NULL) ||\n        (lp->bfp_pivotcount == NULL) ||\n        (lp->bfp_refactcount == NULL) ||\n        (lp->bfp_isSetI == NULL) ||\n        (lp->bfp_findredundant == NULL)\n       )) {\n      set_BFP(lp, NULL);\n      if(result == LIB_LOADED)\n        result = LIB_NOFUNCTION;\n    }\n  }\n  if(filename != NULL) {\n    char info[LIB_STR_MAXLEN+1];\n    switch(result) {\n      case LIB_NOTFOUND:   strcpy(info, LIB_STR_NOTFOUND);\n                           break;\n      case LIB_NOINFO:     strcpy(info, LIB_STR_NOINFO);\n                           break;\n      case LIB_NOFUNCTION: strcpy(info, LIB_STR_NOFUNCTION);\n                           break;\n      case LIB_VERINVALID: strcpy(info, LIB_STR_VERINVALID);\n                           break;\n      default:             strcpy(info, LIB_STR_LOADED);\n    }\n    report(lp, IMPORTANT, \"set_BFP: %s '%s'\\n\",\n                          info, filename);\n  }\n  return( (MYBOOL) (result == LIB_LOADED));\n}\n\n\n/* External language interface routines */\n/* DON'T MODIFY */\nlprec * __WINAPI read_XLI(char *xliname, const char *modelname, const char *dataname, const char *options, int verbose)\n{\n  lprec *lp;\n\n  lp = make_lp(0, 0);\n  if(lp != NULL) {\n    lp->source_is_file = TRUE;\n    lp->verbose = verbose;\n    if(!set_XLI(lp, xliname)) {\n      free_lp(&lp);\n      printf(\"read_XLI: No valid XLI package selected or available.\\n\");\n    }\n    else {\n      if(!lp->xli_readmodel(lp, modelname, (dataname != NULL) && (*dataname != 0) ? dataname : NULL, options, verbose))\n        free_lp(&lp);\n    }\n  }\n  return( lp );\n}\n\nMYBOOL __WINAPI write_XLI(lprec *lp, const char *filename, const char *options, MYBOOL results)\n{\n  return( has_XLI(lp) && mat_validate(lp->matA) && lp->xli_writemodel(lp, filename, options, results) );\n}\n\nMYBOOL __WINAPI has_XLI(lprec *lp)\n{\n  return( is_nativeXLI(lp)\n#if LoadLanguageLib == TRUE\n       || (MYBOOL) (lp->hXLI != NULL)\n#endif\n        );\n}\n\nMYBOOL __WINAPI is_nativeXLI(lprec *lp)\n{\n  (void)lp;\n#ifdef ExcludeNativeLanguage\n  return( FALSE );\n#elif LoadLanguageLib == TRUE\n  return( (MYBOOL) (lp->hXLI == NULL) );\n#else\n  return( TRUE );\n#endif\n}\n\nMYBOOL __WINAPI set_XLI(lprec *lp, const char *filename)\n/* (Re)mapping of external language interface variant methods is done here */\n{\n  int result = LIB_LOADED;\n\n#if LoadLanguageLib == TRUE\n  if(lp->hXLI != NULL) {\n  #ifdef WIN32\n    FreeLibrary(lp->hXLI);\n  #else\n    dlclose(lp->hXLI);\n  #endif\n    lp->hXLI = NULL;\n  }\n#endif\n\n  if(filename == NULL) {\n    if(!is_nativeXLI(lp))\n      return( FALSE );\n#ifndef ExcludeNativeLanguage\n    lp->xli_name = xli_name;\n    lp->xli_compatible = xli_compatible;\n    lp->xli_readmodel = xli_readmodel;\n    lp->xli_writemodel = xli_writemodel;\n#endif\n  }\n  else {\n#if LoadLanguageLib == TRUE\n  #ifdef WIN32\n   /* Get a handle to the Windows DLL module. */\n    lp->hXLI = LoadLibrary(filename);\n\n   /* If the handle is valid, try to get the function addresses. */\n    if(lp->hXLI != NULL) {\n      lp->xli_compatible           = (XLIbool_lpintintint *)\n                                      GetProcAddress(lp->hXLI, \"xli_compatible\");\n      if(lp->xli_compatible == NULL)\n        result = LIB_NOINFO;\n      else if(lp->xli_compatible(lp, XLIVERSION, MAJORVERSION, sizeof(REAL))) {\n\n        lp->xli_name                 = (XLIchar *)\n                                        GetProcAddress(lp->hXLI, \"xli_name\");\n        lp->xli_readmodel            = (XLIbool_lpcharcharcharint *)\n                                        GetProcAddress(lp->hXLI, \"xli_readmodel\");\n        lp->xli_writemodel           = (XLIbool_lpcharcharbool *)\n                                        GetProcAddress(lp->hXLI, \"xli_writemodel\");\n      }\n      else\n        result = LIB_VERINVALID;\n    }\n  #else\n   /* First standardize UNIX .SO library name format. */\n    char xliname[260];\n    const char *ptr;\n\n    strcpy(xliname, filename);\n    if((ptr = strrchr(filename, '/')) == NULL)\n      ptr = filename;\n    else\n      ptr++;\n    xliname[(int) (ptr - filename)] = 0;\n    if(strncmp(ptr, \"lib\", 3))\n      strcat(xliname, \"lib\");\n    strcat(xliname, ptr);\n    if(strcmp(xliname + strlen(xliname) - 3, \".so\"))\n      strcat(xliname, \".so\");\n\n   /* Get a handle to the module. */\n    lp->hXLI = dlopen(xliname, RTLD_LAZY);\n\n   /* If the handle is valid, try to get the function addresses. */\n    if(lp->hXLI != NULL) {\n      lp->xli_compatible           = (XLIbool_lpintintint *)\n                                      dlsym(lp->hXLI, \"xli_compatible\");\n      if(lp->xli_compatible == NULL)\n        result = LIB_NOINFO;\n      else if(lp->xli_compatible(lp, XLIVERSION, MAJORVERSION, sizeof(REAL))) {\n\n        lp->xli_name                 = (XLIchar *)\n                                        dlsym(lp->hXLI, \"xli_name\");\n        lp->xli_readmodel            = (XLIbool_lpcharcharcharint *)\n                                        dlsym(lp->hXLI, \"xli_readmodel\");\n        lp->xli_writemodel           = (XLIbool_lpcharcharbool *)\n                                        dlsym(lp->hXLI, \"xli_writemodel\");\n      }\n      else\n        result = LIB_VERINVALID;\n    }\n  #endif\n    else\n      result = LIB_NOTFOUND;\n#endif\n    /* Do validation */\n    if((result != LIB_LOADED) ||\n       ((lp->xli_name == NULL) ||\n        (lp->xli_compatible == NULL) ||\n        (lp->xli_readmodel == NULL) ||\n        (lp->xli_writemodel == NULL)\n       )) {\n      set_XLI(lp, NULL);\n      if(result == LIB_LOADED)\n        result = LIB_NOFUNCTION;\n    }\n  }\n  if(filename != NULL) {\n    char info[LIB_STR_MAXLEN+1];\n    switch(result) {\n      case LIB_NOTFOUND:   strcpy(info, LIB_STR_NOTFOUND);\n                           break;\n      case LIB_NOINFO:     strcpy(info, LIB_STR_NOINFO);\n                           break;\n      case LIB_NOFUNCTION: strcpy(info, LIB_STR_NOFUNCTION);\n                           break;\n      case LIB_VERINVALID: strcpy(info, LIB_STR_VERINVALID);\n                           break;\n      default:             strcpy(info, LIB_STR_LOADED);\n    }\n    report(lp, IMPORTANT, \"set_XLI: %s '%s'\\n\",\n                          info, filename);\n  }\n  return( (MYBOOL) (result == LIB_LOADED));\n}\n\n\nSTATIC int get_basisOF(lprec *lp, int coltarget[], REAL crow[], int colno[])\n/* Fill vector of basic OF values or subtract incoming values from these.\n   This function is called twice during reduced cost updates when the basis\n   does not contain the basic OF vector as the top row.  The colno[] array\n   is filled with the count of non-zero values and the index to those. */\n{\n  int            i, n = lp->rows, nz = 0;\n  REAL           *obj = lp->obj;\n  REAL epsvalue = lp->epsvalue;\n\n  /* Compute offset over the specified objective indeces (step 2) */\n  if(coltarget != NULL) {\n    int  ix, m = coltarget[0];\n    REAL value;\n\n    for(i = 1, coltarget++; i <= m; i++, coltarget++) {\n      ix = *coltarget;\n      /* Finalize the computation of the reduced costs, based on the format that\n         duals are computed as negatives, ref description for step 1 above */\n      value = crow[ix];\n      if(ix > n)\n        value += obj[ix - n];\n/*      if(value != 0) { */\n      if(fabs(value) > epsvalue) {\n        nz++;\n        if(colno != NULL)\n          colno[nz] = ix;\n      }\n      else\n        value = 0.0;\n      crow[ix] = value;\n    }\n  }\n\n  /* Get the basic objective function values (step 1) */\n  else {\n    int *basvar = lp->var_basic;\n\n    for(i = 1, crow++, basvar++; i <= n;\n         i++, crow++, basvar++) {\n      /* Load the objective value of the active basic variable; note that we\n         change the sign of the value to maintain computational compatibility with\n         the calculation of duals using in-basis storage of the basic OF values */\n      if(*basvar <= n)\n        *crow = 0;\n      else\n        *crow = -obj[(*basvar) - n];\n      if((*crow) != 0) {\n/*      if(fabs(*crow) > epsvalue) { */\n        nz++;\n        if(colno != NULL)\n          colno[nz] = i;\n      }\n    }\n  }\n  if(colno != NULL)\n    colno[0] = nz;\n  return( nz );\n}\n\nint __WINAPI get_basiscolumn(lprec *lp, int j, int rn[], double bj[])\n/* This routine returns sparse vectors for all basis\n   columns, including the OF dummy (index 0) and slack columns.\n   NOTE that the index usage is nonstandard for lp_solve, since\n   the array offset is 1, not 0. */\n{\n  int k = lp->bfp_rowoffset(lp),\n      matbase = lp->bfp_indexbase(lp);\n\n  /* Do target index adjustment (etaPFI with matbase==0 is special case) */\n  if(matbase > 0)\n    matbase += k - 1;\n\n /* Convert index of slack and user columns */\n  j -= k;\n  if((j > 0) && !lp->bfp_isSetI(lp))\n    j = lp->var_basic[j];\n\n /* Process OF dummy and slack columns (always at lower bound) */\n  if(j <= lp->rows) {\n    rn[1] = j + matbase;\n    bj[1] = 1.0;\n    k = 1;\n  }\n /* Process user columns (negated if at lower bound) */\n  else {\n    k = obtain_column(lp, j, bj, rn, NULL);\n    if(matbase != 0)\n      for(j = 1; j <= k; j++)\n        rn[j] += matbase;\n  }\n\n  return( k );\n}\n\nMYBOOL __WINAPI get_primal_solution(lprec *lp, REAL *pv)\n{\n  if(lp->spx_status == OPTIMAL)\n    ;\n  else if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_primal_solution: Not a valid basis\");\n    return(FALSE);\n  }\n\n  MEMCOPY(pv, lp->best_solution, lp->sum + 1);\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_ptr_primal_solution(lprec *lp, REAL **pv)\n{\n  *pv = lp->best_solution;\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_dual_solution(lprec *lp, REAL *rc)\n{\n  REAL *duals;\n  MYBOOL ret;\n\n  if(!lp->basis_valid) {\n    report(lp, CRITICAL, \"get_dual_solution: Not a valid basis\");\n    return(FALSE);\n  }\n\n  ret = get_ptr_sensitivity_rhs(lp, &duals, NULL, NULL);\n\n  if(ret)\n    MEMCOPY(rc, duals - 1, lp->sum + 1);\n  return(ret);\n}\n\nMYBOOL __WINAPI get_ptr_dual_solution(lprec *lp, REAL **rc)\n{\n  MYBOOL ret = lp->basis_valid;\n\n  /* Just return availability of dual information if rc is NULL */\n  if(rc == NULL)\n    return( ret && ((MIP_count(lp) == 0) || (lp->bb_totalnodes > 0)) );\n\n  if(!ret) {\n    report(lp, CRITICAL, \"get_ptr_dual_solution: Not a valid basis\");\n    return(ret);\n  }\n\n  /* Otherwise, get the pointer to the dual information (and optionally produce it) */\n  ret = get_ptr_sensitivity_rhs(lp, rc, NULL, NULL);\n  if(ret)\n    (*rc)--;\n\n  return(ret);\n}\n\nMYBOOL __WINAPI get_lambda(lprec *lp, REAL *lambda)\n{\n  if(!lp->basis_valid || (get_Lrows(lp) == 0)) {\n    report(lp, CRITICAL, \"get_lambda: Not a valid basis\");\n    return(FALSE);\n  }\n\n  MEMCOPY(lambda, lp->lambda+1, get_Lrows(lp));\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_ptr_lambda(lprec *lp, REAL **lambda)\n{\n  *lambda = lp->lambda;\n  return(TRUE);\n}\n\nint __WINAPI get_orig_index(lprec *lp, int lp_index)\n{\n  if(lp->varmap_locked)\n    return(lp->presolve_undo->var_to_orig[lp_index]);\n  else if(lp_index <= lp->presolve_undo->orig_rows)\n    return(lp_index);\n  else\n    return(lp_index-lp->presolve_undo->orig_rows);\n}\nint __WINAPI get_lp_index(lprec *lp, int orig_index)\n{\n  if(lp->varmap_locked)\n    return(lp->presolve_undo->orig_to_var[orig_index]);\n  else if(orig_index <= lp->presolve_undo->orig_rows)\n    return(orig_index);\n  else\n    return(orig_index-lp->presolve_undo->orig_rows);\n}\n\nMYBOOL __WINAPI is_feasible(lprec *lp, REAL *values, REAL threshold)\n/* Recommend to use threshold = lp->epspivot */\n{\n  int     i, j, elmnr, ie;\n  REAL    *this_rhs, dist;\n  REAL    *value;\n  int     *rownr;\n  MATrec  *mat = lp->matA;\n\n  for(i = lp->rows + 1; i <= lp->sum; i++) {\n    if(values[i - lp->rows] < unscaled_value(lp, lp->orig_lowbo[i], i)\n       || values[i - lp->rows] > unscaled_value(lp, lp->orig_upbo[i], i)) {\n      if(!((lp->sc_lobound[i - lp->rows]>0) && (values[i - lp->rows]==0)))\n        return(FALSE);\n    }\n  }\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n  this_rhs = (REAL *) mempool_obtainVector(lp->workarrays, lp->rows+1, sizeof(*this_rhs));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n/*  allocREAL(lp, &this_rhs, lp->rows + 1, TRUE); */\n  for(j = 1; j <= lp->columns; j++) {\n    elmnr = mat->col_end[j - 1];\n    ie = mat->col_end[j];\n    rownr = &COL_MAT_ROWNR(elmnr);\n    value = &COL_MAT_VALUE(elmnr);\n    for(; elmnr < ie; elmnr++, rownr += matRowColStep, value += matValueStep) {\n      this_rhs[*rownr] += unscaled_mat(lp, *value, *rownr, j);\n    }\n  }\n  for(i = 1; i <= lp->rows; i++) {\n    dist = lp->orig_rhs[i] - this_rhs[i];\n    my_roundzero(dist, threshold);\n    if((lp->orig_upbo[i] == 0 && dist != 0) ||( dist < 0)) {\n      FREE(this_rhs);\n      return(FALSE);\n    }\n  }\n  mempool_releaseVector(lp->workarrays, (char *) this_rhs, FALSE);\n/*  FREE(this_rhs); */\n  return(TRUE);\n}\n\nint __WINAPI column_in_lp(lprec *lp, REAL *testcolumn)\n{\n  int    i, j, je, colnr = 0;\n  int    nz, ident = 1;\n  MATrec *mat = lp->matA;\n  int    *matRownr;\n  REAL   value, *matValue;\n\n  for(nz = 0, i = 1; i <= lp->rows; i++)\n    if(fabs(testcolumn[i]) > lp->epsvalue) nz++;\n\n  for(i = 1; (i <= lp->columns) && (ident); i++) {\n    ident = nz;\n    value = fabs(get_mat(lp, 0, i)-testcolumn[0]);\n    if(value > lp->epsvalue)\n      continue;\n    j = mat->col_end[i - 1];\n    je = mat->col_end[i];\n    matRownr = &COL_MAT_ROWNR(j);\n    matValue = &COL_MAT_VALUE(j);\n    for(; (j < je) && (ident >= 0);\n        j++, ident--, matRownr += matRowColStep, matValue += matValueStep) {\n      value = *matValue;\n      if(is_chsign(lp, *matRownr))\n        value = my_flipsign(value);\n      value = unscaled_mat(lp, value, *matRownr, i);\n      value -= testcolumn[*matRownr];\n      if(fabs(value) > lp->epsvalue)\n        break;\n    }\n    if(ident == 0)\n      colnr = i;\n  }\n  return( colnr );\n}\n\nMYBOOL __WINAPI set_lp_name(lprec *lp, const char *name)\n{\n  if (name == NULL) {\n    FREE(lp->lp_name);\n    lp->lp_name = NULL;\n  }\n  else {\n    allocCHAR(lp, &lp->lp_name, (int) (strlen(name) + 1), AUTOMATIC);\n    strcpy(lp->lp_name, name);\n  }\n  return(TRUE);\n}\n\nconst char * __WINAPI get_lp_name(lprec *lp)\n{\n  return((lp->lp_name != NULL) ? lp->lp_name : (char *) \"\");\n}\n\nSTATIC MYBOOL init_rowcol_names(lprec *lp)\n{\n  if(!lp->names_used) {\n    lp->row_name = (hashelem **) calloc(lp->rows_alloc + 1, sizeof(*lp->row_name));\n    lp->col_name = (hashelem **) calloc(lp->columns_alloc + 1, sizeof(*lp->col_name));\n    lp->rowname_hashtab = create_hash_table(lp->rows_alloc + 1, 0);\n    lp->colname_hashtab = create_hash_table(lp->columns_alloc + 1, 1);\n    lp->names_used = TRUE;\n  }\n  return(TRUE);\n}\n\nMYBOOL rename_var(lprec *lp, int varindex, const char *new_name, hashelem **list, hashtable **ht)\n{\n  hashelem *hp;\n  MYBOOL   newitem;\n\n  hp = list[varindex];\n  newitem = (MYBOOL) (hp == NULL);\n  if(newitem)\n    hp = puthash(new_name, varindex, list, *ht);\n  else if((strlen(hp->name) != strlen(new_name)) ||\n          (strcmp(hp->name, new_name) != 0)) {\n    hashtable *newht, *oldht;\n\n    allocCHAR(lp, &hp->name, (int) (strlen(new_name) + 1), AUTOMATIC);\n    strcpy(hp->name, new_name);\n    oldht = *ht;\n    newht = copy_hash_table(oldht, list, oldht->size);\n    *ht = newht;\n    free_hash_table(oldht);\n  }\n  return(newitem);\n}\n\nMYBOOL __WINAPI is_use_names(lprec *lp, MYBOOL isrow)\n{\n  if(isrow)\n    return( lp->use_row_names );\n  else\n    return( lp->use_col_names );\n}\n\nvoid __WINAPI set_use_names(lprec *lp, MYBOOL isrow, MYBOOL use_names)\n{\n  if(isrow)\n    lp->use_row_names = use_names;\n  else\n    lp->use_col_names = use_names;\n}\n\nint __WINAPI get_nameindex(lprec *lp, const char *varname, MYBOOL isrow)\n{\n  if(isrow)\n    return( find_row(lp, varname, FALSE) );\n  else\n    return( find_var(lp, varname, FALSE) );\n}\n\nMYBOOL __WINAPI set_row_name(lprec *lp, int rownr, const char *new_name)\n{\n  if((rownr < 0) || (rownr > lp->rows+1)) {\n    report(lp, IMPORTANT, \"set_row_name: Row %d out of range\", rownr);\n    return(FALSE);\n  }\n\n  /* Prepare for a new row */\n  if((rownr > lp->rows) && !append_rows(lp, rownr-lp->rows))\n    return( FALSE );\n  if(!lp->names_used) {\n    if(!init_rowcol_names(lp))\n      return(FALSE);\n  }\n  rename_var(lp, rownr, new_name, lp->row_name, &lp->rowname_hashtab);\n\n  return(TRUE);\n}\n\nconst char * __WINAPI get_row_name(lprec *lp, int rownr)\n{\n  if((rownr < 0) || (rownr > lp->rows+1)) {\n    report(lp, IMPORTANT, \"get_row_name: Row %d out of range\", rownr);\n    return(NULL);\n  }\n\n  if((lp->presolve_undo->var_to_orig != NULL) && lp->wasPresolved) {\n    if(lp->presolve_undo->var_to_orig[rownr] == 0)\n      rownr = -rownr;\n    else\n      rownr = lp->presolve_undo->var_to_orig[rownr];\n  }\n  return( get_origrow_name(lp, rownr) );\n}\n\nconst char * __WINAPI get_origrow_name(lprec *lp, int rownr)\n{\n  MYBOOL newrow;\n  char   *ptr;\n\n  newrow = (MYBOOL) (rownr < 0);\n  rownr = abs(rownr);\n#ifdef Paranoia\n  if(((lp->presolve_undo->var_to_orig == NULL) && newrow) ||\n     (rownr > MAX(lp->rows, lp->presolve_undo->orig_rows))) {\n    report(lp, IMPORTANT, \"get_origrow_name: Row %d out of range\", rownr);\n    return(NULL);\n  }\n#endif\n\n  if(lp->names_used && lp->use_row_names && (lp->row_name[rownr] != NULL) &&\n                            (lp->row_name[rownr]->name != NULL)) {\n#ifdef Paranoia\n    if(lp->row_name[rownr]->index != rownr)\n      report(lp, SEVERE, \"get_origrow_name: Inconsistent row ordinal %d vs %d\\n\",\n                         rownr, lp->row_name[rownr]->index);\n#endif\n    ptr = lp->row_name[rownr]->name;\n  }\n  else {\n    if(lp->rowcol_name == NULL)\n      if (!allocCHAR(lp, &lp->rowcol_name, 20, FALSE))\n        return(NULL);\n    ptr = lp->rowcol_name;\n    if(newrow)\n      sprintf(ptr, ROWNAMEMASK2, rownr);\n    else\n      sprintf(ptr, ROWNAMEMASK, rownr);\n  }\n  return(ptr);\n}\n\nMYBOOL __WINAPI set_col_name(lprec *lp, int colnr, const char *new_name)\n{\n  if((colnr > lp->columns+1) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"set_col_name: Column %d out of range\", colnr);\n  }\n\n  if((colnr > lp->columns) && !append_columns(lp, colnr-lp->columns))\n    return(FALSE);\n\n  if(!lp->names_used)\n    init_rowcol_names(lp);\n  rename_var(lp, colnr, new_name, lp->col_name, &lp->colname_hashtab);\n\n  return(TRUE);\n}\n\nconst char * __WINAPI get_col_name(lprec *lp, int colnr)\n{\n  if((colnr > lp->columns+1) || (colnr < 1)) {\n    report(lp, IMPORTANT, \"get_col_name: Column %d out of range\", colnr);\n    return(NULL);\n  }\n\n  if((lp->presolve_undo->var_to_orig != NULL) && lp->wasPresolved) {\n    if(lp->presolve_undo->var_to_orig[lp->rows + colnr] == 0)\n      colnr = -colnr;\n    else\n      colnr = lp->presolve_undo->var_to_orig[lp->rows + colnr];\n  }\n  return( get_origcol_name(lp, colnr) );\n}\n\nconst char * __WINAPI get_origcol_name(lprec *lp, int colnr)\n{\n  MYBOOL newcol;\n  char   *ptr;\n\n  newcol = (MYBOOL) (colnr < 0);\n  colnr = abs(colnr);\n#ifdef Paranoia\n  if(((lp->presolve_undo->var_to_orig == NULL) && newcol) ||\n     (colnr > MAX(lp->columns, lp->presolve_undo->orig_columns))) {\n    report(lp, IMPORTANT, \"get_origcol_name: Column %d out of range\", colnr);\n    return(NULL);\n  }\n#endif\n\n  if(lp->names_used && lp->use_col_names && (lp->col_name[colnr] != NULL) && (lp->col_name[colnr]->name != NULL)) {\n#ifdef Paranoia\n    if(lp->col_name[colnr]->index != colnr)\n      report(lp, SEVERE, \"get_origcol_name: Inconsistent column ordinal %d vs %d\\n\",\n                         colnr, lp->col_name[colnr]->index);\n#endif\n    ptr = lp->col_name[colnr]->name;\n  }\n  else {\n    if(lp->rowcol_name == NULL)\n      if (!allocCHAR(lp, &lp->rowcol_name, 20, FALSE))\n        return(NULL);\n    ptr = lp->rowcol_name;\n    if(newcol)\n      sprintf(ptr, COLNAMEMASK2, colnr);\n    else\n      sprintf(ptr, COLNAMEMASK, colnr);\n  }\n  return(ptr);\n}\n\nSTATIC int MIP_count(lprec *lp)\n{\n  return( lp->int_vars+lp->sc_vars+SOS_count(lp) );\n}\nSTATIC int bin_count(lprec *lp, MYBOOL working)\n{\n  int i, n = 0;\n  if(working) {\n    for(i = lp->rows+1; i <= lp->sum; i++)\n      if(fabs(unscaled_value(lp, lp->upbo[i], i) - 1) < lp->epsvalue)\n        n++;\n  }\n  else {\n    for(i = 1; i <= lp->columns; i++)\n      if((fabs(get_upbo(lp, i) - 1) < lp->epsvalue) &&\n         (fabs(get_lowbo(lp, i) - 0) < lp->epsvalue))\n        n++;\n  }\n  return( n );\n}\nSTATIC int SOS_count(lprec *lp)\n{\n  if(lp->SOS == NULL)\n    return( 0 );\n  else\n    return( lp->SOS->sos_count );\n}\nSTATIC int GUB_count(lprec *lp)\n{\n  if(lp->GUB == NULL)\n    return( 0 );\n  else\n    return( lp->GUB->sos_count );\n}\n\nSTATIC REAL compute_violation(lprec *lp, int row_nr)\n/* Returns the bound violation of a given basic variable; the return\n   value is negative if it is below is lower bound, it is positive\n   if it is greater than the upper bound, and zero otherwise. */\n{\n  REAL value, test;\n\n  value  = lp->rhs[row_nr];\n  row_nr = lp->var_basic[row_nr];\n  test = value - my_lowbound(lp->lowbo[row_nr]);\n  my_roundzero(test, lp->epsprimal);\n  if(test > 0) {\n    test = value - lp->upbo[row_nr];\n    my_roundzero(test, lp->epsprimal);\n    if(test < 0)\n      test = 0;\n  }\n  return( test );\n}\n\nSTATIC REAL feasibilityOffset(lprec *lp, MYBOOL isdual)\n{\n  int    i, j;\n  REAL   f, Extra;\n\n  Extra = 0;\n  if(isdual) {\n   /* This section computes a OF offset to ensure that the dual phase 1 is\n      feasible.  It is used to compute a primal feasible base that can be\n      passed to the primal simplex in phase 2. */\n#if 0\n\n   /* This is the legacy (v3.2-) P1extraVal logic that sets Extra to be the\n      smallest negative reduced cost. Note that the reduced costs are the\n      values of the dual slacks, which are [0..Inf> for feasibility.\n      If we have negative reduced costs for bounded non-basic variables, we\n      can simply switch the bound to obtain feasibility and possibly avoid\n      having to set Extra. */\n    if(!isDualFeasible(lp, lp->epsprimal, NULL, NULL, &f)\n      Extra = f;\n\n#else\n  /* Find the most negative of the objective coefficients. We will subtract this\n     value from every element of the objective row, making it non-negative and\n     the problem therefore dual feasible. */\n    for(i = 1; i <= lp->columns; i++) {\n      f = lp->orig_obj[i];\n      if(f < Extra)\n        Extra = f;\n    }\n#endif\n  }\n\n  else {\n  /* Set Extra to be the index of the most negative of the net RHS coefficients;\n     this approach can be used in the primal phase 1 followed by the dual phase 2\n     and when there are no ranged constraints.  When there are ranged constraints,\n     additional artificial variables must be introduced. */\n    Extra = 0;\n    j = 0;\n    Extra = lp->infinite;\n    for(i = 1; i <= lp->rows; i++) {\n      f = lp->rhs[i];\n      if(f < Extra) {\n        Extra = f;\n        j = i;\n      }\n    }\n    Extra = j;\n  }\n\n  return(Extra);\n\n}\n\nSTATIC REAL compute_dualslacks(lprec *lp, int target, REAL **dvalues, int **nzdvalues, MYBOOL dosum)\n/* Note that this function is similar to the compute_reducedcosts function in lp_price.c */\n{\n  int    i, varnr,\n         *coltarget, **nzduals, *nzvtemp = NULL;\n  REAL   d, g = 0, **duals, *vtemp = NULL;\n  MYBOOL localREAL = (MYBOOL) (dvalues == NULL),\n         localINT  = (MYBOOL) (nzdvalues == NULL);\n\n  if(is_action(lp->spx_action, ACTION_REBASE) ||\n     is_action(lp->spx_action, ACTION_REINVERT) || !lp->basis_valid)\n    return( g );\n\n  /* Initialize */\n  if(!localREAL) {\n    duals = dvalues;\n    nzduals = nzdvalues;\n  }\n  else {\n    duals = &vtemp;\n    nzduals = &nzvtemp;\n  }\n  if(localINT || (*nzduals == NULL))\n    allocINT(lp, nzduals, lp->columns + 1, AUTOMATIC);\n  if(localREAL || (*duals == NULL))\n    allocREAL(lp, duals, lp->sum + 1, AUTOMATIC);\n  if(target == 0)\n    target = SCAN_ALLVARS+ USE_NONBASICVARS;\n\n  /* Define variable target list and compute the reduced costs */\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n  coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->columns+1, sizeof(*coltarget));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n  if(!get_colIndexA(lp, target, coltarget, FALSE)) {\n    mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n    return(FALSE);\n  }\n  bsolve(lp, 0, *duals, NULL, lp->epsmachine*DOUBLEROUND, 1.0);\n  prod_xA(lp, coltarget, *duals, NULL, lp->epsmachine, 1.0,\n                         *duals, *nzduals, MAT_ROUNDDEFAULT | MAT_ROUNDRC);\n  mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n\n  /* Compute sum or maximum infeasibility as specified */\n  for(i = 1; i <= (*nzduals)[0]; i++) {\n    varnr = (*nzduals)[i];\n    d = my_chsign(!lp->is_lower[varnr], (*duals)[varnr]);\n    if(d < 0) {\n      if(dosum)\n        g += -d;         /* Compute sum as a positive number */\n      else {\n        SETMIN(g, d);    /* Compute gap as a negative number */\n      }\n    }\n  }\n\n  /* Clean up */\n  if(localREAL)\n    FREE(*duals);\n  if(localINT)\n    FREE(*nzduals);\n\n  return( g );\n}\n\nSTATIC REAL compute_feasibilitygap(lprec *lp, MYBOOL isdual, MYBOOL dosum)\n{\n  REAL f = 0;\n\n  /* This computes the primal feasibility gap (for use with the dual simplex phase 1) */\n  if(isdual) {\n    int  i;\n    REAL g;\n\n    for(i = 1; i <= lp->rows; i++) {\n      if(lp->rhs[i] < 0)\n        g = lp->rhs[i];\n      else if(lp->rhs[i] > lp->upbo[lp->var_basic[i]])\n        g = lp->rhs[i] - lp->upbo[lp->var_basic[i]];\n      else\n        g = 0;\n      if(dosum)\n        f += g;\n      else {\n        SETMAX(f, g);\n      }\n    }\n  }\n  /* This computes the dual feasibility gap (for use with the primal simplex phase 1) */\n  else\n    f = compute_dualslacks(lp, SCAN_USERVARS+USE_ALLVARS, NULL, NULL, dosum);\n\n  return( f );\n}\n\n/* Find the smallest fractional value in a given row of the OF/constraint matrix */\nSTATIC int row_decimals(lprec *lp, int rownr, MYBOOL intsonly, REAL *intscalar)\n{\n  int basi, i, j, ncols = lp->columns;\n  REAL f, /* g, */ epsvalue = lp->epsprimal;\n\n  basi = 0;\n  for(j = 1; j <= ncols; j++) {\n    if(intsonly && !is_int(lp, j)) {\n      if(intsonly == TRUE)\n        break;\n      else\n        continue;\n    }\n    f = fabs(get_mat(lp, rownr, j));\n    /* f = fmod(f, 1); */\n    f -= floor (f + epsvalue);\n/*\n    if(f <= epsvalue)\n      continue;\n    g = f;\n*/\n    for(i = 0; (i <= MAX_FRACSCALE) && (/* g */ f > epsvalue); i++) {\n      f *= 10;\n      /* g = fmod(f, 1); */\n      f -= floor (f + epsvalue);\n    }\n    if(i > MAX_FRACSCALE)\n      /* i = MAX_FRACSCALE */ break;\n    SETMAX(basi, i);\n  }\n  if(j > ncols)\n    *intscalar = pow(10.0, basi);\n  else {\n    basi = -1;\n    *intscalar = 1;\n  }\n  return( basi );\n}\n\nSTATIC int row_intstats(lprec *lp, int rownr, int pivcolnr, int *maxndec,\n                        int *plucount, int *intcount, int *intval, REAL *valGCD, REAL *pivcolval)\n{\n  int    jb, je, jj, nn = 0, multA, multB, intGCD = 0;\n  REAL   rowval, inthold, intfrac;\n  MATrec *mat = lp->matA;\n\n  /* Do we have a valid matrix? */\n  if(mat_validate(mat)) {\n\n    /* Get smallest fractional row value */\n    *maxndec = row_decimals(lp, rownr, AUTOMATIC, &intfrac);\n\n    /* Get OF row starting and ending positions, as well as the first column index */\n    if(rownr == 0) {\n      jb = 1;\n      je = lp->columns+1;\n    }\n    else {\n      jb = mat->row_end[rownr-1];\n      je = mat->row_end[rownr];\n    }\n    nn = je - jb;\n    *pivcolval = 1.0;\n    *plucount = 0;\n    *intcount = 0;\n    *intval   = 0;\n    for(; jb < je; jb++) {\n\n      if(rownr == 0) {\n        if(lp->orig_obj[jb] == 0) {\n          nn--;\n          continue;\n        }\n        jj = jb;\n      }\n      else\n        jj = ROW_MAT_COLNR(jb);\n\n      /* Pick up the value of the pivot column and continue */\n      if(jj == pivcolnr) {\n        if(rownr == 0)\n          *pivcolval = unscaled_mat(lp, lp->orig_obj[jb], 0, jb);\n        else\n          *pivcolval = get_mat_byindex(lp, jb, TRUE, FALSE);\n        continue;\n      }\n      if(!is_int(lp, jj))\n        continue;\n\n      /* Update the count of integer columns */\n      (*intcount)++;\n\n      /* Update the count of positive parameter values */\n      if(rownr == 0)\n        rowval = unscaled_mat(lp, lp->orig_obj[jb], 0, jb);\n      else\n        rowval = get_mat_byindex(lp, jb, TRUE, FALSE);\n      if(rowval > 0)\n        (*plucount)++;\n\n      /* Check if the parameter value is integer and update the row's GCD */\n      rowval = fabs(rowval) * intfrac;\n      rowval += rowval*lp->epsmachine;\n      rowval = modf(rowval, &inthold);\n      if(rowval < lp->epsprimal) {\n        (*intval)++;\n        if(*intval == 1)\n          intGCD = (int) inthold;\n        else\n          intGCD = gcd(intGCD, (LLONG) inthold, &multA, &multB);\n      }\n    }\n    *valGCD = intGCD;\n    *valGCD /= intfrac;\n  }\n\n  return(nn);\n}\n\n#if 0\nREAL MIP_stepOF(lprec *lp)\n/* This function tries to find a non-zero minimum improvement\n   if the OF contains all integer variables (logic only applies if we are\n   looking for a single solution, not possibly several equal-valued ones).\n*/\n{\n  MYBOOL OFgcd;\n  int    colnr, rownr, n, ib, ie, maxndec,\n         pluscount, intcount, intval;\n  REAL   value, valOF, divOF, valGCD;\n  MATrec *mat = lp->matA;\n\n  value = 0;\n  if((lp->int_vars > 0) && (lp->solutionlimit == 1) && mat_validate(mat)) {\n\n    /* Get statistics for integer OF variables and compute base stepsize */\n    n = row_intstats(lp, 0, -1, &maxndec, &pluscount, &intcount, &intval, &valGCD, &divOF);\n    if((n == 0) || (maxndec < 0))\n      return( value );\n    OFgcd = (MYBOOL) (intval > 0);\n    if(OFgcd)\n      value = valGCD;\n\n    /* Check non-ints in the OF to see if we can get more info */\n    if(n - intcount > 0) {\n      int nrv = 0;\n\n      /* See if we have equality constraints */\n      ie = lp->rows;\n      for(ib = 1; ib <= ie; ib++) {\n        if(is_constr_type(lp, ib, EQ))\n          break;\n      }\n\n      /* If so, there may be a chance to find an improved stepsize */\n      if(ib < ie)\n      for(colnr = 1; colnr <= lp->columns; colnr++) {\n\n        /* Go directly to the next variable if this is an integer or\n          there is no row candidate to explore for hidden bounds for\n          real-valued variables (limit scan to one row!) */\n        if(is_int(lp, colnr))\n          continue;\n        nrv++;\n        /* Scan equality constraints */\n        ib = mat->col_end[colnr-1];\n        ie = mat->col_end[colnr];\n        while(ib < ie) {\n          if(is_constr_type(lp, (rownr = COL_MAT_ROWNR(ib)), EQ)) {\n\n            /* Get \"child\" row statistics, but break out if we don't\n              find enough information, i.e. no integers with coefficients of proper type */\n            n = row_intstats(lp, rownr, colnr, &maxndec, &pluscount, &intcount, &intval, &valGCD, &divOF);\n            if((intval < n - 1) || (maxndec < 0)) {\n              value = 0;\n              break;\n            }\n\n            /* We can update */\n            valOF = unscaled_mat(lp, lp->orig_obj[colnr], 0, colnr);\n            valOF = fabs( valOF * (valGCD / divOF) );\n            if(OFgcd) {\n              SETMIN(value, valOF);\n            }\n            else {\n              OFgcd = TRUE;\n              value = valOF;\n            }\n          }\n          ib++;\n        }\n\n        /* No point in continuing scan if we failed in current column */\n        if(value == 0)\n          break;\n      }\n\n      /* Check if we found information for any real-valued variable;\n         if not, then we must set the iprovement delta to 0 */\n      if(nrv == 0)\n        value = 0;\n    }\n  }\n  return( value );\n}\n#elif 0\n/*\n    original v5.5 implementation giving problems with some models\n\n    ex:\n\n        min: +r1 +r2;\n\n        R1: +r1 +r2 >= 1;\n        R2: +r1 -5.345 b1 = 0;\n        R3: +r2 -4.456 b2 = 0;\n\n        b1 <= 1;\n        b2 <= 1;\n\n        //b2>0.1;\n\n        int b1,b2;\n\n*/\nREAL MIP_stepOF(lprec *lp)\n/* This function tries to find a non-zero minimum improvement\n   if the OF contains all integer variables (logic only applies if we are\n   looking for a single solution, not possibly several equal-valued ones). */\n{\n  MYBOOL  OFgcd;\n  int     colnr, rownr, n, ib, ie,\n          pluscount, intcount;\n  int     intval, maxndec;\n  REAL    value = 0, valOF, divOF, valGCD;\n  MATrec  *mat = lp->matA;\n\n  if((lp->int_vars > 0) && (lp->solutionlimit == 1) && mat_validate(mat)) {\n\n    /* Get statistics for integer OF variables and compute base stepsize */\n    n = row_intstats(lp, 0, 0, &maxndec, &pluscount, &intcount, &intval, &valGCD, &divOF);\n    if((n == 0) || (maxndec < 0))\n      return( value );\n    OFgcd = (MYBOOL) (intval > 0);\n    if(OFgcd)\n      value = valGCD;\n\n    /* Check non-ints in the OF to see if we can get more info */\n    if(n - intcount > 0) {\n      int nrv = n - intcount; /* Number of real variables in the objective */\n      int niv = 0;            /* Number of real variables identified as integer */\n      int nrows = lp->rows;\n\n      /* See if we have equality constraints */\n      for(ib = 1; ib <= nrows; ib++) {\n        if(is_constr_type(lp, ib, EQ))\n          break;\n      }\n\n      /* If so, there may be a chance to find an improved stepsize */\n      if(ib <= nrows)\n      for(colnr = 1; colnr <= lp->columns; colnr++) {\n\n        /* Go directly to the next variable if this is an integer or\n          there is no row candidate to explore for hidden bounds for\n          real-valued variables (limit scan to one row/no recursion) */\n        if((lp->orig_obj[colnr] == 0) || is_int(lp, colnr))\n          continue;\n\n        /* Scan equality constraints */\n        ib = mat->col_end[colnr-1];\n        ie = mat->col_end[colnr];\n        while(ib < ie) {\n          if(is_constr_type(lp, (rownr = COL_MAT_ROWNR(ib)), EQ)) {\n\n            /* Get \"child\" row statistics, but break out if we don't\n              find enough information, i.e. no integers with coefficients of proper type */\n            n = row_intstats(lp, rownr, colnr, &maxndec, &pluscount, &intcount, &intval, &valGCD, &divOF);\n            if((intval < n - 1) || (maxndec < 0)) {\n              value = 0;\n              break;\n            }\n            niv++;\n\n            /* We can update */\n            valOF = unscaled_mat(lp, lp->orig_obj[colnr], 0, colnr);\n            valOF = fabs( valOF * (valGCD / divOF) );\n            if(OFgcd) {\n              SETMIN(value, valOF);\n            }\n            else {\n              OFgcd = TRUE;\n              value = valOF;\n            }\n          }\n          ib++;\n        }\n\n        /* No point in continuing scan if we failed in current column */\n        if(value == 0)\n          break;\n      }\n\n      /* Check if we found information for any real-valued variable;\n         if not, then we must set the improvement delta to 0 */\n      if(nrv > niv)\n        value = 0;\n    }\n  }\n  return( value );\n}\n#else\n\nSTATIC REAL row_plusdelta(lprec *lp, int rownr, int excludecol, int *intcount, int *realcount)\n{\n  MATrec   *mat = lp->matA;\n  int      j, jb, je, jj, bincount,\n           n = 0, nrows = lp->rows;\n  REAL     rowval, deltaOF = 0,\n           *obj_orig = lp->orig_obj, *obj_sort = NULL;\n\n  *realcount = 0;\n  *intcount  = 0;\n  bincount = 0;\n\n  /* Get OF row starting and ending positions, as well as the first column index */\n  if(rownr == 0) {\n    jb = 1;\n    je = lp->columns+1;\n  }\n  else {\n    jb = mat->row_end[rownr-1];\n    je = mat->row_end[rownr];\n  }\n\n  /* Fill the array */\n  for(j = jb; j < je; j++) {\n\n    if(rownr == 0) {\n      if(obj_orig[j] == 0)\n        continue;\n      jj = j;\n    }\n    else\n      jj = ROW_MAT_COLNR(j);\n\n    /* Check for exclusion column */\n    if(jj == excludecol)\n      continue;\n\n    /* Check that the variable is integer */\n    if(is_int(lp, jj)) {\n      rowval = lp->orig_upbo[nrows + jj];\n      if((rowval < lp->infinite) && (fabs(unscaled_value(lp, rowval - lp->orig_lowbo[nrows + jj], nrows + jj) - 1) < lp->epsint)) // difference between upper and lower = 1 is ok\n        bincount++;\n      if(rownr == 0)\n        rowval = unscaled_mat(lp, obj_orig[jj], 0, jj);\n      else\n        rowval = get_mat_byindex(lp, j, TRUE, FALSE);\n\n      /* Allocate array of coefficients to be sorted */\n      if(n == 0)\n        allocREAL(lp, &obj_sort, je-jb, FALSE);\n\n      obj_sort[n++] = rowval;\n    }\n    else\n      (*realcount)++;\n\n  }\n  (*intcount) = n;\n\n  if(*realcount == 0) {\n    if (n == 0 || bincount < n)\n      deltaOF = 0;\n    else if(n == 1)\n      deltaOF = obj_sort[0];\n    else {\n\n      REAL   newval;\n      MYBOOL loops = 0;\n\n      while(n > 0) {\n\n        /* Sort the coefficients in ascending order */\n        qsortex(obj_sort, n, 0, sizeof(*obj_sort), FALSE, compareREAL, NULL, 0);\n\n        /* Eliminate array duplicates (could consider applying an eps) */\n        j = 0; jb = 1;\n        do {\n          rowval = obj_sort[j];\n          while((jb < n) && (obj_sort[jb] == rowval)) jb++;\n          if((jb < n) && (++j < jb))\n            obj_sort[j] = obj_sort[jb];\n        } while(++jb < n);\n        n = j+1;\n\n        /* Get the reference minimum stepsize on the first iteration */\n        if(loops == 0) {\n          /* Spool to the coefficient closest to zero, which is the reference OF stepsize */\n          for(j = 0; (j < n) && (obj_sort[j] < 0); j++);\n\n          /* Case 1: All negative coefficients */\n          if(j >= n)\n            deltaOF = -obj_sort[n-1];\n          /* Case2: All positive coefficients */\n          else if(j == 0)\n            deltaOF = obj_sort[j];\n          /* Case 3: Both negative and positive coefficients */\n          else\n            deltaOF = MIN(-obj_sort[j-1], obj_sort[j]);\n        }\n\n        /* Adjust the reference minimum stepsize on next iterations */\n        loops++;\n\n        /* Loop over non-zero coefficient differences to\n             obtain minimum change, i.e. if one increases */\n        newval = lp->infinite;\n        for(j = 1; j < n; j++) {\n          rowval = obj_sort[j]-obj_sort[j-1];\n          SETMIN(newval, rowval);\n          obj_sort[j-1] = rowval;\n        }\n        n--;\n        SETMIN(deltaOF, newval);\n      }\n    }\n  }\n\n  /* Dispose of the work array */\n  FREE(obj_sort);\n\n  return( deltaOF );\n}\n\n/* v6.0 implementation converted to v5.5 */\n\nSTATIC REAL MIP_stepOF(lprec *lp)\n/* This function tries to find a non-zero minimum improvement\n   if the OF contains all integer variables (logic only applies if we are\n   looking for a single solution, not possibly several equal-valued ones). */\n{\n  REAL    OFdelta = 0;\n  MATrec  *mat = lp->matA;\n\n  if((lp->int_vars > 0) && (lp->solutionlimit == 1) && mat_validate(mat)) {\n\n    int colnr, ib, ie,\n        intcount, realcount;\n\n    /* Get statistics for integer OF variables and compute base stepsize */\n    OFdelta = row_plusdelta(lp, 0, 0, &intcount, &realcount);\n/*    return( value ); */\n\n    /* Check non-ints in the OF to see if we can get more info */\n    if(realcount > 0) {\n      int niv = 0;            /* Number of real variables identified as integer */\n      /* int nrows = lp->rows; */\n      REAL    rowdelta;\n\n      OFdelta = lp->infinite;\n      for(colnr = 1; (colnr <= lp->columns) && (niv < realcount); colnr++) {\n\n        /* Go directly to the next variable if this is an integer or\n          there is no row candidate to explore for hidden bounds for\n          real-valued variables (limit scan to one row/no recursion) */\n        if((lp->orig_obj[colnr] == 0) || is_int(lp, colnr))\n          continue;\n\n        /* Scan equality constraints */\n        ib = mat->col_end[colnr-1];\n        ie = mat->col_end[colnr];\n        while(ib < ie) {\n\n          /* Get \"child\" row statistics, but break out if we don't find enough\n             information, i.e. no integers with coefficients of proper type. */\n          rowdelta = row_plusdelta(lp, COL_MAT_ROWNR(ib), colnr, &intcount, &realcount);\n          if(realcount > 0) {\n            OFdelta = 0;\n            break;\n          }\n\n          /* We can update */\n          SETMIN(OFdelta, rowdelta);\n          ib++;\n        }\n\n        /* No point in continuing scan if we failed in the current column */\n        if(OFdelta == 0)\n          break;\n\n        /* We found an implied integer, update count */\n        niv++;\n      }\n\n      /* Check if we found information for any real-valued variable;\n         if not, then we must set the improvement delta to 0 */\n      if(realcount > niv)\n        OFdelta = 0;\n    }\n  }\n  return( OFdelta );\n}\n\n#endif\n\nSTATIC MYBOOL isPrimalSimplex(lprec *lp)\n{\n  return((MYBOOL) (((lp->simplex_mode & SIMPLEX_Phase1_PRIMAL) != 0) ||\n                   ((lp->simplex_mode & SIMPLEX_Phase2_PRIMAL) != 0)));\n}\n\nSTATIC MYBOOL isPhase1(lprec *lp)\n{\n  return((MYBOOL) (((lp->simplex_mode & SIMPLEX_Phase1_PRIMAL) != 0) ||\n                   ((lp->simplex_mode & SIMPLEX_Phase1_DUAL) != 0)));\n}\n\nSTATIC MYBOOL isP1extra(lprec *lp)\n{\n  return((MYBOOL) ((lp->P1extraDim > 0) || (lp->P1extraVal != 0)));\n}\n\nSTATIC MYBOOL feasiblePhase1(lprec *lp, REAL epsvalue)\n{\n  REAL   gap;\n  MYBOOL test;\n\n  gap = fabs(lp->rhs[0] - lp->orig_rhs[0]);\n  test = (MYBOOL) (gap < epsvalue);\n  return( test) ;\n}\n\nSTATIC MYBOOL isDegenerateBasis(lprec *lp, int basisvar)\n{\n  int varindex;\n\n  varindex = lp->var_basic[basisvar];\n  if((fabs(lp->rhs[basisvar]) < lp->epsprimal) ||\n     (fabs(lp->upbo[varindex]-lp->rhs[basisvar]) < lp->epsprimal))\n    return( TRUE );\n  else\n    return( FALSE );\n}\n\nSTATIC int findBasicFixedvar(lprec *lp, int afternr, MYBOOL slacksonly)\n{\n  int varnr, delta = 1;\n\n  if(afternr < 0) {\n    delta = -1;\n    afternr = -afternr;\n  }\n  afternr += delta;\n  if((afternr < 1) || (afternr > lp->rows))\n    return( 0 );\n\n  for(; (afternr > 0) && (afternr <= lp->rows); afternr += delta) {\n    varnr = lp->var_basic[afternr];\n    if(((varnr <= lp->rows) && is_constr_type(lp, varnr, EQ)) ||\n       (!slacksonly && (varnr > lp->rows) && is_fixedvar(lp, varnr)))\n      break;\n  }\n\n  if(afternr > lp->rows)\n    afternr = 0;\n\n  return( afternr );\n}\n\nSTATIC MYBOOL isBasisVarFeasible(lprec *lp, REAL tol, int basis_row)\n{\n  int    col;\n  REAL   x;\n  MYBOOL Ok = TRUE;\n  MYBOOL doSC = FALSE;\n\n  col = lp->var_basic[basis_row];\n  x = lp->rhs[basis_row];         /* The current solution of basic variables stored here! */\n  if((x < -tol) || (x > lp->upbo[col]+tol))\n    Ok = FALSE;\n  else if(doSC && (col > lp->rows) && (fabs(lp->sc_lobound[col - lp->rows]) > 0)) {\n    if((x > tol) && (x < fabs(lp->sc_lobound[col - lp->rows])-tol))\n      Ok = FALSE;\n  }\n  return( Ok );\n}\nSTATIC MYBOOL isPrimalFeasible(lprec *lp, REAL tol, int infeasibles[], REAL *feasibilitygap)\n{\n  int    i;\n  MYBOOL feasible = TRUE;\n\n  /* This is a short-hand call to rowdual() to check for primal infeasibility */\n\n#if 0\n  /* Traditional indexing style */\n  for(i = 1; i <= lp->rows; i++) {\n    feasible = isBasisVarFeasible(lp, tol, i);\n#else\n  /* Fast array pointer style */\n  LREAL *rhsptr;\n  int  *idxptr;\n\n  if(infeasibles != NULL)\n    infeasibles[0] = 0;\n  for(i = 1, rhsptr = lp->rhs+1, idxptr = lp->var_basic+1;\n      (i <= lp->rows); i++, rhsptr++, idxptr++) {\n    feasible = TRUE;\n/*    if(((*rhsptr) < lp->lowbo[*idxptr]-tol) || ((*rhsptr) > lp->upbo[*idxptr]+tol)) */\n    if(((*rhsptr) < -tol) || ((*rhsptr) > lp->upbo[*idxptr]+tol))\n      feasible = FALSE;\n#endif\n    if(!feasible) {\n      if(infeasibles == NULL)\n        break;\n      infeasibles[0]++;\n      infeasibles[infeasibles[0]] = i;\n    }\n  }\n\n  /* Compute feasibility gap (could actually do this calculation above) */\n  if(feasibilitygap != NULL) {\n    if(feasible)\n      *feasibilitygap = 0.0;\n    else\n      *feasibilitygap = feasibilityOffset(lp, FALSE);\n  }\n\n  return(feasible);\n}\n\nSTATIC MYBOOL isDualFeasible(lprec *lp, REAL tol, int *boundflipcount, int infeasibles[], REAL *feasibilitygap)\n{\n  int    i, varnr,\n         n = 0,  /* Number of infeasible duals corrected with bound-swaps */\n         m = 0,\n         target = SCAN_ALLVARS+USE_NONBASICVARS;\n  REAL   f = 0;\n  MYBOOL feasible, islower;\n\n\n  /* The reduced costs are the values of the dual slacks, which\n     are [0..Inf> for feasibility.  If we have negative reduced costs\n     for bounded non-basic variables, we can simply switch the bound\n     of bounded variables to obtain dual feasibility and possibly avoid\n     having to use dual simplex phase 1. */\n  if((infeasibles != NULL) || (boundflipcount != NULL)) {\n    int  *nzdcol = NULL;\n    REAL d, *dcol = NULL;\n\n    f = compute_dualslacks(lp, target, &dcol, &nzdcol, FALSE);\n    if(nzdcol != NULL)\n    for(i = 1; i <= nzdcol[0]; i++) {\n      varnr = nzdcol[i];\n      islower = lp->is_lower[varnr];\n      d = my_chsign(!islower, dcol[varnr]);\n\n      /* Don't bother with uninteresting non-basic variables */\n      if((d > -tol) ||                /* Positive reduced costs with a tolerance */\n         my_unbounded(lp, varnr) ||   /* Free variables cannot change bound */\n         is_fixedvar(lp, varnr))      /* Equality slack or a fixed variable (\"type 3\") */\n        continue;\n\n      /* Check if we have non-flippable bounds, i.e. an unbounded variable\n         (types 2+4), or bounded variables (type 3), and if the counter is NULL. */\n      if( (boundflipcount == NULL) ||\n          ((lp->bb_level <= 1) && (my_rangebo(lp, varnr) > fabs(lp->negrange))) ||\n          (islower && my_infinite(lp, lp->upbo[varnr])) ||\n          (!islower && my_infinite(lp, my_lowbo(lp, varnr))) ) {\n        m++;\n        if(infeasibles != NULL)\n          infeasibles[m] = varnr;\n      }\n      /* Only do bound flips if the user-provided counter is non-NULL */\n      else {\n        lp->is_lower[varnr] = !islower;\n        n++;\n      }\n    }\n    if(infeasibles != NULL)\n      infeasibles[0] = m;\n    FREE(dcol);\n    FREE(nzdcol);\n    if(n > 0) {\n      set_action(&lp->spx_action, ACTION_RECOMPUTE);\n      if(m == 0)\n        f = 0;\n    }\n  }\n  else\n    f = compute_dualslacks(lp, target, NULL, NULL, FALSE);\n/*    f = feasibilityOffset(lp, TRUE); */  /* Safe legacy mode */\n\n  /* Do an extra scan to see if there are bounded variables in the OF not present in any constraint;\n     Most typically, presolve fixes such cases, so this is rarely encountered. */\n\n  varnr = lp->rows + 1;\n  for(i = 1; i <= lp->columns; i++, varnr++) {\n    if (mat_collength(lp->matA, i) == 0) {\n      islower = lp->is_lower[varnr];\n      if((my_chsign(islower, lp->orig_obj[i]) > 0) && !SOS_is_member(lp->SOS, 0, i)) {\n        lp->is_lower[varnr] = !islower;\n        if((islower && my_infinite(lp,  lp->upbo[varnr] /* lp->orig_upbo[varnr] */)) ||\n           (!islower && my_infinite(lp,  my_lowbo(lp, varnr) /* lp->orig_lowbo[varnr] */))) {\n          lp->spx_status = UNBOUNDED;\n          break;\n        }\n        /* lp->is_lower[varnr] = !islower; */\n        n++;\n      }\n    }\n  }\n\n  /* Return status */\n\n  if(boundflipcount != NULL)\n    *boundflipcount = n;\n  if(feasibilitygap != NULL) {\n    my_roundzero(f, tol);\n    *feasibilitygap = f;\n  }\n  feasible = (MYBOOL) ((f == 0) && (m == 0));\n\n  return(feasible);\n}\n\nvoid __WINAPI default_basis(lprec *lp)\n{\n  int i;\n\n  /* Set the slack variables to be basic; note that the is_basic[] array\n     is a helper array filled in presolve() to match var_basic[]. */\n  for(i = 1; i <= lp->rows; i++) {\n    lp->var_basic[i] = i;\n    lp->is_basic[i] = TRUE;\n    lp->is_lower[i] = TRUE;\n  }\n  lp->var_basic[0] = TRUE; /* Set to signal that this is the default basis */\n\n  /* Set user variables at their lower bound, including the\n     dummy slack for the objective \"constraint\" */\n  for(; i <= lp->sum; i++) {\n    lp->is_basic[i] = FALSE;\n    lp->is_lower[i] = TRUE;\n  }\n  lp->is_lower[0] = TRUE;\n\n  set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n  lp->basis_valid = TRUE;  /* Do not re-initialize basis on entering Solve */\n}\n\nint __WINAPI get_basiscrash(lprec *lp)\n{\n  return(lp->crashmode);\n}\n\nvoid __WINAPI set_basiscrash(lprec *lp, int mode)\n{\n  lp->crashmode = mode;\n}\n\nMYBOOL __WINAPI set_basis(lprec *lp, int *bascolumn, MYBOOL nonbasic)   /* Added by KE */\n{\n  int    i,s,k,n;\n\n  /* Make sure we are consistent */\n  if(lp->wasPresolved && ((lp->rows != lp->presolve_undo->orig_rows) ||\n                          (lp->columns != lp->presolve_undo->orig_columns)))\n    return( FALSE );\n\n /* Initialize (lp->is_basic is set in preprocess); Note that as of v5 and before\n    it is an lp_solve convention that basic variables are at their lower bounds!\n    This routine provides for the a possible future case that basic variables\n    can be upper-bounded. */\n  lp->is_lower[0] = TRUE;\n  for(i = 1; i <= lp->sum; i++) {\n    lp->is_lower[i] = TRUE;\n    lp->is_basic[i] = FALSE;\n  }\n  for(i = 1; i <= lp->rows; i++)\n    lp->var_basic[i] = FALSE;\n\n /* Set basic and optionally non-basic variables;\n    negative index means at lower bound, positive at upper bound */\n  if(nonbasic)\n    n = lp->sum;\n  else\n    n = lp->rows;\n  for(i = 1; i <= n; i++) {\n    s = bascolumn[i];\n    k = abs(s);\n    if(k <= 0 || k > lp->sum)\n      return( FALSE );\n    if(i <= lp->rows) {\n      lp->var_basic[i] = k;\n      lp->is_basic[k] = TRUE;\n    }\n    else     /* Remove this test if basic variables can be upper-bounded */\n    if(s > 0)\n      lp->is_lower[k] = FALSE;\n  }\n  if(!verify_basis(lp))\n    return( FALSE );\n\n /* Invalidate basis */\n  set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n  lp->basis_valid = TRUE;   /* Do not re-initialize basis on entering Solve */\n  lp->var_basic[0] = FALSE; /* Set to signal that this is a non-default basis */\n\n  return( TRUE );\n}\n\nvoid __WINAPI reset_basis(lprec *lp)\n{\n  lp->basis_valid = FALSE;   /* Causes reinversion at next opportunity */\n}\n\nMYBOOL __WINAPI get_basis(lprec *lp, int *bascolumn, MYBOOL nonbasic)\n{\n  int    k, i;\n\n  if(!lp->basis_valid ||\n     (lp->rows != lp->presolve_undo->orig_rows) ||\n     (lp->columns != lp->presolve_undo->orig_columns))\n    return( FALSE );\n\n  *bascolumn = 0;\n\n  /* First save basic variable indexes */\n  for(i = 1; i <= lp->rows; i++) {\n    k = lp->var_basic[i];\n    bascolumn[i] = my_chsign(lp->is_lower[k], k);\n  }\n\n  /* Then optionally save non-basic variable indeces */\n  if(nonbasic) {\n    for(k = 1; (k <= lp->sum) && (i <= lp->sum); k++) {\n      if(lp->is_basic[k])\n        continue;\n      bascolumn[i] = my_chsign(lp->is_lower[k], k);\n      i++;\n    }\n  }\n  return( TRUE );\n}\n\nSTATIC MYBOOL is_BasisReady(lprec *lp)\n{\n  return( (MYBOOL) (lp->var_basic[0] != AUTOMATIC) );\n}\n\nSTATIC MYBOOL is_slackbasis(lprec *lp)\n{\n  int n = 0, err = 0;\n  if(lp->basis_valid) {\n    int i, k;\n    MYBOOL *used = NULL;\n\n    allocMYBOOL(lp, &used, lp->rows+1, TRUE);\n    for(i = 1; i <= lp->rows; i++) {\n      k = lp->var_basic[i];\n      if(k <= lp->rows) {\n        if(used[k])\n          err++;\n        else\n          used[k] = TRUE;\n        n++;\n      }\n    }\n    FREE(used);\n    if(err > 0)\n      report(lp, SEVERE, \"is_slackbasis: %d inconsistencies found in slack basis\\n\", err);\n  }\n  return( (MYBOOL) (n == lp->rows) );\n}\n\nSTATIC MYBOOL verify_basis(lprec *lp)\n{\n  int    i, ii, k = 0;\n  MYBOOL result = FALSE;\n\n  for(i = 1; i <= lp->rows; i++) {\n    ii = lp->var_basic[i];\n    if((ii < 1) || (ii > lp->sum) || !lp->is_basic[ii]) {\n      k = i;\n      ii = 0;\n      goto Done;\n    }\n  }\n\n  ii = lp->rows;\n  for(i = 1; i <= lp->sum; i++) {\n    if(lp->is_basic[i])\n      ii--;\n  }\n  result = (MYBOOL) (ii == 0);\n\nDone:\n#if 0  /* For testing */\n  if(!result)\n    ii = 0;\n#endif\n  return(result);\n}\n\nint __WINAPI set_basisvar(lprec *lp, int basisPos, int enteringCol)\n{\n  int leavingCol;\n\n  leavingCol = lp->var_basic[basisPos];\n\n#ifdef Paranoia\n  if((basisPos < 1) || (basisPos > lp->rows))\n    report(lp, SEVERE, \"set_basisvar: Invalid leaving basis position %d specified at iter %.0f\\n\",\n                       basisPos, (double) get_total_iter(lp));\n  if((leavingCol < 1) || (leavingCol > lp->sum))\n    report(lp, SEVERE, \"set_basisvar: Invalid leaving column %d referenced at iter %.0f\\n\",\n                       leavingCol, (double) get_total_iter(lp));\n  if((enteringCol < 1) || (enteringCol > lp->sum))\n    report(lp, SEVERE, \"set_basisvar: Invalid entering column %d specified at iter %.0f\\n\",\n                       enteringCol, (double) get_total_iter(lp));\n#endif\n\n#ifdef ParanoiaXY\n  if(!lp->is_basic[leavingCol])\n    report(lp, IMPORTANT, \"set_basisvar: Leaving variable %d is not basic at iter %.0f\\n\",\n                           leavingCol, (double) get_total_iter(lp));\n  if(enteringCol > lp->rows && lp->is_basic[enteringCol])\n    report(lp, IMPORTANT, \"set_basisvar: Entering variable %d is already basic at iter %.0f\\n\",\n                           enteringCol, (double) get_total_iter(lp));\n#endif\n\n  lp->var_basic[0]          = FALSE;       /* Set to signal that this is a non-default basis */\n  lp->var_basic[basisPos]   = enteringCol;\n  lp->is_basic[leavingCol]  = FALSE;\n  lp->is_basic[enteringCol] = TRUE;\n  if(lp->bb_basis != NULL)\n    lp->bb_basis->pivots++;\n\n  return(leavingCol);\n}\n\n/* Bounds updating and unloading routines; requires that the\n   current values for upbo and lowbo are in the original base. */\nSTATIC int perturb_bounds(lprec *lp, BBrec *perturbed, MYBOOL doRows, MYBOOL doCols, MYBOOL includeFIXED)\n{\n  int  i, ii, n = 0;\n  REAL new_lb, new_ub, *upbo, *lowbo;\n\n  if(perturbed == NULL)\n    return( n );\n\n /* Map reference bounds to previous state, i.e. cumulate\n    perturbations in case of persistent problems */\n  upbo  = perturbed->upbo;\n  lowbo = perturbed->lowbo;\n\n /* Set appropriate target variable range */\n  i = 1;\n  ii = lp->rows;\n  if(!doRows)\n    i += ii;\n  if(!doCols)\n    ii = lp->sum;\n\n /* Perturb (expand) finite variable bounds randomly */\n  for(; i <= ii; i++) {\n\n    /* Don't perturb regular slack variables */\n    if((i <= lp->rows) && (lowbo[i] == 0) && (upbo[i] >= lp->infinite))\n      continue;\n\n    new_lb = lowbo[i];\n    new_ub = upbo[i];\n\n    /* Don't perturb fixed variables if not specified */\n    if(!includeFIXED && (new_ub == new_lb))\n      continue;\n\n    /* Lower bound for variables (consider implementing RHS here w/contentmode== AUTOMATIC) */\n    if((i > lp->rows) && (new_lb < lp->infinite)) {\n      new_lb = rand_uniform(lp, RANDSCALE) + 1;\n      new_lb *= lp->epsperturb;\n      lowbo[i] -= new_lb;\n      n++;\n    }\n\n    /* Upper bound */\n    if(new_ub < lp->infinite) {\n      new_ub = rand_uniform(lp, RANDSCALE) + 1;\n      new_ub *= lp->epsperturb;\n      upbo[i] += new_ub;\n      n++;\n    }\n  }\n\n /* Make sure we start from scratch */\n  set_action(&lp->spx_action, ACTION_REBASE);\n\n  return( n );\n}\n\nSTATIC MYBOOL impose_bounds(lprec *lp, REAL *upbo, REAL *lowbo)\n/* Explicitly set working bounds to given vectors without pushing or popping */\n{\n  MYBOOL ok;\n\n  ok = (MYBOOL) ((upbo != NULL) || (lowbo != NULL));\n  if(ok) {\n    if((upbo != NULL) && (upbo != lp->upbo))\n      MEMCOPY(lp->upbo,  upbo,  lp->sum + 1);\n    if((lowbo != NULL) && (lowbo != lp->lowbo))\n      MEMCOPY(lp->lowbo, lowbo, lp->sum + 1);\n    if(lp->bb_bounds != NULL)\n      lp->bb_bounds->UBzerobased = FALSE;\n    set_action(&lp->spx_action, ACTION_REBASE);\n  }\n  set_action(&lp->spx_action, ACTION_RECOMPUTE);\n  return( ok );\n}\n\nSTATIC MYBOOL validate_bounds(lprec *lp, REAL *upbo, REAL *lowbo)\n/* Check if all bounds are Explicitly set working bounds to given vectors without pushing or popping */\n{\n  MYBOOL ok;\n  int    i;\n\n  ok = (MYBOOL) ((upbo != NULL) || (lowbo != NULL));\n  if(ok) {\n    for(i = 1; i <= lp->sum; i++)\n      if((lowbo[i] > upbo[i]) || (lowbo[i] < lp->orig_lowbo[i]) || (upbo[i] > lp->orig_upbo[i]))\n        break;\n    ok = (MYBOOL) (i > lp->sum);\n  }\n  return( ok );\n}\n\nSTATIC int unload_BB(lprec *lp)\n{\n  int levelsunloaded = 0;\n\n  if(lp->bb_bounds != NULL)\n    while(pop_BB(lp->bb_bounds))\n      levelsunloaded++;\n  return( levelsunloaded );\n}\n\n\n#define LowerStorageModel 1\n#define BasisStorageModel 1\nSTATIC basisrec *push_basis(lprec *lp, int *basisvar, MYBOOL *isbasic, MYBOOL *islower)\n/* Save the ingoing basis and push it onto the stack */\n{\n  int sum = lp->sum + 1;\n  basisrec *newbasis = NULL;\n\n  newbasis = (basisrec *) calloc(sizeof(*newbasis), 1);\n  if((newbasis != NULL) &&\n#if LowerStorageModel == 0\n    allocMYBOOL(lp, &newbasis->is_lower,  sum,  FALSE) &&\n#else\n    allocMYBOOL(lp, &newbasis->is_lower,  (sum + 8) / 8,  TRUE) &&\n#endif\n#if BasisStorageModel == 0\n    allocMYBOOL(lp, &newbasis->is_basic,  sum,  FALSE) &&\n#endif\n    allocINT(lp,    &newbasis->var_basic, lp->rows + 1, FALSE)) {\n\n    if(islower == NULL)\n      islower = lp->is_lower;\n    if(isbasic == NULL)\n      isbasic = lp->is_basic;\n    if(basisvar == NULL)\n      basisvar = lp->var_basic;\n\n#if LowerStorageModel == 0\n    MEMCOPY(newbasis->is_lower,  islower,  sum);\n#else\n    for(sum = 1; sum <= lp->sum; sum++)\n      if(islower[sum])\n        set_biton(newbasis->is_lower, sum);\n#endif\n#if BasisStorageModel == 0\n    MEMCOPY(newbasis->is_basic,  isbasic,  lp->sum + 1);\n#endif\n    MEMCOPY(newbasis->var_basic, basisvar, lp->rows + 1);\n\n    newbasis->previous = lp->bb_basis;\n    if(lp->bb_basis == NULL)\n      newbasis->level = 0;\n    else\n      newbasis->level = lp->bb_basis->level + 1;\n    newbasis->pivots = 0;\n\n    lp->bb_basis = newbasis;\n  }\n  return( newbasis );\n}\n\nSTATIC MYBOOL compare_basis(lprec *lp)\n/* Compares the last pushed basis with the currently active basis */\n{\n  int i, j;\n  MYBOOL same_basis = TRUE;\n\n  if(lp->bb_basis == NULL)\n    return( FALSE );\n\n  /* Loop over basis variables until a mismatch (order can be different) */\n  i = 1;\n  while(same_basis && (i <= lp->rows)) {\n    j = 1;\n    while(same_basis && (j <= lp->rows)) {\n      same_basis = (MYBOOL) (lp->bb_basis->var_basic[i] != lp->var_basic[j]);\n      j++;\n    }\n    same_basis = !same_basis;\n    i++;\n  }\n  /* Loop over bound status indicators until a mismatch */\n  i = 1;\n  while(same_basis && (i <= lp->sum)) {\n    same_basis = (lp->bb_basis->is_lower[i] && lp->is_lower[i]);\n    i++;\n  }\n\n  return( same_basis );\n}\n\nSTATIC MYBOOL restore_basis(lprec *lp)\n/* Restore values from the previously pushed / saved basis without popping it */\n{\n  MYBOOL ok;\n  int    i;\n\n  ok = (MYBOOL) (lp->bb_basis != NULL);\n  if(ok) {\n    MEMCOPY(lp->var_basic, lp->bb_basis->var_basic, lp->rows + 1);\n#if BasisStorageModel == 0\n    MEMCOPY(lp->is_basic,  lp->bb_basis->is_basic,  lp->sum + 1);\n#else\n    MEMCLEAR(lp->is_basic, lp->sum + 1);\n    for(i = 1; i <= lp->rows; i++)\n      lp->is_basic[lp->var_basic[i]] = TRUE;\n#endif\n#if LowerStorageModel == 0\n    MEMCOPY(lp->is_lower,  lp->bb_basis->is_lower,  lp->sum + 1);\n#else\n    for(i = 1; i <= lp->sum; i++)\n      lp->is_lower[i] = is_biton(lp->bb_basis->is_lower, i);\n#endif\n    set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT);\n  }\n  return( ok );\n}\n\nSTATIC MYBOOL pop_basis(lprec *lp, MYBOOL restore)\n/* Pop / free, and optionally restore the previously \"pushed\" / saved basis */\n{\n  MYBOOL ok;\n  basisrec *oldbasis;\n\n  ok = (MYBOOL) (lp->bb_basis != NULL);\n  if(ok) {\n    oldbasis = lp->bb_basis;\n    if(oldbasis != NULL) {\n      lp->bb_basis = oldbasis->previous;\n      FREE(oldbasis->var_basic);\n#if BasisStorageModel == 0\n      FREE(oldbasis->is_basic);\n#endif\n      FREE(oldbasis->is_lower);\n      FREE(oldbasis);\n    }\n    if(restore && (lp->bb_basis != NULL))\n      restore_basis(lp);\n  }\n  return( ok );\n}\n\nSTATIC int unload_basis(lprec *lp, MYBOOL restorelast)\n{\n  int levelsunloaded = 0;\n\n  if(lp->bb_basis != NULL)\n    while(pop_basis(lp, restorelast))\n      levelsunloaded++;\n  return( levelsunloaded );\n}\n\n\nSTATIC REAL scaled_floor(lprec *lp, int colnr, REAL value, REAL epsscale)\n{\n  value = floor(value);\n  if(value != 0)\n  if(lp->columns_scaled && is_integerscaling(lp)) {\n    value = scaled_value(lp, value, colnr);\n    if(epsscale != 0)\n      value += epsscale*lp->epsmachine;\n/*      value += epsscale*lp->epsprimal; */\n/*    value = restoreINT(value, lp->epsint); */\n  }\n  return(value);\n}\n\nSTATIC REAL scaled_ceil(lprec *lp, int colnr, REAL value, REAL epsscale)\n{\n  value = ceil(value);\n  if(value != 0)\n  if(lp->columns_scaled && is_integerscaling(lp)) {\n    value = scaled_value(lp, value, colnr);\n    if(epsscale != 0)\n      value -= epsscale*lp->epsmachine;\n/*      value -= epsscale*lp->epsprimal; */\n/*    value = restoreINT(value, lp->epsint); */\n  }\n  return(value);\n}\n\n/* Branch and bound variable selection functions */\n\nSTATIC MYBOOL is_sc_violated(lprec *lp, int column)\n{\n  int  varno;\n  REAL tmpreal;\n  REAL eps = lp->epsvalue;                                    /*  adding eps here*/\n\n  varno = lp->rows+column;\n  tmpreal = unscaled_value(lp, lp->sc_lobound[column], varno);\n  return( (MYBOOL) ((tmpreal > 0) &&                          /* it is an (inactive) SC variable...    */\n                    (lp->solution[varno] < tmpreal - eps) &&  /* ...and the NZ lower bound is violated */\n                    (lp->solution[varno] > eps)) );           /* ...and the Z lowerbound is violated   */\n}\n\nSTATIC int find_sc_bbvar(lprec *lp, int *count)\n{\n  int    i, ii, n, bestvar;\n  int    firstsc, lastsc;\n  REAL   hold, holdINT, bestval, OFval, randval, scval;\n  MYBOOL reversemode, greedymode, randomizemode,\n         pseudocostmode, pseudocostsel;\n\n  bestvar = 0;\n  if((lp->sc_vars == 0) || (*count > 0))\n    return(bestvar);\n\n  reversemode    = is_bb_mode(lp, NODE_WEIGHTREVERSEMODE);\n  greedymode     = is_bb_mode(lp, NODE_GREEDYMODE);\n  randomizemode  = is_bb_mode(lp, NODE_RANDOMIZEMODE);\n  pseudocostmode = is_bb_mode(lp, NODE_PSEUDOCOSTMODE);\n  pseudocostsel  = is_bb_rule(lp, NODE_PSEUDOCOSTSELECT) ||\n                   is_bb_rule(lp, NODE_PSEUDONONINTSELECT) ||\n                   is_bb_rule(lp, NODE_PSEUDORATIOSELECT);\n\n  bestvar = 0;\n  bestval = -lp->infinite;\n  hold    = 0;\n  randval = 1;\n  firstsc = 0;\n  lastsc  = lp->columns;\n\n  for(n = 1; n <= lp->columns; n++) {\n    ii = get_var_priority(lp, n);\n    i = lp->rows + ii;\n    if(!lp->bb_varactive[ii] && is_sc_violated(lp, ii) && !SOS_is_marked(lp->SOS, 0, ii)) {\n\n      /* Do tallies */\n      (*count)++;\n      lastsc = i;\n      if(firstsc <= 0)\n        firstsc = i;\n      scval = get_pseudorange(lp->bb_PseudoCost, ii, BB_SC);\n\n      /* Select default pricing/weighting mode */\n      if(pseudocostmode)\n        OFval = get_pseudonodecost(lp->bb_PseudoCost, ii, BB_SC, lp->solution[i]);\n      else\n        OFval = my_chsign(is_maxim(lp), get_mat(lp, 0, ii));\n\n      if(randomizemode)\n        randval = exp(rand_uniform(lp, 1.0));\n\n      /* Find the maximum pseudo-cost of a variable (don't apply pseudocostmode here) */\n      if(pseudocostsel) {\n        if(pseudocostmode)\n          hold = OFval;\n        else\n          hold = get_pseudonodecost(lp->bb_PseudoCost, ii, BB_SC, lp->solution[i]);\n        hold *= randval;\n        if(greedymode) {\n          if(pseudocostmode) /* Override! */\n            OFval = my_chsign(is_maxim(lp), get_mat(lp, 0, ii));\n          hold *= OFval;\n        }\n        hold = my_chsign(reversemode, hold);\n      }\n      else\n      /* Find the variable with the largest sc gap (closest to the sc mean) */\n      if(is_bb_rule(lp, NODE_FRACTIONSELECT)) {\n        hold = modf(lp->solution[i]/scval, &holdINT);\n        holdINT = hold-1;\n        if(fabs(holdINT) > hold)\n          hold = holdINT;\n        if(greedymode)\n          hold *= OFval;\n        hold = my_chsign(reversemode, hold)*scval*randval;\n      }\n      else\n      /* Do first or last violated sc index selection (default) */\n      /* if(is_bb_rule(lp, NODE_FIRSTSELECT)) */\n      {\n        if(reversemode)\n          continue;\n        else {\n          bestvar = i;\n          break;\n        }\n      }\n\n      /* Select better, check for ties, and split by proximity to 0.5*sc_lobound */\n      if(hold > bestval) {\n        if( (bestvar == 0) ||\n            (hold > bestval+lp->epsprimal) ||\n            (fabs(modf(lp->solution[i]/scval, &holdINT) - 0.5) <\n             fabs(modf(lp->solution[bestvar]/\n                       get_pseudorange(lp->bb_PseudoCost, bestvar-lp->rows, BB_SC), &holdINT) - 0.5)) ) {\n          bestval = hold;\n          bestvar = i;\n        }\n      }\n    }\n  }\n\n  if(is_bb_rule(lp, NODE_FIRSTSELECT) && reversemode)\n    bestvar = lastsc;\n\n  return(bestvar);\n}\n\nSTATIC int find_sos_bbvar(lprec *lp, int *count, MYBOOL intsos)\n{\n  int k, i, j, var;\n\n  var = 0;\n  if((lp->SOS == NULL) || (*count > 0))\n    return(var);\n\n  /* Check if the SOS'es happen to already be satisified */\n  i = SOS_is_satisfied(lp->SOS, 0, lp->solution);\n  if((i == SOS_COMPLETE) || (i == SOS_INCOMPLETE))\n    return(-1);\n\n  /* Otherwise identify a SOS variable to enter B&B */\n  for(k = 0; k < lp->sos_vars; k++) {\n    i = lp->sos_priority[k];\n#ifdef Paranoia\n    if((i < 1) || (i > lp->columns))\n      report(lp, SEVERE, \"find_sos_bbvar: Invalid SOS variable map %d at %d\\n\",\n                         i, k);\n#endif\n    j = lp->rows + i;\n    if(!SOS_is_marked(lp->SOS, 0, i) && !SOS_is_full(lp->SOS, 0, i, FALSE)) {\n/*    if(!SOS_is_marked(lp->SOS, 0, i) && !SOS_is_full(lp->SOS, 0, i, TRUE)) { */\n      if(!intsos || is_int(lp, i)) {\n        (*count)++;\n        if(var == 0) {\n          var = j;\n          break;\n        }\n      }\n    }\n  }\n#ifdef Paranoia\n  if((var > 0) && !SOS_is_member(lp->SOS, 0, var-lp->rows))\n     report(lp, SEVERE, \"find_sos_bbvar: Found variable %d, which is not a SOS!\\n\", var);\n#endif\n  return(var);\n}\n\nSTATIC int find_int_bbvar(lprec *lp, int *count, BBrec *BB, MYBOOL *isfeasible)\n{\n  int    i, ii, n, k, bestvar, depthmax, *nonint = NULL;\n  REAL   hold, holdINT, bestval, OFval, randval,\n         *lowbo = BB->lowbo, *upbo = BB->upbo;\n  MYBOOL reversemode, greedymode, depthfirstmode, breadthfirstmode,\n         randomizemode, rcostmode,\n         pseudocostmode, pseudocostsel, pseudostrong, isINT, valINT;\n\n  if((lp->int_vars == 0) || (*count > 0))\n    return( 0 );\n  if(lp->bb_usenode != NULL) {\n    i = lp->bb_usenode(lp, lp->bb_nodehandle, BB_INT);\n    if(i >= 0) {\n      if(i > 0)\n        (*count)++;\n      return( i );\n    }\n  }\n\n  reversemode    = is_bb_mode(lp, NODE_WEIGHTREVERSEMODE);\n  greedymode     = is_bb_mode(lp, NODE_GREEDYMODE);\n  randomizemode  = is_bb_mode(lp, NODE_RANDOMIZEMODE);\n  depthfirstmode = is_bb_mode(lp, NODE_DEPTHFIRSTMODE);\n  breadthfirstmode = is_bb_mode(lp, NODE_BREADTHFIRSTMODE) &&\n                     (MYBOOL) (lp->bb_level <= lp->int_vars);\n  rcostmode      = (MYBOOL) /* FALSE */ (BB->lp->solutioncount > 0) && is_bb_mode(lp, NODE_RCOSTFIXING) ; /* 5/2/08 peno disabled NODE_RCOSTFIXING because it results in non-optimal solutions with some models */ /* 15/2/8 peno enabled NODE_RCOSTFIXING again because a fix is found. See lp_simplex.c NODE__RCOSTFIXING fix */\n  pseudocostmode = is_bb_mode(lp, NODE_PSEUDOCOSTMODE);\n  pseudocostsel  = is_bb_rule(lp, NODE_PSEUDOCOSTSELECT) ||\n                   is_bb_rule(lp, NODE_PSEUDONONINTSELECT) ||\n                   is_bb_rule(lp, NODE_PSEUDORATIOSELECT);\n  pseudostrong   = FALSE &&\n                   pseudocostsel && !rcostmode && is_bb_mode(lp, NODE_STRONGINIT);\n\n  /* Fill list of non-ints */\n  allocINT(lp, &nonint, lp->columns + 1, FALSE);\n  n = 0;\n  depthmax = -1;\n  if(isfeasible != NULL)\n    *isfeasible = TRUE;\n  BB->lastrcf = 0;\n  for(k = 1; (k <= lp->columns); k++) {\n    ii = get_var_priority(lp, k);\n    isINT = is_int(lp,ii);\n    i  = lp->rows + ii;\n\n    /* Tally reduced cost fixing opportunities for ranged non-basic nonINTs */\n    if(!isINT) {\n#ifdef UseMilpExpandedRCF\n      if(rcostmode) {\n        bestvar = rcfbound_BB(BB, i, isINT, NULL, isfeasible);\n        if(bestvar != FR)\n          BB->lastrcf++;\n      }\n#endif\n    }\n    else {\n\n      valINT = solution_is_int(lp, i, FALSE);\n\n      /* Skip already fixed variables */\n      if(lowbo[i] == upbo[i]) {\n\n        /* Check for validity */\n#ifdef Paranoia\n        if(!valINT) {\n          report(lp, IMPORTANT,\n                 \"find_int_bbvar: INT var %d was fixed at %d, but computed as %g at node %.0f\\n\",\n                  ii, (int) lowbo[i], lp->solution[i], (double) lp->bb_totalnodes);\n          lp->bb_break = TRUE;\n          lp->spx_status = UNKNOWNERROR;\n          bestvar = 0;\n          goto Done;\n        }\n#endif\n      }\n\n      /* The variable has not yet been fixed */\n      else {\n\n        /* Tally reduced cost fixing opportunities (also when the\n           variables are integer-valued at the current relaxation) */\n        if(rcostmode) {\n          bestvar = rcfbound_BB(BB, i, isINT, NULL, isfeasible);\n          if(bestvar != FR)\n            BB->lastrcf++;\n        }\n        else\n          bestvar = FR;\n\n        /* Only qualify variable as branching node if it is non-integer and\n           it will not be subsequently fixed via reduced cost fixing logic */\n        if(!valINT && (bestvar >= FR)) {\n\n          n++;\n          nonint[n] = ii;\n          SETMAX(depthmax, lp->bb_varactive[ii]);\n        }\n      }\n\n    }\n  }\n\n#ifdef UseMilpSlacksRCF\n  /* Optionally also tally slacks */\n  if(rcostmode) {\n    for(i = 1; (i <= lp->rows) && (BB->lastrcf == 0); i++) {\n      /* Skip already fixed slacks (equalities) */\n      if(lowbo[i] < upbo[i]) {\n        bestvar = rcfbound_BB(BB, i, FALSE, NULL, isfeasible);\n        if(bestvar != FR)\n          BB->lastrcf++;\n      }\n    }\n  }\n#endif\n  nonint[0] = n;\n  *count    = n;\n  bestvar   = 0;\n  if(n == 0)     /* No non-integers found */\n    goto Done;\n\n  bestval  = -lp->infinite;\n  hold     = 0;\n  randval  = 1;\n\n  /* Sort non-ints by depth in case we have breadthfirst or depthfirst modes */\n  if((lp->bb_level > 1) && (depthmax > 0) && (depthfirstmode || breadthfirstmode)) {\n    int *depths = NULL;\n\n    /* Fill attribute array and make sure ordinal order breaks ties during sort */\n    allocINT(lp, &depths, n + 1, FALSE);\n    for(i = 1; i <= n; i++)\n      depths[i] = (depthfirstmode ? n+1-i : i) + (n+1)*lp->bb_varactive[nonint[i]];\n    hpsortex(depths, n, 1, sizeof(*nonint), depthfirstmode, compareINT, nonint);\n    FREE(depths);\n  }\n\n  /* Do simple firstselect handling */\n  if(is_bb_rule(lp, NODE_FIRSTSELECT)) {\n    if(reversemode)\n      bestvar = lp->rows + nonint[nonint[0]];\n    else\n      bestvar = lp->rows + nonint[1];\n  }\n\n  else for(n = 1; n <= nonint[0]; n++) {\n    ii = nonint[n];\n    i = lp->rows + ii;\n\n    /* Do the naive detection */\n    if(n == 1)\n      bestvar = i;\n\n    /* Should we do a \"strong\" pseudo-cost initialization or an incremental update? */\n    if(pseudostrong &&\n       (MAX(lp->bb_PseudoCost->LOcost[ii].rownr,\n            lp->bb_PseudoCost->UPcost[ii].rownr) < lp->bb_PseudoCost->updatelimit) &&\n       (MAX(lp->bb_PseudoCost->LOcost[ii].colnr,\n            lp->bb_PseudoCost->UPcost[ii].colnr) < 5*lp->bb_PseudoCost->updatelimit)) {\n      strongbranch_BB(lp, BB, ii, BB_INT, nonint[0]);\n    }\n\n    /* Select default pricing/weighting mode */\n    if(pseudocostmode)\n      OFval = get_pseudonodecost(lp->bb_PseudoCost, ii, BB_INT, lp->solution[i]);\n    else\n      OFval = my_chsign(is_maxim(lp), get_mat(lp, 0, ii));\n\n    if(randomizemode)\n      randval = exp(rand_uniform(lp, 1.0));\n\n    /* Find the maximum pseudo-cost of a variable (don't apply pseudocostmode here) */\n    if(pseudocostsel) {\n      if(pseudocostmode)\n        hold = OFval;\n      else\n        hold = get_pseudonodecost(lp->bb_PseudoCost, ii, BB_INT, lp->solution[i]);\n      hold *= randval;\n      if(greedymode) {\n        if(pseudocostmode) /* Override! */\n          OFval = my_chsign(is_maxim(lp), get_mat(lp, 0, ii));\n        hold *= OFval;\n      }\n      hold = my_chsign(reversemode, hold);\n    }\n    else\n    /* Find the variable with the largest gap to its bounds (distance from being fixed) */\n    if(is_bb_rule(lp, NODE_GAPSELECT)) {\n      hold = lp->solution[i];\n      holdINT = hold-unscaled_value(lp, upbo[i], i);\n      hold -= unscaled_value(lp, lowbo[i], i);\n      if(fabs(holdINT) > hold)\n        hold = holdINT;\n      if(greedymode)\n        hold *= OFval;\n      hold = my_chsign(reversemode, hold)*randval;\n    }\n    else\n    /* Find the variable with the largest integer gap (closest to 0.5) */\n    if(is_bb_rule(lp, NODE_FRACTIONSELECT)) {\n      hold = modf(lp->solution[i], &holdINT);\n      holdINT = hold-1;\n      if(fabs(holdINT) > hold)\n        hold = holdINT;\n      if(greedymode)\n        hold *= OFval;\n      hold = my_chsign(reversemode, hold)*randval;\n    }\n    else\n    /* Find the \"range\", most flexible variable */\n    if(is_bb_rule(lp, NODE_RANGESELECT)) {\n      hold = unscaled_value(lp, upbo[i]-lowbo[i], i);\n      if(greedymode)\n        hold *= OFval;\n      hold = my_chsign(reversemode, hold)*randval;\n    }\n\n    /* Select better, check for ties, and split by proximity to 0.5 */\n    if(hold > bestval) {\n      if( (hold > bestval+lp->epsprimal) ||\n          (fabs(modf(lp->solution[i], &holdINT) - 0.5) <\n           fabs(modf(lp->solution[bestvar], &holdINT) - 0.5)) ) {\n        bestval = hold;\n        bestvar = i;\n      }\n    }\n  }\n\nDone:\n  FREE(nonint);\n  return(bestvar);\n}\n\nSTATIC BBPSrec *init_pseudocost(lprec *lp, int pseudotype)\n{\n  int     i;\n  REAL    PSinitUP, PSinitLO;\n  BBPSrec *newitem;\n  MYBOOL  isPSCount;\n\n  /* Allocate memory */\n  newitem = (BBPSrec*) malloc(sizeof(*newitem));\n  newitem->lp = lp;\n  newitem->LOcost = (MATitem*) malloc((lp->columns+1) * sizeof(*newitem->LOcost));\n  newitem->UPcost = (MATitem*) malloc((lp->columns+1) * sizeof(*newitem->UPcost));\n  newitem->secondary = NULL;\n\n  /* Initialize with OF values */\n  newitem->pseodotype = (pseudotype & NODE_STRATEGYMASK);\n  isPSCount = ((pseudotype & NODE_PSEUDONONINTSELECT) != 0);\n  for(i = 1; i <= lp->columns; i++) {\n    newitem->LOcost[i].rownr = 1; /* Actual updates */\n    newitem->LOcost[i].colnr = 1; /* Attempted updates */\n    newitem->UPcost[i].rownr = 1;\n    newitem->UPcost[i].colnr = 1;\n\n    /* Initialize with the plain OF value as conventional usage suggests, or\n       override in case of pseudo-nonint count strategy */\n    PSinitUP = my_chsign(is_maxim(lp), get_mat(lp, 0, i));\n    PSinitLO = -PSinitUP;\n    if(isPSCount) {\n      /* Set default assumed reduction in the number of non-ints by choosing this variable;\n         KE changed from 0 on 30 June 2004 and made two-sided selectable.  Note that the\n         typical value range is <0..1>, with a positive bias for an \"a priori\" assumed\n         fast-converging (low \"MIP-complexity\") model. Very hard models may require\n         negative initialized values for one or both. */\n      PSinitUP = 0.1*0;\n#if 0\n      PSinitUP = my_chsign(PSinitUP < 0, PSinitUP);\n      PSinitLO = -PSinitUP;\n#else\n      PSinitLO = PSinitUP;\n#endif\n    }\n    newitem->UPcost[i].value = PSinitUP;\n    newitem->LOcost[i].value = PSinitLO;\n  }\n  newitem->updatelimit     = lp->bb_PseudoUpdates;\n  newitem->updatesfinished = 0;\n  newitem->restartlimit    = DEF_PSEUDOCOSTRESTART;\n\n  /* Let the user get an opportunity to initialize pseudocosts */\n  if(userabort(lp, MSG_INITPSEUDOCOST))\n    lp->spx_status = USERABORT;\n\n  return( newitem );\n}\n\nSTATIC MYBOOL free_pseudoclass(BBPSrec **PseudoClass)\n{\n  BBPSrec *target = *PseudoClass;\n\n  FREE(target->LOcost);\n  FREE(target->UPcost);\n  target = target->secondary;\n  FREE(*PseudoClass);\n  *PseudoClass = target;\n\n  return( (MYBOOL) (target != NULL) );\n}\n\nSTATIC void free_pseudocost(lprec *lp)\n{\n  if((lp != NULL) && (lp->bb_PseudoCost != NULL)) {\n    while(free_pseudoclass(&(lp->bb_PseudoCost)) );\n  }\n}\n\nMYBOOL __WINAPI set_pseudocosts(lprec *lp, REAL *clower, REAL *cupper, int *updatelimit)\n{\n  int i;\n\n  if((lp->bb_PseudoCost == NULL) || ((clower == NULL) && (cupper == NULL)))\n    return(FALSE);\n  for(i = 1; i <= lp->columns; i++) {\n    if(clower != NULL)\n      lp->bb_PseudoCost->LOcost[i].value = clower[i];\n    if(cupper != NULL)\n      lp->bb_PseudoCost->UPcost[i].value = cupper[i];\n  }\n  if(updatelimit != NULL)\n    lp->bb_PseudoCost->updatelimit = *updatelimit;\n  return(TRUE);\n}\n\nMYBOOL __WINAPI get_pseudocosts(lprec *lp, REAL *clower, REAL *cupper, int *updatelimit)\n{\n  int i;\n\n  if((lp->bb_PseudoCost == NULL) || ((clower == NULL) && (cupper == NULL)))\n    return(FALSE);\n  for(i = 1; i <= lp->columns; i++) {\n    if(clower != NULL)\n      clower[i] = lp->bb_PseudoCost->LOcost[i].value;\n    if(cupper != NULL)\n      cupper[i] = lp->bb_PseudoCost->UPcost[i].value;\n  }\n  if(updatelimit != NULL)\n    *updatelimit = lp->bb_PseudoCost->updatelimit;\n  return(TRUE);\n}\n\nSTATIC REAL get_pseudorange(BBPSrec *pc, int mipvar, int varcode)\n{\n  if(varcode == BB_SC)\n    return( unscaled_value(pc->lp, pc->lp->sc_lobound[mipvar], pc->lp->rows+mipvar) );\n  else\n    return( 1.0 );\n}\n\nSTATIC void update_pseudocost(BBPSrec *pc, int mipvar, int varcode, MYBOOL capupper, REAL varsol)\n{\n  REAL     OFsol, uplim;\n  MATitem  *PS;\n  MYBOOL   nonIntSelect = is_bb_rule(pc->lp, NODE_PSEUDONONINTSELECT);\n\n  /* Establish input values;\n     Note: The pseudocosts are normalized to the 0-1 range! */\n  uplim = get_pseudorange(pc, mipvar, varcode);\n  varsol = modf(varsol/uplim, &OFsol);\n\n  /* Set reference value according to pseudocost mode */\n  if(nonIntSelect)\n    OFsol = pc->lp->bb_bounds->lastvarcus;    /* The count of MIP infeasibilities */\n  else\n    OFsol = pc->lp->solution[0];              /* The problem's objective function value */\n\n  if(isnan(varsol)) {\n    pc->lp->bb_parentOF = OFsol;\n    return;\n  }\n\n  /* Point to the applicable (lower or upper) bound and increment attempted update count */\n  if(capupper) {\n    PS = &pc->LOcost[mipvar];\n  }\n  else {\n    PS = &pc->UPcost[mipvar];\n    varsol = 1-varsol;\n  }\n  PS->colnr++;\n\n  /* Make adjustment to divisor if we are using the ratio pseudo-cost approach */\n  if(is_bb_rule(pc->lp, NODE_PSEUDORATIOSELECT))\n    varsol *= capupper;\n\n  /* Compute the update (consider weighting in favor of most recent) */\n  mipvar = pc->updatelimit;\n  if(((mipvar <= 0) || (PS->rownr < mipvar)) &&\n     (fabs(varsol) > pc->lp->epspivot)) {\n    /* We are interested in the change in the MIP measure (contribution to increase\n       or decrease, as the case may be) and not its last value alone. */\n    PS->value = PS->value*PS->rownr + (pc->lp->bb_parentOF-OFsol) / (varsol*uplim);\n    PS->rownr++;\n    PS->value /= PS->rownr;\n    /* Check if we have enough information to restart */\n    if(PS->rownr == mipvar) {\n      pc->updatesfinished++;\n      if(is_bb_mode(pc->lp, NODE_RESTARTMODE) &&\n        (pc->updatesfinished/(2.0*pc->lp->int_vars) >\n         pc->restartlimit)) {\n        pc->lp->bb_break = AUTOMATIC;\n        pc->restartlimit *= 2.681;  /* KE: Who can figure this one out? */\n        if(pc->restartlimit > 1)\n          pc->lp->bb_rule -= NODE_RESTARTMODE;\n        report(pc->lp, NORMAL, \"update_pseudocost: Restarting with updated pseudocosts\\n\");\n      }\n    }\n  }\n  pc->lp->bb_parentOF = OFsol;\n}\n\nSTATIC REAL get_pseudobranchcost(BBPSrec *pc, int mipvar, MYBOOL dofloor)\n{\n  if(dofloor)\n    return( pc->LOcost[mipvar].value );\n  else\n    return( pc->UPcost[mipvar].value );\n}\n\nSTATIC REAL get_pseudonodecost(BBPSrec *pc, int mipvar, int vartype, REAL varsol)\n{\n  REAL hold, uplim;\n\n  uplim = get_pseudorange(pc, mipvar, vartype);\n  varsol = modf(varsol/uplim, &hold);\n  if(isnan(varsol))\n    varsol = 0;\n\n  hold = pc->LOcost[mipvar].value*varsol +\n         pc->UPcost[mipvar].value*(1-varsol);\n\n  return( hold*uplim );\n}\n\nSTATIC int compute_theta(lprec *lp, int rownr, LREAL *theta, int isupbound, REAL HarrisScalar, MYBOOL primal)\n/* The purpose of this routine is to compute the non-basic bound state / value of\n   the leaving variable. Note that the incoming theta is \"d\" in Chvatal-terminology */\n{\n  int             colnr = lp->var_basic[rownr];\n  LREAL x     = lp->rhs[rownr];\n  REAL            lb    = 0,  /* Put lower bound here when the fully bounded version is implemented */\n                  ub    = lp->upbo[colnr],\n                  eps   = lp->epsprimal;  /* Primal feasibility tolerance */\n\n  /* Compute theta for the primal simplex */\n  HarrisScalar *= eps;\n  if(primal) {\n\n    if(*theta > 0)\n      x -= lb - HarrisScalar;   /* A positive number */\n    else if(ub < lp->infinite)\n      x -= ub + HarrisScalar;   /* A negative number */\n    else {\n      *theta = -lp->infinite;\n      return( colnr );\n    }\n  }\n  /* Compute theta for the dual simplex */\n  else {\n\n    if(isupbound)\n      *theta = -(*theta);\n\n    /* Current value is below or equal to its lower bound */\n    if(x < lb+eps)\n      x -= lb - HarrisScalar;\n\n    /* Current value is above or equal to its upper bound */\n    else if(x > ub-eps) {\n      if(ub >= lp->infinite) {\n        *theta = lp->infinite * my_sign(*theta);\n        return( colnr );\n      }\n      else\n        x -= ub + HarrisScalar;\n    }\n  }\n  my_roundzero(x, lp->epsmachine);\n  *theta = x / *theta;\n\n#ifdef EnforcePositiveTheta\n  /* Check if we have negative theta due to rounding or an internal error */\n  if(*theta < 0) {\n    if(primal && (ub == lb))\n      lp->rhs[rownr] = lb;\n    else\n#ifdef Paranoia\n    if(*theta < -eps) {\n      report(lp, DETAILED, \"compute_theta: Negative theta (%g) not allowed in base-0 version of lp_solve\\n\",\n                            *theta);\n    }\n#endif\n    *theta = 0;\n  }\n#endif\n\n  return( colnr );\n}\n\nSTATIC MYBOOL check_degeneracy(lprec *lp, REAL *pcol, int *degencount)\n/* Check if the entering column Pi=Inv(B)*a is likely to produce improvement;\n   (cfr. Istvan Maros: CTOTSM p. 233) */\n{\n  int  i, ndegen;\n  REAL *rhs, sdegen, epsmargin = lp->epsprimal;\n\n  sdegen = 0;\n  ndegen = 0;\n  rhs    = lp->rhs;\n  for(i = 1; i <= lp->rows; i++) {\n    rhs++;\n    pcol++;\n    if(fabs(*rhs) < epsmargin) {\n      sdegen += *pcol;\n      ndegen++;\n    }\n    else if(fabs((*rhs)-lp->upbo[lp->var_basic[i]]) < epsmargin) {\n      sdegen -= *pcol;\n      ndegen++;\n    }\n  }\n  if(degencount != NULL)\n    *degencount = ndegen;\n/*  sdegen += epsmargin*ndegen; */\n  return( (MYBOOL) (sdegen <= 0) );\n}\n\nSTATIC MYBOOL performiteration(lprec *lp, int rownr, int varin, LREAL theta, MYBOOL primal, MYBOOL allowminit,\n                               REAL *prow, int *nzprow, REAL *pcol, int *nzpcol, int *boundswaps)\n{\n  (void)pcol;\n  (void)nzpcol;\n  int    varout;\n  REAL   pivot, epsmargin, leavingValue, leavingUB, enteringUB;\n  MYBOOL leavingToUB = FALSE, enteringFromUB, enteringIsFixed, leavingIsFixed;\n  MYBOOL *islower = &(lp->is_lower[varin]);\n  MYBOOL minitNow = FALSE, minitStatus = ITERATE_MAJORMAJOR;\n  LREAL  deltatheta = theta;\n  (void)pcol;\n  (void)nzpcol;\n\n  if(userabort(lp, MSG_ITERATION))\n    return( minitNow );\n\n#ifdef Paranoia\n  if(rownr > lp->rows) {\n    if (lp->spx_trace)\n      report(lp, IMPORTANT, \"performiteration: Numeric instability encountered!\\n\");\n    lp->spx_status = NUMFAILURE;\n    return( FALSE );\n  }\n#endif\n  varout = lp->var_basic[rownr];\n#ifdef Paranoia\n  if(!lp->is_lower[varout])\n    report(lp, SEVERE, \"performiteration: Leaving variable %d was at its upper bound at iter %.0f\\n\",\n                        varout, (double) get_total_iter(lp));\n#endif\n\n  /* Theta is the largest change possible (strictest constraint) for the entering\n     variable (Theta is Chvatal's \"t\", ref. Linear Programming, pages 124 and 156) */\n  lp->current_iter++;\n\n  /* Test if it is possible to do a cheap \"minor iteration\"; i.e. set entering\n     variable to its opposite bound, without entering the basis - which is\n     obviously not possible for fixed variables! */\n  epsmargin = lp->epsprimal;\n  enteringFromUB = !(*islower);\n  enteringUB = lp->upbo[varin];\n  leavingUB  = lp->upbo[varout];\n  enteringIsFixed = (MYBOOL) (fabs(enteringUB) < epsmargin);\n  leavingIsFixed  = (MYBOOL) (fabs(leavingUB) < epsmargin);\n#if defined _PRICE_NOBOUNDFLIP\n  allowminit     &= !ISMASKSET(lp->piv_strategy, PRICE_NOBOUNDFLIP);\n#endif\n#ifdef Paranoia\n  if(enteringUB < 0)\n    report(lp, SEVERE, \"performiteration: Negative range for entering variable %d at iter %.0f\\n\",\n                        varin, (double) get_total_iter(lp));\n  if(leavingUB < 0)\n    report(lp, SEVERE, \"performiteration: Negative range for leaving variable %d at iter %.0f\\n\",\n                        varout, (double) get_total_iter(lp));\n#endif\n\n  /* Handle batch bound swaps with the dual long-step algorithm;\n     Loop over specified bound swaps; update RHS and Theta for bound swaps */\n  if((boundswaps != NULL) && (boundswaps[0] > 0)) {\n\n    int   i, boundvar;\n    REAL  *hold;\n\n    /* Allocate and initialize accumulation array */\n    allocREAL(lp, &hold, lp->rows + 1, TRUE);\n\n    /* Accumulate effective bound swaps and update flag */\n    for(i = 1; i <= boundswaps[0]; i++) {\n      boundvar = boundswaps[i];\n      deltatheta = my_chsign(!lp->is_lower[boundvar], lp->upbo[boundvar]);\n      mat_multadd(lp->matA, hold, boundvar, deltatheta);\n      lp->is_lower[boundvar] = !lp->is_lower[boundvar];\n    }\n    lp->current_bswap += boundswaps[0];\n    lp->current_iter  += boundswaps[0];\n\n    /* Solve for bound flip update vector (note that this does not\n       overwrite the stored update vector for the entering variable) */\n    ftran(lp, hold, NULL, lp->epsmachine);\n    if(!lp->obj_in_basis)\n      hold[0] = 0; /* The correct reduced cost goes here (adjusted for bound state) ****** */\n\n    /* Update the RHS / basic variable values and set revised thetas */\n    pivot = lp->bfp_pivotRHS(lp, 1, hold);\n    deltatheta = multi_enteringtheta(lp->longsteps);\n    theta = deltatheta;\n\n    FREE(hold);\n  }\n\n  /* Otherwise to traditional check for single bound swap */\n  else if(allowminit &&\n           !enteringIsFixed) {\n\n/*    pivot = epsmargin; */\n    pivot = lp->epsdual;\n/* #define v51mode */ /* Enable this for v5.1 operation mode */\n#ifdef v51mode\n    if(((lp->simplex_mode & SIMPLEX_Phase1_DUAL) == 0) ||\n       !is_constr_type(lp, rownr, EQ))                      /* *** DEBUG CODE KE */\n#endif\n    if(enteringUB - theta < -pivot) {\n\n#ifndef v51mode\n      if(fabs(enteringUB - theta) < pivot)\n        minitStatus = ITERATE_MINORMAJOR;\n      else\n#endif\n        minitStatus = ITERATE_MINORRETRY;\n      minitNow    = (MYBOOL) (minitStatus != ITERATE_MAJORMAJOR);\n    }\n  }\n\n  /* Process for traditional style single minor iteration */\n  if(minitNow) {\n\n   /* Set the new values (note that theta is set to always be positive) */\n    theta = MIN(fabs(theta), enteringUB);\n\n    /* Update the RHS / variable values and do bound-swap */\n    pivot = lp->bfp_pivotRHS(lp, theta, NULL);\n    *islower = !(*islower);\n\n    lp->current_bswap++;\n\n  }\n\n  /* Process for major iteration */\n  else {\n\n    /* Update the active pricer for the current pivot */\n    updatePricer(lp, rownr, varin, lp->bfp_pivotvector(lp), prow, nzprow);\n\n    /* Update the current basic variable values */\n    pivot = lp->bfp_pivotRHS(lp, theta, NULL);\n\n    /* See if the leaving variable goes directly to its upper bound. */\n    leavingValue = lp->rhs[rownr];\n    leavingToUB = (MYBOOL) (leavingValue > 0.5*leavingUB);\n    lp->is_lower[varout] = leavingIsFixed || !leavingToUB;\n\n    /* Set the value of the entering varible (theta always set to be positive) */\n    if(enteringFromUB) {\n      lp->rhs[rownr] = enteringUB - deltatheta;\n      *islower = TRUE;\n    }\n    else\n      lp->rhs[rownr] = deltatheta;\n    my_roundzero(lp->rhs[rownr], epsmargin);\n\n   /* Update basis indeces */\n    varout = set_basisvar(lp, rownr, varin);\n\n   /* Finalize the update in preparation for next major iteration */\n    lp->bfp_finishupdate(lp, enteringFromUB);\n\n  }\n\n  /* Show pivot tracking information, if specified */\n  if((lp->verbose > NORMAL) && (MIP_count(lp) == 0) &&\n     ((lp->current_iter % MAX(2, lp->rows / 10)) == 0))\n    report(lp, NORMAL, \"Objective value \" RESULTVALUEMASK \" at iter %10.0f.\\n\",\n                       lp->rhs[0], (double) get_total_iter(lp));\n\n#if 0\n  if(verify_solution(lp, FALSE, my_if(minitNow, \"MINOR\", \"MAJOR\")) >= 0) {\n    if(minitNow)\n      pivot = get_obj_active(lp, varin);\n    else\n      pivot = get_obj_active(lp, varout);\n  }\n#endif\n#if 0\n  if((lp->longsteps != NULL) && (boundswaps[0] > 0) && lp->longsteps->objcheck &&\n    ((pivot = fabs(my_reldiff(lp->rhs[0], lp->longsteps->obj_last))) > lp->epssolution)) {\n    report(lp, IMPORTANT, \"performiteration: Objective value gap %8.6f found at iter %6.0f (%d bound flips, %d)\\n\",\n                          pivot, (double) get_total_iter(lp), boundswaps[0], enteringFromUB);\n  }\n#endif\n\n  if(lp->spx_trace) {\n    if(minitNow)\n      report(lp, NORMAL, \"I:%5.0f - minor - %5d ignored,          %5d flips  from %s with THETA=%g and OBJ=%g\\n\",\n                         (double) get_total_iter(lp), varout, varin, (enteringFromUB ? \"UPPER\" : \"LOWER\"), theta, lp->rhs[0]);\n    else\n      report(lp, NORMAL, \"I:%5.0f - MAJOR - %5d leaves to %s,  %5d enters from %s with THETA=%g and OBJ=%g\\n\",\n                         (double) get_total_iter(lp), varout, (leavingToUB    ? \"UPPER\" : \"LOWER\"),\n                                           varin,  (enteringFromUB ? \"UPPER\" : \"LOWER\"), theta, lp->rhs[0]);\n    if(minitNow) {\n      if(!lp->is_lower[varin])\n        report(lp, DETAILED,\n        \"performiteration: Variable %d changed to its lower bound at iter %.0f (from %g)\\n\",\n        varin, (double) get_total_iter(lp), enteringUB);\n      else\n        report(lp, DETAILED,\n        \"performiteration: Variable %d changed to its upper bound at iter %.0f (to %g)\\n\",\n        varin, (double) get_total_iter(lp), enteringUB);\n    }\n    else\n      report(lp, NORMAL,\n          \"performiteration: Variable %d entered basis at iter %.0f at \" RESULTVALUEMASK \"\\n\",\n          varin, (double) get_total_iter(lp), lp->rhs[rownr]);\n    if(!primal) {\n      pivot = compute_feasibilitygap(lp, (MYBOOL)!primal, TRUE);\n      report(lp, NORMAL, \"performiteration: Feasibility gap at iter %.0f is \" RESULTVALUEMASK \"\\n\",\n                         (double) get_total_iter(lp), pivot);\n    }\n    else\n      report(lp, NORMAL,\n          \"performiteration: Current objective function value at iter %.0f is \" RESULTVALUEMASK \"\\n\",\n          (double) get_total_iter(lp), lp->rhs[0]);\n  }\n\n  return( minitStatus );\n\n} /* performiteration */\n\nSTATIC REAL get_refactfrequency(lprec *lp, MYBOOL final)\n{\n  COUNTER iters;\n  int     refacts;\n\n  /* Get numerator and divisor information */\n  iters   = (lp->total_iter+lp->current_iter) - (lp->total_bswap+lp->current_bswap);\n  refacts = lp->bfp_refactcount(lp, BFP_STAT_REFACT_TOTAL);\n\n  /* Return frequency for different cases:\n      1) Actual frequency in case final statistic is desired\n      2) Dummy if we are in a B&B process\n      3) Frequency with added initialization offsets which\n         are diluted in course of the solution process */\n  if(final)\n    return( (REAL) (iters) / MAX(1,refacts) );\n  else if(lp->bb_totalnodes > 0)\n    return( (REAL) lp->bfp_pivotmax(lp) );\n  else\n    return( (REAL) (lp->bfp_pivotmax(lp)+iters) / (1+refacts) );\n}\n\n#if 0\n/* INLINE */ MYBOOL is_fixedvar(lprec *lp, int variable)\n{\n  if((lp->bb_bounds != NULL && lp->bb_bounds->UBzerobased) || (variable <= lp->rows))\n    return( (MYBOOL) (lp->upbo[variable] < lp->epsprimal) );\n  else\n    return( (MYBOOL) (lp->upbo[variable]-lp->lowbo[variable] < lp->epsprimal) );\n} /* is_fixedvar */\n#else\nMYBOOL is_fixedvar(lprec *lp, int varnr)\n{\n  if(lp->bb_bounds == NULL) {\n    if(varnr <= lp->rows)\n      return( (MYBOOL) (lp->orig_upbo[varnr] < lp->epsmachine) );\n    else\n      return( (MYBOOL) (lp->orig_upbo[varnr]-lp->orig_lowbo[varnr] < lp->epsmachine) );\n  }\n  else if((varnr <= lp->rows) || (lp->bb_bounds->UBzerobased == TRUE))\n    return( (MYBOOL) (lp->upbo[varnr] < lp->epsvalue) );\n  else\n    return( (MYBOOL) (lp->upbo[varnr]-lp->lowbo[varnr] < lp->epsvalue) );\n}\n#endif\n\nSTATIC MYBOOL solution_is_int(lprec *lp, int index, MYBOOL checkfixed)\n{\n#if 1\n  return( (MYBOOL) (isINT(lp, lp->solution[index]) && (!checkfixed || is_fixedvar(lp, index))) );\n#else\n  if(isINT(lp, lp->solution[index])) {\n    if(checkfixed)\n      return(is_fixedvar(lp, index));\n    else\n      return(TRUE);\n  }\n  return(FALSE);\n#endif\n} /* solution_is_int */\n\n\nMYBOOL __WINAPI set_multiprice(lprec *lp, int multiblockdiv)\n{\n  /* See if we are resetting multiply priced column structures */\n  if(multiblockdiv != lp->multiblockdiv) {\n    if(multiblockdiv < 1)\n      multiblockdiv = 1;\n    lp->multiblockdiv = multiblockdiv;\n    multi_free(&(lp->multivars));\n  }\n  return( TRUE );\n}\n\nint __WINAPI get_multiprice(lprec *lp, MYBOOL getabssize)\n{\n  if((lp->multivars == NULL) || (lp->multivars->used == 0))\n    return( 0 );\n  if(getabssize)\n    return( lp->multivars->size );\n  else\n    return( lp->multiblockdiv );\n}\n\nMYBOOL __WINAPI set_partialprice(lprec *lp, int blockcount, int *blockstart, MYBOOL isrow)\n{\n  int        ne, i, items;\n  partialrec **blockdata;\n\n  /* Determine partial target (rows or columns) */\n  if(isrow)\n    blockdata = &(lp->rowblocks);\n  else\n    blockdata = &(lp->colblocks);\n\n  /* See if we are resetting partial blocks */\n  ne = 0;\n  items = IF(isrow, lp->rows, lp->columns);\n  if(blockcount == 1)\n    partial_freeBlocks(blockdata);\n\n  /* Set a default block count if this was not specified */\n  else if(blockcount <= 0) {\n    blockstart = NULL;\n    if(items < DEF_PARTIALBLOCKS*DEF_PARTIALBLOCKS)\n      blockcount = items / DEF_PARTIALBLOCKS + 1;\n    else\n      blockcount = DEF_PARTIALBLOCKS;\n    ne = items / blockcount;\n    if(ne * blockcount < items)\n      ne++;\n  }\n\n  /* Fill partial block arrays;\n     Note: These will be modified during preprocess to reflect\n           presolved columns and the handling of slack variables. */\n  if(blockcount > 1) {\n    MYBOOL     isNew = (MYBOOL) (*blockdata == NULL);\n\n    /* Provide for extra block with slack variables in the column mode */\n    i = 0;\n    if(!isrow)\n      i++;\n\n    /* (Re)-allocate memory */\n    if(isNew)\n      *blockdata = partial_createBlocks(lp, isrow);\n    allocINT(lp, &((*blockdata)->blockend), blockcount+i+1, AUTOMATIC);\n    allocINT(lp, &((*blockdata)->blockpos), blockcount+i+1, AUTOMATIC);\n\n    /* Copy the user-provided block start positions */\n    if(blockstart != NULL) {\n      MEMCOPY((*blockdata)->blockend+i, blockstart, blockcount+i+1);\n      if(!isrow) {\n        blockcount++;\n        (*blockdata)->blockend[0] = 1;\n        for(i = 1; i < blockcount; i++)\n          (*blockdata)->blockend[i] += lp->rows;\n      }\n    }\n\n    /* Fill the block ending positions if they were not specified */\n    else {\n      (*blockdata)->blockend[0] = 1;\n      (*blockdata)->blockpos[0] = 1;\n      if(ne == 0) {\n        ne = items / blockcount;\n        /* Increase the block size if we have a fractional value */\n        while(ne * blockcount < items)\n          ne++;\n      }\n      i = 1;\n      if(!isrow) {\n        (*blockdata)->blockend[i] = (*blockdata)->blockend[i-1]+lp->rows;\n        blockcount++;\n        i++;\n        items += lp->rows;\n      }\n      for(; i < blockcount; i++)\n        (*blockdata)->blockend[i] = (*blockdata)->blockend[i-1]+ne;\n\n      /* Let the last block handle the \"residual\" */\n      (*blockdata)->blockend[blockcount] = items+1;\n    }\n\n    /* Fill starting positions (used in multiple partial pricing) */\n    for(i = 1; i <= blockcount; i++)\n      (*blockdata)->blockpos[i] = (*blockdata)->blockend[i-1];\n\n  }\n\n  /* Update block count */\n  (*blockdata)->blockcount = blockcount;\n\n\n  return( TRUE );\n} /* set_partialprice */\n\nvoid __WINAPI get_partialprice(lprec *lp, int *blockcount, int *blockstart, MYBOOL isrow)\n{\n  partialrec *blockdata;\n\n  /* Determine partial target (rows or columns) */\n  if(isrow)\n    blockdata = lp->rowblocks;\n  else\n    blockdata = lp->colblocks;\n\n  *blockcount = partial_countBlocks(lp, isrow);\n  if((blockdata != NULL) && (blockstart != NULL)) {\n    int i = 0, k = *blockcount;\n    if(!isrow)\n      i++;\n    MEMCOPY(blockstart, blockdata->blockend + i, k - i);\n    if(!isrow) {\n      k -= i;\n      for(i = 0; i < k; i++)\n        blockstart[i] -= lp->rows;\n    }\n  }\n}\n\n\n/* Solution-related functions */\nSTATIC MYBOOL bb_better(lprec *lp, int target, int mode)\n/* Must handle four modes (logic assumes Min!):\n      -----|--.--|----->\n   1  ++++++-----------  LHS exclusive test point is better\n   2  +++++++++--------  LHS inclusive\n   3  ++++++-----++++++  LHS+RHS exclusive\n   4  --------+++++++++  RHS inclusive\n   5  -----------++++++  RHS exclusive\n*/\n{\n  REAL   epsvalue, offset = lp->epsprimal,\n         refvalue = lp->infinite, testvalue = lp->solution[0];\n  MYBOOL ismax = is_maxim(lp),\n         relgap = is_action(mode, OF_TEST_RELGAP),\n         fcast  = is_action(target, OF_PROJECTED),\n         delta  = is_action(target, OF_DELTA);\n\n  if(relgap) {\n    epsvalue = lp->mip_relgap;\n    clear_action(&mode, OF_TEST_RELGAP);\n  }\n  else\n    epsvalue = lp->mip_absgap;\n\n  if(delta)\n    clear_action(&target, OF_DELTA);\n  if(fcast)\n    clear_action(&target, OF_PROJECTED);\n#ifdef Paranoia\n  if((mode < OF_TEST_BT) || (mode > OF_TEST_WT))\n    report(lp, SEVERE, \"bb_better: Passed invalid mode '%d'\\n\", mode);\n#endif\n\n  switch(target) {\n    case OF_RELAXED:   refvalue = lp->real_solution;\n                       break;\n    case OF_INCUMBENT: refvalue = lp->best_solution[0];\n                       break;\n    case OF_WORKING:  refvalue = my_chsign(!ismax, lp->bb_workOF /* unscaled_value(lp, lp->bb_workOF, 0) */ );\n                       if(fcast)\n                         testvalue = my_chsign(!ismax, lp->longsteps->obj_last) - epsvalue;\n                       else\n                         testvalue = my_chsign(!ismax, lp->rhs[0] /* unscaled_value(lp, lp->rhs[0], 0) */);\n                       break;\n    case OF_USERBREAK: refvalue = lp->bb_breakOF;\n                       break;\n    case OF_HEURISTIC: refvalue = lp->bb_heuristicOF;\n                       break;\n    case OF_DUALLIMIT: refvalue = lp->bb_limitOF;\n                       break;\n    default         :  report(lp, SEVERE, \"bb_better: Passed invalid test target '%d'\\n\", target);\n                       return( FALSE );\n  }\n\n  /* Adjust the test value for the desired acceptability window */\n  if(delta) {\n    SETMAX(epsvalue, lp->bb_deltaOF - epsvalue);\n  }\n  else\n    epsvalue = my_chsign(target >= OF_USERBREAK, epsvalue); /* *** This seems Ok, but should be verified */\n  testvalue += my_chsign(ismax, epsvalue);\n\n  /* Compute the raw test value */\n  if(relgap)\n    testvalue = my_reldiff(testvalue, refvalue);\n  else\n    testvalue -= refvalue;\n\n  /* Make test value adjustment based on the selected option */\n  if(mode == OF_TEST_NE)\n    relgap = (MYBOOL) (fabs(testvalue) >= offset);\n  else {\n    testvalue = my_chsign(mode > OF_TEST_NE, testvalue);\n    testvalue = my_chsign(ismax, testvalue);\n    relgap = (MYBOOL) (testvalue < offset);\n  }\n  return( relgap );\n}\n\nSTATIC void construct_solution(lprec *lp, REAL *target)\n{\n  int     i, j, basi;\n  REAL    f, epsvalue = lp->epsprimal;\n  REAL    *solution;\n  REAL    *value;\n  int     *rownr;\n  MATrec  *mat = lp->matA;\n\n  if(target == NULL)\n    solution = lp->solution;\n  else\n    solution = target;\n\n  /* Initialize OF and slack variables. */\n  for(i = 0; i <= lp->rows; i++) {\n#ifdef LegacySlackDefinition\n    if(i == 0)\n      f = unscaled_value(lp, -lp->orig_rhs[i], i);\n    else {\n      j = lp->presolve_undo->var_to_orig[i];\n      if(j > 0) {\n        f = lp->presolve_undo->fixed_rhs[j];\n        f = unscaled_value(lp, f, i);\n      }\n      else\n        f = 0;\n    }\n#else\n    f = lp->orig_rhs[i];\n    if((i > 0) && !lp->is_basic[i] && !lp->is_lower[i])\n#ifdef SlackInitMinusInf\n      f -= my_chsign(is_chsign(lp, i), fabs(lp->upbo[i]));\n#else\n      f -= my_chsign(is_chsign(lp, i), fabs(lp->lowbo[i] + lp->upbo[i]));\n#endif\n    f = unscaled_value(lp, -f, i);\n#endif\n    solution[i] = f;\n  }\n\n  /* Initialize user variables to their lower bounds. */\n  for(i = lp->rows+1; i <= lp->sum; i++)\n    solution[i] = lp->lowbo[i];\n\n  /* Add values of user basic variables. */\n  for(i = 1; i <= lp->rows; i++) {\n    basi = lp->var_basic[i];\n    if(basi > lp->rows) {\n      solution[basi] += lp->rhs[i];\n    }\n  }\n\n  /* 1. Adjust non-basic variables at their upper bounds,\n     2. Unscale all user variables,\n     3. Optionally do precision management. */\n  for(i = lp->rows + 1; i <= lp->sum; i++) {\n    if(!lp->is_basic[i] && !lp->is_lower[i])\n      solution[i] += lp->upbo[i];\n    solution[i] = unscaled_value(lp, solution[i], i);\n#ifdef xImproveSolutionPrecision\n    if(is_int(lp, i-lp->rows))\n      solution[i] = restoreINT(solution[i], lp->epsint);\n    else\n      solution[i] = restoreINT(solution[i], lp->epsprimal);\n#endif\n  }\n\n  /* Compute the OF and slack values \"in extentio\" */\n  for(j = 1; j <= lp->columns; j++) {\n    f = solution[lp->rows + j];\n    if(f != 0) {\n      solution[0] += f * unscaled_mat(lp, lp->orig_obj[j], 0, j);\n      i = mat->col_end[j-1];\n      basi = mat->col_end[j];\n      rownr = &COL_MAT_ROWNR(i);\n      value = &COL_MAT_VALUE(i);\n      for(; i < basi;\n          i++, rownr += matRowColStep, value += matValueStep)\n        solution[*rownr] += f * unscaled_mat(lp, *value, *rownr, j);\n    }\n  }\n\n  /* Do slack precision management and sign reversal if necessary */\n  for(i = 0; i <= lp->rows; i++) {\n#ifdef ImproveSolutionPrecision\n    my_roundzero(solution[i], epsvalue);\n#endif\n    if(is_chsign(lp, i))\n      solution[i] = my_flipsign(solution[i]);\n  }\n\n /* Record the best real-valued solution and compute a simple MIP solution limit */\n  if(target == NULL) {\n    if(is_infinite(lp, lp->real_solution)) {\n      lp->bb_workOF = lp->rhs[0];\n      lp->real_solution = solution[0];\n      if(is_infinite(lp, lp->bb_limitOF))\n        lp->bb_limitOF = lp->real_solution;\n      else {\n        if(is_maxim(lp)) {\n          SETMIN(lp->bb_limitOF, lp->real_solution);\n        }\n        else {\n          SETMAX(lp->bb_limitOF, lp->real_solution);\n        }\n      }\n\n      /* Do MIP-related tests and computations */\n      if((lp->int_vars > 0) && mat_validate(lp->matA) /* && !lp->wasPresolved */) { /* && !lp->wasPresolved uncommented by findings of William H. Patton. The code was never executed when the test was there. The code has effect in an integer model with all integer objective coeff. to cut-off optimization and thus make it faster */\n        REAL fixedOF = unscaled_value(lp, lp->orig_rhs[0], 0);\n\n        /* Check if we have an all-integer OF */\n        basi = lp->columns;\n        for(j = 1; j <= basi; j++) {\n          f = fabs(get_mat(lp, 0, j)) + lp->epsint / 2;\n          if(f > lp->epsint) { /* If coefficient is 0 then it doesn't influence OF, even it variable is not integer */\n            if(!is_int(lp, j) || (fmod(f, 1) > lp->epsint))\n              break;\n          }\n        }\n\n        /* If so, we can round up the fractional OF */\n        if(j > basi) {\n          f = my_chsign(is_maxim(lp), lp->real_solution) + fixedOF;\n          f = floor(f+(1-epsvalue));\n          f = my_chsign(is_maxim(lp), f - fixedOF);\n          if(is_infinite(lp, lp->bb_limitOF))\n            lp->bb_limitOF = f;\n          else if(is_maxim(lp)) {\n            SETMIN(lp->bb_limitOF, f);\n          }\n          else {\n            SETMAX(lp->bb_limitOF, f);\n          }\n        }\n      }\n\n      /* Check that a user limit on the OF is feasible */\n      if((lp->int_vars > 0) &&\n         (my_chsign(is_maxim(lp), my_reldiff(lp->best_solution[0],lp->bb_limitOF)) < -epsvalue)) {\n        lp->spx_status = INFEASIBLE;\n        lp->bb_break = TRUE;\n      }\n    }\n  }\n\n} /* construct_solution */\n\nSTATIC int check_solution(lprec *lp, int  lastcolumn, REAL *solution,\n                          REAL *upbo, REAL *lowbo, REAL tolerance)\n{\n/*#define UseMaxValueInCheck*/\n#define RelativeAccuracyCheck\n  MYBOOL isSC;\n  REAL   test, value, diff, maxdiff = 0.0, maxerr = 0.0;\n#ifndef RelativeAccuracyCheck\n  REAL   hold;\n#endif\n#ifdef UseMaxValueInCheck\n  REAL *maxvalue = NULL;\n#elif !defined RelativeAccuracyCheck\n  REAL *plusum = NULL, *negsum = NULL;\n#endif\n  int    i,j,n, errlevel = IMPORTANT, errlimit = 10;\n  int    solveStatus = OPTIMAL;\n\n  report(lp, NORMAL, \" \\n\");\n  if(MIP_count(lp) > 0)\n    report(lp, NORMAL, \"%s solution  \" RESULTVALUEMASK \" after %10.0f iter, %9.0f nodes (gap %.1f%%).\\n\",\n                       my_if(lp->bb_break && !bb_better(lp, OF_DUALLIMIT, OF_TEST_BE) && bb_better(lp, OF_RELAXED, OF_TEST_NE), \"Subopt.\", \"Optimal\"),\n                       solution[0], (double) lp->total_iter, (double) lp->bb_totalnodes,\n                       100.0*fabs(my_reldiff(solution[0], lp->bb_limitOF)));\n  else\n    report(lp, NORMAL, \"Optimal solution  \" RESULTVALUEMASK \" after %10.0f iter.\\n\",\n                       solution[0], (double) lp->total_iter);\n\n /* Find the signed sums and the largest absolute product in the matrix (exclude the OF for speed) */\n#ifdef UseMaxValueInCheck\n  allocREAL(lp, &maxvalue, lp->rows + 1, FALSE);\n  for(i = 0; i <= lp->rows; i++)\n    maxvalue[i] = fabs(get_rh(lp, i));\n#elif !defined RelativeAccuracyCheck\n  allocREAL(lp, &plusum, lp->rows + 1, TRUE);\n  allocREAL(lp, &negsum, lp->rows + 1, TRUE);\n#endif\n\n#if defined UseMaxValueInCheck || !defined RelativeAccuracyCheck\n  n = get_nonzeros(lp);\n  matRownr = &COL_MAT_ROWNR(0);\n  matColnr = &COL_MAT_COLNR(0);\n  matValue = &COL_MAT_VALUE(0);\n  for(i = 0; i < n; i++, matRownr += matRowColStep,\n                         matColnr += matRowColStep,\n                         matValue += matValueStep) {\n    test = unscaled_mat(lp, *matValue, *matRownr, *matColnr);\n    test *= solution[lp->rows + (*matColnr)];\n#ifdef UseMaxValueInCheck\n    test = fabs(test);\n    if(test > maxvalue[*matRownr])\n      maxvalue[*matRownr] = test;\n#elif !defined RelativeAccuracyCheck\n    if(test > 0)\n      plusum[*matRownr] += test;\n    else\n      negsum[*matRownr] += test;\n#endif\n  }\n#endif\n\n /* Check if solution values are within the bounds; allowing a margin for numeric errors */\n  n = 0;\n  for(i = lp->rows + 1; i <= lp->rows+lastcolumn; i++) {\n\n    value = solution[i];\n\n    /* Check for case where we are testing an intermediate solution\n       (variables shifted to the origin) */\n    if(lowbo == NULL)\n      test = 0;\n    else\n      test = unscaled_value(lp, lowbo[i], i);\n\n    isSC = is_semicont(lp, i - lp->rows);\n    diff = -my_reldiff(value, test);\n#ifdef RelativeAccuracyCheck\n    if (isSC && diff > 0 && my_reldiff(fabs(value), 0.0) < diff)\n        diff = my_reldiff(fabs(value), 0.0);\n#else\n    if(isSC && diff > 0 && (value < test/2))\n      test = 0;\n#endif\n    if(diff > 0) {\n      SETMAX(maxdiff, diff);\n#ifdef RelativeAccuracyCheck\n      maxerr = maxdiff;\n#else\n      SETMAX(maxerr, test - value);\n#endif\n    }\n    if((diff > tolerance) && !isSC)  {\n      if(n < errlimit)\n      report(lp, errlevel,\n        \"check_solution: Variable   %s = \" RESULTVALUEMASK \" is below its lower bound \" RESULTVALUEMASK \"\\n\",\n         get_col_name(lp, i-lp->rows), value, test);\n      n++;\n    }\n\n    test = unscaled_value(lp, upbo[i], i);\n    diff = my_reldiff(value, test);\n    if(diff > 0) {\n      SETMAX(maxdiff, diff);\n#ifdef RelativeAccuracyCheck\n      maxerr = maxdiff;\n#else\n      SETMAX(maxerr, value - test);\n#endif\n    }\n    if(diff > tolerance) {\n      if(n < errlimit)\n      report(lp, errlevel,\n         \"check_solution: Variable   %s = \" RESULTVALUEMASK \" is above its upper bound \" RESULTVALUEMASK \"\\n\",\n         get_col_name(lp, i-lp->rows), value, test);\n      n++;\n    }\n  }\n\n /* Check if constraint values are within the bounds; allowing a margin for numeric errors */\n  for(i = 1; i <= lp->rows; i++) {\n    test = lp->orig_rhs[i];\n\n    if(is_infinite(lp, test))\n      continue;\n\n#ifdef LegacySlackDefinition\n    j = lp->presolve_undo->var_to_orig[i];\n    if(j != 0) {\n      if(is_infinite(lp, lp->presolve_undo->fixed_rhs[j]))\n        continue;\n      test += lp->presolve_undo->fixed_rhs[j];\n    }\n#endif\n\n    if(is_chsign(lp, i)) {\n      test = my_flipsign(test);\n      test += fabs(upbo[i]);\n    }\n    value = solution[i];\n    test = unscaled_value(lp, test, i);\n#ifndef LegacySlackDefinition\n    value += test;\n#endif\n    diff = my_reldiff(value, test);\n#ifndef RelativeAccuracyCheck\n#ifdef UseMaxValueInCheck\n    hold = maxvalue[i];\n#else\n    hold = plusum[i] - negsum[i];\n#endif\n    if(hold < lp->epsvalue)\n      hold = 1;\n\n    diff = my_reldiff((value+1)/hold, (test+1)/hold);\n#endif\n    if(diff > 0) {\n      SETMAX(maxdiff, diff);\n#ifdef RelativeAccuracyCheck\n      maxerr = maxdiff;\n#else\n      SETMAX(maxerr, value-test);\n#endif\n    }\n    if(diff > tolerance) {\n      if(n < errlimit)\n      report(lp, errlevel,\n        \"check_solution: Constraint %s = \" RESULTVALUEMASK \" is above its %s \" RESULTVALUEMASK \"\\n\",\n        get_row_name(lp, i), value,\n        (is_constr_type(lp, i, EQ) ? \"equality of\" : \"upper bound\"), test);\n      n++;\n    }\n\n    test = lp->orig_rhs[i];\n#ifdef LegacySlackDefinition\n    j = lp->presolve_undo->var_to_orig[i];\n    if(j != 0) {\n      if(is_infinite(lp, lp->presolve_undo->fixed_rhs[j]))\n        continue;\n      test += lp->presolve_undo->fixed_rhs[j];\n    }\n#endif\n\n    value = solution[i];\n    if(is_chsign(lp, i))\n      test = my_flipsign(test);\n    else {\n      if(is_infinite(lp, upbo[i]))\n        continue;\n      test -= fabs(upbo[i]);\n#ifndef LegacySlackDefinition\n      value = fabs(upbo[i]) - value;\n#endif\n    }\n    test = unscaled_value(lp, test, i);\n#ifndef LegacySlackDefinition\n    value += test;\n#endif\n    diff = -my_reldiff(value, test);\n#ifndef RelativeAccuracyCheck\n#ifdef UseMaxValueInCheck\n    hold = maxvalue[i];\n#else\n    hold = plusum[i] - negsum[i];\n#endif\n    if(hold < lp->epsvalue)\n      hold = 1;\n    diff = -my_reldiff((value+1)/hold, (test+1)/hold);\n#endif\n    if(diff > 0) {\n      SETMAX(maxdiff, diff);\n#ifdef RelativeAccuracyCheck\n      maxerr = maxdiff;\n#else\n      SETMAX(maxerr, test-value);\n#endif\n    }\n    if(diff > tolerance) {\n      if(n < errlimit)\n      report(lp, errlevel,\n        \"check_solution: Constraint %s = \" RESULTVALUEMASK \" is below its %s \" RESULTVALUEMASK \"\\n\",\n        get_row_name(lp, i), value,\n        (is_constr_type(lp, i, EQ) ? \"equality of\" : \"lower bound\"), test);\n      n++;\n    }\n  }\n\n#ifdef UseMaxValueInCheck\n  FREE(maxvalue);\n#elif !defined RelativeAccuracyCheck\n  FREE(plusum);\n  FREE(negsum);\n#endif\n\n#ifdef RelativeAccuracyCheck\n  report(lp, NORMAL, \"\\nRelative numeric accuracy ||*|| = %g\\n\", maxdiff);\n  if (maxdiff > lp->accuracy_error)\n  {\n    report(lp, IMPORTANT, \"\\nUnacceptable accuracy found (worse than required %g)\\n\", lp->accuracy_error);\n    solveStatus = ACCURACYERROR;\n  }\n#else\n  if(n > 0) {\n    report(lp, IMPORTANT, \"\\nSeriously low accuracy found ||*|| = %g (rel. error %g)\\n\",\n               maxerr, maxdiff);\n    solveStatus = NUMFAILURE;\n  }\n  else {\n    if(maxerr > 1.0e-7)\n      report(lp, NORMAL, \"\\nMarginal numeric accuracy ||*|| = %g (rel. error %g)\\n\",\n                 maxerr, maxdiff);\n    else if(maxerr > 1.0e-9)\n      report(lp, NORMAL, \"\\nReasonable numeric accuracy ||*|| = %g (rel. error %g)\\n\",\n                 maxerr, maxdiff);\n    else if(maxerr > 1.0e11)\n      report(lp, NORMAL, \"\\nVery good numeric accuracy ||*|| = %g\\n\", maxerr);\n    else\n      report(lp, NORMAL, \"\\nExcellent numeric accuracy ||*|| = %g\\n\", maxerr);\n  }\n#endif\n\n  lp->accuracy = maxerr;\n\n  return(solveStatus);\n} /* check_solution */\n\nREAL __WINAPI get_accuracy(lprec *lp)\n{\n  return(lp->accuracy);\n}\n\nvoid __WINAPI set_break_numeric_accuracy(lprec *lp, REAL accuracy)\n{\n  lp->accuracy_error = accuracy;\n}\n\nREAL __WINAPI get_break_numeric_accuracy(lprec *lp)\n{\n  return(lp->accuracy_error);\n}\n\nSTATIC void transfer_solution_var(lprec *lp, int uservar)\n{\n  if(lp->varmap_locked && (MYBOOL) ((lp->do_presolve & PRESOLVE_LASTMASKMODE) != PRESOLVE_NONE)) {\n    uservar += lp->rows;\n    lp->full_solution[lp->presolve_undo->orig_rows +\n                      lp->presolve_undo->var_to_orig[uservar]] = lp->best_solution[uservar];\n  }\n}\nSTATIC void transfer_solution(lprec *lp, MYBOOL dofinal)\n{\n  int i, ii;\n\n  MEMCOPY(lp->best_solution, lp->solution, lp->sum + 1);\n\n  /* Round integer solution values to actual integers */\n  if(is_integerscaling(lp) && (lp->int_vars > 0))\n    for(i = 1; i <= lp->columns; i++) {\n      if(is_int(lp, i)) {\n        ii = lp->rows + i;\n        lp->best_solution[ii] = floor(lp->best_solution[ii] + 0.5);\n      }\n    }\n\n  /* Transfer to full solution vector in the case of presolved eliminations */\n  if(dofinal && lp->varmap_locked &&\n     (MYBOOL) ((lp->do_presolve & PRESOLVE_LASTMASKMODE) != PRESOLVE_NONE)) {\n    presolveundorec *psundo = lp->presolve_undo;\n\n    lp->full_solution[0] = lp->best_solution[0];\n    for(i = 1; i <= lp->rows; i++) {\n      ii = psundo->var_to_orig[i];\n#ifdef Paranoia\n      if((ii < 0) || (ii > lp->presolve_undo->orig_rows))\n        report(lp, SEVERE, \"transfer_solution: Invalid mapping of row index %d to original index '%d'\\n\",\n                            i, ii);\n#endif\n      lp->full_solution[ii] = lp->best_solution[i];\n    }\n    for(i = 1; i <= lp->columns; i++) {\n      ii = psundo->var_to_orig[lp->rows+i];\n#ifdef Paranoia\n      if((ii < 0) || (ii > lp->presolve_undo->orig_columns))\n        report(lp, SEVERE, \"transfer_solution: Invalid mapping of column index %d to original index '%d'\\n\",\n                            i, ii);\n#endif\n      lp->full_solution[psundo->orig_rows+ii] = lp->best_solution[lp->rows+i];\n    }\n  }\n\n}\n\nSTATIC MYBOOL construct_duals(lprec *lp)\n{\n  int  i, n, *coltarget;\n  REAL scale0, value, dualOF;\n\n  if(lp->duals != NULL)\n    free_duals(lp);\n\n  if(is_action(lp->spx_action, ACTION_REBASE) ||\n     is_action(lp->spx_action, ACTION_REINVERT) || (!lp->basis_valid) ||\n     !allocREAL(lp, &(lp->duals), lp->sum + 1, AUTOMATIC))\n    return(FALSE);\n\n  /* Initialize */\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n  coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->columns+1, sizeof(*coltarget));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n  if(!get_colIndexA(lp, SCAN_USERVARS+USE_NONBASICVARS, coltarget, FALSE)) {\n    mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n    return(FALSE);\n  }\n  bsolve(lp, 0, lp->duals, NULL, lp->epsmachine*DOUBLEROUND, 1.0);\n  prod_xA(lp, coltarget, lp->duals, NULL, lp->epsmachine, 1.0,\n                         lp->duals, NULL, MAT_ROUNDDEFAULT | MAT_ROUNDRC);\n  mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n\n\n  /* The (Lagrangean) dual values are the reduced costs of the primal slacks;\n     when the slack is at its upper bound, change the sign. */\n  n = lp->rows;\n  for(i = 1; i <= n; i++) {\n    if(lp->is_basic[i])\n      lp->duals[i] = 0;\n    /* Added a test if variable is different from 0 because sometime you get -0 and this\n       is different from 0 on for example INTEL processors (ie 0 != -0 on INTEL !) PN */\n    else if((is_chsign(lp, 0) == is_chsign(lp, i)) && lp->duals[i])\n      lp->duals[i] = my_flipsign(lp->duals[i]);\n  }\n  if(is_maxim(lp)) {\n    n = lp->sum;\n    for(i = lp->rows + 1; i <= n; i++)\n      lp->duals[i] = my_flipsign(lp->duals[i]);\n  }\n\n  /* If we presolved, then reconstruct the duals */\n  n = lp->presolve_undo->orig_sum;\n  if(((lp->do_presolve & PRESOLVE_LASTMASKMODE) != PRESOLVE_NONE) &&\n      allocREAL(lp, &(lp->full_duals), n + 1, TRUE)) {\n    int ix, ii = lp->presolve_undo->orig_rows;\n\n    n = lp->sum;\n    for(ix = 1; ix <= n; ix++) {\n      i = lp->presolve_undo->var_to_orig[ix];\n      if(ix > lp->rows)\n        i += ii;\n#ifdef Paranoia\n      /* Check for index out of range due to presolve */\n      if(i > lp->presolve_undo->orig_sum)\n        report(lp, SEVERE, \"construct_duals: Invalid presolve variable mapping found\\n\");\n#endif\n      lp->full_duals[i] = lp->duals[ix];\n    }\n    presolve_rebuildUndo(lp, FALSE);\n  }\n\n  /* Calculate the dual OF and do scaling adjustments to the duals */\n  if(lp->scaling_used)\n    scale0 = lp->scalars[0];\n  else\n    scale0 = 1;\n  dualOF = my_chsign(is_maxim(lp), lp->orig_rhs[0]) / scale0;\n  for(i = 1; i <= lp->sum; i++) {\n    value = scaled_value(lp, lp->duals[i] / scale0, i);\n    my_roundzero(value, lp->epsprimal);\n    lp->duals[i] = value;\n    if(i <= lp->rows)\n      dualOF += value * lp->solution[i];\n  }\n\n#if 0\n  /* See if we can make use of the dual OF;\n     note that we do not currently adjust properly for presolve */\n  if(lp->rows == lp->presolve_undo->orig_rows)\n  if(MIP_count(lp) > 0) {\n    if(is_maxim(lp)) {\n      SETMIN(lp->bb_limitOF, dualOF);\n    }\n    else {\n      SETMAX(lp->bb_limitOF, dualOF);\n    }\n  }\n  else if(fabs(my_reldiff(dualOF, lp->solution[0])) > lp->epssolution)\n    report(lp, IMPORTANT, \"calculate_duals: Check for possible suboptimal solution!\\n\");\n#endif\n\n  return(TRUE);\n} /* construct_duals */\n\n/* Calculate sensitivity duals */\nSTATIC MYBOOL construct_sensitivity_duals(lprec *lp)\n{\n  int  k,varnr, ok = TRUE;\n  int  *workINT = NULL;\n  REAL *pcol,a,infinite,epsvalue,from,till,objfromvalue;\n\n  /* one column of the matrix */\n  FREE(lp->objfromvalue);\n  FREE(lp->dualsfrom);\n  FREE(lp->dualstill);\n  if(!allocREAL(lp, &pcol, lp->rows + 1, TRUE) ||\n     !allocREAL(lp, &lp->objfromvalue, lp->columns + 1, AUTOMATIC) ||\n     !allocREAL(lp, &lp->dualsfrom, lp->sum + 1, AUTOMATIC) ||\n     !allocREAL(lp, &lp->dualstill, lp->sum + 1, AUTOMATIC)) {\n    FREE(pcol);\n    FREE(lp->objfromvalue);\n    FREE(lp->dualsfrom);\n    FREE(lp->dualstill);\n    ok = FALSE;\n  }\n  else {\n    infinite=lp->infinite;\n    epsvalue=lp->epsmachine;\n    for(varnr=1; varnr<=lp->sum; varnr++) {\n      from=infinite;\n      till=infinite;\n      objfromvalue=infinite;\n      if (!lp->is_basic[varnr]) {\n        if (!fsolve(lp, varnr, pcol, workINT, epsvalue, 1.0, FALSE)) {  /* construct one column of the tableau */\n          ok = FALSE;\n          break;\n        }\n        /* Search for the rows(s) which first result in further iterations */\n        for (k=1; k<=lp->rows; k++) {\n          if (fabs(pcol[k])>epsvalue) {\n            a = lp->rhs[k]/pcol[k];\n            if((varnr > lp->rows) && (fabs(lp->solution[varnr]) <= epsvalue) && (a < objfromvalue) && (a >= lp->lowbo[varnr]))\n              objfromvalue = a;\n            if ((a<=0.0) && (pcol[k]<0.0) && (-a<from)) from=my_flipsign(a);\n            if ((a>=0.0) && (pcol[k]>0.0) && ( a<till)) till= a;\n            if (lp->upbo[lp->var_basic[k]] < infinite) {\n              a = (REAL) ((lp->rhs[k]-lp->upbo[lp->var_basic[k]])/pcol[k]);\n              if((varnr > lp->rows) && (fabs(lp->solution[varnr]) <= epsvalue) && (a < objfromvalue) && (a >= lp->lowbo[varnr]))\n                objfromvalue = a;\n              if ((a<=0.0) && (pcol[k]>0.0) && (-a<from)) from=my_flipsign(a);\n              if ((a>=0.0) && (pcol[k]<0.0) && ( a<till)) till= a;\n            }\n          }\n        }\n\n        if (!lp->is_lower[varnr]) {\n          a=from;\n          from=till;\n          till=a;\n        }\n        if ((varnr<=lp->rows) && (!is_chsign(lp, varnr))) {\n          a=from;\n          from=till;\n          till=a;\n        }\n      }\n\n      if (from!=infinite)\n        lp->dualsfrom[varnr]=lp->solution[varnr]-unscaled_value(lp, from, varnr);\n      else\n        lp->dualsfrom[varnr]=-infinite;\n      if (till!=infinite)\n        lp->dualstill[varnr]=lp->solution[varnr]+unscaled_value(lp, till, varnr);\n      else\n        lp->dualstill[varnr]=infinite;\n\n      if (varnr > lp->rows) {\n        if (objfromvalue != infinite) {\n          if ((!sensrejvar) || (lp->upbo[varnr] != 0.0)) {\n            if (!lp->is_lower[varnr])\n              objfromvalue = lp->upbo[varnr] - objfromvalue;\n            if ((lp->upbo[varnr] < infinite) && (objfromvalue > lp->upbo[varnr]))\n              objfromvalue = lp->upbo[varnr];\n          }\n          objfromvalue += lp->lowbo[varnr];\n          objfromvalue = unscaled_value(lp, objfromvalue, varnr);\n        }\n        else\n          objfromvalue = -infinite;\n        lp->objfromvalue[varnr - lp->rows] = objfromvalue;\n      }\n\n    }\n    FREE(pcol);\n  }\n  return((MYBOOL) ok);\n} /* construct_sensitivity_duals */\n\n/* Calculate sensitivity objective function */\nSTATIC MYBOOL construct_sensitivity_obj(lprec *lp)\n{\n  int  i, l, varnr, row_nr, ok = TRUE;\n  REAL *OrigObj = NULL, *drow = NULL, *prow = NULL,\n       sign, a, min1, min2, infinite, epsvalue, from, till;\n\n  /* objective function */\n  FREE(lp->objfrom);\n  FREE(lp->objtill);\n  if(!allocREAL(lp, &drow, lp->sum + 1, TRUE) ||\n     !allocREAL(lp, &OrigObj, lp->columns + 1, FALSE) ||\n     !allocREAL(lp, &prow, lp->sum + 1, TRUE) ||\n     !allocREAL(lp, &lp->objfrom, lp->columns + 1, AUTOMATIC) ||\n     !allocREAL(lp, &lp->objtill, lp->columns + 1, AUTOMATIC)) {\nAbandon:\n    FREE(drow);\n    FREE(OrigObj);\n    FREE(prow);\n    FREE(lp->objfrom);\n    FREE(lp->objtill);\n    ok = FALSE;\n  }\n  else {\n    int *coltarget;\n\n    infinite=lp->infinite;\n    epsvalue=lp->epsmachine;\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n    coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->columns+1, sizeof(*coltarget));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n    if(!get_colIndexA(lp, SCAN_USERVARS+USE_NONBASICVARS, coltarget, FALSE)) {\n      mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n      goto Abandon;\n    }\n    bsolve(lp, 0, drow, NULL, epsvalue*DOUBLEROUND, 1.0);\n    prod_xA(lp, coltarget, drow, NULL, epsvalue, 1.0,\n                           drow, NULL, MAT_ROUNDDEFAULT | MAT_ROUNDRC);\n\n    /* original (unscaled) objective function */\n    get_row(lp, 0, OrigObj);\n    for(i = 1; i <= lp->columns; i++) {\n      from=-infinite;\n      till= infinite;\n      varnr = lp->rows + i;\n      if(!lp->is_basic[varnr]) {\n      /* only the coeff of the objective function of column i changes. */\n        a = unscaled_mat(lp, drow[varnr], 0, i);\n        if(is_maxim(lp))\n          a = -a;\n        if ((!sensrejvar) && (lp->upbo[varnr] == 0.0))\n          /* ignore, because this case doesn't results in further iterations */ ;\n        else if(((lp->is_lower[varnr] != 0) == (is_maxim(lp) == FALSE)) && (a > -epsvalue))\n          from = OrigObj[i] - a; /* less than this value gives further iterations */\n        else\n          till = OrigObj[i] - a; /* bigger than this value gives further iterations */\n      }\n      else {\n      /* all the coeff of the objective function change. Search the minimal change needed for further iterations */\n        for(row_nr=1;\n            (row_nr<=lp->rows) && (lp->var_basic[row_nr]!=varnr); row_nr++)\n          /* Search on which row the variable exists in the basis */ ;\n        if(row_nr<=lp->rows) {       /* safety test; should always be found ... */\n          /* Construct one row of the tableau */\n          bsolve(lp, row_nr, prow, NULL, epsvalue*DOUBLEROUND, 1.0);\n          prod_xA(lp, coltarget, prow, NULL, epsvalue, 1.0,\n                                 prow, NULL, MAT_ROUNDDEFAULT);\n          /* sign = my_chsign(is_chsign(lp, row_nr), -1); */\n          sign = my_chsign(lp->is_lower[row_nr], -1);\n          min1=infinite;\n          min2=infinite;\n          for(l=1; l<=lp->sum; l++)   /* search for the column(s) which first results in further iterations */\n            if ((!lp->is_basic[l]) && (lp->upbo[l]>0.0) &&\n                (fabs(prow[l])>epsvalue) && (drow[l]*(lp->is_lower[l] ? -1 : 1)<epsvalue)) {\n              a = unscaled_mat(lp, fabs(drow[l] / prow[l]), 0, i);\n              if(prow[l]*sign*(lp->is_lower[l] ? 1 : -1) < 0.0) {\n                if(a < min1)\n                  min1 = a;\n              }\n              else {\n                if(a < min2)\n                  min2 = a;\n              }\n            }\n          if ((lp->is_lower[varnr] == 0) == (is_maxim(lp) == FALSE)) {\n            a = min1;\n            min1 = min2;\n            min2 = a;\n          }\n          if (min1<infinite)\n            from = OrigObj[i]-min1;\n          if (min2<infinite)\n            till = OrigObj[i]+min2;\n          a = lp->solution[varnr];\n          if (is_maxim(lp)) {\n            if (a - lp->lowbo[varnr] < epsvalue)\n              from = -infinite; /* if variable is at lower bound then decrementing objective coefficient will not result in extra iterations because it would only extra decrease the value, but since it is at its lower bound ... */\n            else if (((!sensrejvar) || (lp->upbo[varnr] != 0.0)) && (lp->lowbo[varnr] + lp->upbo[varnr] - a < epsvalue))\n              till = infinite;  /* if variable is at upper bound then incrementing objective coefficient will not result in extra iterations because it would only extra increase the value, but since it is at its upper bound ... */\n          }\n          else {\n            if (a - lp->lowbo[varnr] < epsvalue)\n              till = infinite;  /* if variable is at lower bound then incrementing objective coefficient will not result in extra iterations because it would only extra decrease the value, but since it is at its lower bound ... */\n            else if (((!sensrejvar) || (lp->upbo[varnr] != 0.0)) && (lp->lowbo[varnr] + lp->upbo[varnr] - a < epsvalue))\n              from = -infinite; /* if variable is at upper bound then decrementing objective coefficient will not result in extra iterations because it would only extra increase the value, but since it is at its upper bound ... */\n          }\n        }\n      }\n      lp->objfrom[i]=from;\n      lp->objtill[i]=till;\n    }\n    mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n  }\n  FREE(prow);\n  FREE(OrigObj);\n  FREE(drow);\n\n  return((MYBOOL) ok);\n} /* construct_sensitivity_obj */\n\nSTATIC MYBOOL refactRecent(lprec *lp)\n{\n  int pivcount = lp->bfp_pivotcount(lp);\n  if(pivcount == 0)\n    return( AUTOMATIC );\n  else if (pivcount < 2*DEF_MAXPIVOTRETRY)\n    return( TRUE );\n  else\n    return( FALSE );\n}\n\nSTATIC MYBOOL check_if_less(lprec *lp, REAL x, REAL y, int variable)\n{\n  if(y < x-scaled_value(lp, lp->epsint, variable)) {\n    if(lp->bb_trace)\n      report(lp, NORMAL, \"check_if_less: Invalid new bound %g should be < %g for %s\\n\",\n                         x, y, get_col_name(lp, variable));\n    return(FALSE);\n  }\n  else\n    return(TRUE);\n}\n\n/* Various basis utility routines */\n\nSTATIC int findNonBasicSlack(lprec *lp, MYBOOL *is_basic)\n{\n  int i;\n\n  for(i = lp->rows; i > 0; i--)\n    if(!is_basic[i])\n      break;\n  return( i );\n}\n\nSTATIC int findBasisPos(lprec *lp, int notint, int *var_basic)\n{\n  int i;\n\n  if(var_basic == NULL)\n    var_basic = lp->var_basic;\n  for(i = lp->rows; i > 0; i--)\n    if(var_basic[i] == notint)\n      break;\n  return( i );\n}\n\nSTATIC void replaceBasisVar(lprec *lp, int rownr, int var, int *var_basic, MYBOOL *is_basic)\n{\n  (void)lp;\n  int out;\n  (void)lp;\n\n  out = var_basic[rownr];\n  var_basic[rownr] = var;\n  is_basic[out] = FALSE;\n  is_basic[var] = TRUE;\n}\n\nSTATIC void free_duals(lprec *lp)\n{\n  FREE(lp->duals);\n  FREE(lp->full_duals);\n  FREE(lp->dualsfrom);\n  FREE(lp->dualstill);\n  FREE(lp->objfromvalue);\n  FREE(lp->objfrom);\n  FREE(lp->objtill);\n}\n\n/* Transform RHS by adjusting for the bound state of variables;\n   optionally rebase upper bound, and account for this in later calls */\nSTATIC void initialize_solution(lprec *lp, MYBOOL shiftbounds)\n{\n  int     i, k1, k2, *matRownr, colnr;\n  LREAL   theta;\n  REAL    value, *matValue, loB, upB;\n  MATrec  *mat = lp->matA;\n\n  /* Set bounding status indicators */\n  if(lp->bb_bounds != NULL) {\n    if(shiftbounds == INITSOL_SHIFTZERO) {\n      if(lp->bb_bounds->UBzerobased)\n        report(lp, SEVERE, \"initialize_solution: The upper bounds are already zero-based at refactorization %d\\n\",\n                           lp->bfp_refactcount(lp, BFP_STAT_REFACT_TOTAL));\n      lp->bb_bounds->UBzerobased = TRUE;\n    }\n    else if(!lp->bb_bounds->UBzerobased)\n        report(lp, SEVERE, \"initialize_solution: The upper bounds are not zero-based at refactorization %d\\n\",\n                           lp->bfp_refactcount(lp, BFP_STAT_REFACT_TOTAL));\n  }\n\n  /* Initialize the working RHS/basic variable solution vector */\n  i = is_action(lp->anti_degen, ANTIDEGEN_RHSPERTURB) && (lp->monitor != NULL) && lp->monitor->active;\n  if(sizeof(*lp->rhs) == sizeof(*lp->orig_rhs) && !i) {\n    MEMCOPY(lp->rhs, lp->orig_rhs, lp->rows+1);\n  }\n  else if(i) {\n    lp->rhs[0] = lp->orig_rhs[0];\n    for(i = 1; i <= lp->rows; i++) {\n      if(is_constr_type(lp, i, EQ))\n        theta = rand_uniform(lp, lp->epsvalue);\n      else {\n        theta = rand_uniform(lp, lp->epsperturb);\n/*        if(lp->orig_upbo[i] < lp->infinite)\n          lp->orig_upbo[i] += theta; */\n      }\n      lp->rhs[i] = lp->orig_rhs[i] + theta;\n    }\n  }\n  else\n    for(i = 0; i <= lp->rows; i++)\n      lp->rhs[i] = lp->orig_rhs[i];\n\n/* Adjust active RHS for variables at their active upper/lower bounds */\n  for(i = 1; i <= lp->sum; i++) {\n\n    upB = lp->upbo[i];\n    loB = lp->lowbo[i];\n\n    /* Shift to \"ranged\" upper bound, tantamount to defining zero-based variables */\n    if(shiftbounds == INITSOL_SHIFTZERO) {\n      if((loB > -lp->infinite) && (upB < lp->infinite))\n        lp->upbo[i] -= loB;\n      if(lp->upbo[i] < 0)\n        report(lp, SEVERE, \"initialize_solution: Invalid rebounding; variable %d at refact %d, iter %.0f\\n\",\n                           i, lp->bfp_refactcount(lp, BFP_STAT_REFACT_TOTAL), (double) get_total_iter(lp));\n    }\n\n    /* Use \"ranged\" upper bounds */\n    else if(shiftbounds == INITSOL_USEZERO) {\n      if((loB > -lp->infinite) && (upB < lp->infinite))\n        upB += loB;\n    }\n\n    /* Shift upper bound back to original value */\n    else if(shiftbounds == INITSOL_ORIGINAL) {\n      if((loB > -lp->infinite) && (upB < lp->infinite)) {\n        lp->upbo[i] += loB;\n        upB += loB;\n      }\n      continue;\n    }\n    else\n      report(lp, SEVERE, \"initialize_solution: Invalid option value '%d'\\n\",\n                         shiftbounds);\n\n    /* Set the applicable adjustment */\n    if(lp->is_lower[i])\n      theta = loB;\n    else\n      theta = upB;\n\n\n    /* Check if we need to pass through the matrix;\n       remember that basis variables are always lower-bounded */\n    if(theta == 0)\n      continue;\n\n    /* Do user and artificial variables */\n    if(i > lp->rows) {\n\n      /* Get starting and ending indeces in the NZ vector */\n      colnr = i - lp->rows;\n      k1 = mat->col_end[colnr - 1];\n      k2 = mat->col_end[colnr];\n      matRownr = &COL_MAT_ROWNR(k1);\n      matValue = &COL_MAT_VALUE(k1);\n\n      /* Get the objective as row 0, optionally adjusting the objective for phase 1 */\n      value = get_OF_active(lp, i, theta);\n      lp->rhs[0] -= value;\n\n      /* Do the normal case */\n      for(; k1 < k2;\n          k1++, matRownr += matRowColStep, matValue += matValueStep) {\n        lp->rhs[*matRownr] -= theta * (*matValue);\n      }\n    }\n\n    /* Do slack variables (constraint \"bounds\")*/\n    else {\n      lp->rhs[i] -= theta;\n    }\n\n  }\n\n  /* Do final pass to get the maximum value */\n  i = idamax(lp->rows /* +1 */, lp->rhs, 1);\n  lp->rhsmax = fabs(lp->rhs[i]);\n\n  if(shiftbounds == INITSOL_SHIFTZERO)\n    clear_action(&lp->spx_action, ACTION_REBASE);\n\n}\n\n/* This routine recomputes the basic variables using the full inverse */\nSTATIC void recompute_solution(lprec *lp, MYBOOL shiftbounds)\n{\n  /* Compute RHS = b - A(n)*x(n) */\n  initialize_solution(lp, shiftbounds);\n\n  /* Compute x(b) = Inv(B)*RHS (Ref. lp_solve inverse logic and Chvatal p. 121) */\n  lp->bfp_ftran_normal(lp, lp->rhs, NULL);\n  if(!lp->obj_in_basis) {\n    int i, ib, n = lp->rows;\n    for(i = 1; i <= n; i++) {\n      ib = lp->var_basic[i];\n      if(ib > n)\n        lp->rhs[0] -= get_OF_active(lp, ib, lp->rhs[i]);\n    }\n  }\n\n /* Round the values (should not be greater than the factor used in bfp_pivotRHS) */\n  roundVector(lp->rhs, lp->rows, lp->epsvalue);\n\n  clear_action(&lp->spx_action, ACTION_RECOMPUTE);\n}\n\n/* This routine compares an existing basic solution to a recomputed one;\n   Note that the routine must provide for the possibility that the order of the\n   basis variables can be changed by the inversion engine. */\nSTATIC int verify_solution(lprec *lp, MYBOOL reinvert, char *info)\n{\n  int  i, ii, n, *oldmap, *newmap, *refmap = NULL;\n  REAL *oldrhs, err, errmax;\n\n  allocINT(lp, &oldmap, lp->rows+1, FALSE);\n  allocINT(lp, &newmap, lp->rows+1, FALSE);\n  allocREAL(lp, &oldrhs, lp->rows+1, FALSE);\n\n  /* Get sorted mapping of the old basis */\n  for(i = 0; i <= lp->rows; i++)\n    oldmap[i] = i;\n  if(reinvert) {\n    allocINT(lp, &refmap, lp->rows+1, FALSE);\n    MEMCOPY(refmap, lp->var_basic, lp->rows+1);\n    sortByINT(oldmap, refmap, lp->rows, 1, TRUE);\n  }\n\n  /* Save old and calculate the new RHS vector */\n  MEMCOPY(oldrhs, lp->rhs, lp->rows+1);\n  if(reinvert)\n    invert(lp, INITSOL_USEZERO, FALSE);\n  else\n    recompute_solution(lp, INITSOL_USEZERO);\n\n  /* Get sorted mapping of the new basis */\n  for(i = 0; i <= lp->rows; i++)\n    newmap[i] = i;\n  if(reinvert) {\n    MEMCOPY(refmap, lp->var_basic, lp->rows+1);\n    sortByINT(newmap, refmap, lp->rows, 1, TRUE);\n  }\n\n  /* Identify any gap */\n  errmax = 0;\n  ii = -1;\n  n = 0;\n  for(i = lp->rows; i > 0; i--) {\n    err = fabs(my_reldiff(oldrhs[oldmap[i]], lp->rhs[newmap[i]]));\n    if(err > lp->epsprimal) {\n      n++;\n      if(err > errmax) {\n        ii = i;\n        errmax = err;\n      }\n    }\n  }\n  err = fabs(my_reldiff(oldrhs[i], lp->rhs[i]));\n  if(err < lp->epspivot) {\n    i--;\n    err = 0;\n  }\n  else {\n    n++;\n    if(ii < 0) {\n      ii = 0;\n      errmax = err;\n    }\n  }\n  if(n > 0) {\n    report(lp, IMPORTANT, \"verify_solution: Iter %.0f %s - %d errors; OF %g, Max @row %d %g\\n\",\n                           (double) get_total_iter(lp), my_if(info == NULL, \"\", info), n, err, newmap[ii], errmax);\n  }\n  /* Copy old results back (not possible for inversion) */\n  if(!reinvert)\n    MEMCOPY(lp->rhs, oldrhs, lp->rows+1);\n\n  FREE(oldmap);\n  FREE(newmap);\n  FREE(oldrhs);\n  if(reinvert)\n    FREE(refmap);\n\n  return( ii );\n\n}\n\n/* Preprocessing and postprocessing functions */\nSTATIC int identify_GUB(lprec *lp, MYBOOL mark)\n{\n  int    i, j, jb, je, k, knint, srh;\n  REAL   rh, mv, tv, bv;\n  MATrec *mat = lp->matA;\n\n  if((lp->equalities == 0) || !mat_validate(mat))\n    return( 0 );\n\n  k = 0;\n  for(i = 1; i <= lp->rows; i++) {\n\n    /* Check if it is an equality constraint */\n    if(!is_constr_type(lp, i, EQ))\n      continue;\n\n    rh = get_rh(lp, i);\n    srh = my_sign(rh);\n    knint = 0;\n    je = mat->row_end[i];\n    for(jb = mat->row_end[i-1]; jb < je; jb++) {\n      j = ROW_MAT_COLNR(jb);\n\n      /* Check for validity of the equation elements */\n      if(!is_int(lp, j))\n        knint++;\n      if(knint > 1)\n        break;\n\n      mv = get_mat_byindex(lp, jb, TRUE, FALSE);\n      if(fabs(my_reldiff(mv, rh)) > lp->epsprimal)\n        break;\n\n      tv = mv*get_upbo(lp, j);\n      bv = get_lowbo(lp, j);\n#if 0 /* Requires 1 as upper bound */\n      if((fabs(my_reldiff(tv, rh)) > lp->epsprimal) || (bv != 0))\n#else /* Can handle any upper bound >= 1 */\n      if((srh*(tv-rh) < -lp->epsprimal) || (bv != 0))\n#endif\n        break;\n    }\n\n    /* Update GUB count and optionally mark the GUB */\n    if(jb == je) {\n      k++;\n      if(mark == TRUE)\n        lp->row_type[i] |= ROWTYPE_GUB;\n      else if(mark == AUTOMATIC)\n        break;\n    }\n\n  }\n  return( k );\n}\n\nSTATIC int prepare_GUB(lprec *lp)\n{\n  int    i, j, jb, je, k, *members = NULL;\n  REAL   rh;\n  char   GUBname[16];\n  MATrec *mat = lp->matA;\n\n  if((lp->equalities == 0) ||\n     !allocINT(lp, &members, lp->columns+1, TRUE) ||\n     !mat_validate(mat))\n    return( 0 );\n\n  for(i = 1; i <= lp->rows; i++) {\n\n    /* Check if it has been marked as a GUB */\n    if(!(lp->row_type[i] & ROWTYPE_GUB))\n      continue;\n\n    /* Pick up the GUB column indeces */\n    k = 0;\n    je = mat->row_end[i];\n    for(jb = mat->row_end[i-1], k = 0; jb < je; jb++) {\n      members[k] = ROW_MAT_COLNR(jb);\n      k++;\n    }\n\n    /* Add the GUB */\n    j = GUB_count(lp) + 1;\n    sprintf(GUBname, \"GUB_%d\", i);\n    add_GUB(lp, GUBname, j, k, members);\n\n    /* Unmark the GUBs */\n    clear_action(&(lp->row_type[i]), ROWTYPE_GUB);\n\n    /* Standardize coefficients to 1 if necessary */\n    rh = get_rh(lp, i);\n    if(fabs(my_reldiff(rh, 1)) > lp->epsprimal) {\n      set_rh(lp, i, 1);\n      for(jb = mat->row_end[i-1]; jb < je; jb++) {\n        j = ROW_MAT_COLNR(jb);\n        set_mat(lp, i,j, 1);\n      }\n    }\n\n  }\n  FREE(members);\n  return(GUB_count(lp));\n}\n\n/* Pre- and post processing functions, i.a. splitting free variables */\nSTATIC MYBOOL pre_MIPOBJ(lprec *lp)\n{\n#ifdef MIPboundWithOF\n  if(MIP_count(lp) > 0) {\n    int i = 1;\n    while((i <= lp->rows) && !mat_equalRows(lp->matA, 0, i) && !is_constr_type(lp, i, EQ))\n      i++;\n    if(i <= lp->rows)\n      lp->constraintOF = i;\n  }\n#endif\n  lp->bb_deltaOF = MIP_stepOF(lp);\n  if(lp->bb_deltaOF < MAX(lp->epsvalue, lp->mip_absgap))\n      lp->bb_deltaOF = 0;\n\n  return( TRUE );\n}\nSTATIC MYBOOL post_MIPOBJ(lprec *lp)\n{\n  (void)lp;\n#ifdef MIPboundWithOF\n/*\n  if(lp->constraintOF) {\n    del_constraint(lp, lp->rows);\n    if(is_BasisReady(lp) && !verify_basis(lp))\n      return( FALSE );\n  }\n*/\n#endif\n  return( TRUE );\n}\n\nint preprocess(lprec *lp)\n{\n  int    i, j, k, ok = TRUE, *new_index = NULL;\n  REAL   hold, *new_column = NULL;\n  MYBOOL scaled, primal1, primal2;\n\n /* do not process if already preprocessed */\n  if(lp->wasPreprocessed)\n    return( ok );\n\n  /* Write model statistics and optionally initialize partial pricing structures */\n  if(lp->lag_status != RUNNING) {\n    MYBOOL doPP;\n\n    /* Extract the user-specified simplex strategy choices */\n    primal1 = (MYBOOL) (lp->simplex_strategy & SIMPLEX_Phase1_PRIMAL);\n    primal2 = (MYBOOL) (lp->simplex_strategy & SIMPLEX_Phase2_PRIMAL);\n\n    /* Initialize partial pricing structures */\n    doPP = is_piv_mode(lp, PRICE_PARTIAL | PRICE_AUTOPARTIAL);\n/*    doPP &= (MYBOOL) (lp->columns / 2 > lp->rows); */\n    if(doPP) {\n      i = partial_findBlocks(lp, FALSE, FALSE);\n      if(i < 4)\n        i = (int) (5 * log((REAL) lp->columns / lp->rows));\n      report(lp, NORMAL, \"The model is %s to have %d column blocks/stages.\\n\",\n                         (i > 1 ? \"estimated\" : \"set\"), i);\n      set_partialprice(lp, i, NULL, FALSE);\n    }\n/*    doPP &= (MYBOOL) (lp->rows / 4 > lp->columns); */\n    if(doPP) {\n      i = partial_findBlocks(lp, FALSE, TRUE);\n      if(i < 4)\n        i = (int) (5 * log((REAL) lp->rows / lp->columns));\n      report(lp, NORMAL, \"The model is %s to have %d row blocks/stages.\\n\",\n                         (i > 1 ? \"estimated\" : \"set\"), i);\n      set_partialprice(lp, i, NULL, TRUE);\n    }\n\n    /* Check for presence of valid pricing blocks if partial pricing\n      is defined, but not autopartial is not set */\n    if(!doPP && is_piv_mode(lp, PRICE_PARTIAL)) {\n      if((lp->rowblocks == NULL) || (lp->colblocks == NULL)) {\n        report(lp, IMPORTANT, \"Ignoring partial pricing, since block structures are not defined.\\n\");\n        clear_action(&lp->piv_strategy, PRICE_PARTIAL);\n      }\n    }\n\n    /* Initialize multiple pricing block divisor */\n#if 0\n    if(primal1 || primal2)\n      lp->piv_strategy |= PRICE_MULTIPLE | PRICE_AUTOMULTIPLE;\n#endif\n    if(is_piv_mode(lp, PRICE_MULTIPLE) && (primal1 || primal2)) {\n      doPP = is_piv_mode(lp, PRICE_AUTOMULTIPLE);\n      if(doPP) {\n        i = (int) (2.5*log((REAL) lp->sum));\n        SETMAX( i, 1);\n        set_multiprice(lp, i);\n      }\n      if(lp->multiblockdiv > 1)\n      report(lp, NORMAL, \"Using %d-candidate primal simplex multiple pricing block.\\n\",\n                          lp->columns / lp->multiblockdiv);\n    }\n    else\n      set_multiprice(lp, 1);\n\n    report(lp, NORMAL, \"Using %s simplex for phase 1 and %s simplex for phase 2.\\n\",\n                       my_if(primal1, \"PRIMAL\", \"DUAL\"), my_if(primal2, \"PRIMAL\", \"DUAL\"));\n    i = get_piv_rule(lp);\n    if((i == PRICER_STEEPESTEDGE) && is_piv_mode(lp, PRICE_PRIMALFALLBACK))\n      report(lp, NORMAL, \"The pricing strategy is set to '%s' for the dual and '%s' for the primal.\\n\",\n                       get_str_piv_rule(i), get_str_piv_rule(i-1));\n    else\n      report(lp, NORMAL, \"The primal and dual simplex pricing strategy set to '%s'.\\n\",\n                       get_str_piv_rule(i));\n\n    report(lp, NORMAL, \" \\n\");\n  }\n\n  /* Compute a minimum step improvement step requirement */\n  pre_MIPOBJ(lp);\n\n /* First create extra columns for FR variables or flip MI variables */\n  for (j = 1; j <= lp->columns; j++) {\n\n#ifdef Paranoia\n    if((lp->rows != lp->matA->rows) || (lp->columns != lp->matA->columns))\n      report(lp, SEVERE, \"preprocess: Inconsistent variable counts found\\n\");\n#endif\n\n   /* First handle sign-flipping of variables:\n       1) ... with a finite upper bound and a negative Inf-bound (since basis variables are lower-bounded)\n       2) ... with bound assymetry within negrange limits (for stability reasons) */\n    i = lp->rows + j;\n    hold = lp->orig_upbo[i];\n/*\n    if((hold <= 0) || (!is_infinite(lp, lp->negrange) &&\n                       (hold < -lp->negrange) &&\n                       (lp->orig_lowbo[i] <= lp->negrange)) ) {\n*/\n#define fullybounded FALSE\n    if( ((hold < lp->infinite) && my_infinite(lp, lp->orig_lowbo[i])) ||\n        (!fullybounded && !my_infinite(lp, lp->negrange) &&\n         (hold < -lp->negrange) && (lp->orig_lowbo[i] <= lp->negrange)) ) {\n      /* Delete split sibling variable if one existed from before */\n      if((lp->var_is_free != NULL) && (lp->var_is_free[j] > 0))\n        del_column(lp, lp->var_is_free[j]);\n      /* Negate the column / flip to the positive range */\n      mat_multcol(lp->matA, j, -1, TRUE);\n      if(lp->var_is_free == NULL) {\n        if(!allocINT(lp, &lp->var_is_free, MAX(lp->columns, lp->columns_alloc) + 1, TRUE))\n          return(FALSE);\n      }\n      lp->var_is_free[j] = -j; /* Indicator UB and LB are switched, with no helper variable added */\n      lp->orig_upbo[i] = my_flipsign(lp->orig_lowbo[i]);\n      lp->orig_lowbo[i] = my_flipsign(hold);\n      /* Check for presence of negative ranged SC variable */\n      if(lp->sc_lobound[j] > 0) {\n        lp->sc_lobound[j] = lp->orig_lowbo[i];\n        lp->orig_lowbo[i] = 0;\n      }\n    }\n   /* Then deal with -+, full-range/FREE variables by creating a helper variable */\n    else if((lp->orig_lowbo[i] <= lp->negrange) && (hold >= -lp->negrange)) {\n      if(lp->var_is_free == NULL) {\n        if(!allocINT(lp, &lp->var_is_free, MAX(lp->columns,lp->columns_alloc) + 1, TRUE))\n          return(FALSE);\n      }\n      if(lp->var_is_free[j] <= 0) { /* If this variable wasn't split yet ... */\n        if(SOS_is_member(lp->SOS, 0, i - lp->rows)) {   /* Added */\n          report(lp, IMPORTANT, \"preprocess: Converted negative bound for SOS variable %d to zero\",\n                                i - lp->rows);\n          lp->orig_lowbo[i] = 0;\n          continue;\n        }\n        if(new_column == NULL) {\n          if(!allocREAL(lp, &new_column, lp->rows + 1, FALSE) ||\n             !allocINT(lp, &new_index, lp->rows + 1, FALSE)) {\n            ok = FALSE;\n            break;\n          }\n        }\n       /* Avoid precision loss by turning off unscaling and rescaling */\n       /* in get_column and add_column operations; also make sure that */\n       /* full scaling information is preserved */\n        scaled = lp->scaling_used;\n        lp->scaling_used = FALSE;\n        k = get_columnex(lp, j, new_column, new_index);\n        if(!add_columnex(lp, k, new_column, new_index)) {\n          ok = FALSE;\n          break;\n        }\n        mat_multcol(lp->matA, lp->columns, -1, TRUE);\n        if(scaled)\n          lp->scalars[lp->rows+lp->columns] = lp->scalars[i];\n        lp->scaling_used = (MYBOOL) scaled;\n        /* Only create name if we are not clearing a pre-used item, since this\n           variable could have been deleted by presolve but the name is required\n           for solution reconstruction. */\n        if(lp->names_used && (lp->col_name[j] == NULL)) {\n          char fieldn[50];\n\n          sprintf(fieldn, \"__AntiBodyOf(%d)__\", j);\n          if(!set_col_name(lp, lp->columns, fieldn)) {\n/*          if (!set_col_name(lp, lp->columns, get_col_name(lp, j))) { */\n            ok = FALSE;\n            break;\n          }\n        }\n        /* Set (positive) index to the original column's split / helper and back */\n        lp->var_is_free[j] = lp->columns;\n      }\n      lp->orig_upbo[lp->rows + lp->var_is_free[j]] = my_flipsign(lp->orig_lowbo[i]);\n      lp->orig_lowbo[i] = 0;\n\n      /* Negative index indicates x is split var and -var_is_free[x] is index of orig var */\n      lp->var_is_free[lp->var_is_free[j]] = -j;\n      lp->var_type[lp->var_is_free[j]] = lp->var_type[j];\n    }\n   /* Check for positive ranged SC variables */\n    else if(lp->sc_lobound[j] > 0) {\n      lp->sc_lobound[j] = lp->orig_lowbo[i];\n      lp->orig_lowbo[i] = 0;\n    }\n\n   /* Tally integer variables in SOS'es */\n    if(SOS_is_member(lp->SOS, 0, j) && is_int(lp, j))\n      lp->sos_ints++;\n  }\n\n  FREE(new_column);\n  FREE(new_index);\n\n  /* Fill lists of GUB constraints, if appropriate */\n  if((MIP_count(lp) > 0) && is_bb_mode(lp, NODE_GUBMODE) && (identify_GUB(lp, AUTOMATIC) > 0))\n    prepare_GUB(lp);\n\n  /* (Re)allocate reduced cost arrays */\n  ok = allocREAL(lp, &(lp->drow), lp->sum+1, AUTOMATIC) &&\n       allocINT(lp, &(lp->nzdrow), lp->sum+1, AUTOMATIC);\n  if(ok)\n    lp->nzdrow[0] = 0;\n\n  /* Minimize memory usage */\n  memopt_lp(lp, 0, 0, 0);\n\n  lp->wasPreprocessed = TRUE;\n\n  return(ok);\n}\n\nvoid postprocess(lprec *lp)\n{\n  int i,ii,j;\n  REAL hold;\n\n /* Check if the problem actually was preprocessed */\n  if(!lp->wasPreprocessed)\n    return;\n\n /* Must compute duals here in case we have free variables; note that in\n    this case sensitivity analysis is not possible unless done here */\n  if((lp->bb_totalnodes == 0) && (lp->var_is_free == NULL)) {\n    if(is_presolve(lp, PRESOLVE_DUALS))\n      construct_duals(lp);\n    if(is_presolve(lp, PRESOLVE_SENSDUALS))\n      if(!construct_sensitivity_duals(lp) || !construct_sensitivity_obj(lp))\n        report(lp, IMPORTANT, \"postprocess: Unable to allocate working memory for duals.\\n\");\n  }\n\n /* Loop over all columns */\n  for (j = 1; j <= lp->columns; j++) {\n    i = lp->rows + j;\n   /* Reconstruct strictly negative values */\n    if((lp->var_is_free != NULL) && (lp->var_is_free[j] < 0)) {\n      /* Check if we have the simple case where the UP and LB are negated and switched */\n      if(-lp->var_is_free[j] == j) {\n        mat_multcol(lp->matA, j, -1, TRUE);\n        hold = lp->orig_upbo[i];\n        lp->orig_upbo[i] = my_flipsign(lp->orig_lowbo[i]);\n        lp->orig_lowbo[i] = my_flipsign(hold);\n        lp->best_solution[i] = my_flipsign(lp->best_solution[i]);\n        transfer_solution_var(lp, j);\n\n        /* hold = lp->objfrom[j];\n        lp->objfrom[j] = my_flipsign(lp->objtill[j]);\n        lp->objtill[j] = my_flipsign(hold); */ /* under investigation <peno> */\n\n        /* lp->duals[i] = my_flipsign(lp->duals[i]);\n        hold = lp->dualsfrom[i];\n        lp->dualsfrom[i] = my_flipsign(lp->dualstill[i]);\n        lp->dualstill[i] = my_flipsign(hold); */ /* under investigation <peno> */\n       /* Bound switch undone, so clear the status */\n        lp->var_is_free[j] = 0;\n       /* Adjust negative ranged SC */\n        if(lp->sc_lobound[j] > 0)\n          lp->orig_lowbo[lp->rows + j] = -lp->sc_lobound[j];\n      }\n      /* Ignore the split / helper columns (will be deleted later) */\n    }\n   /* Condense values of extra columns of quasi-free variables split in two */\n    else if((lp->var_is_free != NULL) && (lp->var_is_free[j] > 0)) {\n      ii = lp->var_is_free[j]; /* Index of the split helper var */\n      /* if(lp->objfrom[j] == -lp->infinite)\n        lp->objfrom[j] = -lp->objtill[ii];\n      lp->objtill[ii] = lp->infinite;\n      if(lp->objtill[j] == lp->infinite)\n        lp->objtill[j] = my_flipsign(lp->objfrom[ii]);\n      lp->objfrom[ii] = -lp->infinite; */ /* under investigation <peno> */\n\n      ii += lp->rows;\n      lp->best_solution[i] -= lp->best_solution[ii]; /* join the solution again */\n      transfer_solution_var(lp, j);\n      lp->best_solution[ii] = 0;\n\n      /* if(lp->duals[i] == 0)\n        lp->duals[i] = my_flipsign(lp->duals[ii]);\n      lp->duals[ii] = 0;\n      if(lp->dualsfrom[i] == -lp->infinite)\n        lp->dualsfrom[i] = my_flipsign(lp->dualstill[ii]);\n      lp->dualstill[ii] = lp->infinite;\n      if(lp->dualstill[i] == lp->infinite)\n        lp->dualstill[i] = my_flipsign(lp->dualsfrom[ii]);\n      lp->dualsfrom[ii] = -lp->infinite; */ /* under investigation <peno> */\n\n      /* Reset to original bound */\n      lp->orig_lowbo[i] = my_flipsign(lp->orig_upbo[ii]);\n    }\n   /* Adjust for semi-continuous variables */\n    else if(lp->sc_lobound[j] > 0) {\n      lp->orig_lowbo[i] = lp->sc_lobound[j];\n    }\n  }\n\n  /* Remove any split column helper variables */\n  del_splitvars(lp);\n  post_MIPOBJ(lp);\n\n  /* Do extended reporting, if specified */\n  if(lp->verbose > NORMAL) {\n    REPORT_extended(lp);\n\n  }\n\n  lp->wasPreprocessed = FALSE;\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_lib.h",
    "content": "\n#ifndef HEADER_lp_lib\n#define HEADER_lp_lib\n\n/* --------------------------------------------------------------------------\n\n  This is the main library header file for the lp_solve v5.0 release\n\n  Starting at version 3.0, LP_Solve is released under the LGPL license.\n  For full information, see the enclosed file LGPL.txt.\n\n  Original developer:   Michel Berkelaar  -  michel@ics.ele.tue.nl\n  Most changes 1.5-2.0: Jeroen Dirks      -  jeroend@tor.numetrix.com\n  Changes 3.2-4.0:      Kjell Eikland     -  kjell.eikland@broadpark.no\n                        (Simplex code, SOS, SC, code optimization)\n                        Peter Notebaert   -  lpsolve@peno.be\n                        (Sensitivity analysis, documentation)\n  Changes 5.0+:         Kjell Eikland     -  kjell.eikland@broadpark.no\n                        (BFP, XLI, simplex, B&B, code modularization)\n                        Peter Notebaert   -  lpsolve@peno.be\n                        (Sensitivity analysis, New lp parser, LINDO (XLI)\n                        parser, VB/.NET interface, documentation)\n\n  Release notes:\n\n  Version 4.0 enhances version 3.2 in terms of internal program/simplex\n  architecture, call level interfaces, data layout, features and contains\n  several bug fixes.  There is now complete support for semi-continuous\n  variables and SOS constructions.  In the process, a complete API\n  was added. The MPS parser has been amended to support this.\n  Sensitivity analysis and variouse bug fixes was provided by Peter\n  Notebaert in 4.0 sub-releases.  Peter also wrote a complete\n  documentation of the API and contributed a VB interface, both of which\n  significantly enhanced the accessibility of lp_solve.\n\n  Version 5.0 is a major rewrite and code cleanup.  The main additions that\n  drove forward this cleanup were the modular inversion logic with optimal\n  column ordering, addition of primal phase 1 and dual phase 2 logic for\n  full flexibility in the selection of primal and dual simplex modes,\n  DEVEX and steepest edge pivot selection, along with dynamic cycling\n  detection and prevention.  This cleanup made it possible to harmonize the\n  internal rounding principles, contributing to increased numerical stability.\n\n  Version 5.1 rearranges the matrix storage model by enabling both legacy\n  element record-based storage and split vector storage.  In addition the\n  lprec structure is optimized and additional routines are added, mainly for\n  sparse vector additions and enhanced XLI functionality.  Support for XML-\n  based models was added on the basis of the LPFML schema via xli_LPFML.\n\n  Version 5.2 removes the objective function from the constraint matrix,\n  adds a number of presolve options and speed them up.  Degeneracy handling\n  is significantly improved. Support for XLI_ZIMPL was added.\n  Multiple and partial pricing has been enhanced and activated.\n\n  -------------------------------------------------------------------------- */\n/* Define user program feature option switches                               */\n/* ------------------------------------------------------------------------- */\n\n# if defined _WIN32 && !defined __GNUC__\n#  define isnan _isnan\n# endif\n#if defined NOISNAN\n# define isnan(x) FALSE\n#endif\n\n#define SETMASK(variable, mask)     variable |= mask\n#define CLEARMASK(variable, mask)   variable &= ~(mask)\n#define TOGGLEMASK(variable, mask)  variable ^= mask\n#define ISMASKSET(variable, mask)   (MYBOOL) (((variable) & (mask)) != 0)\n\n/* Utility/system settings                                                   */\n/* ------------------------------------------------------------------------- */\n/*#define INTEGERTIME */                    /* Set use of lower-resolution timer */\n\n\n/* New v5.0+ simplex/optimization features and settings                      */\n/* ------------------------------------------------------------------------- */\n/*#define NoRowScaleOF */               /* Optionally skip row-scaling of the OF */\n#define DoMatrixRounding                  /* Round A matrix elements to precision */\n#define DoBorderRounding            /* Round RHS, bounds and ranges to precision */\n#define Phase1EliminateRedundant        /* Remove rows of redundant artificials  */\n#define FixViolatedOptimal\n#define ImproveSolutionPrecision                 /* Round optimal solution values */\n/*#define IncreasePivotOnReducedAccuracy */  /* Increase epspivot on instability */\n/*#define FixInaccurateDualMinit */     /* Reinvert on inaccuracy in dual minits */\n/*#define EnforcePositiveTheta */        /* Ensure that the theta range is valid */\n#define ResetMinitOnReinvert\n/*#define UsePrimalReducedCostUpdate */                            /* Not tested */\n/*#define UseDualReducedCostUpdate */      /* Seems Ok, but slower than expected */\n/*#ifdef UseLegacyExtrad */                     /* Use v3.2- style Extrad method */\n#define UseMilpExpandedRCF         /* Non-ints in reduced cost bound tightening */\n/*#define UseMilpSlacksRCF */  /* Slacks in reduced cost bound tightening (degen\n                                  prone); requires !SlackInitMinusInf */\n#define LegacySlackDefinition      /* Slack as the \"value of the constraint\" */\n\n\n/* Development features (change at own risk)                                 */\n/* ------------------------------------------------------------------------- */\n/*#define MIPboundWithOF */ /* Enable to detect OF constraint for use during B&B */\n/*#define SlackInitMinusInf */        /* Slacks have 0 LB if this is not defined */\n#define FULLYBOUNDEDSIMPLEX FALSE     /* WARNING: Activate at your own risk! */\n\n\n/* Specify use of the basic linear algebra subroutine library                */\n/* ------------------------------------------------------------------------- */\n#define libBLAS                  2        /* 0: No, 1: Internal, 2: External */\n#define libnameBLAS        \"myBLAS\"\n\n\n/* Active inverse logic (default is optimized original etaPFI)               */\n/* ------------------------------------------------------------------------- */\n#if !defined LoadInverseLib\n# define LoadInverseLib TRUE          /* Enable alternate inverse libraries */\n#endif\n/*#define ExcludeNativeInverse     */   /* Disable INVERSE_ACTIVE inverse engine */\n\n#define DEF_OBJINBASIS        TRUE  /* Additional rows inserted at the top (1 => OF) */\n\n#define INVERSE_NONE            -1\n#define INVERSE_LEGACY           0\n#define INVERSE_ETAPFI           1\n#define INVERSE_LUMOD            2\n#define INVERSE_LUSOL            3\n#define INVERSE_GLPKLU           4\n\n#ifndef RoleIsExternalInvEngine            /* Defined in inverse DLL drivers */\n  #ifdef ExcludeNativeInverse\n    #define INVERSE_ACTIVE       INVERSE_NONE       /* Disable native engine */\n  #else\n    #define INVERSE_ACTIVE       INVERSE_LEGACY      /* User or DLL-selected */\n  #endif\n#endif\n\n\n/* Active external language interface logic (default is none)                */\n/* ------------------------------------------------------------------------- */\n#if !defined LoadLanguageLib\n# define LoadLanguageLib TRUE         /* Enable alternate language libraries */\n#endif\n#define ExcludeNativeLanguage                 /* Disable LANGUAGE_ACTIVE XLI */\n\n#define LANGUAGE_NONE           -1\n#define LANGUAGE_LEGACYLP        0\n#define LANGUAGE_CPLEXLP         1\n#define LANGUAGE_MPSX            2\n#define LANGUAGE_LPFML           3\n#define LANGUAGE_MATHPROG        4\n#define LANGUAGE_AMPL            5\n#define LANGUAGE_GAMS            6\n#define LANGUAGE_ZIMPL           7\n#define LANGUAGE_S               8\n#define LANGUAGE_R               9\n#define LANGUAGE_MATLAB         10\n#define LANGUAGE_OMATRIX        11\n#define LANGUAGE_SCILAB         12\n#define LANGUAGE_OCTAVE         13\n#define LANGUAGE_EMPS           14\n\n#ifndef RoleIsExternalLanguageEngine      /* Defined in XLI driver libraries */\n  #ifdef ExcludeNativeLanguage\n    #define LANGUAGE_ACTIVE       LANGUAGE_NONE     /* Disable native engine */\n  #else\n    #define LANGUAGE_ACTIVE       LANGUAGE_CPLEXLP   /* User or DLL-selected */\n  #endif\n#endif\n\n\n/* Default parameters and tolerances                                         */\n/* ------------------------------------------------------------------------- */\n#define OriginalPARAM           0\n#define ProductionPARAM         1\n#define ChvatalPARAM            2\n#define LoosePARAM              3\n#if 1\n  #define ActivePARAM           ProductionPARAM\n#else\n  #define ActivePARAM           LoosePARAM\n#endif\n\n\n/* Miscellaneous settings                                                    */\n/* ------------------------------------------------------------------------- */\n#ifndef Paranoia\n  #ifdef _DEBUG\n    #define Paranoia\n  #endif\n#endif\n\n\n/* Program version data                                                      */\n/* ------------------------------------------------------------------------- */\n#define MAJORVERSION             5\n#define MINORVERSION             5\n#define RELEASE                  2\n#define BUILD                    5\n#define BFPVERSION              12       /* Checked against bfp_compatible() */\n#define XLIVERSION              12       /* Checked against xli_compatible() */\n/* Note that both BFPVERSION and XLIVERSION typically have to be incremented\n   in the case that the lprec structure changes.                             */\n\n\n/* Include/header files                                                      */\n/* ------------------------------------------------------------------------- */\n#include <sys/types.h>\n#include <stdlib.h>\n#include <string.h>\n#include <math.h>\n#include <stdio.h>\n\n#include \"lp_types.h\"\n#include \"lp_utils.h\"\n\n#if (LoadInverseLib == TRUE) || (LoadLanguageLib == TRUE)\n  #ifdef WIN32\n    #include <windows.h>\n  #else\n    #include <dlfcn.h>\n  #endif\n#endif\n\n#ifndef BFP_CALLMODEL\n  #ifdef WIN32\n    #define BFP_CALLMODEL __stdcall   /* \"Standard\" call model */\n  #else\n    #define BFP_CALLMODEL\n  #endif\n#endif\n#ifndef XLI_CALLMODEL\n  #define XLI_CALLMODEL BFP_CALLMODEL\n#endif\n\n#define REGISTER             /* Speed up certain operations */\n\n\n/* Definition of program constrants                                          */\n/* ------------------------------------------------------------------------- */\n#define SIMPLEX_UNDEFINED        0\n#define SIMPLEX_Phase1_PRIMAL    1\n#define SIMPLEX_Phase1_DUAL      2\n#define SIMPLEX_Phase2_PRIMAL    4\n#define SIMPLEX_Phase2_DUAL      8\n#define SIMPLEX_DYNAMIC         16\n#define SIMPLEX_AUTODUALIZE     32\n\n#define SIMPLEX_PRIMAL_PRIMAL   (SIMPLEX_Phase1_PRIMAL + SIMPLEX_Phase2_PRIMAL)\n#define SIMPLEX_DUAL_PRIMAL     (SIMPLEX_Phase1_DUAL   + SIMPLEX_Phase2_PRIMAL)\n#define SIMPLEX_PRIMAL_DUAL     (SIMPLEX_Phase1_PRIMAL + SIMPLEX_Phase2_DUAL)\n#define SIMPLEX_DUAL_DUAL       (SIMPLEX_Phase1_DUAL   + SIMPLEX_Phase2_DUAL)\n#define SIMPLEX_DEFAULT         (SIMPLEX_DUAL_PRIMAL)\n\n/* Variable codes (internal) */\n#define ISREAL                   0\n#define ISINTEGER                1\n#define ISSEMI                   2\n#define ISSOS                    4\n#define ISSOSTEMPINT             8\n#define ISGUB                   16\n\n/* Presolve defines */\n#define PRESOLVE_NONE            0\n#define PRESOLVE_ROWS            1\n#define PRESOLVE_COLS            2\n#define PRESOLVE_LINDEP          4\n#define PRESOLVE_AGGREGATE       8  /* Not implemented */\n#define PRESOLVE_SPARSER        16  /* Not implemented */\n#define PRESOLVE_SOS            32\n#define PRESOLVE_REDUCEMIP      64\n#define PRESOLVE_KNAPSACK      128  /* Implementation not tested completely */\n#define PRESOLVE_ELIMEQ2       256\n#define PRESOLVE_IMPLIEDFREE   512\n#define PRESOLVE_REDUCEGCD    1024\n#define PRESOLVE_PROBEFIX     2048\n#define PRESOLVE_PROBEREDUCE  4096\n#define PRESOLVE_ROWDOMINATE  8192\n#define PRESOLVE_COLDOMINATE 16384  /* Reduced functionality, should be expanded */\n#define PRESOLVE_MERGEROWS   32768\n#define PRESOLVE_IMPLIEDSLK  65536\n#define PRESOLVE_COLFIXDUAL 131072\n#define PRESOLVE_BOUNDS     262144\n#define PRESOLVE_LASTMASKMODE    (PRESOLVE_DUALS - 1)\n#define PRESOLVE_DUALS      524288\n#define PRESOLVE_SENSDUALS 1048576\n\n/* Basis crash options */\n#define CRASH_NONE               0\n#define CRASH_NONBASICBOUNDS     1\n#define CRASH_MOSTFEASIBLE       2\n#define CRASH_LEASTDEGENERATE    3\n\n/* Solution recomputation options (internal) */\n#define INITSOL_SHIFTZERO        0\n#define INITSOL_USEZERO          1\n#define INITSOL_ORIGINAL         2\n\n/* Strategy codes to avoid or recover from degenerate pivots,\n   infeasibility or numeric errors via randomized bound relaxation */\n#define ANTIDEGEN_NONE           0\n#define ANTIDEGEN_FIXEDVARS      1\n#define ANTIDEGEN_COLUMNCHECK    2\n#define ANTIDEGEN_STALLING       4\n#define ANTIDEGEN_NUMFAILURE     8\n#define ANTIDEGEN_LOSTFEAS      16\n#define ANTIDEGEN_INFEASIBLE    32\n#define ANTIDEGEN_DYNAMIC       64\n#define ANTIDEGEN_DURINGBB     128\n#define ANTIDEGEN_RHSPERTURB   256\n#define ANTIDEGEN_BOUNDFLIP    512\n#define ANTIDEGEN_DEFAULT        (ANTIDEGEN_FIXEDVARS | ANTIDEGEN_STALLING /* | ANTIDEGEN_INFEASIBLE */)\n\n/* REPORT defines */\n#define NEUTRAL                  0\n#define CRITICAL                 1\n#define SEVERE                   2\n#define IMPORTANT                3\n#define NORMAL                   4\n#define DETAILED                 5\n#define FULL                     6\n\n/* MESSAGE defines */\n#define MSG_NONE                 0\n#define MSG_PRESOLVE             1\n#define MSG_ITERATION            2\n#define MSG_INVERT               4\n#define MSG_LPFEASIBLE           8\n#define MSG_LPOPTIMAL           16\n#define MSG_LPEQUAL             32\n#define MSG_LPBETTER            64\n#define MSG_MILPFEASIBLE       128\n#define MSG_MILPEQUAL          256\n#define MSG_MILPBETTER         512\n#define MSG_MILPSTRATEGY      1024\n#define MSG_MILPOPTIMAL       2048\n#define MSG_PERFORMANCE       4096\n#define MSG_INITPSEUDOCOST    8192\n\n/* MPS file types */\n#define MPSFIXED                 1\n#define MPSFREE                  2\n#define MPSIBM                   4\n#define MPSNEGOBJCONST           8\n\n#define MPS_FREE                 (MPSFREE<<2)\n#define MPS_IBM                  (MPSIBM<<2)\n#define MPS_NEGOBJCONST          (MPSNEGOBJCONST<<2)\n\n/* MPS defines (internal) */\n#define MPSUNDEF                -4\n#define MPSNAME                 -3\n#define MPSOBJSENSE             -2\n#define MPSOBJNAME              -1\n#define MPSROWS                  0\n#define MPSCOLUMNS               1\n#define MPSRHS                   2\n#define MPSBOUNDS                3\n#define MPSRANGES                4\n#define MPSSOS                   5\n\n#define MPSVARMASK          \"%-8s\"\n#define MPSVALUEMASK        \"%12g\"\n\n/* Constraint type codes  (internal) */\n#define ROWTYPE_EMPTY            0\n#define ROWTYPE_LE               1\n#define ROWTYPE_GE               2\n#define ROWTYPE_EQ               3\n#define ROWTYPE_CONSTRAINT       ROWTYPE_EQ  /* This is the mask for modes */\n#define ROWTYPE_OF               4\n#define ROWTYPE_INACTIVE         8\n#define ROWTYPE_RELAX           16\n#define ROWTYPE_GUB             32\n#define ROWTYPE_OFMAX            (ROWTYPE_OF + ROWTYPE_GE)\n#define ROWTYPE_OFMIN            (ROWTYPE_OF + ROWTYPE_LE)\n#define ROWTYPE_CHSIGN           ROWTYPE_GE\n\n/* Public constraint codes */\n#define FR                       ROWTYPE_EMPTY\n#define LE                       ROWTYPE_LE\n#define GE                       ROWTYPE_GE\n#define EQ                       ROWTYPE_EQ\n#ifdef OF\n# undef OF\n#endif\n#define OF                       ROWTYPE_OF\n\n/* MIP constraint classes */\n#define ROWCLASS_Unknown         0   /* Undefined/unknown */\n#define ROWCLASS_Objective       1   /* The objective function */\n#define ROWCLASS_GeneralREAL     2   /* General real-values constraint */\n#define ROWCLASS_GeneralMIP      3   /* General mixed integer/binary and real valued constraint */\n#define ROWCLASS_GeneralINT      4   /* General integer-only constraint */\n#define ROWCLASS_GeneralBIN      5   /* General binary-only constraint */\n#define ROWCLASS_KnapsackINT     6   /* Sum of positive integer times integer variables <= positive integer */\n#define ROWCLASS_KnapsackBIN     7   /* Sum of positive integer times binary variables <= positive integer */\n#define ROWCLASS_SetPacking      8   /* Sum of binary variables >= 1 */\n#define ROWCLASS_SetCover        9   /* Sum of binary variables <= 1 */\n#define ROWCLASS_GUB            10   /* Sum of binary variables = 1  */\n#define ROWCLASS_MAX             ROWCLASS_GUB\n\n/* Column subsets (internal) */\n#define SCAN_USERVARS            1\n#define SCAN_SLACKVARS           2\n#define SCAN_ARTIFICIALVARS      4\n#define SCAN_PARTIALBLOCK        8\n#define USE_BASICVARS           16\n#define USE_NONBASICVARS        32\n#define SCAN_NORMALVARS         (SCAN_USERVARS + SCAN_ARTIFICIALVARS)\n#define SCAN_ALLVARS            (SCAN_SLACKVARS + SCAN_USERVARS + SCAN_ARTIFICIALVARS)\n#define USE_ALLVARS             (USE_BASICVARS + USE_NONBASICVARS)\n#define OMIT_FIXED              64\n#define OMIT_NONFIXED          128\n\n/* Improvement defines */\n#define IMPROVE_NONE             0\n#define IMPROVE_SOLUTION         1\n#define IMPROVE_DUALFEAS         2\n#define IMPROVE_THETAGAP         4\n#define IMPROVE_BBSIMPLEX        8\n#define IMPROVE_DEFAULT          (IMPROVE_DUALFEAS + IMPROVE_THETAGAP)\n#define IMPROVE_INVERSE          (IMPROVE_SOLUTION + IMPROVE_THETAGAP)\n\n/* Scaling types */\n#define SCALE_NONE               0\n#define SCALE_EXTREME            1\n#define SCALE_RANGE              2\n#define SCALE_MEAN               3\n#define SCALE_GEOMETRIC          4\n#define SCALE_FUTURE1            5\n#define SCALE_FUTURE2            6\n#define SCALE_CURTISREID         7   /* Override to Curtis-Reid \"optimal\" scaling */\n\n/* Alternative scaling weights */\n#define SCALE_LINEAR             0\n#define SCALE_QUADRATIC          8\n#define SCALE_LOGARITHMIC       16\n#define SCALE_USERWEIGHT        31\n#define SCALE_MAXTYPE            (SCALE_QUADRATIC-1)\n\n/* Scaling modes */\n#define SCALE_POWER2            32   /* As is or rounded to power of 2 */\n#define SCALE_EQUILIBRATE       64   /* Make sure that no scaled number is above 1 */\n#define SCALE_INTEGERS         128   /* Apply to integer columns/variables */\n#define SCALE_DYNUPDATE        256   /* Apply incrementally every solve() */\n#define SCALE_ROWSONLY         512   /* Override any scaling to only scale the rows */\n#define SCALE_COLSONLY        1024   /* Override any scaling to only scale the rows */\n\n/* Standard defines for typical scaling models (no Lagrangeans) */\n#define SCALEMODEL_EQUILIBRATED  (SCALE_LINEAR+SCALE_EXTREME+SCALE_INTEGERS)\n#define SCALEMODEL_GEOMETRIC     (SCALE_LINEAR+SCALE_GEOMETRIC+SCALE_INTEGERS)\n#define SCALEMODEL_ARITHMETIC    (SCALE_LINEAR+SCALE_MEAN+SCALE_INTEGERS)\n#define SCALEMODEL_DYNAMIC       (SCALEMODEL_GEOMETRIC+SCALE_EQUILIBRATE)\n#define SCALEMODEL_CURTISREID    (SCALE_CURTISREID+SCALE_INTEGERS+SCALE_POWER2)\n\n/* Iteration status and strategies (internal) */\n#define ITERATE_MAJORMAJOR       0\n#define ITERATE_MINORMAJOR       1\n#define ITERATE_MINORRETRY       2\n\n/* Pricing methods */\n#define PRICER_FIRSTINDEX        0\n#define PRICER_DANTZIG           1\n#define PRICER_DEVEX             2\n#define PRICER_STEEPESTEDGE      3\n#define PRICER_LASTOPTION        PRICER_STEEPESTEDGE\n\n/* Additional settings for pricers (internal) */\n#define PRICER_RANDFACT        0.1\n#define DEVEX_RESTARTLIMIT 1.0e+09    /* Reset the norms if any value exceeds this limit */\n#define DEVEX_MINVALUE       0.000    /* Minimum weight [0..1] for entering variable, consider 0.01 */\n\n/* Pricing strategies */\n#define PRICE_PRIMALFALLBACK     4    /* In case of Steepest Edge, fall back to DEVEX in primal */\n#define PRICE_MULTIPLE           8    /* Enable multiple pricing (primal simplex) */\n#define PRICE_PARTIAL           16    /* Enable partial pricing */\n#define PRICE_ADAPTIVE          32    /* Temporarily use alternative strategy if cycling is detected */\n#define PRICE_HYBRID            64    /* NOT IMPLEMENTED */\n#define PRICE_RANDOMIZE        128    /* Adds a small randomization effect to the selected pricer */\n#define PRICE_AUTOPARTIAL      256    /* Detect and use data on the block structure of the model (primal) */\n#define PRICE_AUTOMULTIPLE     512    /* Automatically select multiple pricing (primal simplex) */\n#define PRICE_LOOPLEFT        1024    /* Scan entering/leaving columns left rather than right */\n#define PRICE_LOOPALTERNATE   2048    /* Scan entering/leaving columns alternatingly left/right */\n#define PRICE_HARRISTWOPASS   4096    /* Use Harris' primal pivot logic rather than the default */\n#define PRICE_FORCEFULL       8192    /* Non-user option to force full pricing */\n#define PRICE_TRUENORMINIT   16384    /* Use true norms for Devex and Steepest Edge initializations */\n\n/*#define _PRICE_NOBOUNDFLIP*/\n#if defined _PRICE_NOBOUNDFLIP\n#define PRICE_NOBOUNDFLIP    65536    /* Disallow automatic bound-flip during pivot */\n#endif\n\n#define PRICE_STRATEGYMASK       (PRICE_PRIMALFALLBACK + \\\n                                  PRICE_MULTIPLE + PRICE_PARTIAL + \\\n                                  PRICE_ADAPTIVE + PRICE_HYBRID + \\\n                                  PRICE_RANDOMIZE + PRICE_AUTOPARTIAL + PRICE_AUTOMULTIPLE + \\\n                                  PRICE_LOOPLEFT + PRICE_LOOPALTERNATE + \\\n                                  PRICE_HARRISTWOPASS + \\\n                                  PRICE_FORCEFULL + PRICE_TRUENORMINIT)\n\n/* B&B active variable codes (internal) */\n#define BB_REAL                  0\n#define BB_INT                   1\n#define BB_SC                    2\n#define BB_SOS                   3\n#define BB_GUB                   4\n\n/* B&B strategies */\n#define NODE_FIRSTSELECT         0\n#define NODE_GAPSELECT           1\n#define NODE_RANGESELECT         2\n#define NODE_FRACTIONSELECT      3\n#define NODE_PSEUDOCOSTSELECT    4\n#define NODE_PSEUDONONINTSELECT  5    /* Kjell Eikland #1 - Minimize B&B depth */\n#define NODE_PSEUDOFEASSELECT   (NODE_PSEUDONONINTSELECT+NODE_WEIGHTREVERSEMODE)\n#define NODE_PSEUDORATIOSELECT   6    /* Kjell Eikland #2 - Minimize a \"cost/benefit\" ratio */\n#define NODE_USERSELECT          7\n#define NODE_STRATEGYMASK        (NODE_WEIGHTREVERSEMODE-1) /* Mask for B&B strategies */\n#define NODE_WEIGHTREVERSEMODE   8\n#define NODE_BRANCHREVERSEMODE  16\n#define NODE_GREEDYMODE         32\n#define NODE_PSEUDOCOSTMODE     64\n#define NODE_DEPTHFIRSTMODE    128\n#define NODE_RANDOMIZEMODE     256\n#define NODE_GUBMODE           512\n#define NODE_DYNAMICMODE      1024\n#define NODE_RESTARTMODE      2048\n#define NODE_BREADTHFIRSTMODE 4096\n#define NODE_AUTOORDER        8192\n#define NODE_RCOSTFIXING     16384\n#define NODE_STRONGINIT      32768\n\n#define BRANCH_CEILING           0\n#define BRANCH_FLOOR             1\n#define BRANCH_AUTOMATIC         2\n#define BRANCH_DEFAULT           3\n\n/* Action constants for simplex and B&B (internal) */\n#define ACTION_NONE              0\n#define ACTION_ACTIVE            1\n#define ACTION_REBASE            2\n#define ACTION_RECOMPUTE         4\n#define ACTION_REPRICE           8\n#define ACTION_REINVERT         16\n#define ACTION_TIMEDREINVERT    32\n#define ACTION_ITERATE          64\n#define ACTION_RESTART         255\n\n/* Solver status values */\n#define UNKNOWNERROR            -5\n#define DATAIGNORED             -4\n#define NOBFP                   -3\n#define NOMEMORY                -2\n#define NOTRUN                  -1\n#define OPTIMAL                  0\n#define SUBOPTIMAL               1\n#define INFEASIBLE               2\n#define UNBOUNDED                3\n#define DEGENERATE               4\n#define NUMFAILURE               5\n#define USERABORT                6\n#define TIMEOUT                  7\n#define RUNNING                  8\n#define PRESOLVED                9\n#define ACCURACYERROR           25\n\n/* Branch & Bound and Lagrangean extra status values (internal) */\n#define PROCFAIL                10\n#define PROCBREAK               11\n#define FEASFOUND               12\n#define NOFEASFOUND             13\n#define FATHOMED                14\n\n/* Status values internal to the solver (internal) */\n#define SWITCH_TO_PRIMAL        20\n#define SWITCH_TO_DUAL          21\n#define SINGULAR_BASIS          22\n#define LOSTFEAS                23\n#define MATRIXERROR             24\n\n/* Objective testing options for \"bb_better\" (internal) */\n#define OF_RELAXED               0\n#define OF_INCUMBENT             1\n#define OF_WORKING               2\n#define OF_USERBREAK             3\n#define OF_HEURISTIC             4\n#define OF_DUALLIMIT             5\n#define OF_DELTA                 8  /* Mode */\n#define OF_PROJECTED            16  /* Mode - future, not active */\n\n#define OF_TEST_BT               1\n#define OF_TEST_BE               2\n#define OF_TEST_NE               3\n#define OF_TEST_WE               4\n#define OF_TEST_WT               5\n#define OF_TEST_RELGAP           8  /* Mode */\n\n\n/* Name list and sparse matrix storage parameters (internal) */\n#define MAT_START_SIZE       10000\n#define DELTACOLALLOC          100\n#define DELTAROWALLOC          100\n#define RESIZEFACTOR             4  /* Fractional increase in selected memory allocations */\n\n/* Default solver parameters and tolerances (internal) */\n#define DEF_PARTIALBLOCKS       10  /* The default number of blocks for partial pricing */\n#define DEF_MAXRELAX             7  /* Maximum number of non-BB relaxations in MILP */\n#define DEF_MAXPIVOTRETRY       10  /* Maximum number of times to retry a div-0 situation */\n#define DEF_MAXSINGULARITIES    10  /* Maximum number of singularities in refactorization */\n#define MAX_MINITUPDATES        60  /* Maximum number of bound swaps between refactorizations\n                                       without recomputing the whole vector - contain errors */\n#define MIN_REFACTFREQUENCY      5  /* Refactorization frequency indicating an inherent\n                                       numerical instability of the basis */\n#define LAG_SINGULARLIMIT        5  /* Number of times the objective does not change\n                                       before it is assumed that the Lagrangean constraints\n                                       are non-binding, and therefore impossible to converge;\n                                       upper iteration limit is divided by this threshold */\n#define MIN_TIMEPIVOT      5.0e-02  /* Minimum time per pivot for reinversion optimization\n                                       purposes; use active monitoring only if a pivot\n                                       takes more than MINTIMEPIVOT seconds.  5.0e-2 is\n                                       roughly suitable for a 1GHz system.  */\n#define MAX_STALLCOUNT          12  /* The absolute upper limit to the number of stalling or\n                                       cycling iterations before switching rule */\n#define MAX_RULESWITCH           5  /* The maximum number of times to try an alternate pricing rule\n                                       to recover from stalling; set negative for no limit. */\n#define DEF_TIMEDREFACT  AUTOMATIC  /* Default for timed refactorization in BFPs;\n                                       can be FALSE, TRUE or AUTOMATIC (dynamic) */\n\n#define DEF_SCALINGLIMIT         5  /* The default maximum number of scaling iterations */\n\n#define DEF_NEGRANGE      -1.0e+06  /* Downward limit for expanded variable range before the\n                                       variable is split into positive and negative components */\n#define DEF_BB_LIMITLEVEL      -50  /* Relative B&B limit to protect against very deep,\n                                       memory-consuming trees */\n\n#define MAX_FRACSCALE            6  /* The maximum decimal scan range for simulated integers */\n#define RANDSCALE              100  /* Randomization scaling range */\n#define DOUBLEROUND        0.0e-02  /* Extra rounding scalar used in btran/ftran calculations; the\n                                       rationale for 0.0 is that prod_xA() uses rounding as well */\n#define DEF_EPSMACHINE    2.22e-16  /* Machine relative precision (doubles) */\n#define MIN_STABLEPIVOT        5.0  /* Minimum pivot magnitude assumed to be numerically stable */\n\n\n/* Precision macros                                                                       */\n/* -------------------------------------------------------------------------------------- */\n#define PREC_REDUCEDCOST        lp->epsvalue\n#define PREC_IMPROVEGAP         lp->epsdual\n#define PREC_SUBSTFEASGAP       lp->epsprimal\n#if 1\n  #define PREC_BASICSOLUTION    lp->epsvalue  /* Zero-rounding of RHS/basic solution vector */\n#else\n  #define PREC_BASICSOLUTION    lp->epsmachine  /* Zero-rounding of RHS/basic solution vector */\n#endif\n#define LIMIT_ABS_REL         10.0  /* Limit for testing using relative metric */\n\n\n/* Parameters constants for short-cut setting of tolerances                           */\n/* -------------------------------------------------------------------------------------- */\n#define EPS_TIGHT                0\n#define EPS_MEDIUM               1\n#define EPS_LOOSE                2\n#define EPS_BAGGY                3\n#define EPS_DEFAULT              EPS_TIGHT\n\n\n#if ActivePARAM==ProductionPARAM    /* PARAMETER SET FOR PRODUCTION                       */\n/* -------------------------------------------------------------------------------------- */\n#define DEF_INFINITE       1.0e+30  /* Limit for dynamic range */\n#define DEF_EPSVALUE       1.0e-12  /* High accuracy and feasibility preserving tolerance */\n#define DEF_EPSPRIMAL      1.0e-10  /* For rounding primal/RHS values to 0 */\n#define DEF_EPSDUAL        1.0e-09  /* For rounding reduced costs to 0 */\n#define DEF_EPSPIVOT       2.0e-07  /* Pivot reject threshold */\n#define DEF_PERTURB        1.0e-05  /* Perturbation scalar for degenerate problems;\n                                       must at least be RANDSCALE greater than EPSPRIMAL */\n#define DEF_EPSSOLUTION    1.0e-05  /* Margin of error for solution bounds */\n#define DEF_EPSINT         1.0e-07  /* Accuracy for considering a float value as integer */\n\n#elif ActivePARAM==OriginalPARAM    /* PARAMETER SET FOR LEGACY VERSIONS                  */\n/* -------------------------------------------------------------------------------------- */\n#define DEF_INFINITE       1.0e+24  /* Limit for dynamic range */\n#define DEF_EPSVALUE       1.0e-08  /* High accuracy and feasibility preserving tolerance */\n#define DEF_EPSPRIMAL     5.01e-07  /* For rounding primal/RHS values to 0, infeasibility */\n#define DEF_EPSDUAL        1.0e-06  /* For rounding reduced costs to 0 */\n#define DEF_EPSPIVOT       1.0e-04  /* Pivot reject threshold */\n#define DEF_PERTURB        1.0e-05  /* Perturbation scalar for degenerate problems;\n                                       must at least be RANDSCALE greater than EPSPRIMAL */\n#define DEF_EPSSOLUTION    1.0e-02  /* Margin of error for solution bounds */\n#define DEF_EPSINT         1.0e-03  /* Accuracy for considering a float value as integer */\n\n#elif ActivePARAM==ChvatalPARAM     /* PARAMETER SET EXAMPLES FROM Vacek Chvatal          */\n/* -------------------------------------------------------------------------------------- */\n#define DEF_INFINITE       1.0e+30  /* Limit for dynamic range */\n#define DEF_EPSVALUE       1.0e-10  /* High accuracy and feasibility preserving tolerance */\n#define DEF_EPSPRIMAL       10e-07  /* For rounding primal/RHS values to 0 */\n#define DEF_EPSDUAL         10e-05  /* For rounding reduced costs to 0 */\n#define DEF_EPSPIVOT        10e-05  /* Pivot reject threshold */\n#define DEF_PERTURB         10e-03  /* Perturbation scalar for degenerate problems;\n                                       must at least be RANDSCALE greater than EPSPRIMAL */\n#define DEF_EPSSOLUTION    1.0e-05  /* Margin of error for solution bounds */\n#define DEF_EPSINT         5.0e-03  /* Accuracy for considering a float value as integer */\n\n#elif ActivePARAM==LoosePARAM       /* PARAMETER SET FOR LOOSE TOLERANCES                 */\n/* -------------------------------------------------------------------------------------- */\n#define DEF_INFINITE       1.0e+30  /* Limit for dynamic range */\n#define DEF_EPSVALUE       1.0e-10  /* High accuracy and feasibility preserving tolerance */\n#define DEF_EPSPRIMAL     5.01e-08  /* For rounding primal/RHS values to 0 */\n#define DEF_EPSDUAL        1.0e-07  /* For rounding reduced costs to 0 */\n#define DEF_EPSPIVOT       1.0e-05  /* Pivot reject threshold */\n#define DEF_PERTURB        1.0e-05  /* Perturbation scalar for degenerate problems;\n                                       must at least be RANDSCALE greater than EPSPRIMAL */\n#define DEF_EPSSOLUTION    1.0e-05  /* Margin of error for solution bounds */\n#define DEF_EPSINT         1.0e-04  /* Accuracy for considering a float value as integer */\n\n#endif\n\n\n#define DEF_MIP_GAP        1.0e-11  /* The default absolute and relative MIP gap */\n#define SCALEDINTFIXRANGE      1.6  /* Epsilon range multiplier < 2 for collapsing bounds to fix */\n\n#define MIN_SCALAR         1.0e-10  /* Smallest allowed scaling adjustment */\n#define MAX_SCALAR         1.0e+10  /* Largest allowed scaling adjustment */\n#define DEF_SCALINGEPS     1.0e-02  /* Relative scaling convergence criterion for auto_scale */\n\n#define DEF_LAGACCEPT      1.0e-03  /* Default Lagrangean convergence acceptance criterion */\n#define DEF_LAGCONTRACT       0.90  /* The contraction parameter for Lagrangean iterations */\n#define DEF_LAGMAXITERATIONS   100  /* The maximum number of Lagrangean iterations */\n\n#define DEF_PSEUDOCOSTUPDATES    7  /* The default number of times pseudo-costs are recalculated;\n                                       experiments indicate that costs tend to stabilize */\n#define DEF_PSEUDOCOSTRESTART 0.15  /* The fraction of price updates required for B&B restart\n                                       when the mode is NODE_RESTARTMODE */\n#define DEF_MAXPRESOLVELOOPS     0  /* Upper limit to the number of loops during presolve,\n                                       <= 0 for no limit. */\n\n\n/* Hashing prototypes and function headers                                   */\n/* ------------------------------------------------------------------------- */\n#include \"lp_Hash.h\"\n\n\n/* Sparse matrix prototypes                                                  */\n/* ------------------------------------------------------------------------- */\n#include \"lp_matrix.h\"\n\n\n/* Basis storage (mainly for B&B) */\ntypedef struct _basisrec\n{\n  int       level;\n  int       *var_basic;\n  MYBOOL    *is_basic;\n  MYBOOL    *is_lower;\n  int       pivots;\n  struct   _basisrec *previous;\n} basisrec;\n\n/* Presolve undo data storage */\ntypedef struct _presolveundorec\n{\n  lprec     *lp;\n  int       orig_rows;\n  int       orig_columns;\n  int       orig_sum;\n  int       *var_to_orig;       /* sum_alloc+1 : Mapping of variables from solution to\n                                   best_solution to account for removed variables and\n                                   rows during presolve; a non-positive value indicates\n                                   that the constraint or variable was removed */\n  int       *orig_to_var;       /* sum_alloc+1 : Mapping from original variable index to\n                                   current / working index number */\n  REAL      *fixed_rhs;         /* rows_alloc+1 : Storage of values of presolved fixed colums */\n  REAL      *fixed_obj;         /* columns_alloc+1: Storage of values of presolved fixed rows */\n  DeltaVrec *deletedA;          /* A matrix of eliminated data from matA */\n  DeltaVrec *primalundo;        /* Affine translation vectors for eliminated primal variables */\n  DeltaVrec *dualundo;          /* Affine translation vectors for eliminated dual variables */\n  MYBOOL    OFcolsdeleted;\n} presolveundorec;\n\n/* Pseudo-cost arrays used during B&B */\ntypedef struct _BBPSrec\n{\n  lprec     *lp;\n  int       pseodotype;\n  int       updatelimit;\n  int       updatesfinished;\n  REAL      restartlimit;\n  MATitem   *UPcost;\n  MATitem   *LOcost;\n  struct   _BBPSrec *secondary;\n} BBPSrec;\n\n#include \"lp_mipbb.h\"\n\n\n/* Partial pricing block data */\ntypedef struct _partialrec {\n  lprec     *lp;\n  int       blockcount;         /* ## The number of logical blocks or stages in the model */\n  int       blocknow;           /* The currently active block */\n  int       *blockend;          /* Array of column indeces giving the start of each block */\n  int       *blockpos;          /* Array of column indeces giving the start scan position */\n  MYBOOL    isrow;\n} partialrec;\n\n\n/* Specially Ordered Sets (SOS) prototypes and settings                      */\n/* ------------------------------------------------------------------------- */\n/* SOS storage structure (LINEARSEARCH is typically in the 0-10 range)       */\n#ifndef LINEARSEARCH\n#define LINEARSEARCH 0\n#endif\n\n#include \"lp_SOS.h\"\n\n\n/* Prototypes for user call-back functions                                   */\n/* ------------------------------------------------------------------------- */\ntypedef int    (__WINAPI lphandle_intfunc)(lprec *lp, void *userhandle);\ntypedef void   (__WINAPI lphandlestr_func)(lprec *lp, void *userhandle, char *buf);\ntypedef void   (__WINAPI lphandleint_func)(lprec *lp, void *userhandle, int message);\ntypedef int    (__WINAPI lphandleint_intfunc)(lprec *lp, void *userhandle, int message);\n\n\n/* API typedef definitions                                                   */\n/* ------------------------------------------------------------------------- */\ntypedef MYBOOL (__WINAPI add_column_func)(lprec *lp, REAL *column);\ntypedef MYBOOL (__WINAPI add_columnex_func)(lprec *lp, int count, REAL *column, int *rowno);\ntypedef MYBOOL (__WINAPI add_constraint_func)(lprec *lp, REAL *row, int constr_type, REAL rh);\ntypedef MYBOOL (__WINAPI add_constraintex_func)(lprec *lp, int count, REAL *row, int *colno, int constr_type, REAL rh);\ntypedef MYBOOL (__WINAPI add_lag_con_func)(lprec *lp, REAL *row, int con_type, REAL rhs);\ntypedef int (__WINAPI add_SOS_func)(lprec *lp, const char *name, int sostype, int priority, int count, int *sosvars, REAL *weights);\ntypedef int (__WINAPI column_in_lp_func)(lprec *lp, REAL *column);\ntypedef lprec * (__WINAPI copy_lp_func)(lprec *lp);\ntypedef void (__WINAPI default_basis_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI del_column_func)(lprec *lp, int colnr);\ntypedef MYBOOL (__WINAPI del_constraint_func)(lprec *lp, int rownr);\ntypedef void (__WINAPI delete_lp_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI dualize_lp_func)(lprec *lp);\ntypedef void (__WINAPI free_lp_func)(lprec **plp);\ntypedef int (__WINAPI get_anti_degen_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI get_basis_func)(lprec *lp, int *bascolumn, MYBOOL nonbasic);\ntypedef int (__WINAPI get_basiscrash_func)(lprec *lp);\ntypedef int (__WINAPI get_bb_depthlimit_func)(lprec *lp);\ntypedef int (__WINAPI get_bb_floorfirst_func)(lprec *lp);\ntypedef int (__WINAPI get_bb_rule_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI get_bounds_tighter_func)(lprec *lp);\ntypedef REAL (__WINAPI get_break_at_value_func)(lprec *lp);\ntypedef const char * (__WINAPI get_col_name_func)(lprec *lp, int colnr);\ntypedef MYBOOL (__WINAPI get_column_func)(lprec *lp, int colnr, REAL *column);\ntypedef int (__WINAPI get_columnex_func)(lprec *lp, int colnr, REAL *column, int *nzrow);\ntypedef int (__WINAPI get_constr_type_func)(lprec *lp, int rownr);\ntypedef REAL (__WINAPI get_constr_value_func)(lprec *lp, int rownr, int count, REAL *primsolution, int *nzindex);\ntypedef MYBOOL (__WINAPI get_constraints_func)(lprec *lp, REAL *constr);\ntypedef MYBOOL (__WINAPI get_dual_solution_func)(lprec *lp, REAL *rc);\ntypedef REAL (__WINAPI get_epsb_func)(lprec *lp);\ntypedef REAL (__WINAPI get_epsd_func)(lprec *lp);\ntypedef REAL (__WINAPI get_epsel_func)(lprec *lp);\ntypedef REAL (__WINAPI get_epsint_func)(lprec *lp);\ntypedef REAL (__WINAPI get_epsperturb_func)(lprec *lp);\ntypedef REAL (__WINAPI get_epspivot_func)(lprec *lp);\ntypedef int (__WINAPI get_improve_func)(lprec *lp);\ntypedef REAL (__WINAPI get_infinite_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI get_lambda_func)(lprec *lp, REAL *lambda);\ntypedef REAL (__WINAPI get_lowbo_func)(lprec *lp, int colnr);\ntypedef int (__WINAPI get_lp_index_func)(lprec *lp, int orig_index);\ntypedef const char * (__WINAPI get_lp_name_func)(lprec *lp);\ntypedef int (__WINAPI get_Lrows_func)(lprec *lp);\ntypedef REAL (__WINAPI get_mat_func)(lprec *lp, int rownr, int colnr);\ntypedef REAL (__WINAPI get_mat_byindex_func)(lprec *lp, int matindex, MYBOOL isrow, MYBOOL adjustsign);\ntypedef int (__WINAPI get_max_level_func)(lprec *lp);\ntypedef int (__WINAPI get_maxpivot_func)(lprec *lp);\ntypedef REAL (__WINAPI get_mip_gap_func)(lprec *lp, MYBOOL absolute);\ntypedef int (__WINAPI get_multiprice_func)(lprec *lp, MYBOOL getabssize);\ntypedef MYBOOL (__WINAPI is_use_names_func)(lprec *lp, MYBOOL isrow);\ntypedef void (__WINAPI set_use_names_func)(lprec *lp, MYBOOL isrow, MYBOOL use_names);\ntypedef int (__WINAPI get_nameindex_func)(lprec *lp, const char *varname, MYBOOL isrow);\ntypedef int (__WINAPI get_Ncolumns_func)(lprec *lp);\ntypedef REAL (__WINAPI get_negrange_func)(lprec *lp);\ntypedef int (__WINAPI get_nz_func)(lprec *lp);\ntypedef int (__WINAPI get_Norig_columns_func)(lprec *lp);\ntypedef int (__WINAPI get_Norig_rows_func)(lprec *lp);\ntypedef int (__WINAPI get_Nrows_func)(lprec *lp);\ntypedef REAL (__WINAPI get_obj_bound_func)(lprec *lp);\ntypedef REAL (__WINAPI get_objective_func)(lprec *lp);\ntypedef int (__WINAPI get_orig_index_func)(lprec *lp, int lp_index);\ntypedef const char * (__WINAPI get_origcol_name_func)(lprec *lp, int colnr);\ntypedef const char * (__WINAPI get_origrow_name_func)(lprec *lp, int rownr);\ntypedef void (__WINAPI get_partialprice_func)(lprec *lp, int *blockcount, int *blockstart, MYBOOL isrow);\ntypedef int (__WINAPI get_pivoting_func)(lprec *lp);\ntypedef int (__WINAPI get_presolve_func)(lprec *lp);\ntypedef int (__WINAPI get_presolveloops_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI get_primal_solution_func)(lprec *lp, REAL *pv);\ntypedef int (__WINAPI get_print_sol_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI get_pseudocosts_func)(lprec *lp, REAL *clower, REAL *cupper, int *updatelimit);\ntypedef MYBOOL (__WINAPI get_ptr_constraints_func)(lprec *lp, REAL **constr);\ntypedef MYBOOL (__WINAPI get_ptr_dual_solution_func)(lprec *lp, REAL **rc);\ntypedef MYBOOL (__WINAPI get_ptr_lambda_func)(lprec *lp, REAL **lambda);\ntypedef MYBOOL (__WINAPI get_ptr_primal_solution_func)(lprec *lp, REAL **pv);\ntypedef MYBOOL (__WINAPI get_ptr_sensitivity_obj_func)(lprec *lp, REAL **objfrom, REAL **objtill);\ntypedef MYBOOL (__WINAPI get_ptr_sensitivity_objex_func)(lprec *lp, REAL **objfrom, REAL **objtill, REAL **objfromvalue, REAL **objtillvalue);\ntypedef MYBOOL (__WINAPI get_ptr_sensitivity_rhs_func)(lprec *lp, REAL **duals, REAL **dualsfrom, REAL **dualstill);\ntypedef MYBOOL (__WINAPI get_ptr_variables_func)(lprec *lp, REAL **var);\ntypedef REAL (__WINAPI get_rh_func)(lprec *lp, int rownr);\ntypedef REAL (__WINAPI get_rh_range_func)(lprec *lp, int rownr);\ntypedef int (__WINAPI get_rowex_func)(lprec *lp, int rownr, REAL *row, int *colno);\ntypedef MYBOOL (__WINAPI get_row_func)(lprec *lp, int rownr, REAL *row);\ntypedef const char * (__WINAPI get_row_name_func)(lprec *lp, int rownr);\ntypedef REAL (__WINAPI get_scalelimit_func)(lprec *lp);\ntypedef int (__WINAPI get_scaling_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI get_sensitivity_obj_func)(lprec *lp, REAL *objfrom, REAL *objtill);\ntypedef MYBOOL (__WINAPI get_sensitivity_objex_func)(lprec *lp, REAL *objfrom, REAL *objtill, REAL *objfromvalue, REAL *objtillvalue);\ntypedef MYBOOL (__WINAPI get_sensitivity_rhs_func)(lprec *lp, REAL *duals, REAL *dualsfrom, REAL *dualstill);\ntypedef int (__WINAPI get_simplextype_func)(lprec *lp);\ntypedef int (__WINAPI get_solutioncount_func)(lprec *lp);\ntypedef int (__WINAPI get_solutionlimit_func)(lprec *lp);\ntypedef int (__WINAPI get_status_func)(lprec *lp);\ntypedef const char * (__WINAPI get_statustext_func)(lprec *lp, int statuscode);\ntypedef long (__WINAPI get_timeout_func)(lprec *lp);\ntypedef COUNTER (__WINAPI get_total_iter_func)(lprec *lp);\ntypedef COUNTER (__WINAPI get_total_nodes_func)(lprec *lp);\ntypedef REAL (__WINAPI get_upbo_func)(lprec *lp, int colnr);\ntypedef int (__WINAPI get_var_branch_func)(lprec *lp, int colnr);\ntypedef REAL (__WINAPI get_var_dualresult_func)(lprec *lp, int index);\ntypedef REAL (__WINAPI get_var_primalresult_func)(lprec *lp, int index);\ntypedef int (__WINAPI get_var_priority_func)(lprec *lp, int colnr);\ntypedef MYBOOL (__WINAPI get_variables_func)(lprec *lp, REAL *var);\ntypedef int (__WINAPI get_verbose_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI guess_basis_func)(lprec *lp, REAL *guessvector, int *basisvector);\ntypedef REAL (__WINAPI get_working_objective_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI has_BFP_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI has_XLI_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_add_rowmode_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_anti_degen_func)(lprec *lp, int testmask);\ntypedef MYBOOL (__WINAPI is_binary_func)(lprec *lp, int colnr);\ntypedef MYBOOL (__WINAPI is_break_at_first_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_constr_type_func)(lprec *lp, int rownr, int mask);\ntypedef MYBOOL (__WINAPI is_debug_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_feasible_func)(lprec *lp, REAL *values, REAL threshold);\ntypedef MYBOOL (__WINAPI is_unbounded_func)(lprec *lp, int colnr);\ntypedef MYBOOL (__WINAPI is_infinite_func)(lprec *lp, REAL value);\ntypedef MYBOOL (__WINAPI is_int_func)(lprec *lp, int column);\ntypedef MYBOOL (__WINAPI is_integerscaling_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_lag_trace_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_maxim_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_nativeBFP_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_nativeXLI_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_negative_func)(lprec *lp, int colnr);\ntypedef MYBOOL (__WINAPI is_obj_in_basis_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI is_piv_mode_func)(lprec *lp, int testmask);\ntypedef MYBOOL (__WINAPI is_piv_rule_func)(lprec *lp, int rule);\ntypedef MYBOOL (__WINAPI is_presolve_func)(lprec *lp, int testmask);\ntypedef MYBOOL (__WINAPI is_scalemode_func)(lprec *lp, int testmask);\ntypedef MYBOOL (__WINAPI is_scaletype_func)(lprec *lp, int scaletype);\ntypedef MYBOOL (__WINAPI is_semicont_func)(lprec *lp, int colnr);\ntypedef MYBOOL (__WINAPI is_SOS_var_func)(lprec *lp, int colnr);\ntypedef MYBOOL (__WINAPI is_trace_func)(lprec *lp);\ntypedef void (__WINAPI lp_solve_version_func)(int *majorversion, int *minorversion, int *release, int *build);\ntypedef lprec * (__WINAPI make_lp_func)(int rows, int columns);\ntypedef void (__WINAPI print_constraints_func)(lprec *lp, int columns);\ntypedef MYBOOL (__WINAPI print_debugdump_func)(lprec *lp, const char *filename);\ntypedef void (__WINAPI print_duals_func)(lprec *lp);\ntypedef void (__WINAPI print_lp_func)(lprec *lp);\ntypedef void (__WINAPI print_objective_func)(lprec *lp);\ntypedef void (__WINAPI print_scales_func)(lprec *lp);\ntypedef void (__WINAPI print_solution_func)(lprec *lp, int columns);\ntypedef void (__WINAPI print_str_func)(lprec *lp, const char *str);\ntypedef void (__WINAPI print_tableau_func)(lprec *lp);\ntypedef void (__WINAPI put_abortfunc_func)(lprec *lp, lphandle_intfunc newctrlc, void *ctrlchandle);\ntypedef void (__WINAPI put_bb_nodefunc_func)(lprec *lp, lphandleint_intfunc newnode, void *bbnodehandle);\ntypedef void (__WINAPI put_bb_branchfunc_func)(lprec *lp, lphandleint_intfunc newbranch, void *bbbranchhandle);\ntypedef void (__WINAPI put_logfunc_func)(lprec *lp, lphandlestr_func newlog, void *loghandle);\ntypedef void (__WINAPI put_msgfunc_func)(lprec *lp, lphandleint_func newmsg, void *msghandle, int mask);\ntypedef lprec * (__WINAPI read_LP_func)(char *filename, int verbose, char *lp_name);\ntypedef lprec * (__WINAPI read_MPS_func)(char *filename, int options);\ntypedef lprec * (__WINAPI read_XLI_func)(char *xliname, const char *modelname, const char *dataname, const char *options, int verbose);\ntypedef MYBOOL (__WINAPI read_basis_func)(lprec *lp, const char *filename, char *info);\ntypedef void (__WINAPI reset_basis_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI read_params_func)(lprec *lp, const char *filename, const char *options);\ntypedef void (__WINAPI reset_params_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI resize_lp_func)(lprec *lp, int rows, int columns);\ntypedef MYBOOL (__WINAPI set_add_rowmode_func)(lprec *lp, MYBOOL turnon);\ntypedef void (__WINAPI set_anti_degen_func)(lprec *lp, int anti_degen);\ntypedef int  (__WINAPI set_basisvar_func)(lprec *lp, int basisPos, int enteringCol);\ntypedef MYBOOL (__WINAPI set_basis_func)(lprec *lp, int *bascolumn, MYBOOL nonbasic);\ntypedef void (__WINAPI set_basiscrash_func)(lprec *lp, int mode);\ntypedef void (__WINAPI set_bb_depthlimit_func)(lprec *lp, int bb_maxlevel);\ntypedef void (__WINAPI set_bb_floorfirst_func)(lprec *lp, int bb_floorfirst);\ntypedef void (__WINAPI set_bb_rule_func)(lprec *lp, int bb_rule);\ntypedef MYBOOL (__WINAPI set_BFP_func)(lprec *lp, const char *filename);\ntypedef MYBOOL (__WINAPI set_binary_func)(lprec *lp, int colnr, MYBOOL must_be_bin);\ntypedef MYBOOL (__WINAPI set_bounds_func)(lprec *lp, int colnr, REAL lower, REAL upper);\ntypedef void (__WINAPI set_bounds_tighter_func)(lprec *lp, MYBOOL tighten);\ntypedef void (__WINAPI set_break_at_first_func)(lprec *lp, MYBOOL break_at_first);\ntypedef void (__WINAPI set_break_at_value_func)(lprec *lp, REAL break_at_value);\ntypedef MYBOOL (__WINAPI set_column_func)(lprec *lp, int colnr, REAL *column);\ntypedef MYBOOL (__WINAPI set_columnex_func)(lprec *lp, int colnr, int count, REAL *column, int *rowno);\ntypedef MYBOOL (__WINAPI set_col_name_func)(lprec *lp, int colnr, const char *new_name);\ntypedef MYBOOL (__WINAPI set_constr_type_func)(lprec *lp, int rownr, int con_type);\ntypedef void (__WINAPI set_debug_func)(lprec *lp, MYBOOL debug);\ntypedef void (__WINAPI set_epsb_func)(lprec *lp, REAL epsb);\ntypedef void (__WINAPI set_epsd_func)(lprec *lp, REAL epsd);\ntypedef void (__WINAPI set_epsel_func)(lprec *lp, REAL epsel);\ntypedef void (__WINAPI set_epsint_func)(lprec *lp, REAL epsint);\ntypedef MYBOOL (__WINAPI set_epslevel_func)(lprec *lp, int epslevel);\ntypedef void (__WINAPI set_epsperturb_func)(lprec *lp, REAL epsperturb);\ntypedef void (__WINAPI set_epspivot_func)(lprec *lp, REAL epspivot);\ntypedef MYBOOL (__WINAPI set_unbounded_func)(lprec *lp, int colnr);\ntypedef void (__WINAPI set_improve_func)(lprec *lp, int improve);\ntypedef void (__WINAPI set_infinite_func)(lprec *lp, REAL infinite);\ntypedef MYBOOL (__WINAPI set_int_func)(lprec *lp, int colnr, MYBOOL must_be_int);\ntypedef void (__WINAPI set_lag_trace_func)(lprec *lp, MYBOOL lag_trace);\ntypedef MYBOOL (__WINAPI set_lowbo_func)(lprec *lp, int colnr, REAL value);\ntypedef MYBOOL (__WINAPI set_lp_name_func)(lprec *lp, const char *lpname);\ntypedef MYBOOL (__WINAPI set_mat_func)(lprec *lp, int row, int column, REAL value);\ntypedef void (__WINAPI set_maxim_func)(lprec *lp);\ntypedef void (__WINAPI set_maxpivot_func)(lprec *lp, int max_num_inv);\ntypedef void (__WINAPI set_minim_func)(lprec *lp);\ntypedef void (__WINAPI set_mip_gap_func)(lprec *lp, MYBOOL absolute, REAL mip_gap);\ntypedef MYBOOL (__WINAPI set_multiprice_func)(lprec *lp, int multiblockdiv);\ntypedef void (__WINAPI set_negrange_func)(lprec *lp, REAL negrange);\ntypedef MYBOOL (__WINAPI set_obj_func)(lprec *lp, int colnr, REAL value);\ntypedef void (__WINAPI set_obj_bound_func)(lprec *lp, REAL obj_bound);\ntypedef MYBOOL (__WINAPI set_obj_fn_func)(lprec *lp, REAL *row);\ntypedef MYBOOL (__WINAPI set_obj_fnex_func)(lprec *lp, int count, REAL *row, int *colno);\ntypedef void (__WINAPI set_obj_in_basis_func)(lprec *lp, MYBOOL obj_in_basis);\ntypedef MYBOOL (__WINAPI set_outputfile_func)(lprec *lp, const char *filename);\ntypedef void (__WINAPI set_outputstream_func)(lprec *lp, FILE *stream);\ntypedef MYBOOL (__WINAPI set_partialprice_func)(lprec *lp, int blockcount, int *blockstart, MYBOOL isrow);\ntypedef void (__WINAPI set_pivoting_func)(lprec *lp, int piv_rule);\ntypedef void (__WINAPI set_preferdual_func)(lprec *lp, MYBOOL dodual);\ntypedef void (__WINAPI set_presolve_func)(lprec *lp, int presolvemode, int maxloops);\ntypedef void (__WINAPI set_print_sol_func)(lprec *lp, int print_sol);\ntypedef MYBOOL (__WINAPI set_pseudocosts_func)(lprec *lp, REAL *clower, REAL *cupper, int *updatelimit);\ntypedef MYBOOL (__WINAPI set_rh_func)(lprec *lp, int rownr, REAL value);\ntypedef MYBOOL (__WINAPI set_rh_range_func)(lprec *lp, int rownr, REAL deltavalue);\ntypedef void (__WINAPI set_rh_vec_func)(lprec *lp, REAL *rh);\ntypedef MYBOOL (__WINAPI set_row_func)(lprec *lp, int rownr, REAL *row);\ntypedef MYBOOL (__WINAPI set_rowex_func)(lprec *lp, int rownr, int count, REAL *row, int *colno);\ntypedef MYBOOL (__WINAPI set_row_name_func)(lprec *lp, int rownr, const char *new_name);\ntypedef void (__WINAPI set_scalelimit_func)(lprec *lp, REAL scalelimit);\ntypedef void (__WINAPI set_scaling_func)(lprec *lp, int scalemode);\ntypedef MYBOOL (__WINAPI set_semicont_func)(lprec *lp, int colnr, MYBOOL must_be_sc);\ntypedef void (__WINAPI set_sense_func)(lprec *lp, MYBOOL maximize);\ntypedef void (__WINAPI set_simplextype_func)(lprec *lp, int simplextype);\ntypedef void (__WINAPI set_solutionlimit_func)(lprec *lp, int limit);\ntypedef void (__WINAPI set_timeout_func)(lprec *lp, long sectimeout);\ntypedef void (__WINAPI set_trace_func)(lprec *lp, MYBOOL trace);\ntypedef MYBOOL (__WINAPI set_upbo_func)(lprec *lp, int colnr, REAL value);\ntypedef MYBOOL (__WINAPI set_var_branch_func)(lprec *lp, int colnr, int branch_mode);\ntypedef MYBOOL (__WINAPI set_var_weights_func)(lprec *lp, REAL *weights);\ntypedef void (__WINAPI set_verbose_func)(lprec *lp, int verbose);\ntypedef MYBOOL (__WINAPI set_XLI_func)(lprec *lp, const char *filename);\ntypedef int (__WINAPI solve_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI str_add_column_func)(lprec *lp, const char *col_string);\ntypedef MYBOOL (__WINAPI str_add_constraint_func)(lprec *lp, const char *row_string ,int constr_type, REAL rh);\ntypedef MYBOOL (__WINAPI str_add_lag_con_func)(lprec *lp, const char *row_string, int con_type, REAL rhs);\ntypedef MYBOOL (__WINAPI str_set_obj_fn_func)(lprec *lp, const char *row_string);\ntypedef MYBOOL (__WINAPI str_set_rh_vec_func)(lprec *lp, const char *rh_string);\ntypedef REAL (__WINAPI time_elapsed_func)(lprec *lp);\ntypedef void (__WINAPI unscale_func)(lprec *lp);\ntypedef MYBOOL (__WINAPI write_lp_func)(lprec *lp, const char *filename);\ntypedef MYBOOL (__WINAPI write_LP_func)(lprec *lp, FILE *output);\ntypedef MYBOOL (__WINAPI write_mps_func)(lprec *lp, const char *filename);\ntypedef MYBOOL (__WINAPI write_MPS_func)(lprec *lp, FILE *output);\ntypedef MYBOOL (__WINAPI write_freemps_func)(lprec *lp, const char *filename);\ntypedef MYBOOL (__WINAPI write_freeMPS_func)(lprec *lp, FILE *output);\ntypedef MYBOOL (__WINAPI write_XLI_func)(lprec *lp, const char *filename, const char *options, MYBOOL results);\ntypedef MYBOOL (__WINAPI write_basis_func)(lprec *lp, const char *filename);\ntypedef MYBOOL (__WINAPI write_params_func)(lprec *lp, const char *filename, const char *options);\n\n\n/* Prototypes for callbacks from basis inverse/factorization libraries       */\n/* ------------------------------------------------------------------------- */\ntypedef MYBOOL (__WINAPI userabortfunc)(lprec *lp, int level);\ntypedef void   (__VACALL reportfunc)(lprec *lp, int level, const char *format, ...);\ntypedef const char * (__VACALL explainfunc)(lprec *lp, const char *format, ...);\ntypedef int    (__WINAPI getvectorfunc)(lprec *lp, int varin, REAL *pcol, int *nzlist, int *maxabs);\ntypedef int    (__WINAPI getpackedfunc)(lprec *lp, int j, int rn[], double bj[]);\ntypedef REAL    (__WINAPI get_OF_activefunc)(lprec *lp, int varnr, REAL mult);\ntypedef int    (__WINAPI getMDOfunc)(lprec *lp, MYBOOL *usedpos, int *colorder, int *size, MYBOOL symmetric);\ntypedef MYBOOL (__WINAPI invertfunc)(lprec *lp, MYBOOL shiftbounds, MYBOOL final);\ntypedef void   (__WINAPI set_actionfunc)(int *actionvar, int actionmask);\ntypedef MYBOOL (__WINAPI is_actionfunc)(int actionvar, int testmask);\ntypedef void   (__WINAPI clear_actionfunc)(int *actionvar, int actionmask);\n\n\n/* Prototypes for basis inverse/factorization libraries                      */\n/* ------------------------------------------------------------------------- */\ntypedef const char   *(BFP_CALLMODEL BFPchar)();\ntypedef void   (BFP_CALLMODEL BFP_lp)(lprec *lp);\ntypedef void   (BFP_CALLMODEL BFP_lpint)(lprec *lp, int newsize);\ntypedef int    (BFP_CALLMODEL BFPint_lp)(lprec *lp);\ntypedef int    (BFP_CALLMODEL BFPint_lpint)(lprec *lp, int kind);\ntypedef REAL   (BFP_CALLMODEL BFPreal_lp)(lprec *lp);\ntypedef REAL   *(BFP_CALLMODEL BFPrealp_lp)(lprec *lp);\ntypedef void   (BFP_CALLMODEL BFP_lpbool)(lprec *lp, MYBOOL maximum);\ntypedef int    (BFP_CALLMODEL BFPint_lpbool)(lprec *lp, MYBOOL maximum);\ntypedef int    (BFP_CALLMODEL BFPint_lpintintboolbool)(lprec *lp, int uservars, int Bsize, MYBOOL *usedpos, MYBOOL final);\ntypedef void   (BFP_CALLMODEL BFP_lprealint)(lprec *lp, REAL *pcol, int *nzidx);\ntypedef void   (BFP_CALLMODEL BFP_lprealintrealint)(lprec *lp, REAL *prow, int *pnzidx, REAL *drow, int *dnzidx);\ntypedef MYBOOL (BFP_CALLMODEL BFPbool_lp)(lprec *lp);\ntypedef MYBOOL (BFP_CALLMODEL BFPbool_lpbool)(lprec *lp, MYBOOL changesign);\ntypedef MYBOOL (BFP_CALLMODEL BFPbool_lpint)(lprec *lp, int size);\ntypedef MYBOOL (BFP_CALLMODEL BFPbool_lpintintchar)(lprec *lp, int size, int deltasize, const char *options);\ntypedef MYBOOL (BFP_CALLMODEL BFPbool_lpintintint)(lprec *lp, int size, int deltasize, int sizeofvar);\ntypedef LREAL  (BFP_CALLMODEL BFPlreal_lpintintreal)(lprec *lp, int row_nr, int col_nr, REAL *pcol);\ntypedef REAL   (BFP_CALLMODEL BFPreal_lplrealreal)(lprec *lp, LREAL theta, REAL *pcol);\n\ntypedef int    (BFP_CALLMODEL getcolumnex_func)(lprec *lp, int colnr, REAL *nzvalues, int *nzrows, int *mapin);\ntypedef int    (BFP_CALLMODEL BFPint_lpintrealcbintint)(lprec *lp, int items, getcolumnex_func cb, int *maprow, int*mapcol);\n\n/* Prototypes for external language libraries                                */\n/* ------------------------------------------------------------------------- */\ntypedef const char   *(XLI_CALLMODEL XLIchar)();\ntypedef MYBOOL (XLI_CALLMODEL XLIbool_lpintintint)(lprec* lp, int size, int deltasize, int sizevar);\ntypedef MYBOOL (XLI_CALLMODEL XLIbool_lpcharcharcharint)(lprec *lp, const char *modelname, const char *dataname, const char *options, int verbose);\ntypedef MYBOOL (XLI_CALLMODEL XLIbool_lpcharcharbool)(lprec *lp, const char *filename, const char *options, MYBOOL results);\n\n\n/* Main lp_solve prototypes and function definitions                         */\n/* ------------------------------------------------------------------------- */\nstruct _lprec\n{\n  /* Full list of exported functions made available in a quasi object-oriented fashion */\n  add_column_func               *add_column;\n  add_columnex_func             *add_columnex;\n  add_constraint_func           *add_constraint;\n  add_constraintex_func         *add_constraintex;\n  add_lag_con_func              *add_lag_con;\n  add_SOS_func                  *add_SOS;\n  column_in_lp_func             *column_in_lp;\n  copy_lp_func                  *copy_lp;\n  default_basis_func            *default_basis;\n  del_column_func               *del_column;\n  del_constraint_func           *del_constraint;\n  delete_lp_func                *delete_lp;\n  dualize_lp_func               *dualize_lp;\n  free_lp_func                  *free_lp;\n  get_anti_degen_func           *get_anti_degen;\n  get_basis_func                *get_basis;\n  get_basiscrash_func           *get_basiscrash;\n  get_bb_depthlimit_func        *get_bb_depthlimit;\n  get_bb_floorfirst_func        *get_bb_floorfirst;\n  get_bb_rule_func              *get_bb_rule;\n  get_bounds_tighter_func       *get_bounds_tighter;\n  get_break_at_value_func       *get_break_at_value;\n  get_col_name_func             *get_col_name;\n  get_columnex_func             *get_columnex;\n  get_constr_type_func          *get_constr_type;\n  get_constr_value_func         *get_constr_value;\n  get_constraints_func          *get_constraints;\n  get_dual_solution_func        *get_dual_solution;\n  get_epsb_func                 *get_epsb;\n  get_epsd_func                 *get_epsd;\n  get_epsel_func                *get_epsel;\n  get_epsint_func               *get_epsint;\n  get_epsperturb_func           *get_epsperturb;\n  get_epspivot_func             *get_epspivot;\n  get_improve_func              *get_improve;\n  get_infinite_func             *get_infinite;\n  get_lambda_func               *get_lambda;\n  get_lowbo_func                *get_lowbo;\n  get_lp_index_func             *get_lp_index;\n  get_lp_name_func              *get_lp_name;\n  get_Lrows_func                *get_Lrows;\n  get_mat_func                  *get_mat;\n  get_mat_byindex_func          *get_mat_byindex;\n  get_max_level_func            *get_max_level;\n  get_maxpivot_func             *get_maxpivot;\n  get_mip_gap_func              *get_mip_gap;\n  get_multiprice_func           *get_multiprice;\n  get_nameindex_func            *get_nameindex;\n  get_Ncolumns_func             *get_Ncolumns;\n  get_negrange_func             *get_negrange;\n  get_nz_func                   *get_nonzeros;\n  get_Norig_columns_func        *get_Norig_columns;\n  get_Norig_rows_func           *get_Norig_rows;\n  get_Nrows_func                *get_Nrows;\n  get_obj_bound_func            *get_obj_bound;\n  get_objective_func            *get_objective;\n  get_orig_index_func           *get_orig_index;\n  get_origcol_name_func         *get_origcol_name;\n  get_origrow_name_func         *get_origrow_name;\n  get_partialprice_func         *get_partialprice;\n  get_pivoting_func             *get_pivoting;\n  get_presolve_func             *get_presolve;\n  get_presolveloops_func        *get_presolveloops;\n  get_primal_solution_func      *get_primal_solution;\n  get_print_sol_func            *get_print_sol;\n  get_pseudocosts_func          *get_pseudocosts;\n  get_ptr_constraints_func      *get_ptr_constraints;\n  get_ptr_dual_solution_func    *get_ptr_dual_solution;\n  get_ptr_lambda_func           *get_ptr_lambda;\n  get_ptr_primal_solution_func  *get_ptr_primal_solution;\n  get_ptr_sensitivity_obj_func  *get_ptr_sensitivity_obj;\n  get_ptr_sensitivity_objex_func *get_ptr_sensitivity_objex;\n  get_ptr_sensitivity_rhs_func  *get_ptr_sensitivity_rhs;\n  get_ptr_variables_func        *get_ptr_variables;\n  get_rh_func                   *get_rh;\n  get_rh_range_func             *get_rh_range;\n  get_row_func                  *get_row;\n  get_rowex_func                *get_rowex;\n  get_row_name_func             *get_row_name;\n  get_scalelimit_func           *get_scalelimit;\n  get_scaling_func              *get_scaling;\n  get_sensitivity_obj_func      *get_sensitivity_obj;\n  get_sensitivity_objex_func    *get_sensitivity_objex;\n  get_sensitivity_rhs_func      *get_sensitivity_rhs;\n  get_simplextype_func          *get_simplextype;\n  get_solutioncount_func        *get_solutioncount;\n  get_solutionlimit_func        *get_solutionlimit;\n  get_status_func               *get_status;\n  get_statustext_func           *get_statustext;\n  get_timeout_func              *get_timeout;\n  get_total_iter_func           *get_total_iter;\n  get_total_nodes_func          *get_total_nodes;\n  get_upbo_func                 *get_upbo;\n  get_var_branch_func           *get_var_branch;\n  get_var_dualresult_func       *get_var_dualresult;\n  get_var_primalresult_func     *get_var_primalresult;\n  get_var_priority_func         *get_var_priority;\n  get_variables_func            *get_variables;\n  get_verbose_func              *get_verbose;\n  get_working_objective_func    *get_working_objective;\n  has_BFP_func                  *has_BFP;\n  has_XLI_func                  *has_XLI;\n  is_add_rowmode_func           *is_add_rowmode;\n  is_anti_degen_func            *is_anti_degen;\n  is_binary_func                *is_binary;\n  is_break_at_first_func        *is_break_at_first;\n  is_constr_type_func           *is_constr_type;\n  is_debug_func                 *is_debug;\n  is_feasible_func              *is_feasible;\n  is_infinite_func              *is_infinite;\n  is_int_func                   *is_int;\n  is_integerscaling_func        *is_integerscaling;\n  is_lag_trace_func             *is_lag_trace;\n  is_maxim_func                 *is_maxim;\n  is_nativeBFP_func             *is_nativeBFP;\n  is_nativeXLI_func             *is_nativeXLI;\n  is_negative_func              *is_negative;\n  is_obj_in_basis_func          *is_obj_in_basis;\n  is_piv_mode_func              *is_piv_mode;\n  is_piv_rule_func              *is_piv_rule;\n  is_presolve_func              *is_presolve;\n  is_scalemode_func             *is_scalemode;\n  is_scaletype_func             *is_scaletype;\n  is_semicont_func              *is_semicont;\n  is_SOS_var_func               *is_SOS_var;\n  is_trace_func                 *is_trace;\n  is_unbounded_func             *is_unbounded;\n  is_use_names_func             *is_use_names;\n  lp_solve_version_func         *lp_solve_version;\n  make_lp_func                  *make_lp;\n  print_constraints_func        *print_constraints;\n  print_debugdump_func          *print_debugdump;\n  print_duals_func              *print_duals;\n  print_lp_func                 *print_lp;\n  print_objective_func          *print_objective;\n  print_scales_func             *print_scales;\n  print_solution_func           *print_solution;\n  print_str_func                *print_str;\n  print_tableau_func            *print_tableau;\n  put_abortfunc_func            *put_abortfunc;\n  put_bb_nodefunc_func          *put_bb_nodefunc;\n  put_bb_branchfunc_func        *put_bb_branchfunc;\n  put_logfunc_func              *put_logfunc;\n  put_msgfunc_func              *put_msgfunc;\n  read_LP_func                  *read_LP;\n  read_MPS_func                 *read_MPS;\n  read_XLI_func                 *read_XLI;\n  read_params_func              *read_params;\n  read_basis_func               *read_basis;\n  reset_basis_func              *reset_basis;\n  reset_params_func             *reset_params;\n  resize_lp_func                *resize_lp;\n  set_add_rowmode_func          *set_add_rowmode;\n  set_anti_degen_func           *set_anti_degen;\n  set_basisvar_func             *set_basisvar;\n  set_basis_func                *set_basis;\n  set_basiscrash_func           *set_basiscrash;\n  set_bb_depthlimit_func        *set_bb_depthlimit;\n  set_bb_floorfirst_func        *set_bb_floorfirst;\n  set_bb_rule_func              *set_bb_rule;\n  set_BFP_func                  *set_BFP;\n  set_binary_func               *set_binary;\n  set_bounds_func               *set_bounds;\n  set_bounds_tighter_func       *set_bounds_tighter;\n  set_break_at_first_func       *set_break_at_first;\n  set_break_at_value_func       *set_break_at_value;\n  set_column_func               *set_column;\n  set_columnex_func             *set_columnex;\n  set_col_name_func             *set_col_name;\n  set_constr_type_func          *set_constr_type;\n  set_debug_func                *set_debug;\n  set_epsb_func                 *set_epsb;\n  set_epsd_func                 *set_epsd;\n  set_epsel_func                *set_epsel;\n  set_epsint_func               *set_epsint;\n  set_epslevel_func             *set_epslevel;\n  set_epsperturb_func           *set_epsperturb;\n  set_epspivot_func             *set_epspivot;\n  set_unbounded_func            *set_unbounded;\n  set_improve_func              *set_improve;\n  set_infinite_func             *set_infinite;\n  set_int_func                  *set_int;\n  set_lag_trace_func            *set_lag_trace;\n  set_lowbo_func                *set_lowbo;\n  set_lp_name_func              *set_lp_name;\n  set_mat_func                  *set_mat;\n  set_maxim_func                *set_maxim;\n  set_maxpivot_func             *set_maxpivot;\n  set_minim_func                *set_minim;\n  set_mip_gap_func              *set_mip_gap;\n  set_multiprice_func           *set_multiprice;\n  set_negrange_func             *set_negrange;\n  set_obj_bound_func            *set_obj_bound;\n  set_obj_fn_func               *set_obj_fn;\n  set_obj_fnex_func             *set_obj_fnex;\n  set_obj_func                  *set_obj;\n  set_obj_in_basis_func         *set_obj_in_basis;\n  set_outputfile_func           *set_outputfile;\n  set_outputstream_func         *set_outputstream;\n  set_partialprice_func         *set_partialprice;\n  set_pivoting_func             *set_pivoting;\n  set_preferdual_func           *set_preferdual;\n  set_presolve_func             *set_presolve;\n  set_print_sol_func            *set_print_sol;\n  set_pseudocosts_func          *set_pseudocosts;\n  set_rh_func                   *set_rh;\n  set_rh_range_func             *set_rh_range;\n  set_rh_vec_func               *set_rh_vec;\n  set_row_func                  *set_row;\n  set_rowex_func                *set_rowex;\n  set_row_name_func             *set_row_name;\n  set_scalelimit_func           *set_scalelimit;\n  set_scaling_func              *set_scaling;\n  set_semicont_func             *set_semicont;\n  set_sense_func                *set_sense;\n  set_simplextype_func          *set_simplextype;\n  set_solutionlimit_func        *set_solutionlimit;\n  set_timeout_func              *set_timeout;\n  set_trace_func                *set_trace;\n  set_upbo_func                 *set_upbo;\n  set_use_names_func            *set_use_names;\n  set_var_branch_func           *set_var_branch;\n  set_var_weights_func          *set_var_weights;\n  set_verbose_func              *set_verbose;\n  set_XLI_func                  *set_XLI;\n  solve_func                    *solve;\n  str_add_column_func           *str_add_column;\n  str_add_constraint_func       *str_add_constraint;\n  str_add_lag_con_func          *str_add_lag_con;\n  str_set_obj_fn_func           *str_set_obj_fn;\n  str_set_rh_vec_func           *str_set_rh_vec;\n  time_elapsed_func             *time_elapsed;\n  unscale_func                  *unscale;\n  write_lp_func                 *write_lp;\n  write_LP_func                 *write_LP;\n  write_mps_func                *write_mps;\n  write_MPS_func                *write_MPS;\n  write_freemps_func            *write_freemps;\n  write_freeMPS_func            *write_freeMPS;\n  write_XLI_func                *write_XLI;\n  write_basis_func              *write_basis;\n  write_params_func             *write_params;\n\n  /* Spacer */\n  int       *alignmentspacer;\n\n  /* Problem description */\n  char      *lp_name;           /* The name of the model */\n\n  /* Problem sizes */\n  int       sum;                /* The total number of variables, including slacks */\n  int       rows;\n  int       columns;\n  int       equalities;         /* No of non-Lagrangean equality constraints in the problem */\n  int       boundedvars;        /* Count of bounded variables */\n  int       INTfuture1;\n\n  /* Memory allocation sizes */\n  int       sum_alloc;          /* The allocated memory for row+column-sized data */\n  int       rows_alloc;         /* The allocated memory for row-sized data */\n  int       columns_alloc;      /* The allocated memory for column-sized data */\n\n  /* Model status and solver result variables */\n  MYBOOL    source_is_file;     /* The base model was read from a file */\n  MYBOOL    model_is_pure;      /* The model has been built entirely from row and column additions */\n  MYBOOL    model_is_valid;     /* Has this lp pased the 'test' */\n  MYBOOL    tighten_on_set;     /* Specify if bounds will be tightened or overriden at bound setting */\n  MYBOOL    names_used;         /* Flag to indicate if names for rows and columns are used */\n  MYBOOL    use_row_names;      /* Flag to indicate if names for rows are used */\n  MYBOOL    use_col_names;      /* Flag to indicate if names for columns are used */\n\n  MYBOOL    lag_trace;          /* Print information on Lagrange progression */\n  MYBOOL    spx_trace;          /* Print information on simplex progression */\n  MYBOOL    bb_trace;           /* TRUE to print extra debug information */\n  MYBOOL    streamowned;        /* TRUE if the handle should be closed at delete_lp() */\n  MYBOOL    obj_in_basis;       /* TRUE if the objective function is in the basis matrix */\n\n  int       spx_status;         /* Simplex solver feasibility/mode code */\n  int       lag_status;         /* Extra status variable for lag_solve */\n  int       solutioncount;      /* number of equal-valued solutions found (up to solutionlimit) */\n  int       solutionlimit;      /* upper number of equal-valued solutions kept track of */\n\n  REAL      real_solution;      /* Optimal non-MIP solution base */\n  REAL      *solution;          /* sum_alloc+1 : Solution array of the next to optimal LP,\n                                   Index   0           : Objective function value,\n                                   Indeces 1..rows     : Slack variable values,\n                                   Indeced rows+1..sum : Variable values */\n  REAL      *best_solution;     /* sum_alloc+1 : Solution array of optimal 'Integer' LP,\n                                   structured as the solution array above */\n  REAL      *full_solution;     /* sum_alloc+1 : Final solution array expanded for deleted variables */\n  REAL      *edgeVector;        /* Array of reduced cost scaling norms (DEVEX and Steepest Edge) */\n\n  REAL      *drow;              /* sum+1: Reduced costs of the last simplex */\n  int       *nzdrow;            /* sum+1: Indeces of non-zero reduced costs of the last simplex */\n  REAL      *duals;             /* rows_alloc+1 : The dual variables of the last LP */\n  REAL      *full_duals;        /* sum_alloc+1: Final duals array expanded for deleted variables */\n  REAL      *dualsfrom;         /* sum_alloc+1 :The sensitivity on dual variables/reduced costs\n                                   of the last LP */\n  REAL      *dualstill;         /* sum_alloc+1 :The sensitivity on dual variables/reduced costs\n                                   of the last LP */\n  REAL      *objfrom;           /* columns_alloc+1 :The sensitivity on objective function\n                                   of the last LP */\n  REAL      *objtill;           /* columns_alloc+1 :The sensitivity on objective function\n                                   of the last LP */\n  REAL      *objfromvalue;      /* columns_alloc+1 :The value of the variables when objective value\n                                   is at its from value of the last LP */\n  REAL      *orig_obj;          /* Unused pointer - Placeholder for OF not part of B */\n  REAL      *obj;               /* Special vector used to temporarily change the OF vector */\n\n  COUNTER   current_iter;       /* Number of iterations in the current/last simplex */\n  COUNTER   total_iter;         /* Number of iterations over all B&B steps */\n  COUNTER   current_bswap;      /* Number of bound swaps in the current/last simplex */\n  COUNTER   total_bswap;        /* Number of bount swaps over all B&B steps */\n  int       solvecount;         /* The number of solve() performed in this model */\n  int       max_pivots;         /* Number of pivots between refactorizations of the basis */\n\n  /* Various execution parameters */\n  int       simplex_strategy;   /* Set desired combination of primal and dual simplex algorithms */\n  int       simplex_mode;       /* Specifies the current simplex mode during solve; see simplex_strategy */\n  int       verbose;            /* Set amount of run-time messages and results */\n  int       print_sol;          /* TRUE to print optimal solution; AUTOMATIC skips zeros */\n  FILE      *outstream;         /* Output stream, initialized to STDOUT */\n\n  /* Main Branch and Bound settings */\n  MYBOOL    *bb_varbranch;      /* Determines branching strategy at the individual variable level;\n                                   the setting here overrides the bb_floorfirst setting */\n  int       piv_strategy;       /* Strategy for selecting row and column entering/leaving */\n  int       _piv_rule_;         /* Internal working rule-part of piv_strategy above */\n  int       bb_rule;            /* Rule for selecting B&B variables */\n  MYBOOL    bb_floorfirst;      /* Set BRANCH_FLOOR for B&B to set variables to floor bound first;\n                                   conversely with BRANCH_CEILING, the ceiling value is set first */\n  MYBOOL    bb_breakfirst;      /* TRUE to stop at first feasible solution */\n  MYBOOL    _piv_left_;         /* Internal variable indicating active pricing loop order */\n  MYBOOL    BOOLfuture1;\n\n  REAL      scalelimit;         /* Relative convergence criterion for iterated scaling */\n  int       scalemode;          /* OR-ed codes for data scaling */\n  int       improve;            /* Set to non-zero for iterative improvement */\n  int       anti_degen;         /* Anti-degen strategy (or none) TRUE to avoid cycling */\n  int       do_presolve;        /* PRESOLVE_ parameters for LP presolving */\n  int       presolveloops;      /* Maximum number of presolve loops */\n\n  int       perturb_count;      /* The number of bound relaxation retries performed */\n\n  /* Row and column names storage variables */\n  hashelem  **row_name;         /* rows_alloc+1 */\n  hashelem  **col_name;         /* columns_alloc+1 */\n  hashtable *rowname_hashtab;   /* hash table to store row names */\n  hashtable *colname_hashtab;   /* hash table to store column names */\n\n  /* Optionally specify continuous rows/column blocks for partial pricing */\n  partialrec *rowblocks;\n  partialrec *colblocks;\n\n  /* Row and column type codes */\n  MYBOOL    *var_type;          /* sum_alloc+1 : TRUE if variable must be integer */\n\n  /* Data for multiple pricing */\n  multirec  *multivars;\n  int       multiblockdiv;      /* The divisor used to set or augment pricing block */\n\n  /* Variable (column) parameters */\n  int       fixedvars;          /* The current number of basic fixed variables in the model */\n  int       int_vars;           /* Number of variables required to be integer */\n\n  int       sc_vars;            /* Number of semi-continuous variables */\n  REAL      *sc_lobound;        /* sum_columns+1 : TRUE if variable is semi-continuous;\n                                   value replaced by conventional lower bound during solve */\n  int       *var_is_free;       /* columns+1: Index of twin variable if variable is free */\n  int       *var_priority;      /* columns: Priority-mapping of variables */\n\n  SOSgroup  *GUB;               /* Pointer to record containing GUBs */\n\n  int       sos_vars;           /* Number of variables in the sos_priority list */\n  int       sos_ints;           /* Number of integers in SOS'es above */\n  SOSgroup  *SOS;               /* Pointer to record containing all SOS'es */\n  int       *sos_priority;      /* Priority-sorted list of variables (no duplicates) */\n\n  /* Optionally specify list of active rows/columns used in multiple pricing */\n  REAL      *bsolveVal;         /* rows+1: bsolved solution vector for reduced costs */\n  int       *bsolveIdx;         /* rows+1: Non-zero indeces of bsolveVal */\n\n  /* RHS storage */\n  REAL      *orig_rhs;          /* rows_alloc+1 : The RHS after scaling and sign\n                                   changing, but before 'Bound transformation' */\n  LREAL     *rhs;               /* rows_alloc+1 : The RHS of the current simplex tableau */\n\n  /* Row (constraint) parameters */\n  int       *row_type;          /* rows_alloc+1 : Row/constraint type coding */\n\n  /* Optionally specify data for dual long-step */\n  multirec  *longsteps;\n\n  /* Original and working row and variable bounds */\n  REAL      *orig_upbo;         /* sum_alloc+1 : Bound before transformations */\n  REAL      *upbo;              /*  \" \" : Upper bound after transformation and B&B work */\n  REAL      *orig_lowbo;        /*  \"       \"                                 */\n  REAL      *lowbo;             /*  \" \" : Lower bound after transformation and B&B work */\n\n  /* User data and basis factorization matrices (ETA or LU, product form) */\n  MATrec    *matA;\n  INVrec    *invB;\n\n  /* Basis and bounds */\n  BBrec     *bb_bounds;         /* The linked list of B&B bounds */\n  BBrec     *rootbounds;        /* The bounds at the lowest B&B level */\n  basisrec  *bb_basis;          /* The linked list of B&B bases */\n  basisrec  *rootbasis;\n  OBJmonrec *monitor;           /* Objective monitoring record for stalling/degeneracy handling */\n\n  /* Scaling parameters */\n  REAL      *scalars;           /* sum_alloc+1:0..Rows the scaling of the rows,\n                                   Rows+1..Sum the scaling of the columns */\n  MYBOOL    scaling_used;       /* TRUE if scaling is used */\n  MYBOOL    columns_scaled;     /* TRUE if the columns are scaled too */\n  MYBOOL    varmap_locked;      /* Determines whether the var_to_orig and orig_to_var are fixed */\n\n  /* Variable state information */\n  MYBOOL    basis_valid;        /* TRUE is the basis is still valid */\n  int       crashmode;          /* Basis crashing mode (or none) */\n  int       *var_basic;         /* rows_alloc+1: The list of columns in the basis */\n  REAL      *val_nonbasic;      /* Array to store current values of non-basic variables */\n  MYBOOL    *is_basic;          /* sum_alloc+1: TRUE if the column is in the basis */\n  MYBOOL    *is_lower;          /*  \"       \" : TRUE if the variable is at its\n                                   lower bound (or in the basis), FALSE otherwise */\n\n  /* Simplex basis indicators */\n  int       *rejectpivot;       /* List of unacceptable pivot choices due to division-by-zero */\n  BBPSrec   *bb_PseudoCost;     /* Data structure for costing of node branchings */\n  int       bb_PseudoUpdates;   /* Maximum number of updates for pseudo-costs */\n  int       bb_strongbranches;  /* The number of strong B&B branches performed */\n  int       is_strongbranch;    /* Are we currently in a strong branch mode? */\n  int       bb_improvements;    /* The number of discrete B&B objective improvement steps */\n\n  /* Solver working variables */\n  REAL      rhsmax;             /* The maximum |value| of the rhs vector at any iteration */\n  REAL      suminfeas;          /* The working sum of primal and dual infeasibilities */\n  REAL      bigM;               /* Original objective weighting in primal phase 1 */\n  REAL      P1extraVal;         /* Phase 1 OF/RHS offset for feasibility */\n  int       P1extraDim;         /* Phase 1 additional columns/rows for feasibility */\n  int       spx_action;         /* ACTION_ variables for the simplex routine */\n  MYBOOL    spx_perturbed;      /* The variable bounds were relaxed/perturbed into this simplex */\n  MYBOOL    bb_break;           /* Solver working variable; signals break of the B&B */\n  MYBOOL    wasPreprocessed;    /* The solve preprocessing was performed */\n  MYBOOL    wasPresolved;       /* The solve presolver was invoked */\n  int      INTfuture2;\n\n  /* Lagragean solver storage and parameters */\n  MATrec    *matL;\n  REAL      *lag_rhs;           /* Array of Lagrangean rhs vector */\n  int       *lag_con_type;      /* Array of GT, LT or EQ */\n  REAL      *lambda;            /* Lambda values (Lagrangean multipliers) */\n  /* REAL      lag_bound; */         /* The Lagrangian lower OF bound */\n  /* REAL      lag_accept; */   /* The Lagrangian convergence criterion */\n\n  REAL      accuracy;\n  REAL      accuracy_error;\n\n  /* Solver thresholds */\n  REAL      infinite;           /* Limit for dynamic range */\n  REAL      negrange;           /* Limit for negative variable range */\n  REAL      epsmachine;         /* Default machine accuracy */\n  REAL      epsvalue;           /* Input data precision / rounding of data values to 0 */\n  REAL      epsprimal;          /* For rounding RHS values to 0/infeasibility */\n  REAL      epsdual;            /* For rounding reduced costs to zero */\n  REAL      epspivot;           /* Pivot reject tolerance */\n  REAL      epsperturb;         /* Perturbation scalar */\n  REAL      epssolution;        /* The solution tolerance for final validation */\n\n  /* Branch & Bound working parameters */\n  int       bb_status;          /* Indicator that the last solvelp() gave an improved B&B solution */\n  int       bb_level;           /* Solver B&B working variable (recursion depth) */\n  int       bb_maxlevel;        /* The deepest B&B level of the last solution */\n  int       bb_limitlevel;      /* The maximum B&B level allowed */\n  COUNTER   bb_totalnodes;      /* Total number of nodes processed in B&B */\n  int       bb_solutionlevel;   /* The B&B level of the last / best solution */\n  int       bb_cutpoolsize;     /* Size of the B&B cut pool */\n  int       bb_cutpoolused;     /* Currently used cut pool */\n  int       bb_constraintOF;    /* General purpose B&B parameter (typically for testing) */\n  int       *bb_cuttype;        /* The type of the currently used cuts */\n  int       *bb_varactive;      /* The B&B state of the variable; 0 means inactive */\n  DeltaVrec *bb_upperchange;    /* Changes to upper bounds during the B&B phase */\n  DeltaVrec *bb_lowerchange;    /* Changes to lower bounds during the B&B phase */\n\n  REAL      bb_deltaOF;         /* Minimum OF step value; computed at beginning of solve() */\n\n  REAL      bb_breakOF;         /* User-settable value for the objective function deemed\n                               to be sufficiently good in an integer problem */\n  REAL      bb_limitOF;         /* \"Dual\" bound / limit to final optimal MIP solution */\n  REAL      bb_heuristicOF;     /* Set initial \"at least better than\" guess for objective function\n                               (can significantly speed up B&B iterations) */\n  REAL      bb_parentOF;        /* The OF value of the previous BB simplex */\n  REAL      bb_workOF;          /* The unadjusted OF value for the current best solution */\n\n  /* Internal work arrays allocated as required */\n  presolveundorec *presolve_undo;\n  workarraysrec   *workarrays;\n\n  /* MIP parameters */\n  REAL      epsint;             /* Margin of error in determining if a float value is integer */\n  REAL      mip_absgap;         /* Absolute MIP gap */\n  REAL      mip_relgap;         /* Relative MIP gap */\n\n  /* Time/timer variables and extended status text */\n  double    timecreate;\n  double    timestart;\n  double    timeheuristic;\n  double    timepresolved;\n  double    timeend;\n  long      sectimeout;\n\n  /* Extended status message text set via explain() */\n  char      *ex_status;\n\n  /* Refactorization engine interface routines (for dynamic DLL/SO BFPs) */\n#if LoadInverseLib == TRUE\n  #ifdef WIN32\n    HINSTANCE                   hBFP;\n  #else\n    void                        *hBFP;\n  #endif\n#endif\n  BFPchar                       *bfp_name;\n  BFPbool_lpintintint           *bfp_compatible;\n  BFPbool_lpintintchar          *bfp_init;\n  BFP_lp                        *bfp_free;\n  BFPbool_lpint                 *bfp_resize;\n  BFPint_lp                     *bfp_memallocated;\n  BFPbool_lp                    *bfp_restart;\n  BFPbool_lp                    *bfp_mustrefactorize;\n  BFPint_lp                     *bfp_preparefactorization;\n  BFPint_lpintintboolbool       *bfp_factorize;\n  BFP_lp                        *bfp_finishfactorization;\n  BFP_lp                        *bfp_updaterefactstats;\n  BFPlreal_lpintintreal         *bfp_prepareupdate;\n  BFPreal_lplrealreal           *bfp_pivotRHS;\n  BFPbool_lpbool                *bfp_finishupdate;\n  BFP_lprealint                 *bfp_ftran_prepare;\n  BFP_lprealint                 *bfp_ftran_normal;\n  BFP_lprealint                 *bfp_btran_normal;\n  BFP_lprealintrealint          *bfp_btran_double;\n  BFPint_lp                     *bfp_status;\n  BFPint_lpbool                 *bfp_nonzeros;\n  BFPbool_lp                    *bfp_implicitslack;\n  BFPint_lp                     *bfp_indexbase;\n  BFPint_lp                     *bfp_rowoffset;\n  BFPint_lp                     *bfp_pivotmax;\n  BFPbool_lpint                 *bfp_pivotalloc;\n  BFPint_lp                     *bfp_colcount;\n  BFPbool_lp                    *bfp_canresetbasis;\n  BFPreal_lp                    *bfp_efficiency;\n  BFPrealp_lp                   *bfp_pivotvector;\n  BFPint_lp                     *bfp_pivotcount;\n  BFPint_lpint                  *bfp_refactcount;\n  BFPbool_lp                    *bfp_isSetI;\n  BFPint_lpintrealcbintint      *bfp_findredundant;\n\n  /* External language interface routines (for dynamic DLL/SO XLIs) */\n#if LoadLanguageLib == TRUE\n  #ifdef WIN32\n    HINSTANCE                   hXLI;\n  #else\n    void                        *hXLI;\n  #endif\n#endif\n  XLIchar                       *xli_name;\n  XLIbool_lpintintint           *xli_compatible;\n  XLIbool_lpcharcharcharint     *xli_readmodel;\n  XLIbool_lpcharcharbool        *xli_writemodel;\n\n  /* Miscellaneous internal functions made available externally */\n  userabortfunc                 *userabort;\n  reportfunc                    *report;\n  explainfunc                   *explain;\n  getvectorfunc                 *get_lpcolumn;\n  getpackedfunc                 *get_basiscolumn;\n  get_OF_activefunc             *get_OF_active;\n  getMDOfunc                    *getMDO;\n  invertfunc                    *invert;\n  set_actionfunc                *set_action;\n  is_actionfunc                 *is_action;\n  clear_actionfunc              *clear_action;\n\n  /* User program interface callbacks */\n  lphandle_intfunc              *ctrlc;\n    void                          *ctrlchandle;     /* User-specified \"owner process ID\" */\n  lphandlestr_func              *writelog;\n    void                          *loghandle;       /* User-specified \"owner process ID\" */\n  lphandlestr_func              *debuginfo;\n  lphandleint_func              *usermessage;\n    int                           msgmask;\n    void                          *msghandle;       /* User-specified \"owner process ID\" */\n  lphandleint_intfunc           *bb_usenode;\n    void                          *bb_nodehandle;   /* User-specified \"owner process ID\" */\n  lphandleint_intfunc           *bb_usebranch;\n    void                          *bb_branchhandle; /* User-specified \"owner process ID\" */\n\n  /* replacement of static variables */\n  char      *rowcol_name;       /* The name of a row/column */\n};\n\n\n#ifdef __cplusplus\n__EXTERN_C {\n#endif\n\n\n/* User and system function interfaces                                       */\n/* ------------------------------------------------------------------------- */\n\nvoid __EXPORT_TYPE __WINAPI lp_solve_version(int *majorversion, int *minorversion, int *release, int *build);\n\nlprec __EXPORT_TYPE * __WINAPI make_lp(int rows, int columns);\nMYBOOL __EXPORT_TYPE __WINAPI resize_lp(lprec *lp, int rows, int columns);\nint __EXPORT_TYPE __WINAPI get_status(lprec *lp);\nconst char __EXPORT_TYPE * __WINAPI get_statustext(lprec *lp, int statuscode);\nMYBOOL __EXPORT_TYPE __WINAPI is_obj_in_basis(lprec *lp);\nvoid __EXPORT_TYPE __WINAPI set_obj_in_basis(lprec *lp, MYBOOL obj_in_basis);\n/* Create and initialise a lprec structure defaults */\n\nlprec __EXPORT_TYPE * __WINAPI copy_lp(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI dualize_lp(lprec *lp);\nSTATIC MYBOOL memopt_lp(lprec *lp, int rowextra, int colextra, int nzextra);\n/* Copy or dualize the lp */\n\nvoid __EXPORT_TYPE __WINAPI delete_lp(lprec *lp);\nvoid __EXPORT_TYPE __WINAPI free_lp(lprec **plp);\n/* Remove problem from memory */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_lp_name(lprec *lp, const char *lpname);\nconst char __EXPORT_TYPE * __WINAPI get_lp_name(lprec *lp);\n/* Set and get the problem name */\n\nMYBOOL __EXPORT_TYPE __WINAPI has_BFP(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI is_nativeBFP(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI set_BFP(lprec *lp, const char *filename);\n/* Set basis factorization engine */\n\nlprec __EXPORT_TYPE * __WINAPI read_XLI(char *xliname, const char *modelname, const char *dataname, const char *options, int verbose);\nMYBOOL __EXPORT_TYPE __WINAPI write_XLI(lprec *lp, const char *filename, const char *options, MYBOOL results);\nMYBOOL __EXPORT_TYPE __WINAPI has_XLI(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI is_nativeXLI(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI set_XLI(lprec *lp, const char *filename);\n/* Set external language interface */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_obj(lprec *lp, int colnr, REAL value);\nMYBOOL __EXPORT_TYPE __WINAPI set_obj_fn(lprec *lp, REAL *row);\nMYBOOL __EXPORT_TYPE __WINAPI set_obj_fnex(lprec *lp, int count, REAL *row, int *colno);\n/* set the objective function (Row 0) of the matrix */\nMYBOOL __EXPORT_TYPE __WINAPI str_set_obj_fn(lprec *lp, const char *row_string);\n/* The same, but with string input */\nvoid __EXPORT_TYPE __WINAPI set_sense(lprec *lp, MYBOOL maximize);\nvoid __EXPORT_TYPE __WINAPI set_maxim(lprec *lp);\nvoid __EXPORT_TYPE __WINAPI set_minim(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI is_maxim(lprec *lp);\n/* Set optimization direction for the objective function */\n\nMYBOOL __EXPORT_TYPE __WINAPI add_constraint(lprec *lp, REAL *row, int constr_type, REAL rh);\nMYBOOL __EXPORT_TYPE __WINAPI add_constraintex(lprec *lp, int count, REAL *row, int *colno, int constr_type, REAL rh);\nMYBOOL __EXPORT_TYPE __WINAPI set_add_rowmode(lprec *lp, MYBOOL turnon);\nMYBOOL __EXPORT_TYPE __WINAPI is_add_rowmode(lprec *lp);\n/* Add a constraint to the problem, row is the constraint row, rh is the right hand side,\n   constr_type is the type of constraint (LE (<=), GE(>=), EQ(=)) */\nMYBOOL __EXPORT_TYPE __WINAPI str_add_constraint(lprec *lp, const char *row_string, int constr_type, REAL rh);\n/* The same, but with string input */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_row(lprec *lp, int rownr, REAL *row);\nMYBOOL __EXPORT_TYPE __WINAPI set_rowex(lprec *lp, int rownr, int count, REAL *row, int *colno);\nMYBOOL __EXPORT_TYPE __WINAPI get_row(lprec *lp, int rownr, REAL *row);\nint __EXPORT_TYPE __WINAPI get_rowex(lprec *lp, int rownr, REAL *row, int *colno);\n/* Fill row with the row row_nr from the problem */\n\nMYBOOL __EXPORT_TYPE __WINAPI del_constraint(lprec *lp, int rownr);\nSTATIC MYBOOL del_constraintex(lprec *lp, LLrec *rowmap);\n/* Remove constrain nr del_row from the problem */\n\nMYBOOL __EXPORT_TYPE __WINAPI add_lag_con(lprec *lp, REAL *row, int con_type, REAL rhs);\n/* add a Lagrangian constraint of form Row' x contype Rhs */\nMYBOOL __EXPORT_TYPE __WINAPI str_add_lag_con(lprec *lp, const char *row_string, int con_type, REAL rhs);\n/* The same, but with string input */\nvoid __EXPORT_TYPE __WINAPI set_lag_trace(lprec *lp, MYBOOL lag_trace);\nMYBOOL __EXPORT_TYPE __WINAPI is_lag_trace(lprec *lp);\n/* Set debugging/tracing mode of the Lagrangean solver */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_constr_type(lprec *lp, int rownr, int con_type);\nint __EXPORT_TYPE __WINAPI get_constr_type(lprec *lp, int rownr);\nREAL __EXPORT_TYPE __WINAPI get_constr_value(lprec *lp, int rownr, int count, REAL *primsolution, int *nzindex);\nMYBOOL __EXPORT_TYPE __WINAPI is_constr_type(lprec *lp, int rownr, int mask);\nSTATIC const char *get_str_constr_type(lprec *lp, int con_type);\nSTATIC int get_constr_class(lprec *lp, int rownr);\nSTATIC const char *get_str_constr_class(lprec *lp, int con_class);\n/* Set the type of constraint in row Row (LE, GE, EQ) */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_rh(lprec *lp, int rownr, REAL value);\nREAL __EXPORT_TYPE __WINAPI get_rh(lprec *lp, int rownr);\n/* Set and get the right hand side of a constraint row */\nMYBOOL __EXPORT_TYPE __WINAPI set_rh_range(lprec *lp, int rownr, REAL deltavalue);\nREAL __EXPORT_TYPE __WINAPI get_rh_range(lprec *lp, int rownr);\n/* Set the RHS range; i.e. the lower and upper bounds of a constraint row */\nvoid __EXPORT_TYPE __WINAPI set_rh_vec(lprec *lp, REAL *rh);\n/* Set the right hand side vector */\nMYBOOL __EXPORT_TYPE __WINAPI str_set_rh_vec(lprec *lp, const char *rh_string);\n/* The same, but with string input */\n\nMYBOOL __EXPORT_TYPE __WINAPI add_column(lprec *lp, REAL *column);\nMYBOOL __EXPORT_TYPE __WINAPI add_columnex(lprec *lp, int count, REAL *column, int *rowno);\nMYBOOL __EXPORT_TYPE __WINAPI str_add_column(lprec *lp, const char *col_string);\n/* Add a column to the problem */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_column(lprec *lp, int colnr, REAL *column);\nMYBOOL __EXPORT_TYPE __WINAPI set_columnex(lprec *lp, int colnr, int count, REAL *column, int *rowno);\n/* Overwrite existing column data */\n\nint __EXPORT_TYPE __WINAPI column_in_lp(lprec *lp, REAL *column);\n/* Returns the column index if column is already present in lp, otherwise 0.\n   (Does not look at bounds and types, only looks at matrix values */\n\nint __EXPORT_TYPE __WINAPI get_columnex(lprec *lp, int colnr, REAL *column, int *nzrow);\nMYBOOL __EXPORT_TYPE __WINAPI get_column(lprec *lp, int colnr, REAL *column);\n/* Fill column with the column col_nr from the problem */\n\nMYBOOL __EXPORT_TYPE __WINAPI del_column(lprec *lp, int colnr);\nSTATIC MYBOOL del_columnex(lprec *lp, LLrec *colmap);\n/* Delete a column */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_mat(lprec *lp, int rownr, int colnr, REAL value);\n/* Fill in element (Row,Column) of the matrix\n   Row in [0..Rows] and Column in [1..Columns] */\nREAL __EXPORT_TYPE __WINAPI get_mat(lprec *lp, int rownr, int colnr);\nREAL __EXPORT_TYPE __WINAPI get_mat_byindex(lprec *lp, int matindex, MYBOOL isrow, MYBOOL adjustsign);\nint __EXPORT_TYPE __WINAPI get_nonzeros(lprec *lp);\n/* get a single element from the matrix */  /* Name changed from \"mat_elm\" by KE */\n\nvoid __EXPORT_TYPE __WINAPI set_bounds_tighter(lprec *lp, MYBOOL tighten);\nMYBOOL get_bounds(lprec *lp, int column, REAL *lower, REAL *upper);\nMYBOOL __EXPORT_TYPE __WINAPI get_bounds_tighter(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI set_upbo(lprec *lp, int colnr, REAL value);\nREAL __EXPORT_TYPE __WINAPI get_upbo(lprec *lp, int colnr);\nMYBOOL __EXPORT_TYPE __WINAPI set_lowbo(lprec *lp, int colnr, REAL value);\nREAL __EXPORT_TYPE __WINAPI get_lowbo(lprec *lp, int colnr);\nMYBOOL __EXPORT_TYPE __WINAPI set_bounds(lprec *lp, int colnr, REAL lower, REAL upper);\nMYBOOL __EXPORT_TYPE __WINAPI set_unbounded(lprec *lp, int colnr);\nMYBOOL __EXPORT_TYPE __WINAPI is_unbounded(lprec *lp, int colnr);\n/* Set the upper and lower bounds of a variable */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_int(lprec *lp, int colnr, MYBOOL must_be_int);\nMYBOOL __EXPORT_TYPE __WINAPI is_int(lprec *lp, int colnr);\nMYBOOL __EXPORT_TYPE __WINAPI set_binary(lprec *lp, int colnr, MYBOOL must_be_bin);\nMYBOOL __EXPORT_TYPE __WINAPI is_binary(lprec *lp, int colnr);\nMYBOOL __EXPORT_TYPE __WINAPI set_semicont(lprec *lp, int colnr, MYBOOL must_be_sc);\nMYBOOL __EXPORT_TYPE __WINAPI is_semicont(lprec *lp, int colnr);\nMYBOOL __EXPORT_TYPE __WINAPI is_negative(lprec *lp, int colnr);\nMYBOOL __EXPORT_TYPE __WINAPI set_var_weights(lprec *lp, REAL *weights);\nint __EXPORT_TYPE __WINAPI get_var_priority(lprec *lp, int colnr);\n/* Set the type of variable */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_pseudocosts(lprec *lp, REAL *clower, REAL *cupper, int *updatelimit);\nMYBOOL __EXPORT_TYPE __WINAPI get_pseudocosts(lprec *lp, REAL *clower, REAL *cupper, int *updatelimit);\n/* Set initial values for, or get computed pseudocost vectors;\n   note that setting of pseudocosts can only happen in response to a\n   call-back function optionally requesting this */\n\nint  __EXPORT_TYPE __WINAPI add_SOS(lprec *lp, const char *name, int sostype, int priority, int count, int *sosvars, REAL *weights);\nMYBOOL __EXPORT_TYPE __WINAPI is_SOS_var(lprec *lp, int colnr);\n/* Add SOS constraints */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_row_name(lprec *lp, int rownr, const char *new_name);\nconst char __EXPORT_TYPE * __WINAPI get_row_name(lprec *lp, int rownr);\nconst char __EXPORT_TYPE * __WINAPI get_origrow_name(lprec *lp, int rownr);\n/* Set/Get the name of a constraint row */   /* Get added by KE */\n\nMYBOOL __EXPORT_TYPE __WINAPI set_col_name(lprec *lp, int colnr, const char *new_name);\nconst char __EXPORT_TYPE * __WINAPI get_col_name(lprec *lp, int colnr);\nconst char __EXPORT_TYPE * __WINAPI get_origcol_name(lprec *lp, int colnr);\n/* Set/Get the name of a variable column */  /* Get added by KE */\n\nvoid __EXPORT_TYPE __WINAPI unscale(lprec *lp);\n/* Undo previous scaling of the problem */\n\nvoid __EXPORT_TYPE __WINAPI set_preferdual(lprec *lp, MYBOOL dodual);\nvoid __EXPORT_TYPE __WINAPI set_simplextype(lprec *lp, int simplextype);\nint __EXPORT_TYPE __WINAPI get_simplextype(lprec *lp);\n/* Set/Get if lp_solve should prefer the dual simplex over the primal -- added by KE */\n\nvoid __EXPORT_TYPE __WINAPI default_basis(lprec *lp);\nvoid __EXPORT_TYPE __WINAPI set_basiscrash(lprec *lp, int mode);\nint __EXPORT_TYPE __WINAPI get_basiscrash(lprec *lp);\nint __EXPORT_TYPE __WINAPI set_basisvar(lprec *lp, int basisPos, int enteringCol);\nMYBOOL __EXPORT_TYPE __WINAPI set_basis(lprec *lp, int *bascolumn, MYBOOL nonbasic);\nMYBOOL __EXPORT_TYPE __WINAPI get_basis(lprec *lp, int *bascolumn, MYBOOL nonbasic);\nvoid __EXPORT_TYPE __WINAPI reset_basis(lprec *lp);\n/* Set/Get basis for a re-solved system */  /* Added by KE */\nMYBOOL __EXPORT_TYPE __WINAPI guess_basis(lprec *lp, REAL *guessvector, int *basisvector);\n\nMYBOOL __EXPORT_TYPE __WINAPI is_feasible(lprec *lp, REAL *values, REAL threshold);\n/* returns TRUE if the vector in values is a feasible solution to the lp */\n\nint __EXPORT_TYPE __WINAPI solve(lprec *lp);\n/* Solve the problem */\n\nREAL __EXPORT_TYPE __WINAPI get_accuracy(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_break_numeric_accuracy(lprec *lp, REAL accuracy);\nREAL __EXPORT_TYPE __WINAPI get_break_numeric_accuracy(lprec *lp);\n\nREAL __EXPORT_TYPE __WINAPI time_elapsed(lprec *lp);\n/* Return the number of seconds since start of solution process */\n\nvoid __EXPORT_TYPE __WINAPI put_bb_nodefunc(lprec *lp, lphandleint_intfunc newnode, void *bbnodehandle);\nvoid __EXPORT_TYPE __WINAPI put_bb_branchfunc(lprec *lp, lphandleint_intfunc newbranch, void *bbbranchhandle);\n/* Allow the user to override B&B node and branching decisions */\n\nvoid __EXPORT_TYPE __WINAPI put_abortfunc(lprec *lp, lphandle_intfunc newctrlc, void *ctrlchandle);\n/* Allow the user to define an interruption callback function */\n\nvoid __EXPORT_TYPE __WINAPI put_logfunc(lprec *lp, lphandlestr_func newlog, void *loghandle);\n/* Allow the user to define a logging function */\n\nvoid __EXPORT_TYPE __WINAPI put_msgfunc(lprec *lp, lphandleint_func newmsg, void *msghandle, int mask);\n/* Allow the user to define an event-driven message/reporting */\n\nMYBOOL __EXPORT_TYPE __WINAPI get_primal_solution(lprec *lp, REAL *pv);\nMYBOOL __EXPORT_TYPE __WINAPI get_ptr_primal_solution(lprec *lp, REAL **pv);\nMYBOOL __EXPORT_TYPE __WINAPI get_dual_solution(lprec *lp, REAL *rc);\nMYBOOL __EXPORT_TYPE __WINAPI get_ptr_dual_solution(lprec *lp, REAL **rc);\nMYBOOL __EXPORT_TYPE __WINAPI get_lambda(lprec *lp, REAL *lambda);\nMYBOOL __EXPORT_TYPE __WINAPI get_ptr_lambda(lprec *lp, REAL **lambda);\n/* Get the primal, dual/reduced costs and Lambda vectors */\n\n/* Read an MPS file */\nlprec __EXPORT_TYPE * __WINAPI read_MPS(char *filename, int options);\nlprec __EXPORT_TYPE * __WINAPI read_mps(FILE *filename, int options);\nlprec __EXPORT_TYPE * __WINAPI read_freeMPS(char *filename, int options);\nlprec __EXPORT_TYPE * __WINAPI read_freemps(FILE *filename, int options);\n\n/* Write a MPS file to output */\nMYBOOL __EXPORT_TYPE __WINAPI write_mps(lprec *lp, const char *filename);\nMYBOOL __EXPORT_TYPE __WINAPI write_MPS(lprec *lp, FILE *output);\nMYBOOL __EXPORT_TYPE __WINAPI write_freemps(lprec *lp, const char *filename);\nMYBOOL __EXPORT_TYPE __WINAPI write_freeMPS(lprec *lp, FILE *output);\n\nMYBOOL __EXPORT_TYPE __WINAPI write_lp(lprec *lp, const char *filename);\nMYBOOL __EXPORT_TYPE __WINAPI write_LP(lprec *lp, FILE *output);\n /* Write a LP file to output */\n\nMYBOOL __WINAPI LP_readhandle(lprec **lp, FILE *filename, int verbose, char *lp_name);\nlprec __EXPORT_TYPE * __WINAPI read_lp(FILE *filename, int verbose, char *lp_name);\nlprec __EXPORT_TYPE * __WINAPI read_LP(char *filename, int verbose, char *lp_name);\n/* Old-style lp format file parser */\n\nMYBOOL __EXPORT_TYPE __WINAPI write_basis(lprec *lp, const char *filename);\nMYBOOL __EXPORT_TYPE __WINAPI read_basis(lprec *lp, const char *filename, char *info);\n/* Read and write basis from/to file in CPLEX BAS format */\n\nMYBOOL __EXPORT_TYPE __WINAPI write_params(lprec *lp, const char *filename, const char *options);\nMYBOOL __EXPORT_TYPE __WINAPI read_params(lprec *lp, const char *filename, const char *options);\nvoid __EXPORT_TYPE __WINAPI reset_params(lprec *lp);\n/* Read and write parameter file */\n\nvoid __EXPORT_TYPE __WINAPI print_lp(lprec *lp);\nvoid __EXPORT_TYPE __WINAPI print_tableau(lprec *lp);\n/* Print the current problem, only useful in very small (test) problems */\n\nvoid __EXPORT_TYPE __WINAPI print_objective(lprec *lp);\nvoid __EXPORT_TYPE __WINAPI print_solution(lprec *lp, int columns);\nvoid __EXPORT_TYPE __WINAPI print_constraints(lprec *lp, int columns);\n/* Print the solution to stdout */\n\nvoid __EXPORT_TYPE __WINAPI print_duals(lprec *lp);\n/* Print the dual variables of the solution */\n\nvoid __EXPORT_TYPE __WINAPI print_scales(lprec *lp);\n/* If scaling is used, print the scaling factors */\n\nvoid __EXPORT_TYPE __WINAPI print_str(lprec *lp, const char *str);\n\nvoid __EXPORT_TYPE __WINAPI set_outputstream(lprec *lp, FILE *stream);\nMYBOOL __EXPORT_TYPE __WINAPI set_outputfile(lprec *lp, const char *filename);\n\nvoid __EXPORT_TYPE __WINAPI set_verbose(lprec *lp, int verbose);\nint __EXPORT_TYPE __WINAPI get_verbose(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_timeout(lprec *lp, long sectimeout);\nlong __EXPORT_TYPE __WINAPI get_timeout(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_print_sol(lprec *lp, int print_sol);\nint __EXPORT_TYPE __WINAPI get_print_sol(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_debug(lprec *lp, MYBOOL debug);\nMYBOOL __EXPORT_TYPE __WINAPI is_debug(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_trace(lprec *lp, MYBOOL trace);\nMYBOOL __EXPORT_TYPE __WINAPI is_trace(lprec *lp);\n\nMYBOOL __EXPORT_TYPE __WINAPI print_debugdump(lprec *lp, const char *filename);\n\nvoid __EXPORT_TYPE __WINAPI set_anti_degen(lprec *lp, int anti_degen);\nint __EXPORT_TYPE __WINAPI get_anti_degen(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI is_anti_degen(lprec *lp, int testmask);\n\nvoid __EXPORT_TYPE __WINAPI set_presolve(lprec *lp, int presolvemode, int maxloops);\nint __EXPORT_TYPE __WINAPI get_presolve(lprec *lp);\nint __EXPORT_TYPE __WINAPI get_presolveloops(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI is_presolve(lprec *lp, int testmask);\n\nint __EXPORT_TYPE __WINAPI get_orig_index(lprec *lp, int lp_index);\nint __EXPORT_TYPE __WINAPI get_lp_index(lprec *lp, int orig_index);\n\nvoid __EXPORT_TYPE __WINAPI set_maxpivot(lprec *lp, int max_num_inv);\nint __EXPORT_TYPE __WINAPI get_maxpivot(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_obj_bound(lprec *lp, REAL obj_bound);\nREAL __EXPORT_TYPE __WINAPI get_obj_bound(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_mip_gap(lprec *lp, MYBOOL absolute, REAL mip_gap);\nREAL __EXPORT_TYPE __WINAPI get_mip_gap(lprec *lp, MYBOOL absolute);\n\nvoid __EXPORT_TYPE __WINAPI set_bb_rule(lprec *lp, int bb_rule);\nint __EXPORT_TYPE __WINAPI get_bb_rule(lprec *lp);\n\nMYBOOL __EXPORT_TYPE __WINAPI set_var_branch(lprec *lp, int colnr, int branch_mode);\nint __EXPORT_TYPE __WINAPI get_var_branch(lprec *lp, int colnr);\n\nMYBOOL __EXPORT_TYPE __WINAPI is_infinite(lprec *lp, REAL value);\nvoid __EXPORT_TYPE __WINAPI set_infinite(lprec *lp, REAL infinite);\nREAL __EXPORT_TYPE __WINAPI get_infinite(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_epsint(lprec *lp, REAL epsint);\nREAL __EXPORT_TYPE __WINAPI get_epsint(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_epsb(lprec *lp, REAL epsb);\nREAL __EXPORT_TYPE __WINAPI get_epsb(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_epsd(lprec *lp, REAL epsd);\nREAL __EXPORT_TYPE __WINAPI get_epsd(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_epsel(lprec *lp, REAL epsel);\nREAL __EXPORT_TYPE __WINAPI get_epsel(lprec *lp);\n\nMYBOOL __EXPORT_TYPE __WINAPI set_epslevel(lprec *lp, int epslevel);\n\nvoid __EXPORT_TYPE __WINAPI set_scaling(lprec *lp, int scalemode);\nint __EXPORT_TYPE __WINAPI get_scaling(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI is_scalemode(lprec *lp, int testmask);\nMYBOOL __EXPORT_TYPE __WINAPI is_scaletype(lprec *lp, int scaletype);\nMYBOOL __EXPORT_TYPE __WINAPI is_integerscaling(lprec *lp);\nvoid __EXPORT_TYPE __WINAPI set_scalelimit(lprec *lp, REAL scalelimit);\nREAL __EXPORT_TYPE __WINAPI get_scalelimit(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_improve(lprec *lp, int improve);\nint __EXPORT_TYPE __WINAPI get_improve(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_pivoting(lprec *lp, int piv_rule);\nint __EXPORT_TYPE __WINAPI get_pivoting(lprec *lp);\nMYBOOL __EXPORT_TYPE __WINAPI set_partialprice(lprec *lp, int blockcount, int *blockstart, MYBOOL isrow);\nvoid __EXPORT_TYPE __WINAPI get_partialprice(lprec *lp, int *blockcount, int *blockstart, MYBOOL isrow);\n\nMYBOOL __EXPORT_TYPE __WINAPI set_multiprice(lprec *lp, int multiblockdiv);\nint __EXPORT_TYPE __WINAPI get_multiprice(lprec *lp, MYBOOL getabssize);\n\nMYBOOL __EXPORT_TYPE __WINAPI is_use_names(lprec *lp, MYBOOL isrow);\nvoid __EXPORT_TYPE __WINAPI set_use_names(lprec *lp, MYBOOL isrow, MYBOOL use_names);\n\nint __EXPORT_TYPE __WINAPI get_nameindex(lprec *lp, const char *varname, MYBOOL isrow);\n\nMYBOOL __EXPORT_TYPE __WINAPI is_piv_mode(lprec *lp, int testmask);\nMYBOOL __EXPORT_TYPE __WINAPI is_piv_rule(lprec *lp, int rule);\n\nvoid __EXPORT_TYPE __WINAPI set_break_at_first(lprec *lp, MYBOOL break_at_first);\nMYBOOL __EXPORT_TYPE __WINAPI is_break_at_first(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_bb_floorfirst(lprec *lp, int bb_floorfirst);\nint __EXPORT_TYPE __WINAPI get_bb_floorfirst(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_bb_depthlimit(lprec *lp, int bb_maxlevel);\nint __EXPORT_TYPE __WINAPI get_bb_depthlimit(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_break_at_value(lprec *lp, REAL break_at_value);\nREAL __EXPORT_TYPE __WINAPI get_break_at_value(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_negrange(lprec *lp, REAL negrange);\nREAL __EXPORT_TYPE __WINAPI get_negrange(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_epsperturb(lprec *lp, REAL epsperturb);\nREAL __EXPORT_TYPE __WINAPI get_epsperturb(lprec *lp);\n\nvoid __EXPORT_TYPE __WINAPI set_epspivot(lprec *lp, REAL epspivot);\nREAL __EXPORT_TYPE __WINAPI get_epspivot(lprec *lp);\n\nint __EXPORT_TYPE __WINAPI get_max_level(lprec *lp);\nCOUNTER __EXPORT_TYPE __WINAPI get_total_nodes(lprec *lp);\nCOUNTER __EXPORT_TYPE __WINAPI get_total_iter(lprec *lp);\n\nREAL __EXPORT_TYPE __WINAPI get_objective(lprec *lp);\nREAL __EXPORT_TYPE __WINAPI get_working_objective(lprec *lp);\n\nREAL __EXPORT_TYPE __WINAPI get_var_primalresult(lprec *lp, int index);\nREAL __EXPORT_TYPE __WINAPI get_var_dualresult(lprec *lp, int index);\n\nMYBOOL __EXPORT_TYPE __WINAPI get_variables(lprec *lp, REAL *var);\nMYBOOL __EXPORT_TYPE __WINAPI get_ptr_variables(lprec *lp, REAL **var);\n\nMYBOOL __EXPORT_TYPE __WINAPI get_constraints(lprec *lp, REAL *constr);\nMYBOOL __EXPORT_TYPE __WINAPI get_ptr_constraints(lprec *lp, REAL **constr);\n\nMYBOOL __EXPORT_TYPE __WINAPI get_sensitivity_rhs(lprec *lp, REAL *duals, REAL *dualsfrom, REAL *dualstill);\nMYBOOL __EXPORT_TYPE __WINAPI get_ptr_sensitivity_rhs(lprec *lp, REAL **duals, REAL **dualsfrom, REAL **dualstill);\n\nMYBOOL __EXPORT_TYPE __WINAPI get_sensitivity_obj(lprec *lp, REAL *objfrom, REAL *objtill);\nMYBOOL __EXPORT_TYPE __WINAPI get_sensitivity_objex(lprec *lp, REAL *objfrom, REAL *objtill, REAL *objfromvalue, REAL *objtillvalue);\nMYBOOL __EXPORT_TYPE __WINAPI get_ptr_sensitivity_obj(lprec *lp, REAL **objfrom, REAL **objtill);\nMYBOOL __EXPORT_TYPE __WINAPI get_ptr_sensitivity_objex(lprec *lp, REAL **objfrom, REAL **objtill, REAL **objfromvalue, REAL **objtillvalue);\n\nvoid __EXPORT_TYPE __WINAPI set_solutionlimit(lprec *lp, int limit);\nint __EXPORT_TYPE __WINAPI get_solutionlimit(lprec *lp);\nint __EXPORT_TYPE __WINAPI get_solutioncount(lprec *lp);\n\nint __EXPORT_TYPE __WINAPI get_Norig_rows(lprec *lp);\nint __EXPORT_TYPE __WINAPI get_Nrows(lprec *lp);\nint __EXPORT_TYPE __WINAPI get_Lrows(lprec *lp);\n\nint __EXPORT_TYPE __WINAPI get_Norig_columns(lprec *lp);\nint __EXPORT_TYPE __WINAPI get_Ncolumns(lprec *lp);\n\ntypedef int (__WINAPI read_modeldata_func)(void *userhandle, char *buf, int max_size);\ntypedef int (__WINAPI write_modeldata_func)(void *userhandle, char *buf);\nMYBOOL __WINAPI MPS_readex(lprec **newlp, void *userhandle, read_modeldata_func read_modeldata, int typeMPS, int options);\n\n/* #if defined develop */\nlprec __EXPORT_TYPE * __WINAPI read_lpex(void *userhandle, read_modeldata_func read_modeldata, int verbose, char *lp_name);\nMYBOOL __EXPORT_TYPE __WINAPI write_lpex(lprec *lp, void *userhandle, write_modeldata_func write_modeldata);\n\nlprec __EXPORT_TYPE * __WINAPI read_mpsex(void *userhandle, read_modeldata_func read_modeldata, int options);\nlprec __EXPORT_TYPE * __WINAPI read_freempsex(void *userhandle, read_modeldata_func read_modeldata, int options);\n\nMYBOOL __EXPORT_TYPE __WINAPI MPS_writefileex(lprec *lp, int typeMPS, void *userhandle, write_modeldata_func write_modeldata);\n/* #endif */\n\n#ifdef __cplusplus\n}\n#endif\n\n\n/* Forward definitions of functions used internaly by the lp toolkit */\nMYBOOL set_callbacks(lprec *lp);\nSTATIC int yieldformessages(lprec *lp);\nMYBOOL __WINAPI userabort(lprec *lp, int message);\n/*char * __VACALL explain(lprec *lp, const char *format, ...);\nvoid __VACALL report(lprec *lp, int level, const char *format, ...);*/\n\n/* Memory management routines */\nSTATIC MYBOOL append_rows(lprec *lp, int deltarows);\nSTATIC MYBOOL append_columns(lprec *lp, int deltacolumns);\nSTATIC void inc_rows(lprec *lp, int delta);\nSTATIC void inc_columns(lprec *lp, int delta);\nSTATIC MYBOOL init_rowcol_names(lprec *lp);\nSTATIC MYBOOL inc_row_space(lprec *lp, int deltarows);\nSTATIC MYBOOL inc_col_space(lprec *lp, int deltacols);\nSTATIC MYBOOL shift_rowcoldata(lprec *lp, int base, int delta, LLrec *usedmap, MYBOOL isrow);\nSTATIC MYBOOL shift_basis(lprec *lp, int base, int delta, LLrec *usedmap, MYBOOL isrow);\nSTATIC MYBOOL shift_rowdata(lprec *lp, int base, int delta, LLrec *usedmap);\nSTATIC MYBOOL shift_coldata(lprec *lp, int base, int delta, LLrec *usedmap);\n\n/* INLINE */ MYBOOL is_chsign(lprec *lp, int rownr);\n\nSTATIC MYBOOL inc_lag_space(lprec *lp, int deltarows, MYBOOL ignoreMAT);\nlprec *make_lag(lprec *server);\n\nREAL get_rh_upper(lprec *lp, int rownr);\nREAL get_rh_lower(lprec *lp, int rownr);\nMYBOOL set_rh_upper(lprec *lp, int rownr, REAL value);\nMYBOOL set_rh_lower(lprec *lp, int rownr, REAL value);\nSTATIC int bin_count(lprec *lp, MYBOOL working);\nSTATIC int MIP_count(lprec *lp);\nSTATIC int SOS_count(lprec *lp);\nSTATIC int GUB_count(lprec *lp);\nSTATIC int identify_GUB(lprec *lp, MYBOOL mark);\nSTATIC int prepare_GUB(lprec *lp);\n\nSTATIC MYBOOL refactRecent(lprec *lp);\nSTATIC MYBOOL check_if_less(lprec *lp, REAL x, REAL y, int variable);\nSTATIC MYBOOL feasiblePhase1(lprec *lp, REAL epsvalue);\nSTATIC void free_duals(lprec *lp);\nSTATIC void initialize_solution(lprec *lp, MYBOOL shiftbounds);\nSTATIC void recompute_solution(lprec *lp, MYBOOL shiftbounds);\nSTATIC int verify_solution(lprec *lp, MYBOOL reinvert, char *info);\nSTATIC int check_solution(lprec *lp, int  lastcolumn, REAL *solution,\n                          REAL *upbo, REAL *lowbo, REAL tolerance);\n/* INLINE */ MYBOOL is_fixedvar(lprec *lp, int variable);\n/* INLINE */ MYBOOL is_splitvar(lprec *lp, int colnr);\n\nvoid   __WINAPI set_action(int *actionvar, int actionmask);\nvoid   __WINAPI clear_action(int *actionvar, int actionmask);\nMYBOOL __WINAPI is_action(int actionvar, int testmask);\n\n/* INLINE */ MYBOOL is_bb_rule(lprec *lp, int bb_rule);\n/* INLINE */ MYBOOL is_bb_mode(lprec *lp, int bb_mask);\n/* INLINE */ int get_piv_rule(lprec *lp);\nSTATIC const char *get_str_piv_rule(int rule);\nSTATIC MYBOOL __WINAPI set_var_priority(lprec *lp);\nSTATIC int find_sc_bbvar(lprec *lp, int *count);\nSTATIC int find_sos_bbvar(lprec *lp, int *count, MYBOOL intsos);\nSTATIC int find_int_bbvar(lprec *lp, int *count, BBrec *BB, MYBOOL *isfeasible);\n\n/* Solution-related functions */\nSTATIC REAL compute_dualslacks(lprec *lp, int target, REAL **dvalues, int **nzdvalues, MYBOOL dosum);\nSTATIC MYBOOL solution_is_int(lprec *lp, int index, MYBOOL checkfixed);\nSTATIC MYBOOL bb_better(lprec *lp, int target, int mode);\nSTATIC void construct_solution(lprec *lp, REAL *target);\nSTATIC void transfer_solution_var(lprec *lp, int uservar);\nSTATIC MYBOOL construct_duals(lprec *lp);\nSTATIC MYBOOL construct_sensitivity_duals(lprec *lp);\nSTATIC MYBOOL construct_sensitivity_obj(lprec *lp);\n\nSTATIC int add_GUB(lprec *lp, const char *name, int priority, int count, int *sosvars);\nSTATIC basisrec *push_basis(lprec *lp, int *basisvar, MYBOOL *isbasic, MYBOOL *islower);\nSTATIC MYBOOL compare_basis(lprec *lp);\nSTATIC MYBOOL restore_basis(lprec *lp);\nSTATIC MYBOOL pop_basis(lprec *lp, MYBOOL restore);\nSTATIC MYBOOL is_BasisReady(lprec *lp);\nSTATIC MYBOOL is_slackbasis(lprec *lp);\nSTATIC MYBOOL verify_basis(lprec *lp);\nSTATIC int unload_basis(lprec *lp, MYBOOL restorelast);\n\nSTATIC int perturb_bounds(lprec *lp, BBrec *perturbed, MYBOOL doRows, MYBOOL doCols, MYBOOL includeFIXED);\nSTATIC MYBOOL validate_bounds(lprec *lp, REAL *upbo, REAL *lowbo);\nSTATIC MYBOOL impose_bounds(lprec *lp, REAL * upbo, REAL *lowbo);\nSTATIC int unload_BB(lprec *lp);\n\nSTATIC REAL feasibilityOffset(lprec *lp, MYBOOL isdual);\nSTATIC MYBOOL isP1extra(lprec *lp);\nSTATIC REAL get_refactfrequency(lprec *lp, MYBOOL final);\nSTATIC int findBasicFixedvar(lprec *lp, int afternr, MYBOOL slacksonly);\nSTATIC MYBOOL isBasisVarFeasible(lprec *lp, REAL tol, int basis_row);\nSTATIC MYBOOL isPrimalFeasible(lprec *lp, REAL tol, int infeasibles[], REAL *feasibilitygap);\nSTATIC MYBOOL isDualFeasible(lprec *lp, REAL tol, int *boundflips, int infeasibles[], REAL *feasibilitygap);\n\n/* Main simplex driver routines */\nSTATIC int preprocess(lprec *lp);\nSTATIC void postprocess(lprec *lp);\nSTATIC MYBOOL performiteration(lprec *lp, int rownr, int varin, LREAL theta, MYBOOL primal, MYBOOL allowminit, REAL *prow, int *nzprow, REAL *pcol, int *nzpcol, int *boundswaps);\nSTATIC void transfer_solution_var(lprec *lp, int uservar);\nSTATIC void transfer_solution(lprec *lp, MYBOOL dofinal);\n\n/* Scaling utilities */\nSTATIC REAL scaled_floor(lprec *lp, int colnr, REAL value, REAL epsscale);\nSTATIC REAL scaled_ceil(lprec *lp, int colnr, REAL value, REAL epsscale);\n\n/* Variable mapping utility routines */\nSTATIC void varmap_lock(lprec *lp);\nSTATIC void varmap_clear(lprec *lp);\nSTATIC MYBOOL varmap_canunlock(lprec *lp);\nSTATIC void varmap_addconstraint(lprec *lp);\nSTATIC void varmap_addcolumn(lprec *lp);\nSTATIC void varmap_delete(lprec *lp, int base, int delta, LLrec *varmap);\nSTATIC void varmap_compact(lprec *lp, int prev_rows, int prev_cols);\nSTATIC MYBOOL varmap_validate(lprec *lp, int varno);\n/* STATIC MYBOOL del_varnameex(lprec *lp, hashelem **namelist, hashtable *ht, int varnr, LLrec *varmap); */\n STATIC MYBOOL del_varnameex(lprec *lp, hashelem **namelist, int items, hashtable *ht, int varnr, LLrec *varmap);\n\n/* Pseudo-cost routines (internal) */\nSTATIC BBPSrec *init_pseudocost(lprec *lp, int pseudotype);\nSTATIC void free_pseudocost(lprec *lp);\nSTATIC REAL get_pseudorange(BBPSrec *pc, int mipvar, int varcode);\nSTATIC void update_pseudocost(BBPSrec *pc, int mipvar, int varcode, MYBOOL capupper, REAL varsol);\nSTATIC REAL get_pseudobranchcost(BBPSrec *pc, int mipvar, MYBOOL dofloor);\nSTATIC REAL get_pseudonodecost(BBPSrec *pc, int mipvar, int vartype, REAL varsol);\n\n/* Matrix access and equation solving routines */\nSTATIC void set_OF_override(lprec *lp, REAL *ofVector);\nSTATIC void set_OF_p1extra(lprec *lp, REAL p1extra);\nSTATIC void unset_OF_p1extra(lprec *lp);\nMYBOOL modifyOF1(lprec *lp, int index, REAL *ofValue, REAL mult);\nREAL __WINAPI get_OF_active(lprec *lp, int varnr, REAL mult);\nSTATIC MYBOOL is_OF_nz(lprec *lp, int colnr);\n\nSTATIC int get_basisOF(lprec *lp, int coltarget[], REAL crow[], int colno[]);\nint    __WINAPI get_basiscolumn(lprec *lp, int j, int rn[], double bj[]);\nint    __WINAPI obtain_column(lprec *lp, int varin, REAL *pcol, int *nzlist, int *maxabs);\nSTATIC int compute_theta(lprec *lp, int rownr, LREAL *theta, int isupbound, REAL HarrisScalar, MYBOOL primal);\n\n/* Pivot utility routines */\nSTATIC int findBasisPos(lprec *lp, int notint, int *var_basic);\nSTATIC MYBOOL check_degeneracy(lprec *lp, REAL *pcol, int *degencount);\n\n#endif /* HEADER_lp_lib */\n"
  },
  {
    "path": "utilities/lp_solve/lp_matrix.c",
    "content": "\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_scale.h\"\n#include \"lp_report.h\"\n#include \"lp_price.h\"\n#include \"lp_pricePSE.h\"\n#include \"lp_matrix.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n/* -------------------------------------------------------------------------\n   Basic matrix routines in lp_solve v5.0+\n   -------------------------------------------------------------------------\n    Author:        Michel Berkelaar (to lp_solve v3.2),\n                   Kjell Eikland    (v4.0 and forward)\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      lp_lib.h, lp_pricerPSE.h, lp_matrix.h\n\n    Release notes:\n    v5.0.0  1 January 2004      First integrated and repackaged version.\n    v5.0.1  7 May 2004          Added matrix transpose function.\n    v5.1.0  20 July 2004        Reworked with flexible matrix storage model.\n    v5.2.0  10 January 2005     Added fast deletion methods.\n                                Added data extraction to matrix method.\n                                Changed to explicit OF storage mode.\n\n   ------------------------------------------------------------------------- */\n\nSTATIC MATrec *mat_create(lprec *lp, int rows, int columns, REAL epsvalue)\n{\n  MATrec *newmat;\n\n  newmat = (MATrec *) calloc(1, sizeof(*newmat));\n  newmat->lp = lp;\n\n  newmat->rows_alloc = 0;\n  newmat->columns_alloc = 0;\n  newmat->mat_alloc = 0;\n\n  inc_matrow_space(newmat, rows);\n  newmat->rows = rows;\n  inc_matcol_space(newmat, columns);\n  newmat->columns = columns;\n  inc_mat_space(newmat, 0);\n\n  newmat->epsvalue = epsvalue;\n\n  return( newmat );\n}\n\nSTATIC void mat_free(MATrec **matrix)\n{\n  if((matrix == NULL) || (*matrix == NULL))\n    return;\n\n#if MatrixColAccess==CAM_Record\n  FREE((*matrix)->col_mat);\n#else /*if MatrixColAccess==CAM_Vector*/\n  FREE((*matrix)->col_mat_colnr);\n  FREE((*matrix)->col_mat_rownr);\n  FREE((*matrix)->col_mat_value);\n#endif\n  FREE((*matrix)->col_end);\n  FREE((*matrix)->col_tag);\n\n#if MatrixRowAccess==RAM_Index\n  FREE((*matrix)->row_mat);\n#elif MatrixColAccess==CAM_Record\n  FREE((*matrix)->row_mat);\n#else /*if MatrixRowAccess==COL_Vector*/\n  FREE((*matrix)->row_mat_colnr);\n  FREE((*matrix)->row_mat_rownr);\n  FREE((*matrix)->row_mat_value);\n#endif\n  FREE((*matrix)->row_end);\n  FREE((*matrix)->row_tag);\n\n  FREE((*matrix)->colmax);\n  FREE((*matrix)->rowmax);\n\n  FREE(*matrix);\n}\n\nSTATIC MYBOOL mat_memopt(MATrec *mat, int rowextra, int colextra, int nzextra)\n{\n  MYBOOL status = TRUE;\n  int matalloc, colalloc, rowalloc;\n\n  if((mat == NULL) ||\n#if 0\n     (++rowextra < 1) || (++colextra < 1) || (++nzextra < 1))\n#else\n     (rowextra < 0) || (colextra < 0) || (nzextra < 0))\n#endif\n    return( FALSE );\n\n  mat->rows_alloc    = MIN(mat->rows_alloc,    mat->rows + rowextra);\n  mat->columns_alloc = MIN(mat->columns_alloc, mat->columns + colextra);\n  mat->mat_alloc     = MIN(mat->mat_alloc,     mat->col_end[mat->columns] + nzextra);\n#if 0\n  rowalloc = mat->rows_alloc;\n  colalloc = mat->columns_alloc;\n  matalloc = mat->mat_alloc;\n#else\n  rowalloc = mat->rows_alloc + 1;\n  colalloc = mat->columns_alloc + 1;\n  matalloc = mat->mat_alloc + 1;\n#endif\n\n#if MatrixColAccess==CAM_Record\n  mat->col_mat = (MATitem *) realloc(mat->col_mat, matalloc * sizeof(*(mat->col_mat)));\n  status &= (mat->col_mat != NULL);\n#else /*if MatrixColAccess==CAM_Vector*/\n  status &= allocINT(mat->lp,  &(mat->col_mat_colnr), matalloc, AUTOMATIC) &&\n            allocINT(mat->lp,  &(mat->col_mat_rownr), matalloc, AUTOMATIC) &&\n            allocREAL(mat->lp, &(mat->col_mat_value), matalloc, AUTOMATIC);\n#endif\n  status &= allocINT(mat->lp, &mat->col_end, colalloc, AUTOMATIC);\n  if(mat->col_tag != NULL)\n    status &= allocINT(mat->lp, &mat->col_tag, colalloc, AUTOMATIC);\n\n#if MatrixRowAccess==RAM_Index\n  status &= allocINT(mat->lp, &(mat->row_mat), matalloc, AUTOMATIC);\n#elif MatrixColAccess==CAM_Record\n  mat->row_mat = (MATitem *) realloc(mat->row_mat, matalloc * sizeof(*(mat->row_mat)));\n  status &= (mat->row_mat != NULL);\n#else /*if MatrixRowAccess==COL_Vector*/\n  status &= allocINT(mat->lp,  &(mat->row_mat_colnr), matalloc, AUTOMATIC) &&\n            allocINT(mat->lp,  &(mat->row_mat_rownr), matalloc, AUTOMATIC) &&\n            allocREAL(mat->lp, &(mat->row_mat_value), matalloc, AUTOMATIC);\n#endif\n  status &= allocINT(mat->lp, &mat->row_end, rowalloc, AUTOMATIC);\n  if(mat->row_tag != NULL)\n    status &= allocINT(mat->lp, &mat->row_tag, rowalloc, AUTOMATIC);\n\n  if(mat->colmax != NULL)\n    status &= allocREAL(mat->lp, &(mat->colmax), colalloc, AUTOMATIC);\n  if(mat->rowmax != NULL)\n    status &= allocREAL(mat->lp, &(mat->rowmax), rowalloc, AUTOMATIC);\n\n  return( status );\n}\n\nSTATIC MYBOOL inc_mat_space(MATrec *mat, int mindelta)\n{\n  int spaceneeded, nz = mat_nonzeros(mat);\n\n  if(mindelta <= 0)\n    mindelta = MAX(mat->rows, mat->columns) + 1;\n  spaceneeded = DELTA_SIZE(mindelta, nz);\n  SETMAX(mindelta, spaceneeded);\n\n  if(mat->mat_alloc == 0)\n    spaceneeded = mindelta;\n  else\n    spaceneeded = nz + mindelta;\n\n  if(spaceneeded >= mat->mat_alloc) {\n    /* Let's allocate at least MAT_START_SIZE entries */\n    if(mat->mat_alloc < MAT_START_SIZE)\n      mat->mat_alloc = MAT_START_SIZE;\n\n    /* Increase the size by RESIZEFACTOR each time it becomes too small */\n    while(spaceneeded >= mat->mat_alloc)\n      mat->mat_alloc += mat->mat_alloc / RESIZEFACTOR;\n\n#if MatrixColAccess==CAM_Record\n    mat->col_mat = (MATitem *) realloc(mat->col_mat, (mat->mat_alloc) * sizeof(*(mat->col_mat)));\n#else /*if MatrixColAccess==CAM_Vector*/\n    allocINT(mat->lp,  &(mat->col_mat_colnr), mat->mat_alloc, AUTOMATIC);\n    allocINT(mat->lp,  &(mat->col_mat_rownr), mat->mat_alloc, AUTOMATIC);\n    allocREAL(mat->lp, &(mat->col_mat_value), mat->mat_alloc, AUTOMATIC);\n#endif\n\n#if MatrixRowAccess==RAM_Index\n    allocINT(mat->lp, &(mat->row_mat), mat->mat_alloc, AUTOMATIC);\n#elif MatrixColAccess==CAM_Record\n    mat->row_mat = (MATitem *) realloc(mat->row_mat, (mat->mat_alloc) * sizeof(*(mat->row_mat)));\n#else /*if MatrixColAccess==CAM_Vector*/\n    allocINT(mat->lp,  &(mat->row_mat_colnr), mat->mat_alloc, AUTOMATIC);\n    allocINT(mat->lp,  &(mat->row_mat_rownr), mat->mat_alloc, AUTOMATIC);\n    allocREAL(mat->lp, &(mat->row_mat_value), mat->mat_alloc, AUTOMATIC);\n#endif\n  }\n  return(TRUE);\n}\n\nSTATIC MYBOOL inc_matrow_space(MATrec *mat, int deltarows)\n{\n  int    rowsum, oldrowsalloc;\n  MYBOOL status = TRUE;\n\n  /* Adjust lp row structures */\n  if(mat->rows+deltarows >= mat->rows_alloc) {\n\n    /* Update memory allocation and sizes */\n    oldrowsalloc = mat->rows_alloc;\n    deltarows = DELTA_SIZE(deltarows, mat->rows);\n    SETMAX(deltarows, DELTAROWALLOC);\n    mat->rows_alloc += deltarows;\n    rowsum = mat->rows_alloc + 1;\n\n    /* Update row pointers */\n    status = allocINT(mat->lp, &mat->row_end, rowsum, AUTOMATIC);\n    mat->row_end_valid = FALSE;\n  }\n  return( status );\n}\n\nSTATIC MYBOOL inc_matcol_space(MATrec *mat, int deltacols)\n{\n  int    i, colsum, oldcolsalloc;\n  MYBOOL status = TRUE;\n\n  /* Adjust lp column structures */\n  if(mat->columns+deltacols >= mat->columns_alloc) {\n\n    /* Update memory allocation and sizes */\n    oldcolsalloc = mat->columns_alloc;\n    deltacols = DELTA_SIZE(deltacols, mat->columns);\n    SETMAX(deltacols, DELTACOLALLOC);\n    mat->columns_alloc += deltacols;\n    colsum = mat->columns_alloc + 1;\n    status = allocINT(mat->lp, &mat->col_end, colsum, AUTOMATIC);\n\n    /* Update column pointers */\n    if(oldcolsalloc == 0)\n      mat->col_end[0] = 0;\n    for(i = MIN(oldcolsalloc, mat->columns) + 1; i < colsum; i++)\n      mat->col_end[i] = mat->col_end[i-1];\n    mat->row_end_valid = FALSE;\n  }\n  return( status );\n}\n\nSTATIC int mat_collength(MATrec *mat, int colnr)\n{\n  return( mat->col_end[colnr] - mat->col_end[colnr-1] );\n}\n\nSTATIC int mat_rowlength(MATrec *mat, int rownr)\n{\n  if(mat_validate(mat)) {\n    if(rownr <= 0)\n      return( mat->row_end[0] );\n    else\n      return( mat->row_end[rownr] - mat->row_end[rownr-1] );\n  }\n  else\n    return( 0 );\n}\n\nSTATIC int mat_nonzeros(MATrec *mat)\n{\n  return( mat->col_end[mat->columns] );\n}\n\nSTATIC MYBOOL mat_indexrange(MATrec *mat, int index, MYBOOL isrow, int *startpos, int *endpos)\n{\n#ifdef Paranoia\n  if(isrow && ((index < 0) || (index > mat->rows)))\n    return( FALSE );\n  else if(!isrow && ((index < 1) || (index > mat->columns)))\n    return( FALSE );\n#endif\n\n  if(isrow && mat_validate(mat)) {\n    if(index == 0)\n      *startpos = 0;\n    else\n      *startpos = mat->row_end[index-1];\n    *endpos = mat->row_end[index];\n  }\n  else {\n    *startpos = mat->col_end[index-1];\n    *endpos = mat->col_end[index];\n  }\n  return( TRUE );\n}\n\nSTATIC int mat_shiftrows(MATrec *mat, int *bbase, int delta, LLrec *varmap)\n{\n  int     j, k, i, ii, thisrow, *colend, base;\n  MYBOOL  preparecompact = FALSE;\n  int     *rownr;\n\n  if(delta == 0)\n    return( 0 );\n  base = abs(*bbase);\n\n  if(delta > 0) {\n\n    /* Insert row by simply incrementing existing row indeces */\n    if(base <= mat->rows) {\n      k = mat_nonzeros(mat);\n      rownr = &COL_MAT_ROWNR(0);\n      for(ii = 0; ii < k; ii++, rownr += matRowColStep) {\n        if(*rownr >= base)\n          *rownr += delta;\n      }\n    }\n\n    /* Set defaults (actual basis set in separate procedure) */\n    for(i = 0; i < delta; i++) {\n      ii = base + i;\n      mat->row_end[ii] = 0;\n    }\n  }\n  else if(base <= mat->rows) {\n\n    /* Check for preparation of mass-deletion of rows */\n    preparecompact = (MYBOOL) (varmap != NULL);\n    if(preparecompact) {\n      /* Create the offset array */\n      int *newrowidx = NULL;\n      allocINT(mat->lp, &newrowidx, mat->rows+1, FALSE);\n      newrowidx[0] = 0;\n      delta = 0;\n      for(j = 1; j <= mat->rows; j++) {\n        if(isActiveLink(varmap, j)) {\n          delta++;\n          newrowidx[j] = delta;\n        }\n        else\n          newrowidx[j] = -1;\n      }\n      k = 0;\n      delta = 0;\n      base = mat_nonzeros(mat);\n      rownr = &COL_MAT_ROWNR(0);\n      for(i = 0; i < base; i++, rownr += matRowColStep) {\n        thisrow = newrowidx[*rownr];\n        if(thisrow < 0) {\n          *rownr = -1;\n          delta++;\n        }\n        else\n          *rownr = thisrow;\n      }\n      FREE(newrowidx);\n      return(delta);\n    }\n\n    /* Check if we should prepare for compacting later\n       (this is in order to speed up multiple row deletions) */\n    preparecompact = (MYBOOL) (*bbase < 0);\n    if(preparecompact)\n      *bbase = my_flipsign((*bbase));\n\n    /* First make sure we don't cross the row count border */\n    if(base-delta-1 > mat->rows)\n      delta = base - mat->rows - 1;\n\n    /* Then scan over all entries shifting and updating rows indeces */\n    if(preparecompact) {\n      k = 0;\n      for(j = 1, colend = mat->col_end + 1;\n          j <= mat->columns; j++, colend++) {\n        i = k;\n        k = *colend;\n        rownr = &COL_MAT_ROWNR(i);\n        for(; i < k; i++, rownr += matRowColStep) {\n          thisrow = *rownr;\n          if(thisrow < base)\n            continue;\n          else if(thisrow >= base-delta)\n            *rownr += delta;\n          else\n            *rownr = -1;\n        }\n      }\n    }\n    else {\n      k = 0;\n      ii = 0;\n      for(j = 1, colend = mat->col_end + 1;\n          j <= mat->columns; j++, colend++) {\n        i = k;\n        k = *colend;\n        rownr = &COL_MAT_ROWNR(i);\n        for(; i < k; i++, rownr += matRowColStep) {\n          thisrow = *rownr;\n          if(thisrow >= base) {\n            if(thisrow >= base-delta)\n              *rownr += delta;\n            else\n              continue;\n          }\n          if(ii != i) {\n            COL_MAT_COPY(ii, i);\n          }\n          ii++;\n        }\n        *colend = ii;\n      }\n    }\n  }\n  return( 0 );\n}\n\n/* Map-based compacting+insertion of matrix elements without changing row and column indeces.\n   When mat2 is NULL, a simple compacting of non-deleted rows and columns is done. */\nSTATIC int mat_mapreplace(MATrec *mat, LLrec *rowmap, LLrec *colmap, MATrec *mat2)\n{\n  lprec *lp = mat->lp;\n  int   i, ib, ie, ii, j, jj, jb, je, nz, *colend, *rownr, *rownr2, *indirect = NULL;\n  REAL  *value, *value2;\n\n  /* Check if there is something to insert */\n  if((mat2 != NULL) && ((mat2->col_tag == NULL) || (mat2->col_tag[0] <= 0) || (mat_nonzeros(mat2) == 0)))\n    return( 0 );\n\n  /* Create map and sort by increasing index in \"mat\" */\n  if(mat2 != NULL) {\n    jj = mat2->col_tag[0];\n    allocINT(lp, &indirect, jj+1, FALSE);\n    indirect[0] = jj;\n    for(i = 1; i <= jj; i++)\n      indirect[i] = i;\n    hpsortex(mat2->col_tag, jj, 1, sizeof(*indirect), FALSE, compareINT, indirect);\n  }\n\n  /* Do the compacting */\n  mat->row_end_valid = FALSE;\n  nz = mat->col_end[mat->columns];\n  ie = 0;\n  ii = 0;\n  if((mat2 == NULL) || (indirect[0] == 0)) {\n    je = mat->columns + 1;\n    jj = 1;\n    jb = 0;\n  }\n  else {\n    je = indirect[0];\n    jj = 0;\n    do {\n      jj++;\n      jb = mat2->col_tag[jj];\n    } while(jb <= 0);\n\n  }\n  for(j = 1, colend = mat->col_end + 1;\n      j <= mat->columns; j++, colend++) {\n    ib = ie;\n    ie = *colend;\n\n    /* Always skip (condense) replacement columns */\n    if(j == jb) {\n      jj++;\n      if(jj <= je)\n        jb = mat2->col_tag[jj];\n      else\n        jb = mat->columns + 1;\n    }\n\n    /* Only include active columns */\n    else if(isActiveLink(colmap, j)) {\n      rownr = &COL_MAT_ROWNR(ib);\n      for(; ib < ie; ib++, rownr += matRowColStep) {\n\n        /* Also make sure the row is active */\n        if(isActiveLink(rowmap, *rownr)) {\n          if(ii != ib) {\n            COL_MAT_COPY(ii, ib);\n          }\n          ii++;\n        }\n      }\n    }\n    *colend = ii;\n  }\n  if(mat2 == NULL)\n    goto Finish;\n\n  /* Tally non-zero insertions */\n  i = 0;\n  for(j = 1; j <= mat2->col_tag[0]; j++) {\n    jj = mat2->col_tag[j];\n    if((jj > 0) && isActiveLink(colmap, jj)) {\n      jj = indirect[j];\n      je = mat2->col_end[jj];\n      jb = mat2->col_end[jj-1];\n      rownr2 = &COL_MAT2_ROWNR(jb);\n      for(; jb < je; jb++, rownr2 += matRowColStep) {\n        if((*rownr2 > 0) && isActiveLink(rowmap, *rownr2))\n          i++;\n      }\n    }\n  }\n\n  /* Make sure we have enough matrix space */\n  ii = mat->col_end[mat->columns] + i;\n  if(mat->mat_alloc <= ii)\n    inc_mat_space(mat, i);\n\n  /* Do shifting and insertion - loop from the end going forward */\n  jj = indirect[0];\n  jj = mat2->col_tag[jj];\n  for(j = mat->columns, colend = mat->col_end + mat->columns, ib = *colend;\n      j > 0; j--) {\n\n    /* Update indeces for this loop */\n    ie = ib;\n    *colend = ii;\n    colend--;\n    ib = *colend;\n\n    /* Insert new values */\n    if(j == jj) {\n      /* Only include an active column */\n      if(isActiveLink(colmap, j)) {\n        jj = indirect[0];\n        jj = indirect[jj];\n        rownr = &COL_MAT_ROWNR(ii-1);\n        value = &COL_MAT_VALUE(ii-1);\n        jb = mat2->col_end[jj-1];\n        je = mat2->col_end[jj] - 1;\n        rownr2 = &COL_MAT2_ROWNR(je);\n        value2 = &COL_MAT2_VALUE(je);\n\n        /* Process constraint coefficients */\n        for(; je >= jb; je--, rownr2 -= matRowColStep, value2 -= matValueStep) {\n          i = *rownr2;\n          if(i == 0) {\n            i = -1;\n            break;\n          }\n          else if(isActiveLink(rowmap, i)) {\n            ii--;\n            *rownr = i;\n            rownr -= matRowColStep;\n            *value = my_chsign(is_chsign(lp, i), *value2);\n            value -= matValueStep;\n          }\n        }\n\n        /* Then handle the objective */\n        if(i == -1) {\n          lp->orig_obj[j] = my_chsign(is_maxim(lp), *value2);\n          rownr2 -= matRowColStep;\n          value2 -= matValueStep;\n        }\n        else\n          lp->orig_obj[j] = 0;\n\n      }\n      /* Update replacement column index or break if no more candidates */\n      jj = --indirect[0];\n      if(jj == 0)\n        break;\n      jj = mat2->col_tag[jj];\n      if(jj <= 0)\n        break;\n    }\n    /* Shift existing values down */\n    else {\n      if(isActiveLink(colmap, j))\n      while(ie > ib) {\n        ii--;\n        ie--;\n        if(ie != ii) {\n          COL_MAT_COPY(ii, ie);\n        }\n      }\n    }\n  }\n\n  /* Return the delta number of non-zero elements */\nFinish:\n  nz -= mat->col_end[mat->columns];\n  FREE(indirect);\n\n  return( nz );\n}\n\n/* Routines to compact rows in matrix based on precoded entries */\nSTATIC int mat_zerocompact(MATrec *mat)\n{\n  return( mat_rowcompact(mat, TRUE) );\n}\nSTATIC int mat_rowcompact(MATrec *mat, MYBOOL dozeros)\n{\n  int  i, ie, ii, j, nn, *colend, *rownr;\n  REAL *value;\n\n  nn = 0;\n  ie = 0;\n  ii = 0;\n  for(j = 1, colend = mat->col_end + 1;\n      j <= mat->columns; j++, colend++) {\n    i = ie;\n    ie = *colend;\n    rownr = &COL_MAT_ROWNR(i);\n    value = &COL_MAT_VALUE(i);\n    for(; i < ie;\n        i++, rownr += matRowColStep, value += matValueStep) {\n      if((*rownr < 0) || (dozeros && (fabs(*value) < mat->epsvalue))) {\n        nn++;\n        continue;\n      }\n      if(ii != i) {\n        COL_MAT_COPY(ii, i);\n      }\n      ii++;\n    }\n    *colend = ii;\n  }\n  return( nn );\n}\n\n/* Routines to compact columns and their indeces based on precoded entries */\nSTATIC int mat_colcompact(MATrec *mat, int prev_rows, int prev_cols)\n{\n  int             i, ii, j, k, n_del, n_sum, *colend, *newcolend, *colnr, newcolnr;\n  MYBOOL          deleted;\n  lprec           *lp = mat->lp;\n  presolveundorec *lpundo = lp->presolve_undo;\n\n\n  n_sum = 0;\n  k  = 0;\n  ii = 0;\n  newcolnr = 1;\n  for(j = 1, colend = newcolend = mat->col_end + 1;\n      j <= prev_cols; j++, colend++) {\n    n_del = 0;\n    i = k;\n    k = *colend;\n    for(colnr = &COL_MAT_COLNR(i); i < k;\n        i++, colnr += matRowColStep) {\n      if(*colnr < 0) {\n        n_del++;\n        n_sum++;\n        continue;\n      }\n      if(ii < i) {\n        COL_MAT_COPY(ii, i);\n      }\n      if(newcolnr < j) {\n        COL_MAT_COLNR(ii) = newcolnr;\n      }\n      ii++;\n    }\n    *newcolend = ii;\n\n    deleted = (MYBOOL) (n_del > 0);\n#if 1\n    /* Do hoops in case there was an empty column */\n    deleted |= (MYBOOL) (!lp->wasPresolved && (lpundo->var_to_orig[prev_rows+j] < 0));\n\n#endif\n    /* Increment column variables if current column was not deleted */\n    if(!deleted) {\n      newcolend++;\n      newcolnr++;\n    }\n  }\n  return(n_sum);\n}\n\nSTATIC int mat_shiftcols(MATrec *mat, int *bbase, int delta, LLrec *varmap)\n{\n  int     i, ii, k, n, base;\n\n\n  k = 0;\n  if(delta == 0)\n    return( k );\n  base = abs(*bbase);\n\n  if(delta > 0) {\n    /* Shift pointers right */\n    for(ii = mat->columns; ii > base; ii--) {\n      i = ii + delta;\n      mat->col_end[i] = mat->col_end[ii];\n    }\n    /* Set defaults */\n    for(i = 0; i < delta; i++) {\n      ii = base + i;\n      mat->col_end[ii] = mat->col_end[ii-1];\n    }\n  }\n  else {\n\n    /* Check for preparation of mass-deletion of columns */\n    MYBOOL preparecompact = (MYBOOL) (varmap != NULL);\n    if(preparecompact) {\n      /* Create the offset array */\n      int j, *colnr, *colend;\n      n = 0;\n      k = 0;\n      base = 0;\n      for(j = 1, colend = mat->col_end + 1;\n          j <= mat->columns; j++, colend++) {\n        i = k;\n        k = *colend;\n        if(isActiveLink(varmap, j)) {\n          base++;\n          ii = base;\n        }\n        else\n          ii = -1;\n        if(ii < 0)\n          n += k - i;\n        colnr = &COL_MAT_COLNR(i);\n        for(; i < k; i++, colnr += matRowColStep)\n          *colnr = ii;\n      }\n      return(n);\n    }\n\n    /* Check if we should prepare for compacting later\n       (this is in order to speed up multiple column deletions) */\n    preparecompact = (MYBOOL) (*bbase < 0);\n    if(preparecompact)\n      *bbase = my_flipsign((*bbase));\n\n    /* First make sure we don't cross the column count border */\n    if(base-delta-1 > mat->columns)\n      delta = base - mat->columns - 1;\n\n    /* Then scan over all entries shifting and updating column indeces */\n    if(preparecompact) {\n      int *colnr;\n      n = 0;\n      i = mat->col_end[base-1];\n      k = mat->col_end[base-delta-1];\n      for(colnr = &COL_MAT_COLNR(i); i < k;\n          i++, colnr += matRowColStep) {\n        n++;\n        *colnr = -1;\n      }\n      k = n;\n    }\n    else {\n      /* Delete sparse matrix data, if required */\n      if(base <= mat->columns) {\n\n        i = mat->col_end[base-1];          /* Beginning of data to be deleted */\n        ii = mat->col_end[base-delta-1];   /* Beginning of data to be shifted left */\n        n = mat_nonzeros(mat);             /* Total number of non-zeros */\n        k = ii-i;                          /* Number of entries to be deleted */\n        if((k > 0) && (n > i)) {\n          n -= ii;\n          COL_MAT_MOVE(i, ii, n);\n        }\n\n        /* Update indexes */\n        for(i = base; i <= mat->columns + delta; i++) {\n          ii = i - delta;\n          mat->col_end[i] = mat->col_end[ii] - k;\n        }\n      }\n    }\n  }\n  return( k );\n}\n\nSTATIC MATrec *mat_extractmat(MATrec *mat, LLrec *rowmap, LLrec *colmap, MYBOOL negated)\n{\n  int    *rownr, *colnr, xa, na;\n  REAL   *value;\n  MATrec *newmat = mat_create(mat->lp, mat->rows, mat->columns, mat->epsvalue);\n\n  /* Initialize */\n  na = mat_nonzeros(mat);\n  rownr = &COL_MAT_ROWNR(0);\n  colnr = &COL_MAT_COLNR(0);\n  value = &COL_MAT_VALUE(0);\n\n  /* Loop over the indeces, picking out values in qualifying rows and colums\n     (note that the loop could be speeded up for dense matrices by making an\n      outer loop for columns and inner loop for rows) */\n  for(xa = 0; xa < na; xa++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) {\n    if((isActiveLink(colmap, *colnr) ^ negated) &&\n       (isActiveLink(rowmap, *rownr) ^ negated))\n      mat_setvalue(newmat, *rownr, *colnr, *value, FALSE);\n  }\n\n  /* Return the populated new matrix */\n  return( newmat );\n}\n\nSTATIC MYBOOL mat_setcol(MATrec *mat, int colno, int count, REAL *column, int *rowno, MYBOOL doscale, MYBOOL checkrowmode)\n{\n  int    i, jj = 0, elmnr, orignr, newnr, firstrow;\n  MYBOOL *addto = NULL, isA, isNZ;\n  REAL   value, saved = 0;\n  lprec  *lp = mat->lp;\n\n  /* Check if we are in row order mode and should add as row instead;\n     the matrix will be transposed at a later stage */\n  if(checkrowmode && mat->is_roworder)\n    return( mat_setrow(mat, colno, count, column, rowno, doscale, FALSE) );\n\n  /* Initialize and validate */\n  isA = (MYBOOL) (mat == mat->lp->matA);\n  isNZ = (MYBOOL) (rowno != NULL);\n  if(!isNZ)\n    count = mat->lp->rows;\n  else if((count < 0) || (count > mat->rows+((mat->is_roworder) ? 0 : 1)))\n    return( FALSE );\n  if(isNZ && (count > 0)) {\n    if(count > 1)\n      sortREALByINT(column, rowno, count, 0, TRUE);\n    if((rowno[0] < 0) || (rowno[count-1] > mat->rows))\n      return( FALSE );\n  }\n\n  /* Capture OF definition in column mode */\n  if(isA && !mat->is_roworder) {\n    if(isNZ && (count > 0) && (rowno[0] == 0)) {\n      value = column[0];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      if(doscale)\n        value = scaled_mat(lp, value, 0, colno);\n      value = my_chsign(is_maxim(lp), value);\n      lp->orig_obj[colno] = value;\n      count--;\n      column++;\n      rowno++;\n    }\n    else if(!isNZ && (column[0] != 0)) {\n      value = saved = column[0];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      if(doscale)\n        value = scaled_mat(lp, value, 0, colno);\n      value = my_chsign(is_maxim(lp), value);\n      lp->orig_obj[colno] = value;\n      column[0] = 0;\n    }\n    else\n      lp->orig_obj[colno] = 0;\n  }\n\n  /* Optionally tally and map the new non-zero values */\n  firstrow = mat->rows + 1;\n  if(isNZ) {\n    newnr = count;\n    if(newnr) {\n      firstrow = rowno[0];\n      jj = rowno[newnr - 1];\n    }\n  }\n  else {\n    newnr = 0;\n    if(!allocMYBOOL(lp, &addto, mat->rows + 1, TRUE)) {\n      return( FALSE );\n    }\n    for(i = mat->rows; i >= 0; i--) {\n      if(fabs(column[i]) > mat->epsvalue) {\n        addto[i] = TRUE;\n        firstrow = i;\n        newnr++;\n      }\n    }\n  }\n\n  /* Make sure we have enough matrix space */\n  if(!inc_mat_space(mat, newnr)) {\n    newnr = 0;\n    goto Done;\n  }\n\n  /* Shift existing column data and adjust position indeces */\n  orignr = mat_collength(mat, colno);\n  elmnr = newnr - orignr;\n  i = mat_nonzeros(mat) - mat->col_end[colno];\n  if((elmnr != 0) && (i > 0)) {\n    COL_MAT_MOVE(mat->col_end[colno] + elmnr, mat->col_end[colno], i);\n  }\n  if(elmnr != 0)\n    for(i = colno; i <= mat->columns; i++)\n      mat->col_end[i] += elmnr;\n\n  /* We are now ready to copy the new data */\n  jj = mat->col_end[colno-1];\n  if(isNZ) {\n    for(i = 0; i < count; jj++, i++) {\n      value = column[i];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      if(mat->is_roworder) {    /* Fix following Ingmar Stein bug report 12.10.2006 */\n        if(isA && doscale)\n          value = scaled_mat(lp, value, colno, rowno[i]);\n        if(isA)\n          value = my_chsign(is_chsign(lp, colno), value);\n      }\n      else {\n        if(isA && doscale)\n          value = scaled_mat(lp, value, rowno[i], colno);\n        if(isA)\n          value = my_chsign(is_chsign(lp, rowno[i]), value);\n      }\n      SET_MAT_ijA(jj, rowno[i], colno, value);\n    }\n  }\n  else {\n    for(i = firstrow; i <= mat->rows; i++) {\n      if(!addto[i])\n        continue;\n      value = column[i];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      if(mat->is_roworder) {    /* Fix following Ingmar Stein bug report 12.10.2006 */\n        if(isA && doscale)\n          value = scaled_mat(lp, value, colno, i);\n        if(isA)\n          value = my_chsign(is_chsign(lp, colno), value);\n      }\n      else {\n        if(isA && doscale)\n          value = scaled_mat(lp, value, i, colno);\n        if(isA)\n          value = my_chsign(is_chsign(lp, i), value);\n      }\n      SET_MAT_ijA(jj, i, colno, value);\n      jj++;\n    }\n  }\n  mat->row_end_valid = FALSE;\n\n  /* Finish and return */\nDone:\n  if(saved != 0)\n    column[0] = saved;\n  FREE(addto);\n  return( TRUE );\n\n}\n\nSTATIC MYBOOL mat_mergemat(MATrec *target, MATrec *source, MYBOOL usecolmap)\n{\n  lprec *lp = target->lp;\n  int   i, ix, iy, n, *colmap = NULL;\n  REAL  *colvalue = NULL;\n\n  if((target->rows < source->rows) || !allocREAL(lp, &colvalue, target->rows+1, FALSE))\n    return( FALSE );\n\n  if(usecolmap) {\n    n = source->col_tag[0];\n    allocINT(lp, &colmap, n+1, FALSE);\n    for(i = 1; i <= n; i++)\n      colmap[i] = i;\n    hpsortex(source->col_tag, n, 1, sizeof(*colmap), FALSE, compareINT, colmap);\n  }\n  else\n    n = source->columns;\n  for(i = 1; i <= n; i++) {\n    if(!usecolmap && (mat_collength(source, i) == 0))\n      continue;\n    if(usecolmap) {\n      ix = colmap[i];\n      if(ix <= 0)\n        continue;\n      iy = source->col_tag[i];\n      if(iy <= 0)\n        continue;\n    }\n    else\n      ix = iy = i;\n    mat_expandcolumn(source, ix, colvalue, NULL, FALSE);\n    mat_setcol(target, iy, 0, colvalue, NULL, FALSE, FALSE);\n  }\n\n  FREE( colvalue );\n  FREE( colmap );\n\n  return( TRUE );\n}\n\nSTATIC int mat_nz_unused(MATrec *mat)\n{\n  return( mat->mat_alloc - mat->col_end[mat->columns] );\n}\n\n#if 0\nSTATIC MYBOOL mat_setrow(MATrec *mat, int rowno, int count, REAL *row, int *colno, MYBOOL doscale, MYBOOL checkrowmode)\n{\n  lprec   *lp = mat->lp;\n  int     delta;\n  int k, kk, i, ii, j, jj = 0, jj_j, elmnr, orignr, newnr, firstcol, rownr, colnr, matz = 0;\n  MYBOOL  *addto = NULL, isA, isNZ;\n  REAL    value = 0.0, saved = 0;\n\n  /* Check if we are in row order mode and should add as column instead;\n     the matrix will be transposed at a later stage */\n  if(checkrowmode && mat->is_roworder)\n    return( mat_setcol(mat, rowno, count, row, colno, doscale, FALSE) );\n\n  /* Do initialization and validation */\n  if(!mat_validate(mat))\n    return( FALSE );\n  isA = (MYBOOL) (mat == lp->matA);\n  isNZ = (MYBOOL) (colno != NULL);\n  if(!isNZ)\n    count = mat->columns;\n  else if((count < 0) || (count > mat->columns))\n    return( FALSE );\n  if(isNZ && (count > 0)) {\n    if(count > 1)\n      sortREALByINT(row, (int *) colno, count, 0, TRUE);\n    if((colno[0] < 1) || (colno[count-1] > mat->columns))\n      return( FALSE );\n  }\n\n  /* Capture OF definition in row mode */\n  if(isA && mat->is_roworder) {\n    lp->orig_obj[rowno] = 0;\n    if(isNZ && (count > 0) && (colno[0] == 0)) {\n      value = row[0];\n      if(doscale)\n        value = scaled_mat(lp, value, 0, rowno);\n      value = my_chsign(is_maxim(lp), value);\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      lp->orig_obj[rowno] = value;\n      count--;\n      row++;\n      colno++;\n    }\n    else if(!isNZ && (row[0] != 0)) {\n      value = saved = row[0];\n      if(doscale)\n        value = scaled_mat(lp, value, 0, rowno);\n      value = my_chsign(is_maxim(lp), value);\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      lp->orig_obj[rowno] = value;\n      row[0] = 0;\n    }\n    else {\n      lp->orig_obj[rowno] = 0;\n      value = 0;\n    }\n  }\n\n  /* Optionally tally and map the new non-zero values */\n  i  = mat->row_end[rowno-1];\n  ii = mat->row_end[rowno];     /* ****** KE 20070106 - was \"-1\" */\n  firstcol = mat->columns + 1;\n  if(isNZ) {\n    /* See if we can do fast in-place replacements of leading items */\n    colnr = 1; /* initialise in case of an empty row */\n    while((i < ii) /* && (count > 0) */ && ((colnr = ROW_MAT_COLNR(i)) == *colno) && (count > 0)) {\n      value = *row;             /* ****** KE 20080111 - Added line */\n      if(mat->is_roworder) {\n        if(isA && doscale)\n          value = scaled_mat(lp, value, colnr, rowno);\n        if(isA)\n          value = my_chsign(is_chsign(lp, colnr), value);\n      }\n      else {\n        if(isA && doscale)\n          value = scaled_mat(lp, value, rowno, colnr);\n        if(isA)\n          value = my_chsign(is_chsign(lp, rowno), value);\n      }\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n      if(value == 0)\n        matz++;\n#endif\n      ROW_MAT_VALUE(i) = value;\n      i++;\n      count--;\n      row++;\n      colno++;\n    }\n  if(i >= ii)\n      colnr = 0;\n    /* Proceed with remaining entries */\n    newnr = count;\n    if(newnr > 0)\n      firstcol = colno[0];\n  }\n  else {\n    newnr = 0;\n    kk = mat->columns;\n    if(i < ii)\n      colnr = ROW_MAT_COLNR(i);\n    else\n      colnr = 0;\n    for(k = 1; k <= kk; k++) {\n      value = row[k];           /* ****** KE 20080111 - Added line */\n      if(fabs(value) > mat->epsvalue) {\n        /* See if we can do fast in-place replacements of leading items */\n        if((addto == NULL) && (i < ii) && (colnr == k)) {\n          if(mat->is_roworder) {\n            if(isA && doscale)\n              value = scaled_mat(lp, value, colnr, rowno);\n            if(isA)\n              value = my_chsign(is_chsign(lp, colnr), value);\n          }\n          else {\n            if(isA && doscale)\n              value = scaled_mat(lp, value, rowno, colnr);\n            if(isA)\n              value = my_chsign(is_chsign(lp, rowno), value);\n          }\n#ifdef DoMatrixRounding\n          value = roundToPrecision(value, mat->epsvalue);\n          if(value == 0)\n            matz++;\n#endif\n          ROW_MAT_VALUE(i) = value;\n          i++;\n          if(i < ii)\n            colnr = ROW_MAT_COLNR(i);\n          else\n            colnr = 0;\n        }\n        /* Otherwise update addto-list */\n        else {\n          if(addto == NULL) {\n            if(!allocMYBOOL(lp, &addto, mat->columns + 1, TRUE))\n              return( FALSE );\n            firstcol = k;\n          }\n          addto[k] = TRUE;\n          newnr++;\n        }\n      }\n    }\n  }\n  if(newnr == 0)\n   if (FALSE)\n    return( TRUE );\n\n  /* Make sure we have enough matrix space */\n  if((newnr > 0) && (mat_nz_unused(mat) <= newnr) && !inc_mat_space(mat, newnr)) {\n    newnr = 0;\n    goto Done;\n  }\n\n  /* Pack initial entries if existing row data has a lower column\n     start index than the first index of the new vector */\n  orignr = mat_nonzeros(mat);\n  /* delta = newnr - mat_rowlength(mat, rowno);*/\n  kk = 0;\n  if(rowno == 0)\n    ii = 0;\n  else\n    ii = mat->row_end[rowno-1];\n\n  if((orignr == 0) || (ii >= orignr))\n    j = firstcol;\n  else if(isNZ||TRUE)\n    j = colnr;\n  else\n    j = ROW_MAT_COLNR(ii); /* first column with a value on that row */\n\n  jj = mat->col_end[firstcol-1];  /* Set the index of the insertion point for the first new value */\n  if(jj >= orignr)\n    colnr = firstcol;\n  else\n    colnr = COL_MAT_COLNR(jj); /* first column with a value starting from firstcol */\n\n  if((j > 0) && (j < colnr)) {\n    jj = elmnr = mat->col_end[j-1];\n    for( ; j < colnr; j++) {\n      /* Shift entries in current column */\n      k = mat->col_end[j];\n      for( ; jj < k; jj++) {\n        if(COL_MAT_ROWNR(jj) != rowno) {\n          COL_MAT_COPY(elmnr, jj);\n          elmnr++;\n        }\n      }\n      /* Update next column start index */\n      mat->col_end[j] = elmnr;\n    }\n    delta = elmnr - jj;  /* The shrinkage count */\n  }\n  else {\n    delta = 0;\n    /* Adjust for case where we simply append values - jj is initially the first column item */\n    if((mat->col_end[firstcol] == orignr) && 0)\n      jj = orignr;\n  }\n\n  /* Make sure we have sufficient space for any additional entries and move existing data down;\n     this ensures that we only have to relocate matrix elements up in the next stage */\n  jj_j = MAX(0, newnr + delta);\n  if(jj_j > 0) {\n    if(!inc_mat_space(mat, jj_j)) {\n      FREE(addto);\n      return( FALSE );\n    }\n    if(orignr-jj > 0) {\n      COL_MAT_MOVE(jj+jj_j, jj, orignr-jj);\n    }\n    jj += jj_j;\n  }\n\n  /* Handle case where the matrix was empty before (or we can simply append) */\n  if((delta >= 0) && (mat->col_end[firstcol] == orignr) && 0) {\n    if(isNZ)\n      elmnr = count;\n    else\n      elmnr = mat->columns;\n    jj_j = mat->col_end[firstcol];\n    for(newnr = 0; newnr < elmnr; newnr++) {\n      if(isNZ)\n        colnr = colno[newnr];\n      else\n        colnr = newnr + 1;\n      /* Update column start position if we have crossed a column */\n      while(colnr > firstcol) {\n        mat->col_end[firstcol] = jj_j;\n        firstcol++;\n      }\n      if(isNZ || ((addto != NULL) && addto[colnr])) {\n        if(isNZ)\n          value = row[newnr];\n        else\n          value = row[colnr];\n        if(isA && doscale)\n          value = scaled_mat(lp, value, rowno, colnr);\n        if(isA)\n          value = my_chsign(is_chsign(lp, rowno), value);\n#ifdef DoMatrixRounding\n        value = roundToPrecision(value, mat->epsvalue);\n        if(value == 0)\n          matz++;\n#endif\n        SET_MAT_ijA(jj_j, rowno, colnr, value);\n        jj_j++;\n        /* Update last column start position */\n        mat->col_end[firstcol] = jj_j;\n        firstcol++;\n      }\n    }\n\n    /* Make sure we update tail empty column offsets */\n    while(firstcol <= mat->columns) {\n      mat->col_end[firstcol] = jj_j;\n      firstcol++;\n    }\n    jj_j = 0;\n  }\n\n  /* Start from the top of the first non-zero column of the new row */\n  elmnr = orignr + jj_j;\n  if(jj <= elmnr) {\n    if(isNZ)\n      newnr = 0;\n    else\n      newnr = firstcol - 1;\n    j = jj - mat->col_end[firstcol-1];\n    colnr = firstcol;\n    while((jj < elmnr) || (newnr < count)) {\n\n      /* Update column start position if we have crossed a column */\n      while(colnr > firstcol) {\n        mat->col_end[firstcol] = kk;\n        firstcol++;\n      }\n\n      /* See if we have a row equal to or greater than the target row */\n      jj_j = jj - j;\n      if(jj < elmnr) {\n        rownr = COL_MAT_ROWNR(jj);\n        colnr = COL_MAT_COLNR(jj);\n      }\n      else {\n        rownr = rowno;\n        if(!isNZ)                              /* KE added this conditional on 13.9.2006 */\n          colnr = firstcol + 1;\n        else\n          colnr = mat->columns + 1;\n      }\n\n      if(isNZ) {\n        if(newnr < count)\n          kk = colno[newnr];\n        else\n          kk = mat->columns + 1;\n      }\n      else\n        kk = newnr + 1;\n\n      /* Test if there is an available new item ... */\n      if((isNZ && (kk > colnr)) ||                    /* If this is not the case */\n         (!isNZ && ((kk > colnr) || (!addto[kk])))) {\n        /* DELETE if there is an existing value */\n        if(!isNZ && (kk <= colnr))\n          newnr++;\n        if(rownr == rowno) {\n          kk = jj_j;\n          j++;\n          jj++;\n          continue;\n        }\n        /* KEEP otherwise and move entry up */\n        if(!isNZ && (colnr > kk)) {\n          colnr = kk;\n          kk = jj_j;\n          continue;\n        }\n      }\n      else if((colnr > kk) ||                         /* Existing column index > new => INSERT */\n              ((colnr == kk) && (rownr >= rowno)) ) { /* Same column index, existing row >= target row => INSERT/REPLACE */\n\n        if(isNZ)\n          value = row[newnr];\n        else\n          value = row[newnr+1];\n        newnr++;\n        if(isA && doscale)\n          value = scaled_mat(lp, value, rowno, kk);\n        if(isA)\n          value = my_chsign(is_chsign(lp, rowno), value);\n#ifdef DoMatrixRounding\n        value = roundToPrecision(value, mat->epsvalue);\n        if(value == 0)\n          matz++;\n#endif\n        SET_MAT_ijA(jj_j, rowno, kk, value);\n\n        /* Adjust if we have inserted an element */\n        if((colnr > kk) || (rownr > rowno)) {\n          j--;\n          jj--;\n        }\n        colnr = kk;\n        kk = jj_j;\n        jj++;\n        continue;\n      }\n\n      /* Shift the matrix element up by the active difference */\n      if(jj_j != jj) {\n        COL_MAT_COPY(jj_j, jj);\n      }\n      kk = jj_j;\n      jj++;\n\n    }\n\n    /* Update pending / incomplete column start position */\n    while(colnr > firstcol) {\n      mat->col_end[firstcol] = kk;\n      firstcol++;\n    }\n\n    /* Make sure we update tail column offsets */\n    jj_j = jj - j;\n    while(firstcol <= mat->columns) {\n      mat->col_end[firstcol] = jj_j;\n      firstcol++;\n    }\n  }\n\n  /* Compact in the case that we added zeros and set flag for row index update */\n  if(matz > 0)\n    mat_zerocompact(mat);\n  mat->row_end_valid = FALSE;\n\nDone:\n  if(saved != 0)\n    row[0] = saved;\n  FREE(addto);\n  return( (MYBOOL) (newnr > 0) );\n\n}\n\n#else\n\nSTATIC MYBOOL mat_setrow(MATrec *mat, int rowno, int count, REAL *row, int *colno, MYBOOL doscale, MYBOOL checkrowmode)\n{\n  lprec   *lp = mat->lp;\n  int     delta, delta1;\n  int k, i, ii, j, jj_j, lendense,\n          origidx = 0, newidx, orignz, newnz,\n          rownr, colnr, colnr1;\n  MYBOOL  isA, isNZ;\n  REAL    value = 0.0;\n\n  /* Check if we are in row order mode and should add as column instead;\n     the matrix will be transposed at a later stage */\n  if(checkrowmode && mat->is_roworder)\n    return( mat_setcol(mat, rowno, count, row, colno, doscale, FALSE) );\n\n  /* Do initialization and validation */\n  if(!mat_validate(mat))\n    return( FALSE );\n  isA = (MYBOOL) (mat == lp->matA);\n  if(doscale && isA && !lp->scaling_used)\n    doscale = FALSE;\n  isNZ = (MYBOOL) (colno != NULL);\n  lendense = (mat->is_roworder ? lp->rows : lp->columns);\n  if((count < 0) || (count > lendense))\n    return( FALSE );\n  colnr1 = lendense + 1;\n\n  /* Capture OF definition in row mode */\n  if(isA && mat->is_roworder) {\n    lp->orig_obj[rowno] = 0;\n    if((count > 0) && (colno[0] == 0)) {\n      value = row[0];\n      if(doscale)\n        value = scaled_mat(lp, value, 0, rowno);\n      value = my_chsign(is_maxim(lp), value);\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      lp->orig_obj[rowno] = value;\n      if(isNZ) {\n        colno++;\n        row++;\n        count--;\n      }\n    }\n    else {\n      lp->orig_obj[rowno] = 0;\n      value = 0;\n    }\n  }\n\n  /* Make local working data copies */\n  if(!isNZ) {\n    REAL *tmprow = NULL;\n    if(!allocINT(lp, &colno, lendense+1, FALSE))\n      return( FALSE );\n    newnz = 0;\n    for(i = 1; i <= lendense; i++)\n      if((value = row[i]) != 0) {\n        if((tmprow == NULL) && !allocREAL(lp, &tmprow, lendense-i+1, FALSE)) {\n          FREE(colno);\n          return( FALSE );\n        }\n        tmprow[newnz] = value;\n        colno[newnz++] = i;\n      }\n    count = newnz;\n    row = tmprow;\n  }\n  else {\n    int *tmpcolno = NULL;\n    if(!allocINT(lp, &tmpcolno, lendense, FALSE))\n      return( FALSE );\n    newnz = count;\n    MEMCOPY(tmpcolno, colno, newnz);\n    colno = tmpcolno;\n    if(newnz > 1)\n      sortREALByINT(row, (int *) colno, newnz, 0, TRUE);\n    if((newnz > 0) && ((colno[0] < 0) || (colno[newnz-1] > lendense))) {\n      FREE(colno);\n      newnz = 0;\n      return( FALSE );\n    }\n  }\n\n  /* Make sure we have enough matrix space */\n  i  = mat->row_end[rowno-1];\n  ii = mat->row_end[rowno];\n  delta1 = delta = count - (ii-i);\n  colnr1 = (newnz > 0 ? colno[0] : lendense+1);\n\n  /* Pack initial entries if existing row data has a lower column\n     start index than the first index of the new vector */\n  orignz = mat_nonzeros(mat);\n  j = (i >= orignz ? colnr1 : ROW_MAT_COLNR(i));\n\n  /* Index of the column-top insertion point for the first new value */\n  origidx = mat->col_end[colnr1-1];\n  colnr = (origidx >= orignz ? colnr1 : COL_MAT_COLNR(origidx));\n\n  if(j < colnr) {\n    origidx = newidx = mat->col_end[j-1];\n    for( ; j < colnr; j++) {\n      /* Shift entries in current column */\n      jj_j = mat->col_end[j];\n      for( ; origidx < jj_j; origidx++) {\n        if(COL_MAT_ROWNR(origidx) != rowno) {\n          if(newidx != origidx) {\n            COL_MAT_COPY(newidx, origidx);\n          }\n          newidx++;\n        }\n      }\n      /* Update next column start index */\n      mat->col_end[j] = newidx;\n    }\n    delta = newidx - origidx;  /* The first stage element shrinkage count */\n  }\n  else {\n    delta = 0;\n    newidx = origidx;\n  }\n\n  /* Make sure we have sufficient space for any additional entries and move existing data down;\n     this ensures that we only have to relocate matrix elements up in the next stage */\n  jj_j = MAX(0, (int) newnz + delta);\n\n  j = !((orignz == lendense) && (newnz == orignz) && (delta1 == 0)) && (jj_j > 0) && (orignz > origidx);\n\n  if ((j) && (jj_j > delta1))\n    delta1 = jj_j;\n\n  if((delta1 > 0) && (mat_nz_unused(mat) <= delta1) && !inc_mat_space(mat, delta1)) {\n    newnz = 0;\n    goto Done;\n  }\n\n  if(j) {\n    COL_MAT_MOVE(origidx+jj_j, origidx, orignz-origidx);\n    origidx += jj_j;\n    orignz += jj_j;\n  }\n\n  /* Start from the top of the first non-zero column of the new row */\n  newnz = 0;\n  j = origidx - mat->col_end[colnr1-1];\n  k = colnr1;  /* Last column for which col_end is valid/updated */\n  while((colnr1 <= lendense) || (origidx < orignz)) {\n\n    /* Get the column index of the active update item */\n    if(newnz < count)\n      colnr1 = colno[newnz];\n    else\n      colnr1 = lendense + 1;\n\n    /* Get coordinate of active existing matrix entries */\n    if(origidx < orignz) {\n      rownr = COL_MAT_ROWNR(origidx);\n      colnr = COL_MAT_COLNR(origidx);\n    }\n    else {\n      if(colnr1 > lendense)\n        break;\n      rownr = rowno;\n      colnr = lendense + 1;\n    }\n\n    /* Update column start position if we just crossed into a column */\n    jj_j = origidx - j;\n    i = MIN(colnr, colnr1);\n    for(; k < i; k++)\n      mat->col_end[k] = jj_j;\n\n    /* Test if there is an available new item ... */\n    if(colnr1 > colnr) {             /* If this is not the case */\n      /* DELETE if there is an existing value */\n      if(rownr == rowno) {\nForceDelete:\n        j++;\n        delta--;\n        origidx++;\n        continue;\n      }\n    }\n    else if((colnr > colnr1) ||                         /* Existing column index > new => INSERT */\n            ((colnr == colnr1) && (rownr >= rowno)) ) { /* Same column index, existing row >= target row => INSERT/REPLACE */\n\n      value = row[newnz];\n      newnz++;\n      if(isA && doscale)\n        value = scaled_mat(lp, value, rowno, colnr1);\n      if(isA)\n        value = my_chsign(is_chsign(lp, rowno), value);\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n      if(value == 0) {\n        if((colnr > colnr1) || (rownr > rowno))\n        ;\n        else\n          goto ForceDelete;\n      }\n#endif\n      SET_MAT_ijA(jj_j, rowno, colnr1, value);\n\n      /* Adjust if we have inserted an element */\n      if((colnr > colnr1) || (rownr > rowno)) {\n        j--;\n        origidx--;\n        jj_j++;\n        delta++;\n      }\n      origidx++;\n      continue;\n    }\n\n    /* Shift the matrix element up by the active difference */\n    if(jj_j != origidx) {\n      COL_MAT_COPY(jj_j, origidx);\n    }\n    origidx++;\n  }\n\n  /* Update pending / incomplete column start position */\n  jj_j = origidx - j;\n  for(; k <= lendense; k++)\n    mat->col_end[k] = jj_j;\n  mat->row_end_valid = FALSE;\n\nDone:\n  if(!isNZ)\n    FREE(row);\n  FREE(colno);\n  return( (MYBOOL) (newnz > 0) );\n\n} /* mat_setrow */\n#endif\n\nSTATIC int mat_appendrow(MATrec *mat, int count, REAL *row, int *colno, REAL mult, MYBOOL checkrowmode)\n{\n  int    i, j, jj = 0, stcol, elmnr, orignr, newnr, firstcol;\n  MYBOOL *addto = NULL, isA, isNZ;\n  REAL   value, saved = 0;\n  lprec  *lp = mat->lp;\n\n  /* Check if we are in row order mode and should add as column instead;\n     the matrix will be transposed at a later stage */\n  if(checkrowmode && mat->is_roworder)\n    return( mat_appendcol(mat, count, row, colno, mult, FALSE) );\n\n  /* Do initialization and validation */\n  isA = (MYBOOL) (mat == lp->matA);\n  isNZ = (MYBOOL) (colno != NULL);\n  if(isNZ && (count > 0)) {\n    if(count > 1)\n      sortREALByINT(row, colno, count, 0, TRUE);\n    if((colno[0] < 1) || (colno[count-1] > mat->columns))\n      return( 0 );\n  }\n  /* else if((row != NULL) && !mat->is_roworder) */\n  else if(!isNZ && (row != NULL) && !mat->is_roworder)\n    row[0] = 0;\n\n  /* Capture OF definition in row mode */\n  if(isA && mat->is_roworder) {\n    if(isNZ && (colno[0] == 0)) {\n      value = row[0];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      value = scaled_mat(lp, value, 0, lp->columns);\n      value = my_chsign(is_maxim(lp), value);\n      lp->orig_obj[lp->columns] = value;\n      count--;\n      row++;\n      colno++;\n    }\n    else if(!isNZ && (row != NULL) && (row[0] != 0)) {\n      value = saved = row[0];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      value = scaled_mat(lp, value, 0, lp->columns);\n      value = my_chsign(is_maxim(lp), value);\n      lp->orig_obj[lp->columns] = value;\n      row[0] = 0;\n    }\n    else\n      lp->orig_obj[lp->columns] = 0;\n  }\n\n  /* Optionally tally and map the new non-zero values */\n  firstcol = mat->columns + 1;\n  if(isNZ) {\n    newnr = count;\n    if(newnr) {\n      firstcol = colno[0];\n      jj = colno[newnr - 1];\n    }\n  }\n  else {\n    newnr = 0;\n    if(row != NULL) {\n      if(!allocMYBOOL(lp, &addto, mat->columns + 1, TRUE)) {\n        return( newnr );\n      }\n      for(i = mat->columns; i >= 1; i--) {\n        if(fabs(row[i]) > mat->epsvalue) {\n          addto[i] = TRUE;\n          firstcol = i;\n          newnr++;\n        }\n      }\n    }\n  }\n\n  /* Make sure we have sufficient space */\n  if(!inc_mat_space(mat, newnr)) {\n    newnr = 0;\n    goto Done;\n  }\n\n  /* Insert the non-zero constraint values */\n  orignr = mat_nonzeros(mat) - 1;\n  elmnr = orignr + newnr;\n\n  for(j = mat->columns; j >= firstcol; j--) {\n    stcol = mat->col_end[j] - 1;\n    mat->col_end[j] = elmnr + 1;\n\n   /* Add a new non-zero entry */\n    if(((isNZ) && (j == jj)) || ((addto != NULL) && (addto[j]))) {\n      newnr--;\n      if(isNZ) {\n        value = row[newnr];\n        if(newnr)\n          jj = colno[newnr - 1];\n        else\n          jj = 0;\n      }\n      else\n        value = row[j];\n#ifdef DoMatrixRounding\n      value = roundToPrecision(value, mat->epsvalue);\n#endif\n      value *= mult;\n      if(isA) {\n        if(mat->is_roworder)\n          value = my_chsign(is_chsign(lp, j), value);\n        value = scaled_mat(lp, value, mat->rows, j);\n      }\n      SET_MAT_ijA(elmnr, mat->rows, j, value);\n      elmnr--;\n    }\n\n   /* Shift previous column entries down */\n    i = stcol - mat->col_end[j-1] + 1;\n    if(i > 0) {\n      orignr -= i;\n      elmnr  -= i;\n      COL_MAT_MOVE(elmnr+1, orignr+1, i);\n    }\n  }\n\nDone:\n  if(saved != 0)\n    row[0] = saved;\n  FREE(addto);\n\n  return( newnr );\n\n}\n\nSTATIC int mat_appendcol(MATrec *mat, int count, REAL *column, int *rowno, REAL mult, MYBOOL checkrowmode)\n{\n  int     i, row, elmnr, lastnr;\n  REAL    value;\n  MYBOOL  isA, isNZ;\n  lprec   *lp = mat->lp;\n\n  /* Check if we are in row order mode and should add as row instead;\n     the matrix will be transposed at a later stage */\n  if(checkrowmode && mat->is_roworder)\n    return( mat_appendrow(mat, count, column, rowno, mult, FALSE) );\n\n  /* Make sure we have enough space */\n/*\n  if(!inc_mat_space(mat, mat->rows+1))\n    return( 0 );\n*/\n  if(column == NULL)\n    i = 0;\n  else if(rowno != NULL)\n    i = count;\n  else {\n    int nrows = mat->rows;\n\n    elmnr = 0;\n    for(i = 1; i <= nrows; i++)\n      if(column[i] != 0)\n        elmnr++;\n    i = elmnr;\n  }\n  if((mat_nz_unused(mat) <= i) && !inc_mat_space(mat, i))\n    return( 0 );\n\n  /* Do initialization and validation */\n  isA = (MYBOOL) (mat == lp->matA);\n  isNZ = (MYBOOL) (column == NULL || rowno != NULL);\n  if(isNZ && (count > 0)) {\n    if(count > 1)\n      sortREALByINT(column, rowno, count, 0, TRUE);\n    if((rowno[0] < 0))\n      return( 0 );\n  }\n  if(rowno != NULL)\n    count--;\n\n  /* Append sparse regular constraint values */\n  elmnr = mat->col_end[mat->columns - 1];\n  if(column != NULL) {\n    row = -1;\n    for(i = ((isNZ || !mat->is_roworder) ? 0 : 1); i <= count ; i++) {\n      value = column[i];\n      if(fabs(value) > mat->epsvalue) {\n        if(isNZ) {\n          lastnr = row;\n          row = rowno[i];\n          /* Check if we have come to the Lagrangean constraints */\n          if(row > mat->rows)\n            break;\n          if(row <= lastnr)\n            return( -1 );\n        }\n        else\n          row = i;\n#ifdef DoMatrixRounding\n        value = roundToPrecision(value, mat->epsvalue);\n#endif\n        if(mat->is_roworder)\n          value *= mult;\n        else if(isA) {\n          value = my_chsign(is_chsign(lp, row), value);\n          value = scaled_mat(lp, value, row, mat->columns);\n          if(!mat->is_roworder && (row == 0)) {\n            lp->orig_obj[mat->columns] = value;\n            continue;\n          }\n        }\n\n       /* Store the item and update counters */\n        SET_MAT_ijA(elmnr, row, mat->columns, value);\n        elmnr++;\n      }\n    }\n\n   /* Fill dense Lagrangean constraints */\n    if(get_Lrows(lp) > 0)\n      mat_appendcol(lp->matL, get_Lrows(lp), column+mat->rows, NULL, mult, checkrowmode);\n\n  }\n\n /* Set end of data */\n  mat->col_end[mat->columns] = elmnr;\n\n  return( mat->col_end[mat->columns] - mat->col_end[mat->columns-1] );\n}\n\nSTATIC int mat_checkcounts(MATrec *mat, int *rownum, int *colnum, MYBOOL freeonexit)\n{\n  int i, j, n;\n  int *rownr;\n\n  if(rownum == NULL)\n    allocINT(mat->lp, &rownum, mat->rows + 1, TRUE);\n  if(colnum == NULL)\n    allocINT(mat->lp, &colnum, mat->columns + 1, TRUE);\n\n  for(i = 1 ; i <= mat->columns; i++) {\n    j = mat->col_end[i - 1];\n    n = mat->col_end[i];\n    rownr = &COL_MAT_ROWNR(j);\n    for(; j < n;\n        j++, rownr += matRowColStep) {\n      colnum[i]++;\n      rownum[*rownr]++;\n    }\n  }\n\n  n = 0;\n  if((mat->lp->do_presolve != PRESOLVE_NONE) &&\n     (mat->lp->spx_trace || (mat->lp->verbose > NORMAL))) {\n    for(j = 1; j <= mat->columns; j++)\n      if(colnum[j] == 0) {\n        n++;\n        report(mat->lp, FULL, \"mat_checkcounts: Variable %s is not used in any constraints\\n\",\n                              get_col_name(mat->lp, j));\n      }\n    for(i = 0; i <= mat->rows; i++)\n      if(rownum[i] == 0) {\n        n++;\n        report(mat->lp, FULL, \"mat_checkcounts: Constraint %s empty\\n\",\n                              get_row_name(mat->lp, i));\n      }\n  }\n\n  if(freeonexit) {\n    FREE(rownum);\n    FREE(colnum);\n  }\n\n  return( n );\n\n}\n\nSTATIC MYBOOL mat_validate(MATrec *mat)\n/* Routine to make sure that row mapping arrays are valid */\n{\n  int     i, j, je, *rownum;\n  int     *rownr, *colnr;\n\n  if(!mat->row_end_valid) {\n\n    MEMCLEAR(mat->row_end, mat->rows + 1);\n    allocINT(mat->lp, &rownum, mat->rows + 1, TRUE);\n\n    /* First tally row counts and then cumulate them */\n    j = mat_nonzeros(mat);\n    rownr = &COL_MAT_ROWNR(0);\n    for(i = 0; i < j; i++, rownr += matRowColStep)\n      mat->row_end[*rownr]++;\n    for(i = 1; i <= mat->rows; i++)\n      mat->row_end[i] += mat->row_end[i - 1];\n\n    /* Calculate the column index for every non-zero */\n    for(i = 1; i <= mat->columns; i++) {\n      j = mat->col_end[i - 1];\n      je = mat->col_end[i];\n      rownr = &COL_MAT_ROWNR(j);\n      colnr = &COL_MAT_COLNR(j);\n      for(; j < je; j++, rownr += matRowColStep, colnr += matRowColStep) {\n#ifdef Paranoia\n        if(/*(*colnr < 0) || (*colnr > mat->columns) || (Normally violated in primal phase 1) */\n           (*rownr < 0) || (*rownr > mat->rows)) {\n          report(mat->lp, SEVERE, \"mat_validate: Matrix value storage error row %d [0..%d], column %d [1..%d]\\n\",\n                                  *rownr, mat->rows, *colnr, mat->columns);\n          mat->lp->spx_status = UNKNOWNERROR;\n          return(FALSE);\n        }\n#endif\n        *colnr = i;\n        if(*rownr == 0)\n          mat_set_rowmap(mat, rownum[*rownr],\n                              *rownr, i, j);\n        else\n          mat_set_rowmap(mat, mat->row_end[*rownr - 1] + rownum[*rownr],\n                              *rownr, i, j);\n        rownum[*rownr]++;\n      }\n    }\n\n    FREE(rownum);\n    mat->row_end_valid = TRUE;\n  }\n\n  if(mat == mat->lp->matA)\n    mat->lp->model_is_valid = TRUE;\n  return( TRUE );\n}\n\nMYBOOL mat_get_data(lprec *lp, int matindex, MYBOOL isrow, int **rownr, int **colnr, REAL **value)\n{\n  MATrec *mat = lp->matA;\n\n#if MatrixRowAccess == RAM_Index\n  if(isrow)\n    matindex = mat->row_mat[matindex];\n  if(rownr != NULL)\n    *rownr = &COL_MAT_ROWNR(matindex);\n  if(colnr != NULL)\n    *colnr = &COL_MAT_COLNR(matindex);\n  if(value != NULL)\n    *value = &COL_MAT_VALUE(matindex);\n\n#else\n  if(isrow) {\n    if(rownr != NULL)\n      *rownr = &ROW_MAT_ROWNR(matindex);\n    if(colnr != NULL)\n      *colnr = &ROW_MAT_COLNR(matindex);\n    if(value != NULL)\n      *value = &ROW_MAT_VALUE(matindex);\n  }\n  else {\n    if(rownr != NULL)\n      *rownr = &COL_MAT_ROWNR(matindex);\n    if(colnr != NULL)\n      *colnr = &COL_MAT_COLNR(matindex);\n    if(value != NULL)\n      *value = &COL_MAT_VALUE(matindex);\n  }\n\n#endif\n\n  return( TRUE );\n}\n\n\nMYBOOL mat_set_rowmap(MATrec *mat, int row_mat_index, int rownr, int colnr, int col_mat_index)\n{\n#if MatrixRowAccess == RAM_Index\n  (void)rownr;\n  (void)colnr;\n  mat->row_mat[row_mat_index] = col_mat_index;\n\n#elif MatrixColAccess==CAM_Record\n  mat->row_mat[row_mat_index].rownr = rownr;\n  mat->row_mat[row_mat_index].colnr = colnr;\n  mat->row_mat[row_mat_index].value = COL_MAT_VALUE(col_mat_index);\n\n#else /* if MatrixColAccess==CAM_Vector */\n  mat->row_mat_rownr[row_mat_index] = rownr;\n  mat->row_mat_colnr[row_mat_index] = colnr;\n  mat->row_mat_value[row_mat_index] = COL_MAT_VALUE(col_mat_index);\n\n#endif\n\n  return( TRUE );\n}\n\n/* Implement combined binary/linear sub-search for matrix look-up */\nint mat_findelm(MATrec *mat, int row, int column)\n{\n  int low, high, mid, item;\n\n#if 0\n  if(mat->row_end_valid && (row > 0) &&\n     (ROW_MAT_COLNR(mat->row_mat[(low = mat->row_end[row-1])]) == column))\n    return(low);\n#endif\n\n  if((column < 1) || (column > mat->columns)) {\n    report(mat->lp, IMPORTANT, \"mat_findelm: Column %d out of range\\n\", column);\n    return( -1 );\n  }\n  if((row < 0) || (row > mat->rows)) {\n    report(mat->lp, IMPORTANT, \"mat_findelm: Row %d out of range\\n\", row);\n    return( -1 );\n  }\n\n  low = mat->col_end[column - 1];\n  high = mat->col_end[column] - 1;\n  if(low > high)\n    return( -2 );\n\n /* Do binary search logic */\n  mid = (low+high) / 2;\n  item = COL_MAT_ROWNR(mid);\n  while(high - low > LINEARSEARCH) {\n    if(item < row) {\n      low = mid + 1;\n      mid = (low+high) / 2;\n      item = COL_MAT_ROWNR(mid);\n    }\n    else if(item > row) {\n      high = mid - 1;\n      mid = (low+high) / 2;\n      item = COL_MAT_ROWNR(mid);\n    }\n    else {\n      low = mid;\n      high = mid;\n    }\n  }\n\n /* Do linear scan search logic */\n  if((high > low) && (high - low <= LINEARSEARCH)) {\n    item = COL_MAT_ROWNR(low);\n    while((low < high) && (item < row)) {\n      low++;\n      item = COL_MAT_ROWNR(low);\n    }\n    if(item == row)\n      high = low;\n  }\n\n  if((low == high) && (row == item))\n    return( low );\n  else\n    return( -2 );\n}\n\nint mat_findins(MATrec *mat, int row, int column, int *insertpos, MYBOOL validate)\n{\n  int low, high, mid, item, exitvalue, insvalue;\n\n#if 0\n  if(mat->row_end_valid && (row > 0) &&\n     (ROW_MAT_COLNR(mat->row_mat[(low = mat->row_end[row-1])]) == column)) {\n    insvalue = low;\n    exitvalue = low;\n    goto Done;\n  }\n#endif\n\n  insvalue = -1;\n\n  if((column < 1) || (column > mat->columns)) {\n    if((column > 0) && !validate) {\n      insvalue = mat->col_end[mat->columns];\n      exitvalue = -2;\n      goto Done;\n    }\n    report(mat->lp, IMPORTANT, \"mat_findins: Column %d out of range\\n\", column);\n    exitvalue = -1;\n    goto Done;\n  }\n  if((row < 0) || (row > mat->rows)) {\n    if((row >= 0) && !validate) {\n      insvalue = mat->col_end[column];\n      exitvalue = -2;\n      goto Done;\n    }\n    report(mat->lp, IMPORTANT, \"mat_findins: Row %d out of range\\n\", row);\n    exitvalue = -1;\n    goto Done;\n  }\n\n  low = mat->col_end[column - 1];\n  insvalue = low;\n  high = mat->col_end[column] - 1;\n  if(low > high) {\n    exitvalue = -2;\n    goto Done;\n  }\n\n /* Do binary search logic */\n  mid = (low+high) / 2;\n  item = COL_MAT_ROWNR(mid);\n  while(high - low > LINEARSEARCH) {\n    if(item < row) {\n      low = mid + 1;\n      mid = (low+high) / 2;\n      item = COL_MAT_ROWNR(mid);\n    }\n    else if(item > row) {\n      high = mid - 1;\n      mid = (low+high) / 2;\n      item = COL_MAT_ROWNR(mid);\n    }\n    else {\n      low = mid;\n      high = mid;\n    }\n  }\n\n /* Do linear scan search logic */\n  if((high > low) && (high - low <= LINEARSEARCH)) {\n    item = COL_MAT_ROWNR(low);\n    while((low < high) && (item < row)) {\n      low++;\n      item = COL_MAT_ROWNR(low);\n    }\n    if(item == row)\n      high = low;\n  }\n\n  insvalue = low;\n  if((low == high) && (row == item))\n    exitvalue = low;\n  else {\n    if((low < mat->col_end[column]) && (COL_MAT_ROWNR(low) < row))\n      insvalue++;\n    exitvalue = -2;\n  }\n\nDone:\n  if(insertpos != NULL)\n    (*insertpos) = insvalue;\n  return( exitvalue );\n}\n\nSTATIC REAL mat_getitem(MATrec *mat, int row, int column)\n{\n  int elmnr;\n\n#ifdef DirectOverrideOF\n  if((row == 0) && (mat == mat->lp->matA) && (mat->lp->OF_override != NULL))\n    return( mat->lp->OF_override[column] );\n  else\n#endif\n  {\n    elmnr = mat_findelm(mat, row, column);\n    if(elmnr >= 0)\n      return( COL_MAT_VALUE(elmnr) );\n    else\n      return( 0 );\n  }\n}\n\nSTATIC MYBOOL mat_additem(MATrec *mat, int row, int column, REAL delta)\n{\n  int elmnr;\n\n#ifdef DirectOverrideOF\n  if((row == 0) && (mat == mat->lp->matA) && (mat->lp->OF_override != NULL))\n    return( mat->lp->OF_override[column] );\n  else\n#endif\n  {\n    elmnr = mat_findelm(mat, row, column);\n    if(elmnr >= 0) {\n      COL_MAT_VALUE(elmnr) += delta;\n      return( TRUE );\n    }\n    else {\n      mat_setitem(mat, row, column, delta);\n      return( FALSE );\n    }\n  }\n}\n\nSTATIC MYBOOL mat_setitem(MATrec *mat, int row, int column, REAL value)\n{\n  return( mat_setvalue(mat, row, column, value, FALSE) );\n}\n\nSTATIC void mat_multrow(MATrec *mat, int row_nr, REAL mult)\n{\n  int i, k1, k2;\n\n#if 0\n  if(row_nr == 0) {\n    k2 = mat->col_end[0];\n    for(i = 1; i <= mat->columns; i++) {\n      k1 = k2;\n      k2 = mat->col_end[i];\n      if((k1 < k2) && (COL_MAT_ROWNR(k1) == row_nr))\n        COL_MAT_VALUE(k1) *= mult;\n    }\n  }\n  else if(mat_validate(mat)) {\n    if(row_nr == 0)\n      k1 = 0;\n    else\n#else\n  if(mat_validate(mat)) {\n    if(row_nr == 0)\n      k1 = 0;\n    else\n#endif\n    k1 = mat->row_end[row_nr-1];\n    k2 = mat->row_end[row_nr];\n    for(i = k1; i < k2; i++)\n      ROW_MAT_VALUE(i) *= mult;\n  }\n}\n\nSTATIC void mat_multcol(MATrec *mat, int col_nr, REAL mult, MYBOOL DoObj)\n{\n  int    i, ie;\n  MYBOOL isA;\n\n#ifdef Paranoia\n  if((col_nr < 1) || (col_nr > mat->columns)) {\n    report(mat->lp, IMPORTANT, \"mult_column: Column %d out of range\\n\", col_nr);\n    return;\n  }\n#endif\n  if(mult == 1.0)\n    return;\n\n  isA = (MYBOOL) (mat == mat->lp->matA);\n\n  ie = mat->col_end[col_nr];\n  for(i = mat->col_end[col_nr - 1]; i < ie; i++)\n    COL_MAT_VALUE(i) *= mult;\n  if(isA) {\n    if(DoObj)\n      mat->lp->orig_obj[col_nr] *= mult;\n    if(get_Lrows(mat->lp) > 0)\n      mat_multcol(mat->lp->matL, col_nr, mult, DoObj);\n  }\n}\n\nSTATIC void mat_multadd(MATrec *mat, REAL *lhsvector, int varnr, REAL mult)\n{\n  int               colnr;\n  int      ib, ie, *matRownr;\n  REAL     *matValue;\n\n  /* Handle case of a slack variable */\n  if(varnr <= mat->lp->rows) {\n    lhsvector[varnr] += mult;\n    return;\n  }\n\n  /* Do operation on the objective */\n  if(mat->lp->matA == mat)\n    lhsvector[0] += get_OF_active(mat->lp, varnr, mult);\n\n  /* Scan the constraint matrix target columns */\n  colnr = varnr - mat->lp->rows;\n  ib = mat->col_end[colnr - 1];\n  ie = mat->col_end[colnr];\n  if(ib < ie) {\n\n    /* Initialize pointers */\n    matRownr = &COL_MAT_ROWNR(ib);\n    matValue = &COL_MAT_VALUE(ib);\n\n    /* Then loop over all regular rows */\n    for(; ib < ie;\n        ib++, matValue += matValueStep, matRownr += matRowColStep) {\n      lhsvector[*matRownr] += mult * (*matValue);\n    }\n  }\n\n}\n\nSTATIC MYBOOL mat_setvalue(MATrec *mat, int Row, int Column, REAL Value, MYBOOL doscale)\n{\n  int    elmnr, lastelm, i, RowA = Row, ColumnA = Column;\n  MYBOOL isA;\n\n  /* This function is inefficient if used to add new matrix entries in\n     other places than at the end of the matrix. OK for replacing existing\n     a non-zero value with another non-zero value */\n  isA = (MYBOOL) (mat == mat->lp->matA);\n  if(mat->is_roworder)\n    swapINT(&Row, &Column);\n\n  /* Set small numbers to zero */\n  if(fabs(Value) < mat->epsvalue)\n    Value = 0;\n#ifdef DoMatrixRounding\n  else\n    Value = roundToPrecision(Value, mat->epsvalue);\n#endif\n\n  /* Check if we need to update column space */\n  if(Column > mat->columns) {\n    if(isA)\n      inc_col_space(mat->lp, ColumnA - mat->columns);\n    else\n      inc_matcol_space(mat, Column - mat->columns);\n  }\n\n  /* Find out if we already have such an entry, or return insertion point */\n  i = mat_findins(mat, Row, Column, &elmnr, FALSE);\n  if(i == -1)\n    return(FALSE);\n\n  if(isA)\n    set_action(&mat->lp->spx_action, ACTION_REBASE | ACTION_RECOMPUTE | ACTION_REINVERT);\n\n  if(i >= 0) {\n    /* there is an existing entry */\n    if(fabs(Value) > mat->epsvalue) { /* we replace it by something non-zero */\n      if(isA) {\n        Value = my_chsign(is_chsign(mat->lp, RowA), Value);\n        if(doscale && mat->lp->scaling_used)\n          Value = scaled_mat(mat->lp, Value, RowA, ColumnA);\n      }\n      COL_MAT_VALUE(elmnr) = Value;\n    }\n    else { /* setting existing non-zero entry to zero. Remove the entry */\n      /* This might remove an entire column, or leave just a bound. No\n          nice solution for that yet */\n\n      /* Shift up tail end of the matrix */\n      lastelm = mat_nonzeros(mat);\n#if 0\n      for(i = elmnr; i < lastelm ; i++) {\n        COL_MAT_COPY(i, i + 1);\n      }\n#else\n      lastelm -= elmnr;\n      COL_MAT_MOVE(elmnr, elmnr + 1, lastelm);\n#endif\n      for(i = Column; i <= mat->columns; i++)\n        mat->col_end[i]--;\n\n      mat->row_end_valid = FALSE;\n    }\n  }\n  else if(fabs(Value) > mat->epsvalue) {\n    /* no existing entry. make new one only if not nearly zero */\n    /* check if more space is needed for matrix */\n    if(!inc_mat_space(mat, 1))\n      return(FALSE);\n\n    if(Column > mat->columns) {\n      i = mat->columns + 1;\n      if(isA)\n        shift_coldata(mat->lp, i, ColumnA - mat->columns, NULL);\n      else\n        mat_shiftcols(mat, &i, Column - mat->columns, NULL);\n    }\n\n    /* Shift down tail end of the matrix by one */\n    lastelm = mat_nonzeros(mat);\n#if 1 /* Does compiler optimization work better here? */\n    for(i = lastelm; i > elmnr ; i--) {\n      COL_MAT_COPY(i, i - 1);\n    }\n#else\n    lastelm -= elmnr - 1;\n    COL_MAT_MOVE(elmnr + 1, elmnr, lastelm);\n#endif\n\n    /* Set new element */\n    if(isA) {\n      Value = my_chsign(is_chsign(mat->lp, RowA), Value);\n      if(doscale)\n        Value = scaled_mat(mat->lp, Value, RowA, ColumnA);\n    }\n    SET_MAT_ijA(elmnr, Row, Column, Value);\n\n    /* Update column indexes */\n    for(i = Column; i <= mat->columns; i++)\n      mat->col_end[i]++;\n\n    mat->row_end_valid = FALSE;\n  }\n\n  if(isA && (mat->lp->var_is_free != NULL) && (mat->lp->var_is_free[ColumnA] > 0))\n    return( mat_setvalue(mat, RowA, mat->lp->var_is_free[ColumnA], -Value, doscale) );\n  return(TRUE);\n}\n\nSTATIC MYBOOL mat_appendvalue(MATrec *mat, int Row, REAL Value)\n{\n  int *elmnr, Column = mat->columns;\n\n  /* Set small numbers to zero */\n  if(fabs(Value) < mat->epsvalue)\n    Value = 0;\n#ifdef DoMatrixRounding\n  else\n    Value = roundToPrecision(Value, mat->epsvalue);\n#endif\n\n  /* Check if more space is needed for matrix */\n  if(!inc_mat_space(mat, 1))\n    return(FALSE);\n\n#ifdef Paranoia\n  /* Check valid indeces */\n  if((Row < 0) || (Row > mat->rows)) {\n    report(mat->lp, SEVERE, \"mat_appendvalue: Invalid row index %d specified\\n\", Row);\n    return(FALSE);\n  }\n#endif\n\n  /* Get insertion point and set value */\n  elmnr = mat->col_end + Column;\n  SET_MAT_ijA((*elmnr), Row, Column, Value);\n\n  /* Update column count */\n  (*elmnr)++;\n  mat->row_end_valid = FALSE;\n\n  return(TRUE);\n}\n\nSTATIC MYBOOL mat_equalRows(MATrec *mat, int baserow, int comprow)\n{\n  MYBOOL status = FALSE;\n\n  if(mat_validate(mat)) {\n    int bj1 = 0, ej1, bj2 = 0, ej2;\n\n    /* Get starting and ending positions */\n    if(baserow >= 0)\n      bj1 = mat->row_end[baserow-1];\n    ej1 = mat->row_end[baserow];\n    if(comprow >= 0)\n      bj2 = mat->row_end[comprow-1];\n    ej2 = mat->row_end[comprow];\n    /* Fail if row lengths are unequal */\n    if((ej1-bj1) != (ej2-bj2))\n      return( status );\n\n    /* Compare column index and value, element by element */\n    for(; bj1 < ej1; bj1++, bj2++) {\n      if(COL_MAT_COLNR(bj1) != COL_MAT_COLNR(bj2))\n        break;\n#if 1\n      if(fabs(get_mat_byindex(mat->lp, bj1, TRUE, FALSE)-get_mat_byindex(mat->lp, bj2, TRUE, FALSE)) > mat->lp->epsprimal)\n#else\n      if(fabs(COL_MAT_VALUE(bj1)-COL_MAT_VALUE(bj2)) > mat->lp->epsprimal)\n#endif\n        break;\n    }\n    status = (MYBOOL) (bj1 == ej1);\n  }\n  return( status );\n}\n\nSTATIC int mat_findcolumn(MATrec *mat, int matindex)\n{\n  int j;\n\n  for(j = 1; j <= mat->columns; j++) {\n    if(matindex < mat->col_end[j])\n      break;\n  }\n  return(j);\n}\n\nSTATIC int mat_expandcolumn(MATrec *mat, int colnr, REAL *column, int *nzlist, MYBOOL signedA)\n{\n  MYBOOL  isA = (MYBOOL) (mat->lp->matA == mat);\n  int     i, ie, j, nzcount = 0;\n  REAL    *matValue;\n  int     *matRownr;\n\n  signedA &= isA;\n\n  /* Retrieve a column from the user data matrix A */\n  MEMCLEAR(column, mat->rows + 1);\n  if(isA) {\n    column[0] = mat->lp->orig_obj[colnr];\n    if(signedA && is_chsign(mat->lp, 0))\n      column[0] = -column[0];\n  }\n\n  i = mat->col_end[colnr - 1];\n  ie = mat->col_end[colnr];\n  matRownr = &COL_MAT_ROWNR(i);\n  matValue = &COL_MAT_VALUE(i);\n  for(; i < ie;\n      i++, matRownr += matRowColStep, matValue += matValueStep) {\n    j = *matRownr;\n    column[j] = *matValue;\n    if(signedA && is_chsign(mat->lp, j))\n      column[j] = -column[j];\n    nzcount++;\n    if(nzlist != NULL)\n      nzlist[nzcount] = j;\n  }\n  if(nzlist != NULL)\n    nzlist[0] = nzcount;\n  return( nzcount );\n}\n\nSTATIC MYBOOL mat_computemax(MATrec *mat)\n{\n  int  *rownr = &COL_MAT_ROWNR(0),\n       *colnr = &COL_MAT_COLNR(0),\n       i = 0, ie = mat->col_end[mat->columns], ez = 0;\n  REAL *value = &COL_MAT_VALUE(0), epsmachine = mat->lp->epsmachine, absvalue;\n\n  /* Prepare arrays */\n  if(!allocREAL(mat->lp, &mat->colmax, mat->columns_alloc+1, AUTOMATIC) ||\n     !allocREAL(mat->lp, &mat->rowmax, mat->rows_alloc+1, AUTOMATIC))\n     return( FALSE );\n  MEMCLEAR(mat->colmax, mat->columns+1);\n  MEMCLEAR(mat->rowmax, mat->rows+1);\n\n  /* Obtain the row and column maxima in one sweep */\n  mat->dynrange = mat->lp->infinite;\n  for(; i < ie;\n      i++, rownr += matRowColStep, colnr += matRowColStep, value += matValueStep) {\n    absvalue = fabs(*value);\n    SETMAX(mat->colmax[*colnr], absvalue);\n    SETMAX(mat->rowmax[*rownr], absvalue);\n    SETMIN(mat->dynrange, absvalue);\n    if(absvalue < epsmachine)\n      ez++;\n  }\n\n  /* Lastly, compute the global maximum and get the dynamic range */\n  for(i = 1; i <= mat->rows; i++)\n    SETMAX(mat->rowmax[0], mat->rowmax[i]);\n  mat->infnorm = mat->colmax[0] = mat->rowmax[0];\n  if(mat->dynrange == 0) {\n    report(mat->lp, SEVERE, \"%d matrix contains zero-valued coefficients.\\n\", ez);\n    mat->dynrange = mat->lp->infinite;\n  }\n  else {\n    mat->dynrange = mat->infnorm / mat->dynrange;\n    if(ez > 0)\n      report(mat->lp, IMPORTANT, \"%d matrix coefficients below machine precision were found.\\n\", ez);\n  }\n\n  return( TRUE );\n}\n\nSTATIC MYBOOL mat_transpose(MATrec *mat)\n{\n  int     i, j, nz, k;\n  MYBOOL  status;\n\n  status = mat_validate(mat);\n  if(status) {\n\n    /* Create a column-ordered sparse element list; \"column\" index must be shifted */\n    nz = mat_nonzeros(mat);\n    if(nz > 0) {\n#if MatrixColAccess==CAM_Record\n      MATitem *newmat;\n      newmat = (MATitem *) malloc((mat->mat_alloc) * sizeof(*(mat->col_mat)));\n      j = mat->row_end[0];\n      for(i = nz-1; i >= j ; i--) {\n        k = i-j;\n        newmat[k] = mat->col_mat[mat->row_mat[i]];\n        newmat[k].row_nr = newmat[k].col_nr;\n      }\n      for(i = j-1; i >= 0 ; i--) {\n        k = nz-j+i;\n        newmat[k] = mat->col_mat[mat->row_mat[i]];\n        newmat[k].row_nr = newmat[k].col_nr;\n      }\n      swapPTR((void **) &mat->col_mat, (void **) &newmat);\n      FREE(newmat);\n#else /*if MatrixColAccess==CAM_Vector*/\n      REAL *newValue = NULL;\n      int  *newRownr = NULL;\n      allocREAL(mat->lp, &newValue, mat->mat_alloc, FALSE);\n      allocINT(mat->lp, &newRownr, mat->mat_alloc, FALSE);\n\n      j = mat->row_end[0];\n      for(i = nz-1; i >= j ; i--) {\n        k = i-j;\n        newValue[k] = ROW_MAT_VALUE(i);\n        newRownr[k] = ROW_MAT_COLNR(i);\n      }\n      for(i = j-1; i >= 0 ; i--) {\n        k = nz-j+i;\n        newValue[k] = ROW_MAT_VALUE(i);\n        newRownr[k] = ROW_MAT_COLNR(i);\n      }\n\n      swapPTR((void **) &mat->col_mat_rownr, (void **) &newRownr);\n      swapPTR((void **) &mat->col_mat_value, (void **) &newValue);\n      FREE(newValue);\n      FREE(newRownr);\n#endif\n    }\n\n    /* Transfer row start to column start position; must adjust for different offsets */\n    if(mat->rows == mat->rows_alloc)\n      inc_matcol_space(mat, 1);\n    j = mat->row_end[0];\n    for(i = mat->rows; i >= 1; i--)\n      mat->row_end[i] -= j;\n    mat->row_end[mat->rows] = nz;\n    swapPTR((void **) &mat->row_end, (void **) &mat->col_end);\n\n    /* Swap arrays of maximum values */\n    swapPTR((void **) &mat->rowmax, (void **) &mat->colmax);\n\n    /* Swap array sizes */\n    swapINT(&mat->rows, &mat->columns);\n    swapINT(&mat->rows_alloc, &mat->columns_alloc);\n\n    /* Finally set current storage mode */\n    mat->is_roworder = (MYBOOL) !mat->is_roworder;\n    mat->row_end_valid = FALSE;\n  }\n  return(status);\n}\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Change-tracking routines                                                           */\n/* ---------------------------------------------------------------------------------- */\nSTATIC DeltaVrec *createUndoLadder(lprec *lp, int levelitems, int maxlevels)\n{\n  DeltaVrec *hold;\n\n  hold = (DeltaVrec *) malloc(sizeof(*hold));\n  hold->lp = lp;\n  hold->activelevel = 0;\n  hold->tracker = mat_create(lp, levelitems, 0, 0.0);\n  inc_matcol_space(hold->tracker, maxlevels);\n  return( hold );\n}\nSTATIC int incrementUndoLadder(DeltaVrec *DV)\n{\n  DV->activelevel++;\n  inc_matcol_space(DV->tracker, 1);\n  mat_shiftcols(DV->tracker, &(DV->activelevel), 1, NULL);\n  DV->tracker->columns++;\n  return(DV->activelevel);\n}\nSTATIC MYBOOL modifyUndoLadder(DeltaVrec *DV, int itemno, REAL target[], REAL newvalue)\n{\n  MYBOOL status;\n  int    varindex = itemno;\n  REAL   oldvalue = target[itemno];\n\n#ifndef UseMilpSlacksRCF  /* Check if we should include ranged constraints */\n  varindex -= DV->lp->rows;\n#endif\n  status = mat_appendvalue(DV->tracker, varindex, oldvalue);\n  target[itemno] = newvalue;\n  return(status);\n}\nSTATIC int countsUndoLadder(DeltaVrec *DV)\n{\n  if(DV->activelevel > 0)\n    return( mat_collength(DV->tracker, DV->activelevel) );\n  else\n    return( 0 );\n}\nSTATIC int restoreUndoLadder(DeltaVrec *DV, REAL target[])\n{\n  int iD = 0;\n\n  if(DV->activelevel > 0) {\n    MATrec *mat = DV->tracker;\n    int    iB = mat->col_end[DV->activelevel-1],\n           iE = mat->col_end[DV->activelevel],\n           *matRownr = &COL_MAT_ROWNR(iB);\n    REAL   *matValue = &COL_MAT_VALUE(iB),\n           oldvalue;\n\n    /* Restore the values */\n    iD = iE-iB;\n    for(; iB < iE; iB++, matValue += matValueStep, matRownr += matRowColStep) {\n      oldvalue = *matValue;\n#ifdef UseMilpSlacksRCF  /* Check if we should include ranged constraints */\n      target[(*matRownr)] = oldvalue;\n#else\n      target[DV->lp->rows+(*matRownr)] = oldvalue;\n#endif\n    }\n\n    /* Get rid of the changes */\n    mat_shiftcols(DV->tracker, &(DV->activelevel), -1, NULL);\n  }\n\n  return(iD);\n}\nSTATIC int decrementUndoLadder(DeltaVrec *DV)\n{\n  int deleted = 0;\n\n  if(DV->activelevel > 0) {\n    deleted = mat_shiftcols(DV->tracker, &(DV->activelevel), -1, NULL);\n    DV->activelevel--;\n    DV->tracker->columns--;\n  }\n  return(deleted);\n}\nSTATIC MYBOOL freeUndoLadder(DeltaVrec **DV)\n{\n  if((DV == NULL) || (*DV == NULL))\n    return(FALSE);\n\n  mat_free(&((*DV)->tracker));\n  FREE(*DV);\n  return(TRUE);\n}\n\nSTATIC MYBOOL appendUndoPresolve(lprec *lp, MYBOOL isprimal, REAL beta, int colnrDep)\n{\n  MATrec *mat;\n\n  /* Point to correct undo structure */\n  if(isprimal)\n    mat = lp->presolve_undo->primalundo->tracker;\n  else\n    mat = lp->presolve_undo->dualundo->tracker;\n\n  /* Append the data */\n  if((colnrDep > 0) && (beta != 0) &&\n     (mat != NULL) && (mat->col_tag[0] > 0)) {\n    int ix = mat->col_tag[0];\n#if 0\n    report(lp, NORMAL, \"appendUndoPresolve: %s %g * x%d\\n\",\n                       ( beta < 0 ? \"-\" : \"+\"), fabs(beta), colnrDep);\n#endif\n\n    /* Do normal user variable case */\n    if(colnrDep <= lp->columns)\n      mat_setvalue(mat, colnrDep, ix, beta, FALSE);\n\n    /* Handle case where a slack variable is referenced */\n    else {\n      int ipos, jx = mat->col_tag[ix];\n      mat_setvalue(mat, jx, ix, beta, FALSE);\n      jx = mat_findins(mat, jx, ix, &ipos, FALSE);\n      COL_MAT_ROWNR(ipos) = colnrDep;\n    }\n    return( TRUE );\n  }\n  else\n    return( FALSE );\n}\nSTATIC MYBOOL addUndoPresolve(lprec *lp, MYBOOL isprimal, int colnrElim, REAL alpha, REAL beta, int colnrDep)\n{\n  int       ix;\n  DeltaVrec **DV;\n  MATrec    *mat;\n  presolveundorec *psdata = lp->presolve_undo;\n\n  /* Point to and initialize undo structure at first call */\n  if(isprimal) {\n    DV = &(psdata->primalundo);\n    if(*DV == NULL) {\n      *DV = createUndoLadder(lp, lp->columns+1, lp->columns);\n      mat = (*DV)->tracker;\n      mat->epsvalue = lp->matA->epsvalue;\n      allocINT(lp, &(mat->col_tag), lp->columns+1, FALSE);\n      mat->col_tag[0] = 0;\n    }\n  }\n  else {\n    DV = &(psdata->dualundo);\n    if(*DV == NULL) {\n      *DV = createUndoLadder(lp, lp->rows+1, lp->rows);\n      mat = (*DV)->tracker;\n      mat->epsvalue = lp->matA->epsvalue;\n      allocINT(lp, &(mat->col_tag), lp->rows+1, FALSE);\n      mat->col_tag[0] = 0;\n    }\n  }\n  mat = (*DV)->tracker;\n#if 0\n  report(lp, NORMAL, \"addUndoPresolve: x%d = %g %s %g * x%d\\n\",\n                     colnrElim, alpha, ( beta < 0 ? \"-\" : \"+\"), fabs(beta), colnrDep);\n#endif\n  /* Add the data */\n  ix = mat->col_tag[0] = incrementUndoLadder(*DV);\n  mat->col_tag[ix] = colnrElim;\n  if(alpha != 0)\n    mat_setvalue(mat, 0, ix, alpha, FALSE);\n/*    mat_appendvalue(*mat, 0, alpha);*/\n  if((colnrDep > 0) && (beta != 0)) {\n    if(colnrDep > lp->columns)\n      return( appendUndoPresolve(lp, isprimal, beta, colnrDep) );\n    else\n      mat_setvalue(mat, colnrDep, ix, beta, FALSE);\n  }\n\n  return( TRUE );\n}\n\n\n\n/* ---------------------------------------------------------------------------------- */\n/* High level matrix inverse and product routines in lp_solve                         */\n/* ---------------------------------------------------------------------------------- */\n\n/* ---------------------------------------------------------------------------------- */\n/*    A brief description of the basis inverse and factorization logic in lp_solve    */\n/* ---------------------------------------------------------------------------------- */\n/*\n\n   In order to better understand the legacy code for operating with the\n   basis and its factorization in lp_solve I (KE) will briefly explain\n   the conventions and associated matrix algebra.  Note that with lp_solve\n   version 5.5, it is also possible to direct lp_solve to use the traditional\n   (textbook) format by setting the obj_in_B parameter to FALSE.\n\n   The matrix description of a linear program (as represented by lp_solve) goes\n   like this:\n\n           maximize         c'x\n           subject to  r <=  Ax <= b\n           where       l <=   x <= u\n\n   The matrix A is partitioned into two column sets [B|N], where B is\n   a square matrix of \"basis\" variables containing non-fixed\n   variables of the linear program at any given stage and N is the\n   submatrix of corresponding non-basic, fixed variables. The\n   variables (columns) in N may be fixed at their lower or upper levels.\n\n   Similarly, the c vector is partitioned into the basic and non-basic\n   parts [z|n].\n\n   While lp_solve stores the objective vector c in a dense format, and\n   the constraint matrix A in a (fairly standard) sparse format, the\n   column vectors passed to the factorization routine include the\n   objective coefficient at row index 0.  (In versions of lp_solve\n   before v5.2, c was actually explicitly stored as the 0-th row of A).\n   The expanded matrix may be called the \"A~\" form and looks like this:\n\n                       A~ = [ c ]\n                            [ A ]\n\n   Linear programming involves solving linear equations based on the\n   square basis matrix B, which includes is a subset of columns from A~.\n   The implications of the common storage of c and A (e.g. A~) vs. the\n   inverse / factorization of B for the operations and updates performed\n   by the simplex routine therefore needs to be understood.  As a consquence\n   of A~, in lp_solve B is stored in an expanded, bordered format using the\n   following (non-singular) representation:\n\n                       B~ = [ 1 z ]\n                            [ 0 B ]\n\n   Any basis inversion / factorization engine used by lp_solve must therefore\n   explicitly represent and handle the implications of this structure for\n   associated matrix operations.\n\n   The standard matrix formula for computing the inverse of a bordered\n   matrix shows what the inversion of B~ actually produces:\n\n                  Inv(B~) = [ 1 -z*Inv(B) ]\n                            [ 0   Inv(B)  ]\n\n   The A~ and B~ representations require awareness by the developer of the side\n   effects of the presence of the top row when doing product operations such as\n   b'N, btran and ftran.  Note in particular z*Inv(B) in the top row of Inv(B~),\n   which is actually the dual solution vector of the given basis.  This fact\n   makes a very common update in the simplex algorithm (reduced costs) returnable\n   as a vector simply by setting 1 at the top of a vector being pre-multiplied\n   with Inv(B~).\n\n   However, if the objective vector (c) is changed, the expanded representation\n   requires that B / B~ be refactorized.  Also, when doing FTRAN, BTRAN\n   and x'A-type operations, you will patently get the incorrect result\n   if you simply copy the operations given in textbooks.  First I'll show the\n   results of an FTRAN operation:\n\n                   Bx = a  ==>  x = FTRAN(a)\n\n   In lp_solve, this operation solves:\n\n                   [ 1 z ] [y] = [d]\n                   [ 0 B ] [x]   [a]\n\n   Using the Inv(B~) expression earlier, the FTRAN result is therefore:\n\n             [y] = [ 1 -z*Inv(B) ] [d] = [ d - z*Inv(B)*a ]\n             [x]   [ 0   Inv(B)  ] [a]   [   Inv(B)*a     ]\n\n   As an example, the value of the dual objective can be returned at the\n   0-th index by passing the active RHS vector with 0 at the 0-th position.\n\n   Similarily, doing the left solve - performing the BTRAN calculation:\n\n                   [x y] [ 1 z ] = [d a']\n                         [ 0 B ]\n\n   ... will produce the following result in lp_solve:\n\n   [x y] = [d a'] [ 1 -z*Inv(B) ] = [ d | -d*z*Inv(B) + a'*Inv(B) ]\n                  [ 0   Inv(B)  ]\n\n   So, if you thought you were simply computing \"a'*Inv(B)\", look again.\n   In order to produce the desired result, you have to set d to 0 before\n   the BTRAN operation.  On the other hand, if you set d to 1 and a to 0,\n   then you are very conveniently on your way to obtain the reduced costs\n   (needs a further matrix premultiplication with non-basic variables).\n\n   Incidentally, the BTRAN with [1 0] that yields [ 1 | -z*Inv(B) ] can\n   also be used as a fast way of checking the accuracy of the current\n   factorization.\n\n   Equipped with this understanding, I hope that you see that\n   the approach in lp_solve is actually pretty convenient.  It also\n   becomes easier to extend functionality in lp_solve by drawing on\n   formulas and expressions from LP literature that otherwise assume\n   the non-bordered syntax and representation.\n\n                                     Kjell Eikland -- November 2003\n                                     KE update     -- April 2005\n                                     KE update     -- June 2005\n\n*/\n\nSTATIC MYBOOL __WINAPI invert(lprec *lp, MYBOOL shiftbounds, MYBOOL final)\n{\n  MYBOOL *usedpos, resetbasis;\n  REAL   test;\n  int    k, i, j;\n  int    singularities, usercolB;\n\n /* Make sure the tags are correct */\n  if(!mat_validate(lp->matA)) {\n    lp->spx_status = INFEASIBLE;\n    return(FALSE);\n  }\n\n /* Create the inverse management object at the first call to invert() */\n  if(lp->invB == NULL)\n    lp->bfp_init(lp, lp->rows, 0, NULL);\n  else\n    lp->bfp_preparefactorization(lp);\n  singularities = 0;\n\n /* Must save spx_status since it is used to carry information about\n    the presence and handling of singular columns in the matrix */\n  if(userabort(lp, MSG_INVERT))\n    return(FALSE);\n\n#ifdef Paranoia\n  if(lp->spx_trace)\n    report(lp, DETAILED, \"invert: Iter %10g, fact-length %7d, OF \" RESULTVALUEMASK \".\\n\",\n                         (double) get_total_iter(lp), lp->bfp_colcount(lp), (double) -lp->rhs[0]);\n#endif\n\n /* Store state of pre-existing basis, and at the same time check if\n    the basis is I; in this case take the easy way out */\n  if(!allocMYBOOL(lp, &usedpos, lp->sum + 1, TRUE)) {\n    lp->bb_break = TRUE;\n    return(FALSE);\n  }\n  usedpos[0] = TRUE;\n  usercolB = 0;\n  for(i = 1; i <= lp->rows; i++) {\n    k = lp->var_basic[i];\n    if(k > lp->rows)\n      usercolB++;\n    usedpos[k] = TRUE;\n  }\n#ifdef Paranoia\n  if(!verify_basis(lp))\n    report(lp, SEVERE, \"invert: Invalid basis detected (iter %g).\\n\",\n                       (double) get_total_iter(lp));\n#endif\n\n /* Tally matrix nz-counts and check if we should reset basis\n    indicators to all slacks */\n  resetbasis = (MYBOOL) ((usercolB > 0) && lp->bfp_canresetbasis(lp));\n  k = 0;\n  for(i = 1; i <= lp->rows; i++) {\n    if(lp->var_basic[i] > lp->rows)\n      k += mat_collength(lp->matA, lp->var_basic[i] - lp->rows) + (is_OF_nz(lp,lp->var_basic[i] - lp->rows) ? 1 : 0);\n    if(resetbasis) {\n      j = lp->var_basic[i];\n      if(j > lp->rows)\n        lp->is_basic[j] = FALSE;\n      lp->var_basic[i] = i;\n      lp->is_basic[i] = TRUE;\n    }\n  }\n\n /* Now do the refactorization */\n  singularities = lp->bfp_factorize(lp, usercolB, k, usedpos, final);\n\n /* Do user reporting */\n  if(userabort(lp, MSG_INVERT))\n    goto Cleanup;\n\n /* Finalize factorization/inversion */\n  lp->bfp_finishfactorization(lp);\n\n  /* Recompute the RHS ( Ref. lp_solve inverse logic and Chvatal p. 121 ) */\n#ifdef DebugInv\n  blockWriteLREAL(stdout, \"RHS-values pre invert\", lp->rhs, 0, lp->rows);\n#endif\n  recompute_solution(lp, shiftbounds);\n  restartPricer(lp, AUTOMATIC);\n#ifdef DebugInv\n  blockWriteLREAL(stdout, \"RHS-values post invert\", lp->rhs, 0, lp->rows);\n#endif\n\nCleanup:\n  /* Check for numerical instability indicated by frequent refactorizations */\n  test = get_refactfrequency(lp, FALSE);\n  if(test < MIN_REFACTFREQUENCY) {\n    test = get_refactfrequency(lp, TRUE);\n    report(lp, NORMAL, \"invert: Refactorization frequency %.1g indicates numeric instability.\\n\",\n                       test);\n    lp->spx_status = NUMFAILURE;\n  }\n\n  FREE(usedpos);\n  return((MYBOOL) (singularities <= 0));\n} /* invert */\n\n\nSTATIC MYBOOL fimprove(lprec *lp, REAL *pcol, int *nzidx, REAL roundzero)\n{\n  REAL   *errors, sdp;\n  int    j;\n  MYBOOL Ok = TRUE;\n\n  allocREAL(lp, &errors, lp->rows + 1, FALSE);\n  if(errors == NULL) {\n    Ok = FALSE;\n    return(Ok);\n  }\n  MEMCOPY(errors, pcol, lp->rows + 1);\n  lp->bfp_ftran_normal(lp, pcol, nzidx);\n  prod_Ax(lp, NULL, pcol, NULL, 0.0, -1,\n                                errors, NULL, MAT_ROUNDDEFAULT);\n  lp->bfp_ftran_normal(lp, errors, NULL);\n\n  sdp = 0;\n  for(j = 1; j <= lp->rows; j++)\n    if(fabs(errors[j])>sdp)\n      sdp = fabs(errors[j]);\n  if(sdp > lp->epsmachine) {\n    report(lp, DETAILED, \"Iterative FTRAN correction metric %g\", sdp);\n    for(j = 1; j <= lp->rows; j++) {\n      pcol[j] += errors[j];\n      my_roundzero(pcol[j], roundzero);\n    }\n  }\n  FREE(errors);\n  return(Ok);\n}\n\nSTATIC MYBOOL bimprove(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero)\n{\n  int    j;\n  REAL   *errors, err, maxerr;\n  MYBOOL Ok = TRUE;\n\n  allocREAL(lp, &errors, lp->sum + 1, FALSE);\n  if(errors == NULL) {\n    Ok = FALSE;\n    return(Ok);\n  }\n  MEMCOPY(errors, rhsvector, lp->sum + 1);\n\n  /* Solve Ax=b for x, compute b back */\n  lp->bfp_btran_normal(lp, errors, nzidx);\n  prod_xA(lp, NULL, errors, NULL, 0.0, 1.0,\n                                  errors, NULL,\n                                  MAT_ROUNDDEFAULT);\n\n  /* Take difference with ingoing values, while shifting the column values\n     to the rows section and zeroing the columns again */\n  for(j = 1; j <= lp->rows; j++)\n    errors[j] = errors[lp->rows+lp->var_basic[j]] - rhsvector[j];\n  for(j = lp->rows; j <= lp->sum; j++)\n    errors[j] = 0;\n\n  /* Solve the b errors for the iterative x adjustment */\n  lp->bfp_btran_normal(lp, errors, NULL);\n\n  /* Generate the adjustments and compute statistic */\n  maxerr = 0;\n  for(j = 1; j <= lp->rows; j++) {\n    if(lp->var_basic[j]<=lp->rows) continue;\n    err = errors[lp->rows+lp->var_basic[j]];\n    if(fabs(err)>maxerr)\n      maxerr = fabs(err);\n  }\n  if(maxerr > lp->epsmachine) {\n    report(lp, DETAILED, \"Iterative BTRAN correction metric %g\", maxerr);\n    for(j = 1; j <= lp->rows; j++) {\n      if(lp->var_basic[j]<=lp->rows) continue;\n      rhsvector[j] += errors[lp->rows+lp->var_basic[j]];\n      my_roundzero(rhsvector[j], roundzero);\n    }\n  }\n  FREE(errors);\n  return(Ok);\n}\n\nSTATIC void ftran(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero)\n{\n  (void)roundzero;\n#if 0\n  if(is_action(lp->improve, IMPROVE_SOLUTION) && lp->bfp_pivotcount(lp))\n    fimprove(lp, rhsvector, nzidx, roundzero);\n  else\n#endif\n    lp->bfp_ftran_normal(lp, rhsvector, nzidx);\n}\n\nSTATIC void btran(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero)\n{\n  (void)roundzero;\n#if 0\n  if(is_action(lp->improve, IMPROVE_SOLUTION) && lp->bfp_pivotcount(lp))\n    bimprove(lp, rhsvector, nzidx, roundzero);\n  else\n#endif\n    lp->bfp_btran_normal(lp, rhsvector, nzidx);\n}\n\nSTATIC MYBOOL fsolve(lprec *lp, int varin, REAL *pcol, int *nzidx, REAL roundzero, REAL ofscalar, MYBOOL prepareupdate)\n/* Was setpivcol in versions earlier than 4.0.1.8 - KE */\n{\n  MYBOOL ok = TRUE;\n\n  if(varin > 0)\n    obtain_column(lp, varin, pcol, nzidx, NULL);\n\n /* Solve, adjusted for objective function scalar */\n  pcol[0] *= ofscalar;\n  if(prepareupdate)\n    lp->bfp_ftran_prepare(lp, pcol, nzidx);\n  else\n    ftran(lp, pcol, nzidx, roundzero);\n\n  return(ok);\n\n} /* fsolve */\n\n\nSTATIC MYBOOL bsolve(lprec *lp, int row_nr, REAL *rhsvector, int *nzidx, REAL roundzero, REAL ofscalar)\n{\n  MYBOOL ok = TRUE;\n\n  if(row_nr >= 0) /* Note that row_nr == 0 returns the [1, 0...0 ] vector */\n    row_nr = obtain_column(lp, row_nr, rhsvector, nzidx, NULL);\n\n  /* Solve, adjusted for objective function scalar */\n  rhsvector[0] *= ofscalar;\n  btran(lp, rhsvector, nzidx, roundzero);\n\n  return(ok);\n\n} /* bsolve */\n\n\n/* Vector compression and expansion routines */\nSTATIC MYBOOL vec_compress(REAL *densevector, int startpos, int endpos, REAL epsilon,\n                           REAL *nzvector, int *nzindex)\n{\n  int n;\n\n  if((densevector == NULL) || (nzindex == NULL) || (startpos > endpos))\n    return( FALSE );\n\n  n = 0;\n  densevector += startpos;\n  while(startpos <= endpos) {\n    if(fabs(*densevector) > epsilon) {  /* Apply zero-threshold */\n      if(nzvector != NULL)                       /* Only produce index if no nzvector is given */\n        nzvector[n] = *densevector;\n      n++;\n      nzindex[n] = startpos;\n    }\n    startpos++;\n    densevector++;\n  }\n  nzindex[0] = n;\n  return( TRUE );\n}\n\nSTATIC MYBOOL vec_expand(REAL *nzvector, int *nzindex, REAL *densevector, int startpos, int endpos)\n{\n  int i, n;\n\n  n = nzindex[0];\n  i = nzindex[n];\n  densevector += endpos;\n  while(endpos >= startpos) {                     /* Loop from behind to allow densevector == nzvector */\n    if(endpos == i) {\n      n--;\n      *densevector = nzvector[n];\n      i = nzindex[n];\n    }\n    else\n      *densevector = 0;\n    endpos--;\n    densevector--;\n  }\n  return( TRUE );\n}\n\n\n/* ----------------------------------------------------------------------- */\n/* Sparse matrix product routines and utility                              */\n/* ----------------------------------------------------------------------- */\n\nSTATIC MYBOOL get_colIndexA(lprec *lp, int varset, int *colindex, MYBOOL append)\n{\n  int      i, varnr, P1extraDim, vb, ve, n, nrows = lp->rows, nsum = lp->sum;\n  MYBOOL   omitfixed, omitnonfixed;\n  REAL     v;\n\n  /* Find what variable range to scan - default is {SCAN_USERVARS} */\n  /* First determine the starting position; add from the top, going down */\n  P1extraDim = abs(lp->P1extraDim);\n  vb = nrows + 1;\n  if(varset & SCAN_ARTIFICIALVARS)\n    vb = nsum - P1extraDim + 1;\n  if(varset & SCAN_USERVARS)\n    vb = nrows + 1;\n  if(varset & SCAN_SLACKVARS)\n    vb = 1;\n\n  /* Then determine the ending position, add from the bottom, going up */\n  ve = nsum;\n  if(varset & SCAN_SLACKVARS)\n    ve = nrows;\n  if(varset & SCAN_USERVARS)\n    ve = nsum - P1extraDim;\n  if(varset & SCAN_ARTIFICIALVARS)\n    ve = nsum;\n\n  /* Adjust for partial pricing */\n  if(varset & SCAN_PARTIALBLOCK) {\n    SETMAX(vb, partial_blockStart(lp, FALSE));\n    SETMIN(ve, partial_blockEnd(lp, FALSE));\n  }\n\n  /* Determine exclusion columns */\n  omitfixed = (MYBOOL) ((varset & OMIT_FIXED) != 0);\n  omitnonfixed = (MYBOOL) ((varset & OMIT_NONFIXED) != 0);\n  if(omitfixed && omitnonfixed)\n    return(FALSE);\n\n  /* Scan the target colums */\n  if(append)\n    n = colindex[0];\n  else\n    n = 0;\n  for(varnr = vb; varnr <= ve; varnr++) {\n\n    /* Skip gap in the specified column scan range (possibly user variables) */\n    if(varnr > nrows) {\n      if((varnr <= nsum-P1extraDim) && !(varset & SCAN_USERVARS))\n        continue;\n#if 1\n      /* Skip empty columns */\n      if(/*(lp->P1extraVal == 0) &&*/\n         (mat_collength(lp->matA, varnr-nrows) == 0))\n        continue;\n#endif\n    }\n\n    /* Find if the variable is in the scope - default is {} */\n    i = lp->is_basic[varnr];\n    if((varset & USE_BASICVARS) > 0 && (i))\n      ;\n    else if((varset & USE_NONBASICVARS) > 0 && (!i))\n      ;\n    else\n      continue;\n\n    v = lp->upbo[varnr];\n    if((omitfixed && (v == 0)) ||\n       (omitnonfixed && (v != 0)))\n      continue;\n\n    /* Append to list */\n    n++;\n    colindex[n] = varnr;\n  }\n  colindex[0] = n;\n\n  return(TRUE);\n}\n\nSTATIC int prod_Ax(lprec *lp, int *coltarget, REAL *input, int *nzinput,\n                              REAL roundzero, REAL ofscalar,\n                              REAL *output, int *nzoutput, int roundmode)\n/* prod_Ax is only used in fimprove; note that it is NOT VALIDATED/verified as of 20030801 - KE */\n{\n  (void)nzoutput;\n  int      j, colnr, ib, ie, vb, ve;\n  MYBOOL   localset, localnz = FALSE, isRC;\n  MATrec   *mat = lp->matA;\n  REAL     sdp;\n  REAL     *value;\n  int      *rownr;\n  (void)nzoutput;\n\n  /* Find what variable range to scan - default is {SCAN_USERVARS} */\n  /* Define default column target if none was provided */\n  isRC = (MYBOOL) ((roundmode & MAT_ROUNDRC) != 0);\n  localset = (MYBOOL) (coltarget == NULL);\n  if(localset) {\n    int varset = SCAN_SLACKVARS | SCAN_USERVARS |\n                 USE_BASICVARS | OMIT_FIXED;\n    if(isRC && is_piv_mode(lp, PRICE_PARTIAL) && !is_piv_mode(lp, PRICE_FORCEFULL))\n      varset |= SCAN_PARTIALBLOCK;\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n    coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->sum+1, sizeof(*coltarget));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n    if(!get_colIndexA(lp, varset, coltarget, FALSE)) {\n      mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n      return(FALSE);\n    }\n  }\n  localnz = (MYBOOL) (nzinput == NULL);\n  if(localnz) {\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n    nzinput = (int *) mempool_obtainVector(lp->workarrays, lp->rows+1, sizeof(*nzinput));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n    vec_compress(input, 0, lp->rows, lp->matA->epsvalue, NULL, nzinput);\n  }\n\n  /* Scan the columns */\n  vb = 1;\n  ve = coltarget[0];\n  for(vb = 1; vb <= coltarget[0]; vb++) {\n    colnr = coltarget[vb];\n    j = lp->is_basic[colnr];\n\n    /* Perform the multiplication */\n    sdp = ofscalar*input[j];\n    if(colnr <= lp->rows)               /* A slack variable is in the basis */\n      output[colnr] += sdp;\n    else {                              /* A normal variable is in the basis */\n      colnr -= lp->rows;\n      ib = mat->col_end[colnr - 1];\n      ie = mat->col_end[colnr];\n      rownr = &COL_MAT_ROWNR(ib);\n      value = &COL_MAT_VALUE(ib);\n      for(; ib < ie;\n          ib++, rownr += matRowColStep, value += matValueStep) {\n        output[*rownr] += (*value)*sdp;\n      }\n    }\n  }\n  roundVector(output+1, lp->rows-1, roundzero);\n\n  /* Clean up and return */\n  if(localset)\n    mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n  if(localnz)\n    mempool_releaseVector(lp->workarrays, (char *) nzinput, FALSE);\n\n  return(TRUE);\n}\n\nSTATIC int prod_xA(lprec *lp, int *coltarget,\n                              REAL *input, int *nzinput, REAL roundzero, REAL ofscalar,\n                              REAL *output, int *nzoutput, int roundmode)\n/* Note that the dot product xa is stored at the active column index of A, i.e. of a.\n   This means that if the basis only contains non-slack variables, output may point to\n   the same vector as input, without overwriting the [0..rows] elements. */\n{\n  int      colnr, rownr, varnr, ib, ie, vb, ve, nrows = lp->rows;\n  MYBOOL   localset, localnz = FALSE, includeOF, isRC;\n  REALXP   vmax;\n  REALXP v;\n  int      inz, *rowin, countNZ = 0;\n  MATrec   *mat = lp->matA;\n  REAL     *matValue;\n  int      *matRownr;\n\n  /* Clean output area (only necessary if we are returning the full vector) */\n  isRC = (MYBOOL) ((roundmode & MAT_ROUNDRC) != 0);\n  if(nzoutput == NULL) {\n    if(input == output)\n      MEMCLEAR(output+nrows+1, lp->columns);\n    else\n      MEMCLEAR(output, lp->sum+1);\n  }\n\n  /* Find what variable range to scan - default is {SCAN_USERVARS} */\n  /* Define default column target if none was provided */\n  localset = (MYBOOL) (coltarget == NULL);\n  if(localset) {\n    int varset = SCAN_SLACKVARS | SCAN_USERVARS |\n                 USE_NONBASICVARS | OMIT_FIXED;\n    if(isRC && is_piv_mode(lp, PRICE_PARTIAL) && !is_piv_mode(lp, PRICE_FORCEFULL))\n      varset |= SCAN_PARTIALBLOCK;\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n    coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->sum+1, sizeof(*coltarget));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n    if(!get_colIndexA(lp, varset, coltarget, FALSE)) {\n      mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n      return(FALSE);\n    }\n  }\n/*#define UseLocalNZ*/\n#ifdef UseLocalNZ\n  localnz = (MYBOOL) (nzinput == NULL);\n  if(localnz) {\n    nzinput = (int *) mempool_obtainVector(lp->workarrays, nrows+1, sizeof(*nzinput));\n    vec_compress(input, 0, nrows, lp->matA->epsvalue, NULL, nzinput);\n  }\n#endif\n  includeOF = (MYBOOL) (((nzinput == NULL) || (nzinput[1] == 0)) &&\n                        (input[0] != 0) && lp->obj_in_basis);\n\n  /* Scan the target colums */\n  vmax = 0;\n  ve = coltarget[0];\n  for(vb = 1; vb <= ve; vb++) {\n\n    varnr = coltarget[vb];\n\n    if(varnr <= nrows) {\n      v = input[varnr];\n    }\n    else {\n      colnr = varnr - nrows;\n      v = 0;\n      ib = mat->col_end[colnr - 1];\n      ie = mat->col_end[colnr];\n      if(ib < ie) {\n\n        /* Do dense input vector version */\n#ifdef UseLocalNZ\n        if(localnz || (nzinput == NULL)) {\n#else\n        if(nzinput == NULL) {\n#endif\n          /* Do the OF */\n          if(includeOF)\n#ifdef DirectArrayOF\n            v += input[0] * lp->obj[colnr] * ofscalar;\n#else\n            v += input[0] * get_OF_active(lp, varnr, ofscalar);\n#endif\n\n          /* Initialize pointers */\n          matRownr = &COL_MAT_ROWNR(ib);\n          matValue = &COL_MAT_VALUE(ib);\n\n          /* Do extra loop optimization based on target window overlaps */\n#ifdef UseLocalNZ\n          if((ib < ie)\n             && (colnr <= *nzinput)\n             && (COL_MAT_ROWNR(ie-1) >= nzinput[colnr])\n             && (*matRownr <= nzinput[*nzinput])\n             )\n#endif\n#ifdef NoLoopUnroll\n          /* Then loop over all regular rows */\n          for(; ib < ie; ib++) {\n            v += input[*matRownr] * (*matValue);\n            matValue += matValueStep;\n            matRownr += matRowColStep;\n          }\n#else\n          /* Prepare for simple loop unrolling */\n          if(((ie-ib) % 2) == 1) {\n            v += input[*matRownr] * (*matValue);\n            ib++;\n            matValue += matValueStep;\n            matRownr += matRowColStep;\n          }\n\n          /* Then loop over remaining pairs of regular rows */\n          while(ib < ie) {\n            v += input[*matRownr] * (*matValue);\n            v += input[*(matRownr+matRowColStep)] * (*(matValue+matValueStep));\n            ib += 2;\n            matValue += 2*matValueStep;\n            matRownr += 2*matRowColStep;\n          }\n#endif\n        }\n        /* Do sparse input vector version */\n        else {\n\n          /* Do the OF */\n          if(includeOF)\n#ifdef DirectArrayOF\n            v += input[0] * lp->obj[colnr] * ofscalar;\n#else\n            v += input[0] * get_OF_active(lp, varnr, ofscalar);\n#endif\n\n          /* Initialize pointers */\n          inz = 1;\n          rowin = nzinput+inz;\n          matRownr = &COL_MAT_ROWNR(ib);\n          matValue = &COL_MAT_VALUE(ib);\n          ie--;\n\n          /* Then loop over all non-OF rows */\n          while((inz <= *nzinput) && (ib <= ie)) {\n\n           /* Try to synchronize at right */\n            while((*rowin > *matRownr) && (ib < ie)) {\n              ib++;\n              matValue += matValueStep;\n              matRownr += matRowColStep;\n            }\n            /* Try to synchronize at left */\n            while((*rowin < *matRownr) && (inz < *nzinput)) {\n              inz++;\n              rowin++;\n            }\n            /* Perform dot product operation if there was a match */\n            if(*rowin == *matRownr) {\n              v += input[*rowin] * (*matValue);\n              /* Step forward at left */\n              inz++;\n              rowin++;\n            }\n          }\n        }\n      }\n      if((roundmode & MAT_ROUNDABS) != 0) {\n        my_roundzero(v, roundzero);\n      }\n    }\n\n    /* Special handling of small reduced cost values */\n    if(!isRC || (my_chsign(lp->is_lower[varnr], v) < 0)) {\n      SETMAX(vmax, fabs((REAL) v));\n    }\n    if(v != 0) {\n      countNZ++;\n      if(nzoutput != NULL)\n        nzoutput[countNZ] = varnr;\n    }\n    output[varnr] = (REAL) v;\n  }\n\n  /* Compute reduced cost if this option is active */\n  if(isRC && !lp->obj_in_basis)\n    countNZ = get_basisOF(lp, coltarget, output, nzoutput);\n\n  /* Check if we should do relative rounding */\n  if((roundmode & MAT_ROUNDREL) != 0) {\n    if((roundzero > 0) && (nzoutput != NULL)) {\n      ie = 0;\n      if(isRC) {\n        SETMAX(vmax, MAT_ROUNDRCMIN);  /* Make sure we don't use very small values */\n      }\n      vmax *= roundzero;\n      for(ib = 1; ib <= countNZ;  ib++) {\n        rownr = nzoutput[ib];\n        if(fabs(output[rownr]) < vmax)\n          output[rownr] = 0;\n        else {\n          ie++;\n          nzoutput[ie] = rownr;\n        }\n      }\n      countNZ = ie;\n    }\n  }\n\n  /* Clean up and return */\n  if(localset)\n    mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n  if(localnz)\n    mempool_releaseVector(lp->workarrays, (char *) nzinput, FALSE);\n\n  if(nzoutput != NULL)\n    *nzoutput = countNZ;\n  return(countNZ);\n}\n\nSTATIC MYBOOL prod_xA2(lprec *lp, int *coltarget,\n                                  REAL *prow, REAL proundzero, int *nzprow,\n                                  REAL *drow, REAL droundzero, int *nzdrow,\n                                  REAL ofscalar, int roundmode)\n{\n  int      varnr, colnr, ib, ie, vb, ve, nrows = lp->rows;\n  MYBOOL   includeOF, isRC;\n  REALXP   dmax, pmax;\n  REALXP d, p;\n  MATrec   *mat = lp->matA;\n  REAL     value;\n  REAL     *matValue;\n  int      *matRownr;\n  MYBOOL localset;\n\n  /* Find what variable range to scan - default is {SCAN_USERVARS} */\n  /* First determine the starting position; add from the top, going down */\n  localset = (MYBOOL) (coltarget == NULL);\n  if(localset) {\n    int varset = SCAN_SLACKVARS + SCAN_USERVARS + /*SCAN_ALLVARS +*/\n                 /*SCAN_PARTIALBLOCK+*/\n                 USE_NONBASICVARS+OMIT_FIXED;\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n    coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->sum+1, sizeof(*coltarget));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n    if(!get_colIndexA(lp, varset, coltarget, FALSE)) {\n      mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n      return(FALSE);\n    }\n  }\n\n  /* Initialize variables */\n  isRC = (MYBOOL) ((roundmode & MAT_ROUNDRC) != 0);\n  pmax = 0;\n  dmax = 0;\n  if(nzprow != NULL)\n    *nzprow = 0;\n  if(nzdrow != NULL)\n    *nzdrow = 0;\n  includeOF = (MYBOOL) (((prow[0] != 0) || (drow[0] != 0)) &&\n                        lp->obj_in_basis);\n\n  /* Scan the target colums */\n  ve = coltarget[0];\n  for(vb = 1; vb <= ve; vb++) {\n\n    varnr = coltarget[vb];\n\n    if(varnr <= nrows) {\n      p = prow[varnr];\n      d = drow[varnr];\n    }\n    else {\n\n      colnr = varnr - nrows;\n\n      p = 0;\n      d = 0;\n      ib = mat->col_end[colnr - 1];\n      ie = mat->col_end[colnr];\n\n      if(ib < ie) {\n\n        /* Do the OF */\n        if(includeOF) {\n#ifdef DirectArrayOF\n          value = lp->obj[colnr] * ofscalar;\n#else\n          value = get_OF_active(lp, varnr, ofscalar);\n#endif\n          p += prow[0] * value;\n          d += drow[0] * value;\n        }\n\n        /* Then loop over all regular rows */\n        matRownr = &COL_MAT_ROWNR(ib);\n        matValue = &COL_MAT_VALUE(ib);\n#ifdef NoLoopUnroll\n        for( ; ib < ie; ib++) {\n          p += prow[*matRownr] * (*matValue);\n          d += drow[*matRownr] * (*matValue);\n          matValue += matValueStep;\n          matRownr += matRowColStep;\n        }\n#else\n        /* Prepare for simple loop unrolling */\n        if(((ie-ib) % 2) == 1) {\n          p += prow[*matRownr] * (*matValue);\n          d += drow[*matRownr] * (*matValue);\n          ib++;\n          matValue += matValueStep;\n          matRownr += matRowColStep;\n        }\n\n        /* Then loop over remaining pairs of regular rows */\n        while(ib < ie) {\n          p += prow[*matRownr] * (*matValue);\n          p += prow[*(matRownr+matRowColStep)] * (*(matValue+matValueStep));\n          d += drow[*matRownr] * (*matValue);\n          d += drow[*(matRownr+matRowColStep)] * (*(matValue+matValueStep));\n          ib += 2;\n          matValue += 2*matValueStep;\n          matRownr += 2*matRowColStep;\n        }\n#endif\n\n      }\n      if((roundmode & MAT_ROUNDABS) != 0) {\n        my_roundzero(p, proundzero);\n        my_roundzero(d, droundzero);\n      }\n    }\n\n    SETMAX(pmax, fabs((REAL) p));\n    prow[varnr] = (REAL) p;\n    if((nzprow != NULL) && (p != 0)) {\n      (*nzprow)++;\n      nzprow[*nzprow] = varnr;\n    }\n\n    /* Special handling of reduced cost rounding */\n    if(!isRC || (my_chsign(lp->is_lower[varnr], d) < 0)) {\n      SETMAX(dmax, fabs((REAL) d));\n    }\n    drow[varnr] = (REAL) d;\n    if((nzdrow != NULL) && (d != 0)) {\n      (*nzdrow)++;\n      nzdrow[*nzdrow] = varnr;\n    }\n  }\n\n  /* Compute reduced cost here if this option is active */\n  if((drow != 0) && !lp->obj_in_basis)\n    get_basisOF(lp, coltarget, drow, nzdrow);\n\n  /* Check if we should do relative rounding */\n  if((roundmode & MAT_ROUNDREL) != 0) {\n    if((proundzero > 0) && (nzprow != NULL)) {\n      ie = 0;\n      pmax *= proundzero;\n      for(ib = 1; ib <= *nzprow;  ib++) {\n        varnr = nzprow[ib];\n        if(fabs(prow[varnr]) < pmax)\n          prow[varnr] = 0;\n        else {\n          ie++;\n          nzprow[ie] = varnr;\n        }\n      }\n      *nzprow = ie;\n    }\n    if((droundzero > 0) && (nzdrow != NULL)) {\n      ie = 0;\n      if(isRC) {\n        SETMAX(dmax, MAT_ROUNDRCMIN);  /* Make sure we don't use very small values */\n      }\n      dmax *= droundzero;\n      for(ib = 1; ib <= *nzdrow;  ib++) {\n        varnr = nzdrow[ib];\n        if(fabs(drow[varnr]) < dmax)\n          drow[varnr] = 0;\n        else {\n          ie++;\n          nzdrow[ie] = varnr;\n        }\n      }\n      *nzdrow = ie;\n    }\n  }\n\n  /* Clean up and return */\n  if(localset)\n    mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n  return( TRUE );\n}\n\nSTATIC void bsolve_xA2(lprec *lp, int* coltarget,\n                                  int row_nr1, REAL *vector1, REAL roundzero1, int *nzvector1,\n                                  int row_nr2, REAL *vector2, REAL roundzero2, int *nzvector2, int roundmode)\n{\n  REAL ofscalar = 1.0;\n\n /* Clear and initialize first vector */\n  if(nzvector1 == NULL)\n    MEMCLEAR(vector1, lp->sum + 1);\n  else\n    MEMCLEAR(vector1, lp->rows + 1);\n  vector1[row_nr1] = 1;\n/*  workINT[0] = 1;\n  workINT[1] = row_nr1; */\n\n  if(vector2 == NULL) {\n    lp->bfp_btran_normal(lp, vector1, NULL);\n    prod_xA(lp, coltarget, vector1, NULL, roundzero1, ofscalar*0,\n                           vector1, nzvector1, roundmode);\n  }\n  else {\n\n   /* Clear and initialize second vector */\n    if(nzvector2 == NULL)\n      MEMCLEAR(vector2, lp->sum + 1);\n    else\n      MEMCLEAR(vector2, lp->rows + 1);\n    if(lp->obj_in_basis || (row_nr2 > 0)) {\n      vector2[row_nr2] = 1;\n/*      workINT[2] = 1;\n      workINT[3] = row_nr2; */\n    }\n    else\n      get_basisOF(lp, NULL, vector2, nzvector2);\n\n   /* A double BTRAN equation solver process is implemented \"in-line\" below in\n      order to save time and to implement different rounding for the two */\n    lp->bfp_btran_double(lp, vector1, NULL, vector2, NULL);\n\n   /* Multiply solution vectors with matrix values */\n    prod_xA2(lp, coltarget, vector1, roundzero1, nzvector1,\n                            vector2, roundzero2, nzvector2,\n                            ofscalar, roundmode);\n  }\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_matrix.h",
    "content": "#ifndef HEADER_lp_matrix\n#define HEADER_lp_matrix\n\n#include \"lp_types.h\"\n#include \"lp_utils.h\"\n\n\n/* Sparse matrix element (ordered columnwise) */\ntypedef struct _MATitem\n{\n  int  rownr;\n  int  colnr;\n  REAL value;\n} MATitem;\n\n/* Constants for matrix product rounding options */\n#define MAT_ROUNDNONE             0\n#define MAT_ROUNDABS              1\n#define MAT_ROUNDREL              2\n#define MAT_ROUNDABSREL          (MAT_ROUNDABS + MAT_ROUNDREL)\n#define MAT_ROUNDRC               4\n#define MAT_ROUNDRCMIN            1.0 /* lp->epspivot */\n#if 1\n #define MAT_ROUNDDEFAULT         MAT_ROUNDREL  /* Typically increases performance */\n#else\n #define MAT_ROUNDDEFAULT         MAT_ROUNDABS  /* Probably gives more precision */\n#endif\n\n/* Compiler option development features */\n/*#define DebugInv*/               /* Report array values at factorization/inversion */\n#define NoLoopUnroll              /* Do not do loop unrolling */\n#define DirectArrayOF             /* Reference lp->obj[] array instead of function call */\n\n\n/* Matrix column access macros to be able to easily change storage model */\n#define CAM_Record                0\n#define CAM_Vector                1\n#if 0\n #define MatrixColAccess           CAM_Record\n#else\n #define MatrixColAccess           CAM_Vector\n#endif\n\n#if MatrixColAccess==CAM_Record\n#define SET_MAT_ijA(item,i,j,A)   mat->col_mat[item].rownr = i; \\\n                                  mat->col_mat[item].colnr = j; \\\n                                  mat->col_mat[item].value = A\n#define COL_MAT_COLNR(item)       (mat->col_mat[item].colnr)\n#define COL_MAT_ROWNR(item)       (mat->col_mat[item].rownr)\n#define COL_MAT_VALUE(item)       (mat->col_mat[item].value)\n#define COL_MAT_COPY(left,right)  mat->col_mat[left] = mat->col_mat[right]\n#define COL_MAT_MOVE(to,from,rec) MEMMOVE(&(mat->col_mat[to]),&(mat->col_mat[from]),rec)\n#define COL_MAT2_COLNR(item)      (mat2->col_mat[item].colnr)\n#define COL_MAT2_ROWNR(item)      (mat2->col_mat[item].rownr)\n#define COL_MAT2_VALUE(item)      (mat2->col_mat[item].value)\n#define matRowColStep             (sizeof(MATitem)/sizeof(int))\n#define matValueStep              (sizeof(MATitem)/sizeof(REAL))\n\n#else /* if MatrixColAccess==CAM_Vector */\n#define SET_MAT_ijA(item,i,j,A)   mat->col_mat_rownr[item] = i; \\\n                                  mat->col_mat_colnr[item] = j; \\\n                                  mat->col_mat_value[item] = A\n#define COL_MAT_COLNR(item)       (mat->col_mat_colnr[item])\n#define COL_MAT_ROWNR(item)       (mat->col_mat_rownr[item])\n#define COL_MAT_VALUE(item)       (mat->col_mat_value[item])\n#define COL_MAT_COPY(left,right)  COL_MAT_COLNR(left) = COL_MAT_COLNR(right); \\\n                                  COL_MAT_ROWNR(left) = COL_MAT_ROWNR(right); \\\n                                  COL_MAT_VALUE(left) = COL_MAT_VALUE(right)\n#define COL_MAT_MOVE(to,from,rec) MEMMOVE(&COL_MAT_COLNR(to),&COL_MAT_COLNR(from),rec); \\\n                                  MEMMOVE(&COL_MAT_ROWNR(to),&COL_MAT_ROWNR(from),rec); \\\n                                  MEMMOVE(&COL_MAT_VALUE(to),&COL_MAT_VALUE(from),rec)\n#define COL_MAT2_COLNR(item)      (mat2->col_mat_colnr[item])\n#define COL_MAT2_ROWNR(item)      (mat2->col_mat_rownr[item])\n#define COL_MAT2_VALUE(item)      (mat2->col_mat_value[item])\n#define matRowColStep             1\n#define matValueStep              1\n\n#endif\n\n\n/* Matrix row access macros to be able to easily change storage model */\n#define RAM_Index                 0\n#define RAM_FullCopy              1\n#define MatrixRowAccess           RAM_Index\n\n#if MatrixRowAccess==RAM_Index\n#define ROW_MAT_COLNR(item)       COL_MAT_COLNR(mat->row_mat[item])\n#define ROW_MAT_ROWNR(item)       COL_MAT_ROWNR(mat->row_mat[item])\n#define ROW_MAT_VALUE(item)       COL_MAT_VALUE(mat->row_mat[item])\n\n#elif MatrixColAccess==CAM_Record\n#define ROW_MAT_COLNR(item)       (mat->row_mat[item].colnr)\n#define ROW_MAT_ROWNR(item)       (mat->row_mat[item].rownr)\n#define ROW_MAT_VALUE(item)       (mat->row_mat[item].value)\n\n#else /* if MatrixColAccess==CAM_Vector */\n#define ROW_MAT_COLNR(item)       (mat->row_mat_colnr[item])\n#define ROW_MAT_ROWNR(item)       (mat->row_mat_rownr[item])\n#define ROW_MAT_VALUE(item)       (mat->row_mat_value[item])\n\n#endif\n\n\ntypedef struct _MATrec\n{\n  /* Owner reference */\n  lprec     *lp;\n\n  /* Active dimensions */\n  int       rows;\n  int       columns;\n\n  /* Allocated memory */\n  int       rows_alloc;\n  int       columns_alloc;\n  int       mat_alloc;          /* The allocated size for matrix sized structures */\n\n  /* Sparse problem matrix storage */\n#if MatrixColAccess==CAM_Record\n  MATitem   *col_mat;           /* mat_alloc : The sparse data storage */\n#else /*MatrixColAccess==CAM_Vector*/\n  int       *col_mat_colnr;\n  int       *col_mat_rownr;\n  REAL      *col_mat_value;\n#endif\n  int       *col_end;           /* columns_alloc+1 : col_end[i] is the index of the\n                                   first element after column i; column[i] is stored\n                                   in elements col_end[i-1] to col_end[i]-1 */\n  int       *col_tag;           /* user-definable tag associated with each column */\n\n#if MatrixRowAccess==RAM_Index\n  int       *row_mat;           /* mat_alloc : From index 0, row_mat contains the\n                                   row-ordered index of the elements of col_mat */\n#elif MatrixColAccess==CAM_Record\n  MATitem   *row_mat;           /* mat_alloc : From index 0, row_mat contains the\n                                   row-ordered copy of the elements in col_mat */\n#else /*if MatrixColAccess==CAM_Vector*/\n  int       *row_mat_colnr;\n  int       *row_mat_rownr;\n  REAL      *row_mat_value;\n#endif\n  int       *row_end;           /* rows_alloc+1 : row_end[i] is the index of the\n                                   first element in row_mat after row i */\n  int       *row_tag;           /* user-definable tag associated with each row */\n\n  REAL      *colmax;            /* Array of maximum values of each column */\n  REAL      *rowmax;            /* Array of maximum values of each row */\n\n  REAL      epsvalue;           /* Zero element rejection threshold */\n  REAL      infnorm;            /* The largest absolute value in the matrix */\n  REAL      dynrange;\n  MYBOOL    row_end_valid;      /* TRUE if row_end & row_mat are valid */\n  MYBOOL    is_roworder;        /* TRUE if the current (temporary) matrix order is row-wise */\n\n} MATrec;\n\ntypedef struct _DeltaVrec\n{\n  lprec     *lp;\n  int       activelevel;\n  MATrec    *tracker;\n} DeltaVrec;\n\n\n#ifdef __cplusplus\n__EXTERN_C {\n#endif\n\n/* Sparse matrix routines */\nSTATIC MATrec *mat_create(lprec *lp, int rows, int columns, REAL epsvalue);\nSTATIC MYBOOL mat_memopt(MATrec *mat, int rowextra, int colextra, int nzextra);\nSTATIC void mat_free(MATrec **matrix);\nSTATIC MYBOOL inc_matrow_space(MATrec *mat, int deltarows);\nSTATIC int mat_mapreplace(MATrec *mat, LLrec *rowmap, LLrec *colmap, MATrec *insmat);\nSTATIC int mat_matinsert(MATrec *mat, MATrec *insmat);\nSTATIC int mat_zerocompact(MATrec *mat);\nSTATIC int mat_rowcompact(MATrec *mat, MYBOOL dozeros);\nSTATIC int mat_colcompact(MATrec *mat, int prev_rows, int prev_cols);\nSTATIC MYBOOL inc_matcol_space(MATrec *mat, int deltacols);\nSTATIC MYBOOL inc_mat_space(MATrec *mat, int mindelta);\nSTATIC int mat_shiftrows(MATrec *mat, int *bbase, int delta, LLrec *varmap);\nSTATIC int mat_shiftcols(MATrec *mat, int *bbase, int delta, LLrec *varmap);\nSTATIC MATrec *mat_extractmat(MATrec *mat, LLrec *rowmap, LLrec *colmap, MYBOOL negated);\nSTATIC int mat_appendrow(MATrec *mat, int count, REAL *row, int *colno, REAL mult, MYBOOL checkrowmode);\nSTATIC int mat_appendcol(MATrec *mat, int count, REAL *column, int *rowno, REAL mult, MYBOOL checkrowmode);\nMYBOOL mat_get_data(lprec *lp, int matindex, MYBOOL isrow, int **rownr, int **colnr, REAL **value);\nMYBOOL mat_set_rowmap(MATrec *mat, int row_mat_index, int rownr, int colnr, int col_mat_index);\nSTATIC MYBOOL mat_indexrange(MATrec *mat, int index, MYBOOL isrow, int *startpos, int *endpos);\nSTATIC MYBOOL mat_validate(MATrec *mat);\nSTATIC MYBOOL mat_equalRows(MATrec *mat, int baserow, int comprow);\nSTATIC int mat_findelm(MATrec *mat, int row, int column);\nSTATIC int mat_findins(MATrec *mat, int row, int column, int *insertpos, MYBOOL validate);\nSTATIC void mat_multcol(MATrec *mat, int col_nr, REAL mult, MYBOOL DoObj);\nSTATIC REAL mat_getitem(MATrec *mat, int row, int column);\nSTATIC MYBOOL mat_setitem(MATrec *mat, int row, int column, REAL value);\nSTATIC MYBOOL mat_additem(MATrec *mat, int row, int column, REAL delta);\nSTATIC MYBOOL mat_setvalue(MATrec *mat, int Row, int Column, REAL Value, MYBOOL doscale);\nSTATIC int mat_nonzeros(MATrec *mat);\nSTATIC int mat_collength(MATrec *mat, int colnr);\nSTATIC int mat_rowlength(MATrec *mat, int rownr);\nSTATIC void mat_multrow(MATrec *mat, int row_nr, REAL mult);\nSTATIC void mat_multadd(MATrec *mat, REAL *lhsvector, int varnr, REAL mult);\nSTATIC MYBOOL mat_setrow(MATrec *mat, int rowno, int count, REAL *row, int *colno, MYBOOL doscale, MYBOOL checkrowmode);\nSTATIC MYBOOL mat_setcol(MATrec *mat, int colno, int count, REAL *column, int *rowno, MYBOOL doscale, MYBOOL checkrowmode);\nSTATIC MYBOOL mat_mergemat(MATrec *target, MATrec *source, MYBOOL usecolmap);\nSTATIC int mat_checkcounts(MATrec *mat, int *rownum, int *colnum, MYBOOL freeonexit);\nSTATIC int mat_expandcolumn(MATrec *mat, int colnr, REAL *column, int *nzlist, MYBOOL signedA);\nSTATIC MYBOOL mat_computemax(MATrec *mat);\nSTATIC MYBOOL mat_transpose(MATrec *mat);\n\n/* Refactorization and recomputation routine */\nMYBOOL __WINAPI invert(lprec *lp, MYBOOL shiftbounds, MYBOOL final);\n\n/* Vector compression and expansion routines */\nSTATIC MYBOOL vec_compress(REAL *densevector, int startpos, int endpos, REAL epsilon, REAL *nzvector, int *nzindex);\nSTATIC MYBOOL vec_expand(REAL *nzvector, int *nzindex, REAL *densevector, int startpos, int endpos);\n\n/* Sparse matrix products */\nSTATIC MYBOOL get_colIndexA(lprec *lp, int varset, int *colindex, MYBOOL append);\nSTATIC int prod_Ax(lprec *lp, int *coltarget, REAL *input, int *nzinput, REAL roundzero, REAL ofscalar, REAL *output, int *nzoutput, int roundmode);\nSTATIC int prod_xA(lprec *lp, int *coltarget, REAL *input, int *nzinput, REAL roundzero, REAL ofscalar, REAL *output, int *nzoutput, int roundmode);\nSTATIC MYBOOL prod_xA2(lprec *lp, int *coltarget, REAL *prow, REAL proundzero, int *pnzprow,\n                                                  REAL *drow, REAL droundzero, int *dnzdrow, REAL ofscalar, int roundmode);\n\n/* Equation solution */\nSTATIC MYBOOL fimprove(lprec *lp, REAL *pcol, int *nzidx, REAL roundzero);\nSTATIC void ftran(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero);\nSTATIC MYBOOL bimprove(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero);\nSTATIC void btran(lprec *lp, REAL *rhsvector, int *nzidx, REAL roundzero);\n\n/* Combined equation solution and matrix product for simplex operations */\nSTATIC MYBOOL fsolve(lprec *lp, int varin, REAL *pcol, int *nzidx, REAL roundzero, REAL ofscalar, MYBOOL prepareupdate);\nSTATIC MYBOOL bsolve(lprec *lp, int row_nr, REAL *rhsvector, int *nzidx, REAL roundzero, REAL ofscalar);\nSTATIC void bsolve_xA2(lprec *lp, int* coltarget,\n                                  int row_nr1, REAL *vector1, REAL roundzero1, int *nzvector1,\n                                  int row_nr2, REAL *vector2, REAL roundzero2, int *nzvector2, int roundmode);\n\n/* Change-tracking routines (primarily for B&B and presolve) */\nSTATIC DeltaVrec *createUndoLadder(lprec *lp, int levelitems, int maxlevels);\nSTATIC int incrementUndoLadder(DeltaVrec *DV);\nSTATIC MYBOOL modifyUndoLadder(DeltaVrec *DV, int itemno, REAL target[], REAL newvalue);\nSTATIC int countsUndoLadder(DeltaVrec *DV);\nSTATIC int restoreUndoLadder(DeltaVrec *DV, REAL target[]);\nSTATIC int decrementUndoLadder(DeltaVrec *DV);\nSTATIC MYBOOL freeUndoLadder(DeltaVrec **DV);\n\n/* Specialized presolve undo functions */\nSTATIC MYBOOL appendUndoPresolve(lprec *lp, MYBOOL isprimal, REAL beta, int colnrDep);\nSTATIC MYBOOL addUndoPresolve(lprec *lp, MYBOOL isprimal, int colnrElim, REAL alpha, REAL beta, int colnrDep);\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* HEADER_lp_matrix */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_mipbb.c",
    "content": "\n/*\n    Mixed integer programming optimization drivers for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Michel Berkelaar (to lp_solve v3.2)\n                   Kjell Eikland    (v4.0 and forward)\n    Contact:\n    License terms: LGPL.\n\n    Requires:      string.h, float.h, commonlib.h, lp_lib.h, lp_report.h,\n                   lp_simplex.h\n\n    Release notes:\n    v5.0.0 31 January 2004      New unit isolating B&B routines.\n    v5.0.1 01 February 2004     Complete rewrite into non-recursive version.\n    v5.0.2 05 April 2004        Expanded pseudocosting with options for MIP fraction\n                                counts and \"cost/benefit\" ratio (KE special!).\n                                Added GUB functionality based on SOS structures.\n    v5.0.3    1 May 2004        Changed routine names to be more intuitive.\n    v5.0.4    15 May 2004       Added functinality to pack bounds in order to\n                                conserve memory in B&B-processing large MIP models.\n    v5.1.0    25 July 2004      Added functions for dynamic cut generation.\n    v5.2.0    15 December 2004  Added functions for reduced cost variable fixing\n                                and converted to delta-model of B&B bound storage.\n   ----------------------------------------------------------------------------------\n*/\n\n#include <string.h>\n#include <float.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_scale.h\"\n#include \"lp_report.h\"\n#include \"lp_simplex.h\"\n#include \"lp_mipbb.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n/* Allocation routine for the BB record structure */\nSTATIC BBrec *create_BB(lprec *lp, BBrec *parentBB, MYBOOL dofullcopy)\n{\n  BBrec *newBB;\n\n  newBB = (BBrec *) calloc(1, sizeof(*newBB));\n  if(newBB != NULL) {\n\n    if(parentBB == NULL) {\n      allocREAL(lp, &newBB->upbo,  lp->sum + 1, FALSE);\n      allocREAL(lp, &newBB->lowbo, lp->sum + 1, FALSE);\n      MEMCOPY(newBB->upbo,  lp->orig_upbo,  lp->sum + 1);\n      MEMCOPY(newBB->lowbo, lp->orig_lowbo, lp->sum + 1);\n    }\n    else if(dofullcopy) {\n      allocREAL(lp, &newBB->upbo,  lp->sum + 1, FALSE);\n      allocREAL(lp, &newBB->lowbo, lp->sum + 1, FALSE);\n      MEMCOPY(newBB->upbo,  parentBB->upbo,  lp->sum + 1);\n      MEMCOPY(newBB->lowbo, parentBB->lowbo, lp->sum + 1);\n    }\n    else {\n      newBB->upbo  = parentBB->upbo;\n      newBB->lowbo = parentBB->lowbo;\n    }\n    newBB->contentmode = dofullcopy;\n\n    newBB->lp = lp;\n\n    /* Set parent by default, but not child */\n    newBB->parent = parentBB;\n\n  }\n  return( newBB );\n}\n\n\n/* Pushing and popping routines for the B&B structure */\n\nSTATIC BBrec *push_BB(lprec *lp, BBrec *parentBB, int varno, int vartype, int varcus)\n/* Push ingoing bounds and B&B data onto the stack */\n{\n  BBrec *newBB;\n\n  /* Do initialization and updates */\n  if(parentBB == NULL)\n    parentBB = lp->bb_bounds;\n  newBB = create_BB(lp, parentBB, FALSE);\n  if(newBB != NULL) {\n\n    newBB->varno = varno;\n    newBB->vartype = vartype;\n    newBB->lastvarcus = varcus;\n    incrementUndoLadder(lp->bb_lowerchange);\n    newBB->LBtrack++;\n    incrementUndoLadder(lp->bb_upperchange);\n    newBB->UBtrack++;\n\n    /* Adjust variable fixing/bound tightening based on the last reduced cost */\n    if((parentBB != NULL) && (parentBB->lastrcf > 0)) {\n      MYBOOL isINT;\n      int    k, ii, nfixed = 0, ntighten = 0;\n      REAL   deltaUL;\n\n      for(k = 1; k <= lp->nzdrow[0]; k++) {\n        ii = lp->nzdrow[k];\n#ifdef UseMilpSlacksRCF  /* Check if we should include ranged constraints */\n        isINT = FALSE;\n#else\n        if(ii <= lp->rows)\n          continue;\n        isINT = is_int(lp, ii-lp->rows);\n#endif\n#ifndef UseMilpExpandedRCF  /* Don't include non-integers if it is not defined */\n        if(!isINT)\n          continue;\n#endif\n        switch(abs(rcfbound_BB(newBB, ii, isINT, &deltaUL, NULL))) {\n          case LE: SETMIN(deltaUL, newBB->upbo[ii]);\n                   SETMAX(deltaUL, newBB->lowbo[ii]);\n                   modifyUndoLadder(lp->bb_upperchange, ii, newBB->upbo, deltaUL);\n                   break;\n          case GE: SETMAX(deltaUL, newBB->lowbo[ii]);\n                   SETMIN(deltaUL, newBB->upbo[ii]);\n                   modifyUndoLadder(lp->bb_lowerchange, ii, newBB->lowbo, deltaUL);\n                   break;\n          default: continue;\n        }\n        if(newBB->upbo[ii] == newBB->lowbo[ii])\n          nfixed++;\n        else\n          ntighten++;\n      }\n      if(lp->bb_trace) {\n        report(lp, DETAILED,\n                 \"push_BB: Used reduced cost to fix %d variables and tighten %d bounds\\n\",\n                  nfixed, ntighten);\n      }\n    }\n\n    /* Handle case where we are pushing at the end */\n    if(parentBB == lp->bb_bounds)\n      lp->bb_bounds = newBB;\n    /* Handle case where we are pushing in the middle */\n    else\n      newBB->child = parentBB->child;\n    if(parentBB != NULL)\n      parentBB->child = newBB;\n\n    lp->bb_level++;\n    if(lp->bb_level > lp->bb_maxlevel)\n      lp->bb_maxlevel = lp->bb_level;\n\n    if(!initbranches_BB(newBB))\n      newBB = pop_BB(newBB);\n    else if(MIP_count(lp) > 0) {\n      if( (lp->bb_level <= 1) && (lp->bb_varactive == NULL) &&\n          (!allocINT(lp, &lp->bb_varactive, lp->columns+1, TRUE) ||\n           !initcuts_BB(lp)) )\n        newBB = pop_BB(newBB);\n      if(varno > 0) {\n        lp->bb_varactive[varno-lp->rows]++;\n      }\n    }\n  }\n  return( newBB );\n}\n\nSTATIC MYBOOL free_BB(BBrec **BB)\n{\n  MYBOOL parentreturned = FALSE;\n\n  if((BB != NULL) && (*BB != NULL)) {\n    BBrec *parent = (*BB)->parent;\n\n    if((parent == NULL) || (*BB)->contentmode) {\n      FREE((*BB)->upbo);\n      FREE((*BB)->lowbo);\n    }\n    FREE((*BB)->varmanaged);\n    FREE(*BB);\n\n    parentreturned = (MYBOOL) (parent != NULL);\n    if(parentreturned)\n      *BB = parent;\n\n  }\n  return( parentreturned );\n}\n\nSTATIC BBrec *pop_BB(BBrec *BB)\n/* Pop / free the previously \"pushed\" / saved bounds */\n{\n  int   k;\n  BBrec *parentBB;\n  lprec *lp = BB->lp;\n\n  if(BB == NULL)\n    return( BB );\n\n  /* Handle case where we are popping the end of the chain */\n  parentBB = BB->parent;\n  if(BB == lp->bb_bounds) {\n    lp->bb_bounds = parentBB;\n    if(parentBB != NULL)\n      parentBB->child = NULL;\n  }\n  /* Handle case where we are popping inside or at the beginning of the chain */\n  else {\n    if(parentBB != NULL)\n      parentBB->child = BB->child;\n    if(BB->child != NULL)\n      BB->child->parent = parentBB;\n  }\n\n  /* Unwind other variables */\n  if(lp->bb_upperchange != NULL) {\n    restoreUndoLadder(lp->bb_upperchange, BB->upbo);\n    for(; BB->UBtrack > 0; BB->UBtrack--) {\n      decrementUndoLadder(lp->bb_upperchange);\n      restoreUndoLadder(lp->bb_upperchange, BB->upbo);\n    }\n  }\n  if(lp->bb_lowerchange != NULL) {\n    restoreUndoLadder(lp->bb_lowerchange, BB->lowbo);\n    for(; BB->LBtrack > 0; BB->LBtrack--) {\n      decrementUndoLadder(lp->bb_lowerchange);\n      restoreUndoLadder(lp->bb_lowerchange, BB->lowbo);\n    }\n  }\n  lp->bb_level--;\n  k = BB->varno - lp->rows;\n  if(lp->bb_level == 0) {\n    if(lp->bb_varactive != NULL) {\n      FREE(lp->bb_varactive);\n      freecuts_BB(lp);\n    }\n    if(lp->int_vars+lp->sc_vars > 0)\n      free_pseudocost(lp);\n    pop_basis(lp, FALSE);\n    lp->rootbounds = NULL;\n  }\n  else\n    lp->bb_varactive[k]--;\n\n  /* Undo SOS/GUB markers */\n  if(BB->isSOS && (BB->vartype != BB_INT))\n    SOS_unmark(lp->SOS, 0, k);\n  else if(BB->isGUB)\n    SOS_unmark(lp->GUB, 0, k);\n\n  /* Undo the SC marker */\n  if(BB->sc_canset)\n    lp->sc_lobound[k] *= -1;\n\n  /* Pop the associated basis */\n#if 1\n  /* Original version that does not restore previous basis */\n  pop_basis(lp, FALSE);\n#else\n  /* Experimental version that restores previous basis */\n  pop_basis(lp, BB->isSOS);\n#endif\n\n  /* Finally free the B&B object */\n  free_BB(&BB);\n\n  /* Return the parent BB */\n  return( parentBB );\n}\n\n/* Here are heuristic routines to see if we need bother with branching further\n\n    1. A probing routine to see of the best OF can be better than incumbent\n    2. A presolve routine to fix other variables and detect infeasibility\n\n   THIS IS INACTIVE CODE, PLACEHOLDERS FOR FUTURE DEVELOPMENT!!! */\nSTATIC REAL probe_BB(BBrec *BB)\n{\n  int  i, ii;\n  REAL coefOF, sum = 0;\n  lprec *lp = BB->lp;\n\n  /* Loop over all ints to see if the best possible solution\n     stands any chance of being better than the incumbent solution */\n  if(lp->solutioncount == 0)\n    return( lp->infinite );\n  for(i = 1; i <= lp->columns; i++) {\n    if(!is_int(lp, i))\n      continue;\n    ii = lp->rows + i;\n    coefOF = lp->obj[i];\n    if(coefOF < 0) {\n      if(is_infinite(lp, BB->lowbo[ii]))\n        return( lp->infinite );\n      sum += coefOF * (lp->solution[ii]-BB->lowbo[ii]);\n    }\n    else {\n      if(is_infinite(lp, BB->upbo[ii]))\n        return( lp->infinite );\n      sum += coefOF * (BB->upbo[ii] - lp->solution[ii]);\n    }\n  }\n  return( sum );\n}\n\nSTATIC REAL presolve_BB(BBrec *BB)\n{\n  (void)BB;\n  return( 0 );\n}\n\n/* Node and branch management routines */\nSTATIC MYBOOL initbranches_BB(BBrec *BB)\n{\n  REAL   new_bound, temp;\n  int    k;\n  lprec  *lp = BB->lp;\n\n /* Create and initialize local bounds and basis */\n  BB->nodestatus = NOTRUN;\n  BB->noderesult = lp->infinite;\n  push_basis(lp, NULL, NULL, NULL);\n\n /* Set default number of branches at the current B&B branch */\n  if(BB->vartype == BB_REAL)\n    BB->nodesleft = 1;\n\n  else {\n   /* The default is a binary up-low branching */\n    BB->nodesleft = 2;\n\n   /* Initialize the MIP status code pair and set reference values */\n    k = BB->varno - lp->rows;\n    BB->lastsolution = lp->solution[BB->varno];\n\n   /* Determine if we must process in the B&B SOS mode */\n    BB->isSOS = (MYBOOL) ((BB->vartype == BB_SOS) || SOS_is_member(lp->SOS, 0, k));\n#ifdef Paranoia\n    if((BB->vartype == BB_SOS) && !SOS_is_member(lp->SOS, 0, k))\n      report(lp, SEVERE, \"initbranches_BB: Inconsistent identification of SOS variable %s (%d)\\n\",\n                         get_col_name(lp, k), k);\n#endif\n\n   /* Check if we have a GUB-member variable that needs a triple-branch */\n    BB->isGUB = (MYBOOL) ((BB->vartype == BB_INT) && SOS_can_activate(lp->GUB, 0, k));\n    if(BB->isGUB) {\n      /* Obtain variable index list from applicable GUB - now the first GUB is used,\n        but we could also consider selecting the longest */\n      BB->varmanaged = SOS_get_candidates(lp->GUB, -1, k, TRUE, BB->upbo, BB->lowbo);\n      BB->nodesleft++;\n    }\n\n\n   /* Set local pruning info, automatic, or user-defined strategy */\n    if(BB->vartype == BB_SOS) {\n      if(!SOS_can_activate(lp->SOS, 0, k)) {\n        BB->nodesleft--;\n        BB->isfloor = TRUE;\n      }\n      else\n        BB->isfloor = (MYBOOL) (BB->lastsolution == 0);\n    }\n\n    /* First check if the user wishes to select the branching direction */\n    else if(lp->bb_usebranch != NULL)\n      BB->isfloor = (MYBOOL) lp->bb_usebranch(lp, lp->bb_branchhandle, k);\n\n    /* Otherwise check if we should do automatic branching */\n    else if(get_var_branch(lp, k) == BRANCH_AUTOMATIC) {\n      new_bound = modf(BB->lastsolution/get_pseudorange(lp->bb_PseudoCost, k, BB->vartype), &temp);\n      if(isnan(new_bound))\n        new_bound = 0;\n      else if(new_bound < 0)\n        new_bound += 1.0;\n      BB->isfloor = (MYBOOL) (new_bound <= 0.5);\n\n      /* Set direction by OF value; note that a zero-value in\n         the OF gives priority to floor_first = TRUE */\n      if(is_bb_mode(lp, NODE_GREEDYMODE)) {\n        if(is_bb_mode(lp, NODE_PSEUDOCOSTMODE))\n          BB->sc_bound = get_pseudonodecost(lp->bb_PseudoCost, k, BB->vartype, BB->lastsolution);\n        else\n          BB->sc_bound = mat_getitem(lp->matA, 0, k);\n        new_bound -= 0.5;\n        BB->sc_bound *= new_bound;\n        BB->isfloor = (MYBOOL) (BB->sc_bound > 0);\n      }\n      /* Set direction by pseudocost (normally used in tandem with NODE_PSEUDOxxxSELECT) */\n      else if(is_bb_mode(lp, NODE_PSEUDOCOSTMODE)) {\n        BB->isfloor = (MYBOOL) (get_pseudobranchcost(lp->bb_PseudoCost, k, TRUE) >\n                                get_pseudobranchcost(lp->bb_PseudoCost, k, FALSE));\n        if(is_maxim(lp))\n          BB->isfloor = !BB->isfloor;\n      }\n\n      /* Check for reversal */\n      if(is_bb_mode(lp, NODE_BRANCHREVERSEMODE))\n        BB->isfloor = !BB->isfloor;\n    }\n    else\n      BB->isfloor = (MYBOOL) (get_var_branch(lp, k) == BRANCH_FLOOR);\n\n    /* SC logic: If the current SC variable value is in the [0..NZLOBOUND> range, then\n\n      UP: Set lower bound to NZLOBOUND, upper bound is the original\n      LO: Fix the variable by setting upper/lower bound to zero\n\n      ... indicate that the variable is B&B-active by reversing sign of sc_lobound[]. */\n    new_bound = fabs(lp->sc_lobound[k]);\n    BB->sc_bound = new_bound;\n    BB->sc_canset = (MYBOOL) (new_bound != 0);\n\n   /* Must make sure that we handle fractional lower bounds properly;\n      also to ensure that we do a full binary tree search */\n    new_bound = unscaled_value(lp, new_bound, BB->varno);\n    if(is_int(lp, k) && ((new_bound > 0) &&\n                         (BB->lastsolution > floor(new_bound)))) {\n      if(BB->lastsolution < ceil(new_bound))\n        BB->lastsolution += 1;\n      modifyUndoLadder(lp->bb_lowerchange, BB->varno, BB->lowbo,\n                       scaled_floor(lp, BB->varno, BB->lastsolution, 1));\n    }\n  }\n\n  /* Now initialize the brances and set to first */\n  return( fillbranches_BB(BB) );\n}\n\nSTATIC MYBOOL fillbranches_BB(BBrec *BB)\n{\n  int    K, k;\n  REAL   ult_upbo, ult_lowbo;\n  REAL   new_bound, SC_bound, intmargin = BB->lp->epsprimal;\n  lprec  *lp = BB->lp;\n  MYBOOL OKstatus = FALSE;\n\n  if(lp->bb_break || userabort(lp, MSG_MILPSTRATEGY))\n    return( OKstatus );\n\n  K = BB->varno;\n  if(K > 0) {\n\n  /* Shortcut variables */\n    k = BB->varno - lp->rows;\n    ult_upbo  = lp->orig_upbo[K];\n    ult_lowbo = lp->orig_lowbo[K];\n    SC_bound  = unscaled_value(lp, BB->sc_bound, K);\n\n    /* First, establish the upper bound to be applied (when isfloor == TRUE)\n       --------------------------------------------------------------------- */\n/*SetUB:*/\n    BB->UPbound = lp->infinite;\n\n    /* Handle SC-variables for the [0-LoBound> range */\n    if((SC_bound > 0) && (fabs(BB->lastsolution) < SC_bound-intmargin)) {\n      new_bound = 0;\n    }\n    /* Handle pure integers (non-SOS, non-SC) */\n    else if(BB->vartype == BB_INT) {\n#if 1\n      if(((ult_lowbo >= 0) &&\n          ((floor(BB->lastsolution) < /* Skip cases where the lower bound becomes violated */\n            unscaled_value(lp, MAX(ult_lowbo, fabs(lp->sc_lobound[k])), K)-intmargin))) ||\n         ((ult_upbo <= 0) &&   /*  Was  ((ult_lowbo < 0) && */\n          ((floor(BB->lastsolution) > /* Skip cases where the upper bound becomes violated */\n            unscaled_value(lp, MIN(ult_upbo, -fabs(lp->sc_lobound[k])), K)-intmargin)))) {\n#else\n      if((floor(BB->lastsolution) <  /* Skip cases where the lower bound becomes violated */\n          unscaled_value(lp, MAX(ult_lowbo, fabs(lp->sc_lobound[k])), K)-intmargin)) {\n#endif\n        BB->nodesleft--;\n        goto SetLB;\n      }\n      new_bound = scaled_floor(lp, K, BB->lastsolution, 1);\n    }\n    else if(BB->isSOS) {           /* Handle all SOS variants */\n      new_bound = ult_lowbo;\n      if(is_int(lp, k))\n        new_bound = scaled_ceil(lp, K, unscaled_value(lp, new_bound, K), -1);\n    }\n    else                           /* Handle all other variable incarnations */\n      new_bound = BB->sc_bound;\n\n    /* Check if the new bound might conflict and possibly make adjustments */\n    if(new_bound < BB->lowbo[K])\n      new_bound = BB->lowbo[K] - my_avoidtiny(new_bound-BB->lowbo[K], intmargin);\n    if(new_bound < BB->lowbo[K]) {\n#ifdef Paranoia\n      debug_print(lp,\n          \"fillbranches_BB: New upper bound value %g conflicts with old lower bound %g\\n\",\n          new_bound, BB->lowbo[K]);\n#endif\n      BB->nodesleft--;\n      goto SetLB;\n    }\n#ifdef Paranoia\n    /* Do additional consistency checking */\n    else if(!check_if_less(lp, new_bound, BB->upbo[K], K)) {\n      BB->nodesleft--;\n      goto SetLB;\n    }\n#endif\n    /* Bound (at least near) feasible */\n    else {\n      /* Makes a difference with models like QUEEN\n         (note consistent use of epsint for scaled integer variables) */\n      if(fabs(new_bound - BB->lowbo[K]) < intmargin*SCALEDINTFIXRANGE)\n        new_bound = BB->lowbo[K];\n    }\n\n    BB->UPbound = new_bound;\n\n\n    /* Next, establish the lower bound to be applied (when isfloor == FALSE)\n       --------------------------------------------------------------------- */\nSetLB:\n    BB->LObound = -lp->infinite;\n\n    /* Handle SC-variables for the [0-LoBound> range */\n    if((SC_bound > 0) && (fabs(BB->lastsolution) < SC_bound)) {\n      if(is_int(lp, k))\n        new_bound = scaled_ceil(lp, K, SC_bound, 1);\n      else\n        new_bound = BB->sc_bound;\n    }\n    /* Handle pure integers (non-SOS, non-SC, but Ok for GUB!) */\n    else if(BB->vartype == BB_INT) {\n      if(((ceil(BB->lastsolution) == BB->lastsolution)) ||    /* Skip branch 0 if the current solution is integer */\n         (ceil(BB->lastsolution) >   /* Skip cases where the upper bound becomes violated */\n          unscaled_value(lp, ult_upbo, K)+intmargin) ||\n          (BB->isSOS && (BB->lastsolution == 0))) {           /* Don't branch 0 since this is handled in SOS logic */\n        BB->nodesleft--;\n        goto Finish;\n      }\n      new_bound = scaled_ceil(lp, K, BB->lastsolution, 1);\n    }\n    else if(BB->isSOS) {             /* Handle all SOS variants */\n      if(SOS_is_member_of_type(lp->SOS, k, SOS3))\n        new_bound = scaled_floor(lp, K, 1, 1);\n      else {\n        new_bound = ult_lowbo;\n        if(is_int(lp, k))\n          new_bound = scaled_floor(lp, K, unscaled_value(lp, new_bound, K), 1);\n        /* If we have a high-order SOS (SOS3+) and this variable is \"intermediate\"\n          between members previously lower-bounded at a non-zero level, then we should\n          set this and similar neighbouring variables at non-zero lowbo-values (remember\n          that SOS3+ members are all either integers or semi-continuous). Flag this\n          situation and prune tree, since we cannot lower-bound. */\n        if((lp->SOS->maxorder > 2) && (BB->lastsolution == 0) &&\n           SOS_is_member_of_type(lp->SOS, k, SOSn)) {\n          BB->isSOS = AUTOMATIC;\n        }\n      }\n    }\n    else                              /* Handle all other variable incarnations */\n      new_bound = BB->sc_bound;\n\n    /* Check if the new bound might conflict and possibly make adjustments */\n    if(new_bound > BB->upbo[K])\n      new_bound = BB->upbo[K] + my_avoidtiny(new_bound-BB->upbo[K], intmargin);\n    if(new_bound > BB->upbo[K]) {\n#ifdef Paranoia\n      debug_print(lp,\n        \"fillbranches_BB: New lower bound value %g conflicts with old upper bound %g\\n\",\n        new_bound, BB->upbo[K]);\n#endif\n      BB->nodesleft--;\n      goto Finish;\n    }\n#ifdef Paranoia\n    /* Do additional consistency checking */\n    else if(!check_if_less(lp, BB->lowbo[K], new_bound, K)) {\n      BB->nodesleft--;\n      goto Finish;\n    }\n#endif\n    /* Bound (at least near-)feasible */\n    else {\n      /* Makes a difference with models like QUEEN\n         (note consistent use of lp->epsprimal for scaled integer variables) */\n      if(fabs(BB->upbo[K]-new_bound) < intmargin*SCALEDINTFIXRANGE)\n        new_bound = BB->upbo[K];\n    }\n\n    BB->LObound = new_bound;\n\n    /* Prepare for the first branch by making sure we are pointing correctly */\nFinish:\n    if(BB->nodesleft > 0) {\n\n      /* Make sure the change tracker levels are \"clean\" for the B&B */\n      if(countsUndoLadder(lp->bb_upperchange) > 0) {\n        incrementUndoLadder(lp->bb_upperchange);\n        BB->UBtrack++;\n      }\n      if(countsUndoLadder(lp->bb_lowerchange) > 0) {\n        incrementUndoLadder(lp->bb_lowerchange);\n        BB->LBtrack++;\n      }\n\n      /* Do adjustments */\n      if((BB->vartype != BB_SOS) && (fabs(BB->LObound-BB->UPbound) < intmargin)) {\n        BB->nodesleft--;\n        if(fabs(BB->lowbo[K]-BB->LObound) < intmargin)\n          BB->isfloor = FALSE;\n        else if(fabs(BB->upbo[K]-BB->UPbound) < intmargin)\n          BB->isfloor = TRUE;\n        else {\n          BB->isfloor = TRUE;\n          report(BB->lp, IMPORTANT, \"fillbranches_BB: Inconsistent equal-valued bounds for %s\\n\",\n                                    get_col_name(BB->lp, k));\n        }\n      }\n      if((BB->nodesleft == 1) &&\n         ((BB->isfloor && (BB->UPbound >= lp->infinite)) ||\n          (!BB->isfloor && (BB->LObound <= -lp->infinite))))\n        BB->isfloor = !BB->isfloor;\n      /* Header initialization */\n      BB->isfloor = !BB->isfloor;\n      while(!OKstatus && /* !userabort(lp, -1) */ lp->spx_status != TIMEOUT && !lp->bb_break && (BB->nodesleft > 0))\n        OKstatus = nextbranch_BB( BB );\n    }\n\n    /* Set an SC variable active, if necessary */\n    if(BB->sc_canset)\n      lp->sc_lobound[k] *= -1;\n\n  }\n  else {\n    BB->nodesleft--;\n    OKstatus = TRUE;\n  }\n\n  return( OKstatus );\n}\n\nSTATIC MYBOOL nextbranch_BB(BBrec *BB)\n{\n  int    k;\n  lprec  *lp = BB->lp;\n  MYBOOL OKstatus = FALSE;\n\n  /* Undo the most recently imposed B&B bounds using the data\n     in the last level of change tracker; this code handles changes\n     to both upper and lower bounds */\n  if(BB->nodessolved > 0) {\n      restoreUndoLadder(lp->bb_upperchange, BB->upbo);\n      restoreUndoLadder(lp->bb_lowerchange, BB->lowbo);\n  }\n\n  if(lp->bb_break || userabort(lp, MSG_MILPSTRATEGY)) {\n    /* Handle the special case of B&B restart;\n       (typically used with the restart after pseudocost initialization) */\n    if((lp->bb_level == 1) && (lp->bb_break == AUTOMATIC)) {\n      lp->bb_break = FALSE;\n      OKstatus = TRUE;\n    }\n    return( OKstatus );\n  }\n\n  if(BB->nodesleft > 0) {\n\n    /* Step and update remaining branch count */\n    k = BB->varno - lp->rows;\n    BB->isfloor = !BB->isfloor;\n    BB->nodesleft--;\n\n    /* Special SOS handling:\n       1) Undo and set new marker for k,\n       2) In case that previous branch was ceiling restore upper bounds of the\n          non-k variables outside of the SOS window set to 0 */\n    if(BB->isSOS && (BB->vartype != BB_INT)) {\n\n      /* First undo previous marker */\n      if((BB->nodessolved > 0) || ((BB->nodessolved == 0) && (BB->nodesleft == 0))) {\n        if(BB->isfloor) {\n          if((BB->nodesleft == 0) && (lp->orig_lowbo[BB->varno] != 0))\n            return( OKstatus );\n        }\n        SOS_unmark(lp->SOS, 0, k);\n      }\n\n      /* Set new SOS marker */\n      if(BB->isfloor) {\n        SOS_set_marked(lp->SOS, 0, k, (MYBOOL) (BB->UPbound != 0));\n        /* Do case of high-order SOS where intervening variables need to be set */\n        if(BB->isSOS == AUTOMATIC) {\n\n/*          SOS_fix_list(lp->SOS, 0, k, BB->lowbo, NULL, AUTOMATIC, lp->bb_lowerchange); */\n        }\n      }\n      else {\n        SOS_set_marked(lp->SOS, 0, k, TRUE);\n        if(SOS_fix_unmarked(lp->SOS, 0, k, BB->upbo, 0, TRUE,\n                            NULL, lp->bb_upperchange) < 0)\n          return( OKstatus );\n      }\n    }\n\n    /* Special GUB handling (three branches):\n       1) Undo and set new marker for k,\n       2) Restore upper bounds of the left/right/all non-k variables\n          set to 0 in the previous branch\n       3) Set new upper bounds for the non-k variables (k is set later) */\n    else if(BB->isGUB) {\n\n      /* First undo previous marker */\n      if(BB->nodessolved > 0)\n        SOS_unmark(lp->GUB, 0, k);\n\n      /* Make sure we take floor bound twice */\n      if((BB->nodesleft == 0) && !BB->isfloor)\n        BB->isfloor = !BB->isfloor;\n\n      /* Handle two floor instances;\n         (selected variable and left/right halves of non-selected variables at 0) */\n      SOS_set_marked(lp->GUB, 0, k, (MYBOOL) !BB->isfloor);\n      if(BB->isfloor) {\n        if(SOS_fix_list(lp->GUB, 0, k, BB->upbo,\n                        BB->varmanaged, (MYBOOL) (BB->nodesleft > 0), lp->bb_upperchange) < 0)\n          return( OKstatus );\n      }\n      /* Handle one ceil instance;\n         (selected variable at 1, all other at 0) */\n      else {\n        if(SOS_fix_unmarked(lp->GUB, 0, k, BB->upbo, 0, TRUE,\n                            NULL, lp->bb_upperchange) < 0)\n          return( OKstatus );\n      }\n    }\n\n    OKstatus = TRUE;\n\n  }\n  /* Initialize simplex status variables */\n  if(OKstatus) {\n    lp->bb_totalnodes++;\n    BB->nodestatus = NOTRUN;\n    BB->noderesult = lp->infinite;\n  }\n  return( OKstatus );\n}\n\n\n/* Cut generation and management routines */\nSTATIC MYBOOL initcuts_BB(lprec *lp)\n{\n  (void)lp;\n  return( TRUE );\n}\n\nSTATIC int updatecuts_BB(lprec *lp)\n{\n  (void)lp;\n  return( 0 );\n}\n\nSTATIC MYBOOL freecuts_BB(lprec *lp)\n{\n  if(lp->bb_cuttype != NULL)\n    FREE(lp->bb_cuttype);\n  return( TRUE );\n}\n\n/* B&B solver routines */\nSTATIC int solve_LP(lprec *lp, BBrec *BB)\n{\n  int    tilted, restored, status;\n  REAL   testOF, *upbo = BB->upbo, *lowbo = BB->lowbo;\n  BBrec  *perturbed = NULL;\n\n  if(lp->bb_break)\n    return(PROCBREAK);\n\n#ifdef Paranoia\n  debug_print(lp, \"solve_LP: Starting solve for iter %.0f, B&B node level %d.\\n\",\n                   (double) lp->total_iter, lp->bb_level);\n  if(lp->bb_trace &&\n     !validate_bounds(lp, upbo, lowbo))\n    report(lp, SEVERE, \"solve_LP: Inconsistent bounds at iter %.0f, B&B node level %d.\\n\",\n                       (double) lp->total_iter, lp->bb_level);\n#endif\n\n  /* Copy user-specified entering bounds into lp_solve working bounds */\n  impose_bounds(lp, upbo, lowbo);\n\n  /* Restore previously pushed / saved basis for this level if we are in\n     the B&B mode and it is not the first call of the binary tree */\n  if(BB->nodessolved > 1)\n    restore_basis(lp);\n\n  /* Solve and possibly handle degeneracy cases via bound relaxations */\n  status   = RUNNING;\n  tilted   = 0;\n  restored = 0;\n\n  while(status == RUNNING) {\n\n    /* Copy user-specified entering bounds into lp_solve working bounds and run */\n    status = spx_run(lp, (MYBOOL) (tilted+restored > 0));\n    lp->bb_status     = status;\n    lp->spx_perturbed = FALSE;\n\n    if(tilted < 0)\n      break;\n\n    else if((status == OPTIMAL) && (tilted > 0)) {\n      if(lp->spx_trace)\n        report(lp, DETAILED, \"solve_LP: Restoring relaxed bounds at level %d.\\n\",\n                              tilted);\n\n    /* Restore original pre-perturbed problem bounds, and solve again using the basis\n       found for the perturbed problem; also make sure we rebase and recompute. */\n      free_BB(&perturbed);\n      if((perturbed == NULL) || (perturbed == BB)) {\n        perturbed = NULL;\n        impose_bounds(lp, upbo, lowbo);\n      }\n      else\n        impose_bounds(lp, perturbed->upbo, perturbed->lowbo);\n      set_action(&lp->spx_action, ACTION_REBASE | ACTION_RECOMPUTE);\n      BB->UBzerobased = FALSE;\n      if(lp->bb_totalnodes == 0)\n        lp->real_solution = lp->infinite;\n      status = RUNNING;\n      tilted--;\n      restored++;\n      lp->spx_perturbed = TRUE;\n    }\n\n    else if(((lp->bb_level <= 1) ||     is_anti_degen(lp, ANTIDEGEN_DURINGBB)) &&\n            (((status == LOSTFEAS) &&   is_anti_degen(lp, ANTIDEGEN_LOSTFEAS)) ||\n             ((status == INFEASIBLE) && is_anti_degen(lp, ANTIDEGEN_INFEASIBLE)) ||\n             ((status == NUMFAILURE) && is_anti_degen(lp, ANTIDEGEN_NUMFAILURE)) ||\n             ((status == DEGENERATE) && is_anti_degen(lp, ANTIDEGEN_STALLING)))) {\n     /* Allow up to .. consecutive relaxations for non-B&B phases */\n      if((tilted <= DEF_MAXRELAX) &&                       /* Conventional recovery case,...  */\n         !((tilted == 0) && (restored > DEF_MAXRELAX))) {  /* but not iterating infeasibility */\n\n        /* Create working copy of ingoing bounds if this is the first perturbation */\n        if(tilted == 0)\n          perturbed = BB;\n        perturbed = create_BB(lp, perturbed, TRUE);\n\n        /* Perturb/shift variable bounds; also make sure we rebase and recompute\n           (no refactorization is necessary, since the basis is unchanged) */\n#if 1\n        perturb_bounds(lp, perturbed, TRUE, TRUE, TRUE);\n#else\n        perturb_bounds(lp, perturbed, TRUE, TRUE, FALSE);\n#endif\n        impose_bounds(lp, perturbed->upbo, perturbed->lowbo);\n        set_action(&lp->spx_action, ACTION_REBASE | ACTION_RECOMPUTE);\n        BB->UBzerobased = FALSE;\n        status = RUNNING;\n        tilted++;\n        lp->perturb_count++;\n        lp->spx_perturbed = TRUE;\n        if(lp->spx_trace)\n          report(lp, DETAILED, \"solve_LP: Starting bound relaxation #%d ('%s')\\n\",\n                               tilted, get_statustext(lp, status));\n      }\n      else  {\n        if(lp->spx_trace)\n          report(lp, DETAILED, \"solve_LP: Relaxation limit exceeded in resolving infeasibility\\n\");\n        while((perturbed != NULL) && (perturbed != BB))\n          free_BB(&perturbed);\n        perturbed = NULL;\n      }\n    }\n  }\n\n  /* Handle the different simplex outcomes */\n  if(status != OPTIMAL) {\n    if(lp->bb_level <= 1)\n      lp->bb_parentOF = lp->infinite;\n    if((status == USERABORT) || (status == TIMEOUT)) {\n      /* Construct the last feasible solution, if available */\n      if((lp->solutioncount == 0) &&\n         /*\n            30/01/08 <peno> added MIP_count test because in following situation thing were wrong:\n             - The model contains integers\n             - A break at first is set\n             - A timeout is set\n             - The timeout occurs before a first integer solution is found\n             - When the timeout occurs, the simplex algorithm is in phase 2 and has a feasible (but non-integer) solution, but not optimal yet.\n            If above situation occurs then a (sub-optimal) solution was returned while no integer\n            solution isn't found yet at this time\n         */\n         (MIP_count(lp) == 0) &&\n         ((lp->simplex_mode & (SIMPLEX_Phase2_PRIMAL | SIMPLEX_Phase2_DUAL)) > 0)) {\n        lp->solutioncount++;\n        construct_solution(lp, NULL);\n        transfer_solution(lp, TRUE);\n      }\n      /* Return messages */\n      report(lp, NORMAL, \"\\nlp_solve optimization was stopped %s.\\n\",\n                         ((status == USERABORT) ? \"by the user\" : \"due to time-out\"));\n    }\n    else if(BB->varno == 0)\n      report(lp, NORMAL, \"The model %s\\n\",\n      (status == UNBOUNDED) ? \"is UNBOUNDED\" :\n      ((status == INFEASIBLE) ? \"is INFEASIBLE\" : \"FAILED\"));\n    else {\n#ifdef Paranoia\n      if((status != FATHOMED) && (status != INFEASIBLE))\n        report(lp, SEVERE, \"spx_solve: Invalid return code %d during B&B\\n\", status);\n#endif\n      /* If we fathomed a node due to an inferior OF having been detected, return infeasible */\n      if(status == FATHOMED)\n        lp->spx_status = INFEASIBLE;\n    }\n  }\n\n  else { /* ... there is a good solution */\n    construct_solution(lp, NULL);\n    if((lp->bb_level <= 1) && (restored > 0))\n      report(lp, DETAILED, \"%s numerics encountered; validate accuracy\\n\",\n                 (restored == 1) ? \"Difficult\" : \"Severe\");\n    /* Handle case where a user bound on the OF was found to\n       have been set too aggressively, giving an infeasible model */\n    if(lp->spx_status != OPTIMAL)\n      status = lp->spx_status;\n\n    else if((lp->bb_totalnodes == 0) && (MIP_count(lp) > 0)) {\n      if(lp->lag_status != RUNNING) {\n        report(lp, NORMAL, \"\\nRelaxed solution  \" RESULTVALUEMASK \" after %10.0f iter is B&B base.\\n\",\n                           lp->solution[0], (double) lp->total_iter);\n        report(lp, NORMAL, \" \\n\");\n      }\n      if((lp->usermessage != NULL) && (lp->msgmask & MSG_LPOPTIMAL)) {\n        REAL *best_solution = lp->best_solution;\n\n        /* transfer_solution(lp, TRUE); */\n        lp->best_solution = lp->solution;\n        lp->usermessage(lp, lp->msghandle, MSG_LPOPTIMAL);\n        lp->best_solution = best_solution;\n      }\n      set_var_priority(lp);\n    }\n\n   /* Check if we have a numeric problem (an earlier version of this code used the\n      absolute difference, but it is not robust for large-valued OFs) */\n    testOF = my_chsign(is_maxim(lp), my_reldiff(lp->solution[0], lp->real_solution));\n    if(testOF < -lp->epsprimal) {\n      report(lp, DETAILED, \"solve_LP: A MIP subproblem returned a value better than the base.\\n\");\n      status = INFEASIBLE;\n      lp->spx_status = status;\n      set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n    }\n    else if(testOF < 0)  /* Avoid problems later (could undo integer roundings, but usually Ok) */\n      lp->solution[0] = lp->real_solution;\n\n  }\n\n  /* status can have the following values:\n     OPTIMAL, SUBOPTIMAL, TIMEOUT, USERABORT, PROCFAIL, UNBOUNDED and INFEASIBLE. */\n\n  return( status );\n} /* solve_LP */\n\nSTATIC BBrec *findself_BB(BBrec *BB)\n{\n  int   varno = BB->varno, vartype = BB->vartype;\n\n  BB = BB->parent;\n  while((BB != NULL) && (BB->vartype != vartype) && (BB->varno != varno))\n    BB = BB->parent;\n  return( BB );\n}\n\n/* Function to determine the opportunity for variable fixing and bound\n   tightening based on a previous best MILP solution and a variable's\n   reduced cost at the current relaxation - inspired by Wolsley */\nSTATIC int rcfbound_BB(BBrec *BB, int varno, MYBOOL isINT, REAL *newbound, MYBOOL *isfeasible)\n{\n  int   i = FR;\n  lprec *lp = BB->lp;\n  REAL  deltaRC, rangeLU, deltaOF, lowbo, upbo;\n\n  /* Make sure we only accept non-basic variables */\n  if(lp->is_basic[varno])\n    return( i );\n\n  /* Make sure we only accept non-fixed variables */\n  lowbo = BB->lowbo[varno];\n  upbo  = BB->upbo[varno];\n  rangeLU = upbo - lowbo;\n\n  if(rangeLU > lp->epsprimal) {\n#if 1      /* v5.5 problematic - Gap between current node and the current best bound */\n    deltaOF = lp->rhs[0] - lp->bb_workOF;\n#elif 0    /* v6 less aggressive - Gap between current best bound and the relaxed problem */\n    deltaOF = my_chsign(is_maxim(lp), lp->real_solution) - lp->bb_workOF;\n#else      /* v6 more aggressive - Gap between current node and the relaxed problem */\n    deltaOF = my_chsign(is_maxim(lp), lp->real_solution) - lp->rhs[0];\n#endif\n\n    deltaRC = my_chsign(!lp->is_lower[varno], lp->drow[varno]);\n    /* Protect against divisions with tiny numbers and stray sign\n       reversals of the reduced cost */\n    if(deltaRC < lp->epspivot)\n      return( i );\n    deltaRC = deltaOF / deltaRC;  /* Should always be a positive number! */\n#ifdef Paranoia\n    if(deltaRC <= 0)\n      report(lp, SEVERE, \"rcfbound_BB: A negative bound fixing level was encountered after node %.0f\\n\",\n                         (double) lp->bb_totalnodes);\n#endif\n\n    /* Check if bound implied by the reduced cost is less than existing range */\n    if(deltaRC < rangeLU + lp->epsint) {\n      if(lp->is_lower[varno]) {\n        if(isINT)\n          deltaRC = scaled_floor(lp, varno, unscaled_value(lp, deltaRC, varno)+lp->epsprimal, 1);\n        upbo = lowbo + deltaRC;\n        deltaRC = upbo;\n        i = LE;  /* Sets the upper bound */\n      }\n      else {\n        if(isINT)\n          deltaRC = scaled_ceil(lp, varno, unscaled_value(lp, deltaRC, varno)+lp->epsprimal, 1);\n        lowbo = upbo - deltaRC;\n        deltaRC = lowbo;\n        i = GE;  /* Sets the lower bound */\n      }\n\n      /* Check and set feasibility status */\n      if((isfeasible != NULL) && (upbo - lowbo < -lp->epsprimal))\n        *isfeasible = FALSE;\n\n      /* Flag that we can fix the variable by returning the relation code negated */\n      else if(fabs(upbo - lowbo) < lp->epsprimal)\n        i = -i;\n      if(newbound != NULL) {\n        my_roundzero(deltaRC, lp->epsprimal);\n        *newbound = deltaRC;\n      }\n    }\n\n  }\n  return( i );\n}\n\n\nSTATIC MYBOOL findnode_BB(BBrec *BB, int *varno, int *vartype, int *varcus)\n{\n  int    countsossc, countnint, k, reasonmsg = MSG_NONE;\n  REAL   varsol;\n  MYBOOL is_better = FALSE, is_equal = FALSE, is_feasible = TRUE;\n  lprec  *lp = BB->lp;\n\n  /* Initialize result and return variables */\n  *varno    = 0;\n  *vartype  = BB_REAL;\n  *varcus   = 0;\n  countnint = 0;\n  BB->nodestatus = lp->spx_status;\n  BB->noderesult = lp->solution[0];\n\n  /* If this solution is worse than the best so far, this branch dies.\n     If we can only have integer OF values, and we only need the first solution\n     then the OF must be at least (unscaled) 1 better than the best so far */\n  if((lp->bb_limitlevel != 1) && (MIP_count(lp) > 0)) {\n\n    /* Check that we don't have a limit on the recursion level; two versions supported:\n        1) Absolute B&B level (bb_limitlevel > 0), and\n        2) B&B level relative to the \"B&B order\" (bb_limitlevel < 0). */\n    countsossc =  lp->sos_vars + lp->sc_vars;\n    if((lp->bb_limitlevel > 0) && (lp->bb_level > lp->bb_limitlevel+countsossc))\n      return( FALSE );\n    else if((lp->bb_limitlevel < 0) &&\n            (lp->bb_level > 2*(lp->int_vars+countsossc)*abs(lp->bb_limitlevel))) {\n      if(lp->bb_limitlevel == DEF_BB_LIMITLEVEL)\n        report(lp, IMPORTANT, \"findnode_BB: Default B&B limit reached at %d; optionally change strategy or limit.\\n\\n\",\n                              lp->bb_level);\n      return( FALSE );\n    }\n\n    /* First initialize or update pseudo-costs from previous optimal solution */\n    if(BB->varno == 0) {\n      varsol = lp->infinite;\n      if((lp->int_vars+lp->sc_vars > 0) && (lp->bb_PseudoCost == NULL))\n        lp->bb_PseudoCost = init_pseudocost(lp, get_bb_rule(lp));\n    }\n    else {\n      varsol = lp->solution[BB->varno];\n      if( ((lp->int_vars > 0) && (BB->vartype == BB_INT)) ||\n          ((lp->sc_vars > 0) && (BB->vartype == BB_SC) && !is_int(lp, BB->varno-lp->rows)) )\n        update_pseudocost(lp->bb_PseudoCost, BB->varno-lp->rows, BB->vartype, BB->isfloor, varsol);\n    }\n\n    /* Make sure we don't have numeric problems (typically due to integer scaling) */\n    if((lp->bb_totalnodes > 0) && !bb_better(lp, OF_RELAXED, OF_TEST_WE)) {\n      if(lp->bb_trace)\n        report(lp, IMPORTANT, \"findnode_BB: Simplex failure due to loss of numeric accuracy\\n\");\n      lp->spx_status = NUMFAILURE;\n      return( FALSE );\n    }\n\n    /* Abandon this branch if the solution is \"worse\" than a heuristically\n      determined limit or the previous best MIP solution */\n    if(((lp->solutioncount == 0) && !bb_better(lp, OF_HEURISTIC, OF_TEST_BE)) ||\n       ((lp->solutioncount > 0) &&\n        (!bb_better(lp, OF_INCUMBENT | OF_DELTA, OF_TEST_BE | OF_TEST_RELGAP) ||\n         !bb_better(lp, OF_INCUMBENT | OF_DELTA, OF_TEST_BE)))) {\n      return( FALSE );\n    }\n\n    /* Collect violated SC variables (since they can also be real-valued); the\n       approach is to get them out of the way, since a 0-value is assumed to be \"cheap\" */\n    if(lp->sc_vars > 0) {\n      *varno = find_sc_bbvar(lp, &countnint);\n      if(*varno > 0)\n        *vartype = BB_SC;\n    }\n\n    /* Look among SOS variables if no SC candidate was found */\n    if((SOS_count(lp) > 0) && (*varno == 0)) {\n      *varno = find_sos_bbvar(lp, &countnint, FALSE);\n      if(*varno < 0)\n        *varno = 0;\n      else if(*varno > 0)\n        *vartype = BB_SOS;\n    }\n\n    /* Then collect INTS that are not integer valued, and verify bounds */\n    if((lp->int_vars > 0) && (*varno == 0)) {\n      *varno = find_int_bbvar(lp, &countnint, BB, &is_feasible);\n      if(*varno > 0) {\n        *vartype = BB_INT;\n        if((countnint == 1) && !is_feasible) {\n          BB->lastrcf = 0;\n          return( FALSE );\n        }\n      }\n    }\n\n#if 1 /* peno */\n    /* Check if we have reached the depth limit for any individual variable\n      (protects against infinite recursions of mainly integer variables) */\n    k = *varno-lp->rows;\n    if((*varno > 0) && (lp->bb_limitlevel != 0) && (lp->bb_varactive[k] >= abs(lp->bb_limitlevel) /* abs(DEF_BB_LIMITLEVEL) */)) {\n      /* if(!is_action(lp->nomessage, NOMSG_BBLIMIT)) {*/\n/*\n        report(lp, IMPORTANT, \"findnode_BB: Reached B&B depth limit %d for variable %d; will not dive further.\\n\\n\",\n                              lp->bb_varactive[k], k);\n*/\n      /*  set_action(&lp->nomessage, NOMSG_BBLIMIT); */\n      /* } */\n      return( FALSE );\n    }\n#endif\n\n    /* Check if the current MIP solution is optimal; equal or better */\n    if(*varno == 0) {\n      is_better = (MYBOOL) (lp->solutioncount == 0) || bb_better(lp, OF_INCUMBENT | OF_DELTA, OF_TEST_BT);\n#if 1\n      is_better &= bb_better(lp, OF_INCUMBENT | OF_DELTA, OF_TEST_BT | OF_TEST_RELGAP);\n#else\n      /* Check if we can determine clear improvement */\n      is_better = (MYBOOL) (lp->solutioncount == 0) ||\n                  (MYBOOL) ((lp->bb_deltaOF > 0) &&\n                            (my_chsign(is_maxim(lp), lp->solution[0]-lp->best_solution[0]) < 0));\n\n      /* Apply gap-based improvement testing if the current solution is not clearly better */\n\n      if(!is_better) {\n        is_better  = bb_better(lp, OF_INCUMBENT | OF_DELTA, OF_TEST_BT);\n        is_better |= bb_better(lp, OF_INCUMBENT | OF_DELTA, OF_TEST_BT | OF_TEST_RELGAP);\n      }\n#endif\n      is_equal  = !is_better;\n\n      if(is_equal) {\n        if((lp->solutionlimit <= 0) || (lp->solutioncount < lp->solutionlimit)) {\n          lp->solutioncount++;\n          SETMIN(lp->bb_solutionlevel, lp->bb_level);\n          reasonmsg = MSG_MILPEQUAL;\n        }\n      }\n\n      /* Current solution is better */\n      else if(is_better) {\n\n        /* Update grand total solution count and check if we should go from\n           depth-first to best-first variable selection mode */\n        if(lp->bb_varactive != NULL) {\n          lp->bb_varactive[0]++;\n          if((lp->bb_varactive[0] == 1) &&\n             is_bb_mode(lp, NODE_DEPTHFIRSTMODE) && is_bb_mode(lp, NODE_DYNAMICMODE))\n            lp->bb_rule &= !NODE_DEPTHFIRSTMODE;\n        }\n\n        if(lp->bb_trace ||\n           ((lp->verbose >= NORMAL) && (lp->print_sol == FALSE) && (lp->lag_status != RUNNING))) {\n          report(lp, IMPORTANT,\n                 \"%s solution \" RESULTVALUEMASK \" after %10.0f iter, %9.0f nodes (gap %.1f%%)\\n\",\n                 (lp->bb_improvements == 0) ? \"Feasible\" : \"Improved\",\n                 lp->solution[0], (double) lp->total_iter, (double) lp->bb_totalnodes,\n                 100.0*fabs(my_reldiff(lp->solution[0], lp->bb_limitOF)));\n        }\n        if(MIP_count(lp) > 0) {\n          if(lp->bb_improvements == 0)\n            reasonmsg = MSG_MILPFEASIBLE;\n          else\n            reasonmsg = MSG_MILPBETTER;\n        }\n\n        lp->bb_status = FEASFOUND;\n        lp->bb_solutionlevel = lp->bb_level;\n        lp->solutioncount = 1;\n        lp->bb_improvements++;\n        lp->bb_workOF = lp->rhs[0];\n\n        if(lp->bb_breakfirst ||\n           (!is_infinite(lp, lp->bb_breakOF) && bb_better(lp, OF_USERBREAK, OF_TEST_BE)))\n          lp->bb_break = TRUE;\n      }\n    }\n  }\n  else {\n    is_better = TRUE;\n    lp->solutioncount = 1;\n  }\n\n  /* Transfer the successful solution vector */\n  if(is_better || is_equal) {\n#ifdef ParanoiaMIP\n    if((lp->bb_level > 0) &&\n       (check_solution(lp, lp->columns, lp->solution,\n                           lp->orig_upbo, lp->orig_lowbo, lp->epssolution) != OPTIMAL)) {\n      lp->solutioncount = 0;\n      lp->spx_status = NUMFAILURE;\n      lp->bb_status = lp->spx_status;\n      lp->bb_break = TRUE;\n      return( FALSE );\n    }\n#endif\n    transfer_solution(lp, (MYBOOL) ((lp->do_presolve & PRESOLVE_LASTMASKMODE) != PRESOLVE_NONE));\n    if((MIP_count(lp) > 0) && (lp->bb_totalnodes > 0)) {\n      if ((!construct_duals(lp)) ||\n          (is_presolve(lp, PRESOLVE_SENSDUALS) &&\n           (!construct_sensitivity_duals(lp) || !construct_sensitivity_obj(lp))\n          )\n         ) {\n      }\n    }\n    if((reasonmsg != MSG_NONE) && (lp->msgmask & reasonmsg) && (lp->usermessage != NULL))\n      lp->usermessage(lp, lp->msghandle, reasonmsg);\n\n    if(lp->print_sol != FALSE) {\n      print_objective(lp);\n      print_solution(lp, 1);\n    }\n  }\n\n  /* Do tracing and determine if we have arrived at the estimated lower MIP limit */\n  *varcus = countnint;\n  if(MIP_count(lp) > 0) {\n    if((countnint == 0) && (lp->solutioncount == 1) && (lp->solutionlimit == 1) &&\n       (bb_better(lp, OF_DUALLIMIT, OF_TEST_BE) || bb_better(lp, OF_USERBREAK, OF_TEST_BE | OF_TEST_RELGAP))) {\n      lp->bb_break = (MYBOOL) (countnint == 0);\n      return( FALSE );\n    }\n    else if(lp->bb_level > 0) {\n#ifdef MIPboundWithOF\n      if((lp->constraintOF > 0) && (countnint == 0))\n         set_rh(lp, lp->constraintOF, lp->solution[0] + my_chsign(!is_maxim(lp), lp->bb_deltaOF));\n#endif\n      if(lp->spx_trace)\n        report(lp, DETAILED, \"B&B level %5d OPT %16s value \" RESULTVALUEMASK \"\\n\",\n                             lp->bb_level, (*varno) ? \"   \" : \"INT\", lp->solution[0]);\n    }\n    return( (MYBOOL) (*varno > 0));\n  }\n  else\n    return( FALSE );\n\n}\n\nSTATIC int solve_BB(BBrec *BB)\n{\n  int   K, status;\n  lprec *lp = BB->lp;\n\n  /* Protect against infinite recursions do to integer rounding effects */\n  status = PROCFAIL;\n\n  /* Shortcut variables, set default bounds */\n  K = BB->varno;\n\n  /* Load simple MIP bounds */\n  if(K > 0) {\n\n    /* Update cuts, if specified */\n    updatecuts_BB(lp);\n\n    /* BRANCH_FLOOR: Force the variable to be smaller than the B&B upper bound */\n    if(BB->isfloor)\n      modifyUndoLadder(lp->bb_upperchange, K, BB->upbo, BB->UPbound);\n\n    /* BRANCH_CEILING: Force the variable to be greater than the B&B lower bound */\n    else\n      modifyUndoLadder(lp->bb_lowerchange, K, BB->lowbo, BB->LObound);\n\n    /* Update MIP node count */\n    BB->nodessolved++;\n\n  }\n\n  /* Solve! */\n  status = solve_LP(lp, BB);\n\n  /* Do special feasibility assessment of high order SOS'es */\n#if 1\n  if((status == OPTIMAL) && (BB->vartype == BB_SOS) && !SOS_is_feasible(lp->SOS, 0, lp->solution))\n    status = INFEASIBLE;\n#endif\n\n  return( status );\n}\n\n/* Routine to compute a \"strong\" pseudo-cost update for a node */\nSTATIC MYBOOL strongbranch_BB(lprec *lp, BBrec *BB, int varno, int vartype, int varcus)\n{\n  MYBOOL   success = FALSE;\n  int      i;\n  BBrec    *strongBB;\n\n  /* Create new B&B level and solve each of the branches */\n  lp->is_strongbranch = TRUE;\n  push_basis(lp, lp->var_basic, lp->is_basic, lp->is_lower);\n  strongBB = push_BB(lp, BB, lp->rows+varno, vartype, varcus);\n  if(strongBB == BB)\n    return( success );\n\n  do {\n\n    /* Solve incremental problem to local optimality */\n    lp->bb_strongbranches++;\n/*    set_action(&lp->spx_action, ACTION_REBASE | ACTION_RECOMPUTE); */\n    if(solve_BB(strongBB) == OPTIMAL) {\n\n      /* Update result indicator*/\n      success |= 1 << strongBB->isfloor;\n\n      /* Compute new count of non-ints */\n      strongBB->lastvarcus = 0;\n      for(i = 1; i <= lp->columns; i++) {\n        if(is_int(lp, i) && !solution_is_int(lp, lp->rows+i, FALSE))\n          strongBB->lastvarcus++;\n      }\n\n      /* Perform the pseudo-cost update */\n      update_pseudocost(lp->bb_PseudoCost, varno, strongBB->vartype, strongBB->isfloor,\n                                           lp->solution[strongBB->varno]);\n    }\n  }\n  while(nextbranch_BB(strongBB));\n\n  strongBB = pop_BB(strongBB);\n  if(strongBB != BB)\n    report(lp, SEVERE, \"strongbranch_BB: Invalid bound settings restored for variable %d\\n\",\n                       varno);\n  pop_basis(lp, TRUE);\n  set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n\n  lp->is_strongbranch = FALSE;\n\n  return( success );\n}\n\n/* Future functions */\nSTATIC MYBOOL pre_BB(lprec *lp)\n{\n  (void)lp;\n  return( TRUE );\n}\nSTATIC MYBOOL post_BB(lprec *lp)\n{\n  (void)lp;\n  return( TRUE );\n}\n\n/* This is the non-recursive B&B driver routine - beautifully simple, yet so subtle! */\nSTATIC int run_BB(lprec *lp)\n{\n  BBrec *currentBB;\n  int   varno, vartype, varcus, prevsolutions;\n  int   status = NOTRUN;\n\n  /* Initialize */\n  pre_BB(lp);\n  prevsolutions = lp->solutioncount;\n#ifdef UseMilpSlacksRCF  /* Check if we should include ranged constraints */\n  varno = lp->sum;\n#else\n  varno = lp->columns;\n#endif\n  lp->bb_upperchange = createUndoLadder(lp, varno, 2*MIP_count(lp));\n  lp->bb_lowerchange = createUndoLadder(lp, varno, 2*MIP_count(lp));\n  lp->rootbounds = currentBB = push_BB(lp, NULL, 0, BB_REAL, 0);\n\n  /* Perform the branch & bound loop */\n  while(lp->bb_level > 0) {\n    status = solve_BB(currentBB);\n\n#if 0\n    if((lp->bb_level == 1) && (MIP_count(lp) > 0)) {\n      if(status == RUNNING)\n        ;\n\n      /* Check if there was an integer solution of an aborted model */\n      else if((status == SUBOPTIMAL) && (lp->solutioncount == 1) &&\n              findnode_BB(currentBB, &varno, &vartype, &varcus))\n        status = USERABORT;\n    }\n#endif\n\n    if((status == OPTIMAL) && findnode_BB(currentBB, &varno, &vartype, &varcus))\n      currentBB = push_BB(lp, currentBB, varno, vartype, varcus);\n\n    else while((lp->bb_level > 0) && !nextbranch_BB(currentBB))\n      currentBB = pop_BB(currentBB);\n\n  }\n\n  /* Finalize */\n  freeUndoLadder(&(lp->bb_upperchange));\n  freeUndoLadder(&(lp->bb_lowerchange));\n\n  /* Check if we should adjust status */\n  if(lp->solutioncount > prevsolutions) {\n    if((status == PROCBREAK) || (status == USERABORT) || (status == TIMEOUT) || userabort(lp, -1))\n      status = SUBOPTIMAL;\n    else\n      status = OPTIMAL;\n    if(lp->bb_totalnodes > 0)\n      lp->spx_status = OPTIMAL;\n  }\n  post_BB(lp);\n  return( status );\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_mipbb.h",
    "content": "#ifndef HEADER_lp_mipbb\n#define HEADER_lp_mipbb\n\n#include \"lp_types.h\"\n#include \"lp_utils.h\"\n\n\n/* Bounds storage for B&B routines */\ntypedef struct _BBrec\n{\n  struct    _BBrec *parent;\n  struct    _BBrec *child;\n  lprec     *lp;\n  int       varno;\n  int       vartype;\n  int       lastvarcus;            /* Count of non-int variables of the previous branch */\n  int       lastrcf;\n  int       nodesleft;\n  int       nodessolved;\n  int       nodestatus;\n  REAL      noderesult;\n  REAL      lastsolution;          /* Optimal solution of the previous branch */\n  REAL      sc_bound;\n  REAL      *upbo,   *lowbo;\n  REAL      UPbound, LObound;\n  int       UBtrack, LBtrack;      /* Signals that incoming bounds were changed */\n  MYBOOL    contentmode;           /* Flag indicating if we \"own\" the bound vectors */\n  MYBOOL    sc_canset;\n  MYBOOL    isSOS;\n  MYBOOL    isGUB;\n  int       *varmanaged;           /* Extended list of variables managed by this B&B level */\n  MYBOOL    isfloor;               /* State variable indicating the active B&B bound */\n  MYBOOL    UBzerobased;           /* State variable indicating if bounds have been rebased */\n} BBrec;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nSTATIC BBrec *create_BB(lprec *lp, BBrec *parentBB, MYBOOL dofullcopy);\nSTATIC BBrec *push_BB(lprec *lp, BBrec *parentBB, int varno, int vartype, int varcus);\nSTATIC MYBOOL initbranches_BB(BBrec *BB);\nSTATIC MYBOOL fillbranches_BB(BBrec *BB);\nSTATIC MYBOOL nextbranch_BB(BBrec *BB);\nSTATIC MYBOOL strongbranch_BB(lprec *lp, BBrec *BB, int varno, int vartype, int varcus);\nSTATIC MYBOOL initcuts_BB(lprec *lp);\nSTATIC int updatecuts_BB(lprec *lp);\nSTATIC MYBOOL freecuts_BB(lprec *lp);\nSTATIC BBrec *findself_BB(BBrec *BB);\nSTATIC int solve_LP(lprec *lp, BBrec *BB);\nSTATIC int rcfbound_BB(BBrec *BB, int varno, MYBOOL isINT, REAL *newbound, MYBOOL *isfeasible);\nSTATIC MYBOOL findnode_BB(BBrec *BB, int *varno, int *vartype, int *varcus);\nSTATIC int solve_BB(BBrec *BB);\nSTATIC MYBOOL free_BB(BBrec **BB);\nSTATIC BBrec *pop_BB(BBrec *BB);\n\nSTATIC int run_BB(lprec *lp);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_mipbb */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_params.c",
    "content": "#include <stdio.h>\n#include <stdlib.h>\n#include <ctype.h>\n#include <errno.h>\n\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_report.h\"\n#include \"ini.h\"\n\ntypedef int (__WINAPI fn_int_get_function)(lprec *lp);\ntypedef long (__WINAPI fn_long_get_function)(lprec *lp);\ntypedef MYBOOL (__WINAPI fn_MYBOOL_get_function)(lprec *lp);\ntypedef REAL (__WINAPI fn_REAL_get_function)(lprec *lp);\ntypedef void (__WINAPI fn_int_set_function)(lprec *lp, int value);\ntypedef void (__WINAPI fn_long_set_function)(lprec *lp, long value);\ntypedef void (__WINAPI fn_MYBOOL_set_function)(lprec *lp, MYBOOL value);\ntypedef void (__WINAPI fn_REAL_set_function)(lprec *lp, REAL value);\n\n#define intfunction    1\n#define longfunction   2\n#define MYBOOLfunction 3\n#define REALfunction   4\n\n#define setvalues(values, basemask) values, sizeof(values) / sizeof(*values), basemask\n#define setNULLvalues NULL, 0, 0\n#define setvalue(value) value, #value\n#define setintfunction(get_function, set_function) { get_function }, { set_function }, intfunction\n#define setlongfunction(get_function, set_function) { (fn_int_get_function *) get_function }, {(fn_int_set_function *) set_function }, longfunction\n#define setMYBOOLfunction(get_function, set_function) { (fn_int_get_function *) get_function }, { (fn_int_set_function *) set_function }, MYBOOLfunction\n#define setREALfunction(get_function, set_function) {(fn_int_get_function *) get_function }, { (fn_int_set_function *) set_function }, REALfunction\n\n#define WRITE_COMMENTED 0\n#define WRITE_ACTIVE    1\n\nstruct _values {\n  int value;\n  const char *svalue;\n};\n\nstruct _functions {\n  const char *par;                                    /* name of parameter in ini file */\n  union {\n    fn_int_get_function *int_get_function;         /* set via setintfunction */\n    fn_long_get_function *long_get_function;       /* set via setlongfunction */\n    fn_MYBOOL_get_function *MYBOOL_get_function;   /* set via setMYBOOLfunction */\n    fn_REAL_get_function *REAL_get_function;       /* set via setREALfunction */\n  } get_function;\n  union {\n    fn_int_set_function *int_set_function;         /* set via setintfunction */\n    fn_long_set_function *long_set_function;       /* set via setlongfunction */\n    fn_MYBOOL_set_function *MYBOOL_set_function;   /* set via setMYBOOLfunction */\n    fn_REAL_set_function *REAL_set_function;       /* set via setREALfunction */\n  } set_function;\n  int type;                                     /* set via set*function */\n  struct _values *values;                       /* set via setvalues to a structure of _values */\n  int elements;                                 /*  or via setNULLvalues if the value is shown as is */\n  unsigned int basemask;\n  int mask;                                     /* WRITE_ACTIVE or WRITE_COMMENTED */\n};\n\nstatic struct _values anti_degen[] =\n{\n  { setvalue(ANTIDEGEN_NONE) },\n  { setvalue(ANTIDEGEN_FIXEDVARS) },\n  { setvalue(ANTIDEGEN_COLUMNCHECK) },\n  { setvalue(ANTIDEGEN_STALLING) },\n  { setvalue(ANTIDEGEN_NUMFAILURE) },\n  { setvalue(ANTIDEGEN_LOSTFEAS) },\n  { setvalue(ANTIDEGEN_INFEASIBLE) },\n  { setvalue(ANTIDEGEN_DYNAMIC) },\n  { setvalue(ANTIDEGEN_DURINGBB) },\n  { setvalue(ANTIDEGEN_RHSPERTURB) },\n  { setvalue(ANTIDEGEN_BOUNDFLIP) },\n};\n\nstatic struct _values basiscrash[] =\n{\n  { setvalue(CRASH_NONE) },\n  /* { setvalue(CRASH_NONBASICBOUNDS) }, */ /* not yet implemented */\n  { setvalue(CRASH_MOSTFEASIBLE) },\n  { setvalue(CRASH_LEASTDEGENERATE) },\n};\n\nstatic struct _values bb_floorfirst[] =\n{\n  { setvalue(BRANCH_CEILING) },\n  { setvalue(BRANCH_FLOOR) },\n  { setvalue(BRANCH_AUTOMATIC) },\n};\n\nstatic struct _values bb_rule[] =\n{\n  { setvalue(NODE_FIRSTSELECT) },\n  { setvalue(NODE_GAPSELECT) },\n  { setvalue(NODE_RANGESELECT) },\n  { setvalue(NODE_FRACTIONSELECT) },\n  { setvalue(NODE_PSEUDOCOSTSELECT) },\n  { setvalue(NODE_PSEUDONONINTSELECT) },\n  { setvalue(NODE_PSEUDORATIOSELECT) },\n  { setvalue(NODE_USERSELECT) },\n  { setvalue(NODE_WEIGHTREVERSEMODE) },\n  { setvalue(NODE_BRANCHREVERSEMODE) },\n  { setvalue(NODE_GREEDYMODE) },\n  { setvalue(NODE_PSEUDOCOSTMODE) },\n  { setvalue(NODE_DEPTHFIRSTMODE) },\n  { setvalue(NODE_RANDOMIZEMODE) },\n  { setvalue(NODE_GUBMODE) },\n  { setvalue(NODE_DYNAMICMODE) },\n  { setvalue(NODE_RESTARTMODE) },\n  { setvalue(NODE_BREADTHFIRSTMODE) },\n  { setvalue(NODE_AUTOORDER) },\n  { setvalue(NODE_RCOSTFIXING) },\n  { setvalue(NODE_STRONGINIT) },\n};\n\nstatic struct _values improve[] =\n{\n  { setvalue(IMPROVE_NONE) },\n  { setvalue(IMPROVE_SOLUTION) },\n  { setvalue(IMPROVE_DUALFEAS) },\n  { setvalue(IMPROVE_THETAGAP) },\n  { setvalue(IMPROVE_BBSIMPLEX) },\n};\n\nstatic REAL __WINAPI get_mip_gap_abs(lprec *lp)\n{\n  return(get_mip_gap(lp, TRUE));\n}\n\nstatic REAL __WINAPI get_mip_gap_rel(lprec *lp)\n{\n  return(get_mip_gap(lp, FALSE));\n}\n\nstatic void __WINAPI set_mip_gap_abs(lprec *lp, REAL mip_gap)\n{\n  set_mip_gap(lp, TRUE, mip_gap);\n}\n\nstatic void __WINAPI set_mip_gap_rel(lprec *lp, REAL mip_gap)\n{\n  set_mip_gap(lp, FALSE, mip_gap);\n}\n\nstatic struct _values pivoting[] =\n{\n  { setvalue(PRICER_FIRSTINDEX) },\n  { setvalue(PRICER_DANTZIG) },\n  { setvalue(PRICER_DEVEX) },\n  { setvalue(PRICER_STEEPESTEDGE) },\n  { setvalue(PRICE_PRIMALFALLBACK) },\n  { setvalue(PRICE_MULTIPLE) },\n  { setvalue(PRICE_PARTIAL) },\n  { setvalue(PRICE_ADAPTIVE) },\n  { setvalue(PRICE_RANDOMIZE) },\n  { setvalue(PRICE_AUTOPARTIAL) },\n  { setvalue(PRICE_LOOPLEFT) },\n  { setvalue(PRICE_LOOPALTERNATE) },\n  { setvalue(PRICE_HARRISTWOPASS) },\n  { setvalue(PRICE_TRUENORMINIT) },\n};\n\nstatic struct _values presolving[] =\n{\n  { setvalue(PRESOLVE_NONE) },\n  { setvalue(PRESOLVE_ROWS) },\n  { setvalue(PRESOLVE_COLS) },\n  { setvalue(PRESOLVE_LINDEP) },\n  { setvalue(PRESOLVE_AGGREGATE) },\n  { setvalue(PRESOLVE_SPARSER) },\n  { setvalue(PRESOLVE_SOS) },\n  { setvalue(PRESOLVE_REDUCEMIP) },\n  { setvalue(PRESOLVE_KNAPSACK) },\n  { setvalue(PRESOLVE_ELIMEQ2) },\n  { setvalue(PRESOLVE_IMPLIEDFREE) },\n  { setvalue(PRESOLVE_REDUCEGCD) },\n  { setvalue(PRESOLVE_PROBEFIX) },\n  { setvalue(PRESOLVE_PROBEREDUCE) },\n  { setvalue(PRESOLVE_ROWDOMINATE) },\n  { setvalue(PRESOLVE_COLDOMINATE) },\n  { setvalue(PRESOLVE_MERGEROWS) },\n  { setvalue(PRESOLVE_IMPLIEDSLK) },\n  { setvalue(PRESOLVE_COLFIXDUAL) },\n  { setvalue(PRESOLVE_BOUNDS) },\n  { setvalue(PRESOLVE_DUALS) },\n  { setvalue(PRESOLVE_SENSDUALS) },\n};\n\nstatic char *STRLWR(char *str)\n{\n  char *ptr;\n\n  for(ptr = str; *ptr; ptr++)\n    *ptr = (char) tolower((unsigned char) *ptr);\n\n  return(str);\n}\n\nstatic char *STRUPR(char *str)\n{\n  char *ptr;\n\n  for(ptr = str; *ptr; ptr++)\n    *ptr = (char) toupper((unsigned char) *ptr);\n\n  return(str);\n}\n\nstatic void __WINAPI set_presolve1(lprec *lp, int do_presolve)\n{\n  set_presolve(lp, do_presolve, get_presolveloops(lp));\n}\n\nstatic void __WINAPI set_presolve2(lprec *lp, int maxloops)\n{\n  set_presolve(lp, get_presolve(lp), maxloops);\n}\n\nstatic struct _values print_sol[] =\n{\n  { FALSE, \"0\" },\n  { TRUE,  \"1\" },\n  { setvalue(AUTOMATIC) },\n};\n\nstatic struct _values scaling[] =\n{\n  { setvalue(SCALE_NONE) },\n  { setvalue(SCALE_EXTREME) },\n  { setvalue(SCALE_RANGE) },\n  { setvalue(SCALE_MEAN) },\n  { setvalue(SCALE_GEOMETRIC) },\n  { setvalue(SCALE_CURTISREID) },\n  { setvalue(SCALE_QUADRATIC) },\n  { setvalue(SCALE_LOGARITHMIC) },\n  { setvalue(SCALE_USERWEIGHT) },\n  { setvalue(SCALE_POWER2) },\n  { setvalue(SCALE_EQUILIBRATE) },\n  { setvalue(SCALE_INTEGERS) },\n  { setvalue(SCALE_DYNUPDATE) },\n  { setvalue(SCALE_ROWSONLY) },\n  { setvalue(SCALE_COLSONLY) },\n};\n\nstatic struct _values simplextype[] =\n{\n  { setvalue(SIMPLEX_PRIMAL_PRIMAL) },\n  { setvalue(SIMPLEX_DUAL_PRIMAL) },\n  { setvalue(SIMPLEX_PRIMAL_DUAL) },\n  { setvalue(SIMPLEX_DUAL_DUAL) },\n};\n\nstatic struct _values verbose[] =\n{\n  { setvalue(NEUTRAL) },\n  { setvalue(CRITICAL) },\n  { setvalue(SEVERE) },\n  { setvalue(IMPORTANT) },\n  { setvalue(NORMAL) },\n  { setvalue(DETAILED) },\n  { setvalue(FULL) },\n};\n\nstatic struct _functions functions[] =\n{\n  /* solve options */\n  { \"ANTI_DEGEN\", setintfunction(get_anti_degen, set_anti_degen), setvalues(anti_degen, ~0), WRITE_ACTIVE },\n  { \"BASISCRASH\", setintfunction(get_basiscrash, set_basiscrash), setvalues(basiscrash, ~0), WRITE_ACTIVE },\n  { \"IMPROVE\", setintfunction(get_improve, set_improve), setvalues(improve, ~0), WRITE_ACTIVE },\n  { \"MAXPIVOT\", setintfunction(get_maxpivot, set_maxpivot), setNULLvalues, WRITE_ACTIVE },\n  { \"NEGRANGE\", setREALfunction(get_negrange, set_negrange), setNULLvalues, WRITE_ACTIVE },\n  { \"PIVOTING\", setintfunction(get_pivoting, set_pivoting), setvalues(pivoting, PRICER_LASTOPTION), WRITE_ACTIVE },\n  { \"PRESOLVE\", setintfunction(get_presolve, set_presolve1), setvalues(presolving, ~0), WRITE_ACTIVE },\n  { \"PRESOLVELOOPS\", setintfunction(get_presolveloops, set_presolve2), setNULLvalues, WRITE_ACTIVE },\n  { \"SCALELIMIT\", setREALfunction(get_scalelimit, set_scalelimit), setNULLvalues, WRITE_ACTIVE },\n  { \"SCALING\", setintfunction(get_scaling, set_scaling), setvalues(scaling, SCALE_CURTISREID), WRITE_ACTIVE },\n  { \"SIMPLEXTYPE\", setintfunction(get_simplextype, set_simplextype), setvalues(simplextype, ~0), WRITE_ACTIVE },\n  { \"OBJ_IN_BASIS\", setMYBOOLfunction(is_obj_in_basis, set_obj_in_basis), setNULLvalues, WRITE_COMMENTED },\n\n  /* B&B options */\n  { \"BB_DEPTHLIMIT\", setintfunction(get_bb_depthlimit, set_bb_depthlimit), setNULLvalues, WRITE_ACTIVE },\n  { \"BB_FLOORFIRST\", setintfunction(get_bb_floorfirst, set_bb_floorfirst), setvalues(bb_floorfirst, ~0), WRITE_ACTIVE },\n  { \"BB_RULE\", setintfunction(get_bb_rule, set_bb_rule), setvalues(bb_rule, NODE_STRATEGYMASK), WRITE_ACTIVE },\n  { \"BREAK_AT_FIRST\", setMYBOOLfunction(is_break_at_first, set_break_at_first), setNULLvalues, WRITE_COMMENTED },\n  { \"BREAK_AT_VALUE\", setREALfunction(get_break_at_value, set_break_at_value), setNULLvalues, WRITE_COMMENTED },\n  { \"MIP_GAP_ABS\", setREALfunction(get_mip_gap_abs, set_mip_gap_abs), setNULLvalues, WRITE_ACTIVE },\n  { \"MIP_GAP_REL\", setREALfunction(get_mip_gap_rel, set_mip_gap_rel), setNULLvalues, WRITE_ACTIVE },\n  { \"EPSINT\", setREALfunction(get_epsint, set_epsint), setNULLvalues, WRITE_ACTIVE },\n\n  /* tolerances, values */\n  { \"EPSB\", setREALfunction(get_epsb, set_epsb), setNULLvalues, WRITE_ACTIVE },\n  { \"EPSD\", setREALfunction(get_epsd, set_epsd), setNULLvalues, WRITE_ACTIVE },\n  { \"EPSEL\", setREALfunction(get_epsel, set_epsel), setNULLvalues, WRITE_ACTIVE },\n  { \"EPSPERTURB\", setREALfunction(get_epsperturb, set_epsperturb), setNULLvalues, WRITE_ACTIVE },\n  { \"EPSPIVOT\", setREALfunction(get_epspivot, set_epspivot), setNULLvalues, WRITE_ACTIVE },\n  { \"INFINITE\", setREALfunction(get_infinite, set_infinite), setNULLvalues, WRITE_ACTIVE },\n  { \"BREAK_NUMERIC_ACCURACY\", setREALfunction(get_break_numeric_accuracy, set_break_numeric_accuracy), setNULLvalues, WRITE_ACTIVE },\n\n  /* read-only options */\n  { \"DEBUG\", setMYBOOLfunction(is_debug, set_debug), setNULLvalues, WRITE_COMMENTED },\n  { \"OBJ_BOUND\", setREALfunction(get_obj_bound, set_obj_bound), setNULLvalues, WRITE_COMMENTED },\n  { \"PRINT_SOL\", setintfunction(get_print_sol, set_print_sol), setvalues(print_sol, ~0), WRITE_COMMENTED },\n  { \"TIMEOUT\", setlongfunction(get_timeout, set_timeout), setNULLvalues, WRITE_COMMENTED },\n  { \"TRACE\", setMYBOOLfunction(is_trace, set_trace), setNULLvalues, WRITE_COMMENTED },\n  { \"VERBOSE\", setintfunction(get_verbose, set_verbose), setvalues(verbose, ~0), WRITE_COMMENTED },\n};\n\nstatic void write_params1(lprec *lp, FILE *fp, const char *header, int newline)\n{\n  int ret = 0, ret2, j, k, value, value2, elements, majorversion, minorversion, release, build;\n  size_t i;\n  unsigned int basemask;\n  REAL a = 0;\n  char buf[4096], par[30];\n\n  ini_writeheader(fp, header, newline);\n  lp_solve_version(&majorversion, &minorversion, &release, &build);\n  sprintf(buf, \"lp_solve version %d.%d settings\\n\", majorversion, minorversion);\n  ini_writecomment(fp, buf);\n  for(i = 0; i < sizeof(functions) / sizeof(*functions); i++) {\n    switch(functions[i].type) {\n    case intfunction:\n      if(functions[i].get_function.int_get_function == NULL)\n        continue;\n      ret = functions[i].get_function.int_get_function(lp);\n      break;\n    case longfunction:\n      if(functions[i].get_function.long_get_function == NULL)\n        continue;\n      ret = functions[i].get_function.long_get_function(lp);\n      break;\n    case MYBOOLfunction:\n      if(functions[i].get_function.MYBOOL_get_function == NULL)\n        continue;\n      ret = (int) functions[i].get_function.MYBOOL_get_function(lp);\n      break;\n    case REALfunction:\n      if(functions[i].get_function.REAL_get_function == NULL)\n        continue;\n      a = functions[i].get_function.REAL_get_function(lp);\n      break;\n    }\n    buf[0] = 0;\n    if(functions[i].values == NULL) {\n      switch(functions[i].type) {\n      case intfunction:\n      case longfunction:\n      case MYBOOLfunction:\n        sprintf(buf, \"%d\", ret);\n        break;\n      case REALfunction:\n        sprintf(buf, \"%g\", a);\n        break;\n      }\n    }\n    else {\n      elements = functions[i].elements;\n      basemask = functions[i].basemask;\n      for(j = 0; j < elements; j++) {\n        value = functions[i].values[j].value;\n        ret2 = ret;\n        if(((unsigned int) value) < basemask)\n          ret2 &= basemask;\n        if(value == 0) {\n          if(ret2 == 0) {\n            if(*buf)\n              strcat(buf, \" + \");\n            strcat(buf, functions[i].values[j].svalue);\n          }\n        }\n        else if((ret2 & value) == value) {\n          for(k = 0; k < elements; k++) {\n            value2 = functions[i].values[k].value;\n            if((k != j) && (value2 > value) && ((value2 & value) == value) && ((ret2 & value2) == value2))\n              break;\n          }\n          if(k == elements) {\n            if(*buf)\n              strcat(buf, \" + \");\n            strcat(buf, functions[i].values[j].svalue);\n          }\n        }\n      }\n    }\n    if(functions[i].mask & WRITE_ACTIVE)\n      par[0] = 0;\n    else\n      strcpy(par, \";\");\n    strcat(par, functions[i].par);\n    ini_writedata(fp, STRLWR(par), buf);\n  }\n}\n\nstatic void readoptions(const char *options, char **header)\n{\n  const char *ptr1;\n  const char *ptr2;\n\n  if(options != NULL) {\n    ptr1 = options;\n    while(*ptr1) {\n      ptr2 = strchr(ptr1, '-');\n      if(ptr2 == NULL)\n        break;\n      ptr2++;\n      if(tolower((unsigned char) *ptr2) == 'h') {\n        for(++ptr2; (*ptr2) && (isspace(*ptr2)); ptr2++);\n        for(ptr1 = ptr2; (*ptr1) && (!isspace(*ptr1)); ptr1++);\n        *header = (char *) calloc(1 + (int) (ptr1 - ptr2), 1);\n        memcpy(*header, ptr2, (int) (ptr1 - ptr2));\n      }\n    }\n  }\n\n  if(*header == NULL)\n    *header = strdup(\"Default\");\n}\n\nMYBOOL __WINAPI write_params(lprec *lp, const char *filename, const char *options)\n{\n  int k, ret, params_written;\n  FILE *fp, *fp0;\n  int state = 0, looping, newline;\n  char buf[4096], *filename0, *ptr1, *ptr2, *header = NULL;\n\n  readoptions(options, &header);\n\n  k = (int) strlen(filename);\n  filename0 = (char *) malloc(k + 1 + 1);\n  strcpy(filename0, filename);\n  ptr1 = strrchr(filename0, '.');\n  ptr2 = strrchr(filename0, '\\\\');\n  if((ptr1 == NULL) || ((ptr2 != NULL) && (ptr1 < ptr2)))\n    ptr1 = filename0 + k;\n  memmove(ptr1 + 1, ptr1, k + 1 - (int) (ptr1 - filename0));\n  ptr1[0] = '_';\n  if(rename(filename, filename0)) {\n    switch(errno) {\n    case ENOENT: /* File or path specified by oldname not found */\n      FREE(filename0);\n      filename0 = NULL;\n      break;\n    case EACCES: /* File or directory specified by newname already exists or could not be created (invalid path); or oldname is a directory and newname specifies a different path. */\n      FREE(filename0);\n      FREE(header);\n      return(FALSE);\n      break;\n    }\n  }\n\n  if((fp = ini_create(filename)) == NULL)\n    ret = FALSE;\n  else {\n    params_written = FALSE;\n    newline = TRUE;\n    if(filename0 != NULL) {\n      fp0 = ini_open(filename0);\n      if(fp0 == NULL) {\n        rename(filename0, filename);\n        FREE(filename0);\n        FREE(header);\n        return(FALSE);\n      }\n      looping = TRUE;\n      while(looping) {\n        switch(ini_readdata(fp0, buf, sizeof(buf), TRUE)) {\n        case 0: /* End of file */\n          looping = FALSE;\n          break;\n        case 1: /* header */\n          ptr1 = strdup(buf);\n          STRUPR(buf);\n          ptr2 = strdup(header);\n          STRUPR(ptr2);\n          if(strcmp(buf, ptr2) == 0) {\n            write_params1(lp, fp, ptr1, newline);\n            params_written = TRUE;\n            newline = TRUE;\n            state = 1;\n          }\n          else {\n            state = 0;\n            ini_writeheader(fp, ptr1, newline);\n            newline = TRUE;\n          }\n          FREE(ptr2);\n          FREE(ptr1);\n          break;\n        case 2: /* data */\n          if(state == 0) {\n            ini_writedata(fp, NULL, buf);\n            newline = (*buf != 0);\n          }\n          break;\n        }\n      }\n      ini_close(fp0);\n    }\n\n    if(!params_written)\n      write_params1(lp, fp, header, newline);\n\n    ini_close(fp);\n    ret = TRUE;\n  }\n\n  if(filename0 != NULL) {\n    remove(filename0);\n    FREE(filename0);\n  }\n\n  FREE(header);\n\n  return( (MYBOOL) ret );\n}\n\n\nMYBOOL __WINAPI read_params(lprec *lp, const char *filename, const char *options)\n{\n  int ret, looping, line;\n  FILE *fp;\n  hashtable *hashfunctions, *hashparameters;\n  hashelem *hp;\n  int i, j, elements, n, intvalue, state = 0;\n  REAL REALvalue;\n  char buf[4096], *header = NULL, *ptr, *ptr1, *ptr2;\n\n  if((fp = ini_open(filename)) == NULL)\n    ret = FALSE;\n  else {\n    /* create hashtable of all callable commands to find them quickly */\n    hashfunctions = create_hash_table(sizeof(functions) / sizeof(*functions), 0);\n    for (n = 0, i = 0; i < (int) (sizeof(functions)/sizeof(*functions)); i++) {\n      puthash(functions[i].par, i, NULL, hashfunctions);\n      if(functions[i].values != NULL)\n        n += functions[i].elements;\n    }\n    /* create hashtable of all arguments to find them quickly */\n    hashparameters = create_hash_table(n, 0);\n    for (n = 0, i = 0; i < (int) (sizeof(functions)/sizeof(*functions)); i++) {\n      if(functions[i].values != NULL) {\n        elements = functions[i].elements;\n        for(j = 0; j < elements; j++)\n          if((strcmp(functions[i].values[j].svalue, \"0\") != 0) &&\n             (strcmp(functions[i].values[j].svalue, \"1\") != 0))\n            puthash(functions[i].values[j].svalue, j, NULL, hashparameters);\n      }\n    }\n\n    readoptions(options, &header);\n\n    STRUPR(header);\n    ret = looping = TRUE;\n    line = 0;\n    while((ret) && (looping)) {\n      line++;\n      switch(ini_readdata(fp, buf, sizeof(buf), FALSE)) {\n        case 0: /* End of file */\n          looping = FALSE;\n          break;\n        case 1: /* header */\n          switch(state) {\n            case 0:\n              STRUPR(buf);\n              if(strcmp(buf, header) == 0)\n                state = 1;\n              break;\n            case 1:\n              looping = FALSE;\n              break;\n          }\n          break;\n        case 2: /* data */\n          if(state == 1) {\n            for(ptr = buf; (*ptr) && (isspace(*ptr)); ptr++);\n          }\n          else\n            ptr = NULL;\n          if((ptr != NULL) && (*ptr)) {\n            STRUPR(buf);\n            ptr = strchr(buf, '=');\n            if(ptr == NULL) {\n              report(lp, IMPORTANT, \"read_params: No equal sign on line %d\\n\", line);\n              ret = FALSE;\n            }\n            else {\n              *ptr = 0;\n              for(ptr1 = buf; isspace(*ptr1); ptr1++);\n              for(ptr2 = ptr - 1; (ptr2 >= ptr1) && (isspace(*ptr2)); ptr2--);\n              if(ptr2 <= ptr1) {\n                report(lp, IMPORTANT, \"read_params: No parameter name before equal sign on line %d\\n\", line);\n                ret = FALSE;\n              }\n              else {\n                ptr2[1] = 0;\n                hp = findhash(ptr1, hashfunctions);\n                if(hp == NULL) {\n                  report(lp, IMPORTANT, \"read_params: Unknown parameter name (%s) before equal sign on line %d\\n\", ptr1, line);\n                  ret = FALSE;\n                }\n                else {\n                  i = hp->index;\n                  ptr1 = ++ptr;\n                  intvalue = 0;\n                  REALvalue = 0;\n                  if(functions[i].values == NULL) {\n                    switch(functions[i].type) {\n                      case intfunction:\n                      case longfunction:\n                      case MYBOOLfunction:\n                        intvalue = strtol(ptr1, &ptr2, 10);\n                        while((*ptr2) && (isspace(*ptr2)))\n                          ptr2++;\n                        if(*ptr2) {\n                          report(lp, IMPORTANT, \"read_params: Invalid integer value on line %d\\n\", line);\n                          ret = FALSE;\n                        }\n                        break;\n                      case REALfunction:\n                        REALvalue = strtod(ptr1, &ptr2);\n                        while((*ptr2) && (isspace(*ptr2)))\n                          ptr2++;\n                        if(*ptr2) {\n                          report(lp, IMPORTANT, \"read_params: Invalid real value on line %d\\n\", line);\n                          ret = FALSE;\n                        }\n                        break;\n                    }\n                  }\n                  else {\n                    while(ret) {\n                      ptr = strchr(ptr1, '+');\n                      if(ptr == NULL)\n                        ptr = ptr1 + strlen(ptr1);\n                      for(; isspace(*ptr1); ptr1++);\n                      for(ptr2 = ptr - 1; (ptr2 >= ptr1) && (isspace(*ptr2)); ptr2--);\n                      if(ptr2 <= ptr1)\n                        break;\n                      else {\n                        ptr2[1] = 0;\n                        hp = findhash(ptr1, hashparameters);\n                        if (hp == NULL) {\n                          report(lp, IMPORTANT, \"read_params: Invalid parameter name (%s) on line %d\\n\", ptr1, line);\n                          ret = FALSE;\n                        }\n                        else {\n                          j = hp->index;\n                          if((j >= functions[i].elements) ||\n                             (strcmp(functions[i].values[j].svalue, ptr1))) {\n                            report(lp, IMPORTANT, \"read_params: Inappropriate parameter name (%s) on line %d\\n\", ptr1, line);\n                            ret = FALSE;\n                          }\n                          else {\n                            intvalue += functions[i].values[j].value;\n                          }\n                        }\n                        ptr1 = ptr + 1;\n                      }\n                    }\n                  }\n                  if(ret) {\n                    switch(functions[i].type) {\n                      case intfunction:\n                        functions[i].set_function.int_set_function(lp, intvalue);\n                        break;\n                      case longfunction:\n                        functions[i].set_function.long_set_function(lp, intvalue);\n                        break;\n                      case MYBOOLfunction:\n                        functions[i].set_function.MYBOOL_set_function(lp, (MYBOOL) intvalue);\n                        break;\n                      case REALfunction:\n                        functions[i].set_function.REAL_set_function(lp, REALvalue);\n                        break;\n                    }\n                  }\n                }\n              }\n            }\n          }\n          break;\n      }\n    }\n\n    FREE(header);\n    free_hash_table(hashfunctions);\n    free_hash_table(hashparameters);\n\n    ini_close(fp);\n  }\n\n  return( (MYBOOL) ret );\n}\n"
  },
  {
    "path": "utilities/lp_solve/lp_presolve.c",
    "content": "\n/* -------------------------------------------------------------------------\n   Presolve routines for lp_solve v5.0+\n   -------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      lp_lib.h, lp_presolve, lp_crash.h, lp_scale.h, lp_report.h\n\n    Release notes:\n    v1.0.0  1 January 2003      Initial crude version used with lp_solve v4.\n    v5.0.0  1 January 2004      Significantly expanded and repackaged\n                                presolve routines for lp_solve v5 release.\n    v5.0.1  1 April   2004      Added reference to new crash module\n    v5.1.0  20 August 2004      Reworked infeasibility detection.\n                                Added encapsulation of presolve undo logic.\n    v5.1.1  10 September 2004   Added variable bound tightening based on\n                                full-constraint information, as well as\n                                variable fixing by duality.\n    v5.2.0  1 January 2005      Fixes to bound fixing handling.\n                                Added fast batch compression after presolve.\n                                Restructured calls by adding presolve wrapper.\n                                Major optimization of identification logic\n                                  along with bug fixes.\n                                Enabled storage of eliminated matrix data.\n                                Added function to report on constraint classes.\n    v5.5.0  1 June 2005         Added implied slack presolve, restructured\n                                looping logic to be more modular, and made\n                                active row/column selection logic faster.\n    v5.5.1  18 June 2005        Finished sparsity-enhancing logic and added\n                                initial version of column aggregation code.\n   ------------------------------------------------------------------------- */\n\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_presolve.h\"\n#include \"lp_crash.h\"\n#include \"lp_scale.h\"\n#include \"lp_report.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n#define presolve_setstatus(one, two)  presolve_setstatusex(one, two, __LINE__, __FILE__)\nSTATIC int presolve_setstatusex(presolverec *psdata, int status, int lineno, const char *filename)\n{\n  if((status == INFEASIBLE) || (status == UNBOUNDED)) {\n    report(psdata->lp,\n#ifdef Paranoia\n           NORMAL,\n#else\n           DETAILED,\n#endif\n           \"presolve_setstatus: Status set to '%s' on code line %d, file '%s'\\n\",\n           (status == INFEASIBLE ? \"INFEASIBLE\" : \"UNBOUNDED\"), lineno, (filename == NULL ? \"Unknown\" : filename));\n  }\n  return( status );\n}\n\nSTATIC MYBOOL presolve_statuscheck(presolverec *psdata, int *status)\n{\n  if(*status == RUNNING) {\n    lprec *lp = psdata->lp;\n    if(!mat_validate(lp->matA))\n      *status = MATRIXERROR;\n    else if(userabort(lp, -1))\n      *status = lp->spx_status;\n  }\n  return( (MYBOOL) (*status == RUNNING) );\n}\n\nSTATIC MYBOOL presolve_createUndo(lprec *lp)\n{\n  if(lp->presolve_undo != NULL)\n    presolve_freeUndo(lp);\n  lp->presolve_undo = (presolveundorec *) calloc(1, sizeof(presolveundorec));\n  lp->presolve_undo->lp = lp;\n  if(lp->presolve_undo == NULL)\n    return( FALSE );\n  return( TRUE );\n}\nSTATIC MYBOOL inc_presolve_space(lprec *lp, int delta, MYBOOL isrows)\n{\n  int i, ii,\n      oldrowcolalloc, rowcolsum, oldrowalloc, oldcolalloc;\n  presolveundorec *psundo = lp->presolve_undo;\n\n  if(psundo == NULL) {\n    presolve_createUndo(lp);\n    psundo = lp->presolve_undo;\n  }\n\n  /* Set constants */\n  oldrowalloc = lp->rows_alloc-delta;\n  oldcolalloc = lp->columns_alloc-delta;\n  oldrowcolalloc = lp->sum_alloc-delta;\n  rowcolsum = lp->sum_alloc + 1;\n\n  /* Reallocate lp memory */\n  if(isrows)\n    allocREAL(lp, &psundo->fixed_rhs,   lp->rows_alloc+1, AUTOMATIC);\n  else\n    allocREAL(lp, &psundo->fixed_obj,   lp->columns_alloc+1, AUTOMATIC);\n  allocINT(lp,  &psundo->var_to_orig, rowcolsum, AUTOMATIC);\n  allocINT(lp,  &psundo->orig_to_var, rowcolsum, AUTOMATIC);\n\n  /* Fill in default values, where appropriate */\n  if(isrows)\n    ii = oldrowalloc+1;\n  else\n    ii = oldcolalloc+1;\n  for(i = oldrowcolalloc+1; i < rowcolsum; i++, ii++) {\n    psundo->var_to_orig[i] = 0;\n    psundo->orig_to_var[i] = 0;\n    if(isrows)\n      psundo->fixed_rhs[ii] = 0;\n    else\n      psundo->fixed_obj[ii] = 0;\n  }\n\n  return(TRUE);\n}\nSTATIC MYBOOL presolve_setOrig(lprec *lp, int orig_rows, int orig_cols)\n{\n  presolveundorec *psundo = lp->presolve_undo;\n\n  if(psundo == NULL)\n    return( FALSE );\n  psundo->orig_rows = orig_rows;\n  psundo->orig_columns = orig_cols;\n  psundo->orig_sum = orig_rows + orig_cols;\n  if(lp->wasPresolved)\n    presolve_fillUndo(lp, orig_rows, orig_cols, FALSE);\n  return( TRUE );\n}\nSTATIC MYBOOL presolve_fillUndo(lprec *lp, int orig_rows, int orig_cols, MYBOOL setOrig)\n{\n  int i;\n  presolveundorec *psundo = lp->presolve_undo;\n\n  for(i = 0; i <= orig_rows; i++) {\n    psundo->var_to_orig[i] = i;\n    psundo->orig_to_var[i] = i;\n    psundo->fixed_rhs[i]   = 0;\n  }\n  for(i = 1; i <= orig_cols; i++) {\n    psundo->var_to_orig[orig_rows + i] = i;\n    psundo->orig_to_var[orig_rows + i] = i;\n    psundo->fixed_obj[i] = 0;\n  }\n  if(setOrig)\n    presolve_setOrig(lp, orig_rows, orig_cols);\n\n  return( TRUE );\n}\nSTATIC MYBOOL presolve_rebuildUndo(lprec *lp, MYBOOL isprimal)\n{\n  int             ik, ie, ix, j, k, *colnrDep;\n  REAL             hold, *value, *solution, *slacks;\n  presolveundorec *psdata = lp->presolve_undo;\n  MATrec          *mat = NULL;\n\n  /* Point to and initialize undo structure at first call */\n  if(isprimal) {\n    if(psdata->primalundo != NULL)\n      mat = psdata->primalundo->tracker;\n    solution = lp->full_solution + lp->presolve_undo->orig_rows;\n    slacks   = lp->full_solution;\n  }\n  else {\n    if(psdata->dualundo != NULL)\n      mat = psdata->dualundo->tracker;\n    solution = lp->full_duals;\n    slacks   = lp->full_duals + lp->presolve_undo->orig_rows;\n  }\n  if(mat == NULL)\n    return( FALSE );\n\n  /* Loop backward over the undo chain */\n  for(j = mat->col_tag[0]; j > 0; j--) {\n    ix = mat->col_tag[j];\n    ik = mat->col_end[j-1];\n    ie = mat->col_end[j];\n    colnrDep = &COL_MAT_ROWNR(ik);\n    value    = &COL_MAT_VALUE(ik);\n    hold = 0;\n    k = 0;\n    for(; ik < ie; ik++, colnrDep += matRowColStep, value += matValueStep) {\n\n      /* Constant term */\n      if(*colnrDep == 0)\n        hold += *value;\n\n      /* Special case with dependence on a slack variable */\n      else if(isprimal && (*colnrDep > lp->presolve_undo->orig_columns)) {\n        k = (*colnrDep) - lp->presolve_undo->orig_columns;\n        hold -= (*value) * slacks[k];\n        slacks[k] = 0;\n      }\n      else if(!isprimal && (*colnrDep > lp->presolve_undo->orig_rows)) {\n        k = (*colnrDep) - lp->presolve_undo->orig_rows;\n        hold -= (*value) * slacks[k];\n        slacks[k] = 0;\n      }\n\n      /* Dependence on other user variable */\n      else\n        hold -= (*value) * solution[*colnrDep];\n\n      *value = 0;\n    }\n    if(fabs(hold) > lp->epsvalue)\n      solution[ix] = hold;\n  }\n\n  return( TRUE );\n}\nSTATIC MYBOOL presolve_freeUndo(lprec *lp)\n{\n  presolveundorec *psundo = lp->presolve_undo;\n\n  if(psundo == NULL)\n    return( FALSE );\n  FREE(psundo->orig_to_var);\n  FREE(psundo->var_to_orig);\n  FREE(psundo->fixed_rhs);\n  FREE(psundo->fixed_obj);\n  if(psundo->deletedA != NULL)\n    freeUndoLadder(&(psundo->deletedA));\n  if(psundo->primalundo != NULL)\n    freeUndoLadder(&(psundo->primalundo));\n  if(psundo->dualundo != NULL)\n    freeUndoLadder(&(psundo->dualundo));\n  FREE(lp->presolve_undo);\n  return( TRUE );\n}\n\nSTATIC void presolve_storeDualUndo(presolverec *psdata, int rownr, int colnr)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   firstdone = FALSE;\n  int      ix, iix, item;\n  REAL     Aij = get_mat(lp, rownr, colnr);\n  MATrec   *mat = lp->matA;\n\n  if(presolve_collength(psdata, colnr) == 0)\n    return;\n\n  /* Add undo information for the dual of the deleted constraint */\n  item = 0;\n  for(ix = presolve_nextrow(psdata, colnr, &item); ix >= 0;\n      ix = presolve_nextrow(psdata, colnr, &item)) {\n    iix = COL_MAT_ROWNR(ix);\n    if(iix == rownr)\n      continue;\n    if(!firstdone)\n      firstdone = addUndoPresolve(lp, FALSE, rownr, get_mat(lp, 0, colnr)/Aij,\n                                                    get_mat_byindex(lp, ix, FALSE, TRUE)/Aij, iix);\n    else\n      appendUndoPresolve(lp, FALSE, get_mat_byindex(lp, ix, FALSE, TRUE)/Aij, iix);\n  }\n}\n\n/* ----------------------------------------------------------------------------- */\n/* Presolve debugging routines                                                   */\n/* ----------------------------------------------------------------------------- */\nSTATIC MYBOOL presolve_SOScheck(presolverec *psdata)\n{\n  MYBOOL status = TRUE;\n  lprec  *lp = psdata->lp;\n  int    *list, i, j, n, k, nk, colnr, nSOS = SOS_count(lp), nerr = 0;\n  SOSrec *SOS;\n\n  if(nSOS == 0)\n    return( status );\n\n  /* For each SOS and each member check validity */\n  for(i = 1; i<= nSOS; i++) {\n    SOS = lp->SOS->sos_list[i-1];\n    list = SOS->members;\n    n = list[0];\n    for(j = 1; j<= n; j++) {\n      colnr = list[j];\n      /* Check valid range */\n      if((colnr < 1) || (colnr > lp->columns)) {\n        nerr++;\n        report(lp, IMPORTANT, \"presolve_SOScheck: A - Column index %d is outside of valid range\\n\",\n                              colnr);\n      }\n      /* Check for deletion */\n      if(!isActiveLink(psdata->cols->varmap, colnr)) {\n        nerr++;\n        report(lp, IMPORTANT, \"presolve_SOScheck: B - Column index %d has been marked for deletion\\n\",\n                              colnr);\n      }\n      /* Check if sorted member array is Ok */\n      if(SOS_member_index(lp->SOS, i, colnr) != j) {\n        nerr++;\n        report(lp, IMPORTANT, \"presolve_SOScheck: C - Column index %d not found in fast search array\\n\",\n                              colnr);\n      }\n      /* Check for variable membership in this SOS record of the sparse storage */\n      k = lp->SOS->memberpos[colnr-1];\n      nk = lp->SOS->memberpos[colnr];\n      while((k < nk) && (lp->SOS->membership[k] != i))\n        k++;\n      if(k >= nk) {\n        nerr++;\n        report(lp, IMPORTANT, \"presolve_SOScheck: D - Column index %d was not found in sparse array\\n\",\n                              colnr);\n      }\n    }\n  }\n\n  /* Check that all members in the sparse array can be validated as SOS members */\n  for(colnr = 1; colnr <= lp->columns; colnr++) {\n    k = lp->SOS->memberpos[colnr-1];\n    nk = lp->SOS->memberpos[colnr];\n    for(; k < nk; k++) {\n      if(!SOS_is_member(lp->SOS, lp->SOS->membership[k], colnr)) {\n        nerr++;\n        report(lp, IMPORTANT, \"presolve_SOScheck: E - Sparse array did not indicate column index %d as member of SOS %d\\n\",\n                              colnr, lp->SOS->membership[k]);\n      }\n    }\n  }\n  status = (MYBOOL) (nerr == 0);\n  if(!status)\n    report(lp, IMPORTANT, \"presolve_SOScheck: There were %d errors\\n\",\n                           nerr);\n\n\n  return( status );\n}\n\n/* ----------------------------------------------------------------------------- */\n/* Presolve routines for tightening the model                                    */\n/* ----------------------------------------------------------------------------- */\n\nINLINE REAL presolve_roundrhs(lprec *lp, REAL value, MYBOOL isGE)\n{\n#ifdef DoPresolveRounding\n  REAL eps = PRESOLVE_EPSVALUE*1000,\n  /* REAL eps = PRESOLVE_EPSVALUE*pow(10.0,MAX(0,log10(1+fabs(value)))), */\n  testout = my_precision(value, eps);\n#if 1\n  if(my_chsign(isGE, value-testout) < 0)\n    value = testout;\n#elif 0\n  if(my_chsign(isGE, value-testout) < 0)\n    value = testout;\n  else if(value != testout)\n    value += my_chsign(isGE, (value-testout)/2);\n    /* value = testout + my_chsign(isGE, (value-testout)/2); */\n#else\n  if(testout != value)\n    value += my_chsign(isGE, eps*1000);              /* BASE OPTION */\n#endif\n\n#endif\n  return( value );\n}\n\nINLINE REAL presolve_roundval(lprec *lp, REAL value)\n{\n#ifdef DoPresolveRounding\n  /* value = my_precision(value, PRESOLVE_EPSVALUE*MAX(1,log10(1+fabs(value)))); */\n  value = my_precision(value, PRESOLVE_EPSVALUE);    /* BASE OPTION */\n#endif\n  return( value );\n}\n\n/*\nINLINE MYBOOL presolve_mustupdate(lprec *lp, int colnr)\n{\n#if 0\n  return( my_infinite(lp, get_lowbo(lp, colnr)) ||\n          my_infinite(lp, get_upbo(lp, colnr)) );\n#else\n  return( my_infinite(lp, lp->orig_lowbo[lp->rows+colnr]) ||\n          my_infinite(lp, lp->orig_upbo[lp->rows+colnr]) );\n#endif\n}\n*/\n\nINLINE REAL presolve_sumplumin(lprec *lp, int item, psrec *ps, MYBOOL doUpper)\n{\n  REAL *plu = (doUpper ? ps->pluupper : ps->plulower),\n       *neg = (doUpper ? ps->negupper : ps->neglower);\n\n  if(fabs(plu[item]) >= lp->infinite)\n    return( plu[item] );\n  else if(fabs(neg[item]) >= lp->infinite)\n    return( neg[item] );\n  else\n    return( plu[item]+neg[item] );\n}\n\nINLINE void presolve_range(lprec *lp, int rownr, psrec *ps, REAL *loValue, REAL *hiValue)\n{\n  *loValue = presolve_sumplumin(lp, rownr,   ps, FALSE);\n  *hiValue = presolve_sumplumin(lp, rownr,   ps, TRUE);\n}\n\nSTATIC void presolve_rangeorig(lprec *lp, int rownr, psrec *ps, REAL *loValue, REAL *hiValue, REAL delta)\n{\n  delta = my_chsign(is_chsign(lp, rownr), lp->presolve_undo->fixed_rhs[rownr] + delta);\n  *loValue = presolve_sumplumin(lp, rownr,   ps, FALSE) + delta;\n  *hiValue = presolve_sumplumin(lp, rownr,   ps, TRUE) + delta;\n}\n\nSTATIC MYBOOL presolve_rowfeasible(presolverec *psdata, int rownr, MYBOOL userowmap)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   status = TRUE;\n  int      contype, origrownr = rownr;\n  REAL     LHS, RHS, value;\n\n  /* Optionally loop across all active rows in the provided map (debugging) */\n  if(userowmap)\n    rownr = firstActiveLink(psdata->rows->varmap);\n\n  /* Now do once for ingoing rownr or loop across rowmap */\n  while((status == TRUE) && (rownr != 0)) {\n\n    /* Check the lower bound */\n    value = presolve_sumplumin(lp, rownr, psdata->rows, TRUE);\n    LHS = get_rh_lower(lp, rownr);\n    if(value < LHS-lp->epssolution) {\n      contype = get_constr_type(lp, rownr);\n      report(lp, NORMAL, \"presolve_rowfeasible: Lower bound infeasibility in %s row %s (%g << %g)\\n\",\n                          get_str_constr_type(lp, contype), get_row_name(lp, rownr), value, LHS);\n      if(rownr != origrownr)\n      report(lp, NORMAL, \"        ...           Input row base used for testing was %s\\n\",\n                                                    get_row_name(lp, origrownr));\n      status = FALSE;\n    }\n\n    /* Check the upper bound */\n    value = presolve_sumplumin(lp, rownr, psdata->rows, FALSE);\n    RHS = get_rh_upper(lp, rownr);\n    if(value > RHS+lp->epssolution) {\n      contype = get_constr_type(lp, rownr);\n      report(lp, NORMAL, \"presolve_rowfeasible: Upper bound infeasibility in %s row %s (%g >> %g)\\n\",\n                          get_str_constr_type(lp, contype), get_row_name(lp, rownr), value, RHS);\n      status = FALSE;\n    }\n    if(userowmap)\n      rownr = nextActiveLink(psdata->rows->varmap, rownr);\n    else\n      rownr = 0;\n  }\n  return( status );\n}\n\nSTATIC MYBOOL presolve_debugmap(presolverec *psdata, const char *caption)\n{\n  lprec *lp = psdata->lp;\n  MATrec *mat = lp->matA;\n  int    colnr, ix, ie, nx, jx, je, *cols, *rows, n;\n  int    nz = mat->col_end[lp->columns] - 1;\n  MYBOOL status = FALSE;\n\n  for(colnr = 1; colnr <= lp->columns; colnr++) {\n    rows = psdata->cols->next[colnr];\n    if(!isActiveLink(psdata->cols->varmap, colnr)) {\n      if(rows != NULL) {\n        report(lp, SEVERE, \"presolve_debugmap: Inactive column %d is non-empty\\n\",\n                           colnr);\n        goto Done;\n      }\n      else\n        continue;\n    }\n    if(rows == NULL)\n      report(lp, SEVERE, \"presolve_debugmap: Active column %d is empty\\n\",\n                         colnr);\n    je = *rows;\n    rows++;\n    for(jx = 1; jx <= je; jx++, rows++) {\n      if((*rows < 0) || (*rows > nz)) {\n        report(lp, SEVERE, \"presolve_debugmap: NZ index %d for column %d out of range (index %d<=%d)\\n\",\n                           *rows, colnr, jx, je);\n        goto Done;\n      }\n      cols = psdata->rows->next[COL_MAT_ROWNR(*rows)];\n      ie = cols[0];\n      n = 0;\n      for(ix = 1; ix <= ie; ix++) {\n        nx = cols[ix];\n        if((nx < 0) || (nx > nz)) {\n          report(lp, SEVERE, \"presolve_debugmap: NZ index %d for column %d to row %d out of range\\n\",\n                             nx, colnr, jx);\n          goto Done;\n        }\n      }\n    }\n  }\n  status = TRUE;\nDone:\n  if(!status && (caption != NULL))\n    report(lp, SEVERE, \"...caller was '%s'\\n\", caption);\n  return( status );\n}\n\nSTATIC MYBOOL presolve_validate(presolverec *psdata, MYBOOL forceupdate)\n{\n  int    i, ie, j, je, k, rownr, *items;\n  REAL   upbound, lobound, value;\n  lprec  *lp = psdata->lp;\n  MATrec *mat = lp->matA;\n  MYBOOL status = mat->row_end_valid && !forceupdate;\n\n  if(status)\n    return( status );\n  else if(!mat->row_end_valid)\n    status = mat_validate(mat);\n  else\n    status = forceupdate;\n  if(status) {\n\n    /* First update rows... */\n    for(i = 1; i <= lp->rows; i++) {\n\n      psdata->rows->plucount[i] = 0;\n      psdata->rows->negcount[i] = 0;\n      psdata->rows->pluneg[i]   = 0;\n\n      if(!isActiveLink(psdata->rows->varmap, i)) {\n        FREE(psdata->rows->next[i]);\n      }\n      else {\n        /* Create next column pointers by row */\n        k = mat_rowlength(mat, i);\n        allocINT(lp, &(psdata->rows->next[i]), k+1, AUTOMATIC);\n        items = psdata->rows->next[i];\n        je = mat->row_end[i];\n        k = 0;\n        for(j = mat->row_end[i-1]; j < je; j++)\n          if(isActiveLink(psdata->cols->varmap, ROW_MAT_COLNR(j))) {\n            k++;\n            items[k] = j;\n          }\n        items[0] = k;\n      }\n    }\n\n    /* ...then update columns */\n    for(j = 1; j <= lp->columns; j++) {\n\n      psdata->cols->plucount[j] = 0;\n      psdata->cols->negcount[j] = 0;\n      psdata->cols->pluneg[j]   = 0;\n\n      if(!isActiveLink(psdata->cols->varmap, j)) {\n        FREE(psdata->cols->next[j]);\n      }\n      else {\n        upbound = get_upbo(lp, j);\n        lobound = get_lowbo(lp, j);\n        if(is_semicont(lp, j) && (upbound > lobound)) {\n          if(lobound > 0)\n            lobound = 0;\n          else if(upbound < 0)\n            upbound = 0;\n        }\n\n        /* Create next row pointers by column */\n        k = mat_collength(mat, j);\n        allocINT(lp, &(psdata->cols->next[j]), k+1, AUTOMATIC);\n        items = psdata->cols->next[j];\n        ie = mat->col_end[j];\n        k = 0;\n        for(i = mat->col_end[j-1]; i < ie; i++) {\n          rownr = COL_MAT_ROWNR(i);\n          if(isActiveLink(psdata->rows->varmap, rownr)) {\n            k++;\n            items[k] = i;\n\n            /* Cumulate counts */\n            value = COL_MAT_VALUE(i);\n            if(my_chsign(is_chsign(lp, rownr), value) > 0) {\n              psdata->rows->plucount[rownr]++;\n              psdata->cols->plucount[j]++;\n            }\n            else {\n              psdata->rows->negcount[rownr]++;\n              psdata->cols->negcount[j]++;\n            }\n            if((lobound < 0) && (upbound >= 0)) {\n              psdata->rows->pluneg[rownr]++;\n              psdata->cols->pluneg[j]++;\n            }\n          }\n        }\n        items[0] = k;\n      }\n    }\n#ifdef Paranoia\n    presolve_debugmap(psdata, \"presolve_validate\");\n#endif\n  }\n  return( status );\n}\n\nSTATIC MYBOOL presolve_rowtallies(presolverec *psdata, int rownr, int *plu, int *neg, int *pluneg)\n{\n  REAL   value;\n  lprec  *lp = psdata->lp;\n  MATrec *mat = lp->matA;\n  int    ix, jx, ib = 0;\n  MYBOOL chsign = is_chsign(lp, rownr);\n\n  /* Initialize */\n  *plu = 0;\n  *neg = 0;\n  *pluneg = 0;\n\n  /* Loop over still active row members */\n  for(ix = presolve_nextcol(psdata, rownr, &ib); ix >= 0; ix = presolve_nextcol(psdata, rownr, &ib)) {\n\n    /* Get matrix column and value */\n    jx    = ROW_MAT_COLNR(ix);\n    value = ROW_MAT_VALUE(ix);\n\n    /* Cumulate counts */\n    if(my_chsign(chsign, value) > 0)\n      (*plu)++;\n    else\n      (*neg)++;\n    if((get_lowbo(lp, jx) < 0) && (get_upbo(lp, jx) >= 0))\n      (*pluneg)++;\n  }\n  return( TRUE );\n}\nSTATIC MYBOOL presolve_debugrowtallies(presolverec *psdata)\n{\n  lprec  *lp = psdata->lp;\n  int    i, plu, neg, pluneg, nerr = 0;\n\n  for(i = 1; i <= lp->rows; i++)\n    if(isActiveLink(psdata->rows->varmap, i) &&\n       presolve_rowtallies(psdata, i, &plu, &neg, &pluneg)) {\n      if((psdata->rows->plucount[i] != plu) ||\n         (psdata->rows->negcount[i] != neg) ||\n         (psdata->rows->pluneg[i] != pluneg)) {\n        nerr++;\n        report(lp, SEVERE, \"presolve_debugrowtallies: Detected inconsistent count for row %d\\n\", i);\n      }\n    }\n  return( (MYBOOL) (nerr == 0) );\n}\n\nSTATIC int presolve_debugcheck(lprec *lp, LLrec *rowmap, LLrec *colmap)\n{\n  int i, j, errc = 0;\n\n  /* Validate constraint bounds */\n  for(i = 1; i < lp->rows; i++) {\n    if((rowmap != NULL) && !isActiveLink(rowmap, i))\n      continue;\n    /* Check if we have a negative range */\n    if(lp->orig_upbo[i] < 0) {\n      errc++;\n      report(lp, SEVERE, \"presolve_debugcheck: Detected negative range %g for row %d\\n\",\n                         lp->orig_upbo[i], i);\n    }\n  }\n  /* Validate variables */\n  for(j = 1; j < lp->columns; j++) {\n    if((colmap != NULL) && !isActiveLink(colmap, j))\n      continue;\n    i = lp->rows+j;\n    /* Check if we have infeasible  bounds */\n    if(lp->orig_lowbo[i] > lp->orig_upbo[i]) {\n      errc++;\n      report(lp, SEVERE, \"presolve_debugcheck: Detected UB < LB for column %d\\n\",\n                         j);\n    }\n  }\n  /* Return total number of errors */\n  return( errc );\n}\n\nSTATIC MYBOOL presolve_candeletevar(presolverec *psdata, int colnr)\n{\n  lprec    *lp = psdata->lp;\n  int      usecount = SOS_memberships(lp->SOS, colnr);\n\n  return( (MYBOOL) ((lp->SOS == NULL) || (usecount == 0) ||\n                    (/*is_presolve(lp, PRESOLVE_SOS) &&*/\n                     (((lp->SOS->sos1_count == lp->SOS->sos_count)) ||\n                      (usecount == SOS_is_member_of_type(lp->SOS, colnr, SOS1))))) );\n}\n\nSTATIC int presolve_rowlengthex(presolverec *psdata, int rownr)\n{\n  int j1 = psdata->rows->plucount[rownr] + psdata->rows->negcount[rownr];\n#ifdef Paranoia\n  int j2 = presolve_rowlength(psdata, rownr);\n\n  if(j1 != j2) {\n    report(psdata->lp, SEVERE, \"presolve_rowlengthex: Expected row length %d, but found %d in row %s\\n\",\n                                j2, j1, get_row_name(psdata->lp, rownr));\n    j1 = -j1;\n  }\n#endif\n\n  return( j1 );\n}\nSTATIC int presolve_rowlengthdebug(presolverec *psdata)\n{\n  int rownr, n = 0;\n\n  for(rownr = firstActiveLink(psdata->rows->varmap); rownr != 0;\n    rownr = nextActiveLink(psdata->rows->varmap, rownr))\n    n += presolve_rowlengthex(psdata, rownr);\n  return( n );\n}\n\nINLINE int presolve_nextrecord(psrec *ps, int recnr, int *previtem)\n{\n  int *nzlist = ps->next[recnr], nzcount = nzlist[0], status = -1;\n\n  /* Check if we simply wish the last active column */\n  if(previtem == NULL) {\n    if(nzlist != NULL)\n      status = nzlist[*nzlist];\n    return( status );\n  }\n\n  /* Step to next */\n#ifdef Paranoia\n  else if((*previtem < 0) || (*previtem > nzcount))\n    return( status );\n#endif\n  (*previtem)++;\n\n  /* Set the return values */\n  if(*previtem > nzcount)\n    (*previtem) = 0;\n  else\n    status = nzlist[*previtem];\n\n  return( status );\n}\nINLINE int presolve_nextcol(presolverec *psdata, int rownr, int *previtem)\n/* Find the first active (non-eliminated) nonzero column in rownr after prevcol */\n{\n  return( presolve_nextrecord(psdata->rows, rownr, previtem) );\n}\nINLINE int presolve_lastcol(presolverec *psdata, int rownr)\n{\n  return( presolve_nextrecord(psdata->rows, rownr, NULL) );\n}\nINLINE int presolve_nextrow(presolverec *psdata, int colnr, int *previtem)\n/* Find the first active (non-eliminated) nonzero row in colnr after prevrow */\n{\n  return( presolve_nextrecord(psdata->cols, colnr, previtem) );\n}\nINLINE int presolve_lastrow(presolverec *psdata, int colnr)\n{\n  return( presolve_nextrecord(psdata->cols, colnr, NULL) );\n}\n\nINLINE void presolve_adjustrhs(presolverec *psdata, int rownr, REAL fixdelta, REAL epsvalue)\n{\n  lprec *lp = psdata->lp;\n\n  lp->orig_rhs[rownr] -= fixdelta;\n  if(epsvalue > 0)\n#if 1\n    my_roundzero(lp->orig_rhs[rownr], epsvalue);\n#else\n    lp->orig_rhs[rownr] = presolve_roundrhs(lp, lp->orig_rhs[rownr], FALSE);\n#endif\n  lp->presolve_undo->fixed_rhs[rownr] += fixdelta;\n}\n\nSTATIC int presolve_shrink(presolverec *psdata, int *nConRemove, int *nVarRemove)\n{\n  SOSgroup *SOS = psdata->lp->SOS;\n  int     status = RUNNING, countR = 0, countC = 0,\n          i, ix, n, *list;\n  REAL    fixValue;\n\n  /* Remove empty rows */\n  list = psdata->rows->empty;\n  if(list != NULL) {\n    n = list[0];\n    for(i = 1; i <= n; i++)\n      if(isActiveLink(psdata->rows->varmap, list[i])) {\n        presolve_rowremove(psdata, list[i], FALSE);\n        countR++;\n      }\n    if(nConRemove != NULL)\n      (*nConRemove) += countR;\n    list[0] = 0;\n  }\n\n  /* Fix and remove empty columns (unless they are in a SOS) */\n  list = psdata->cols->empty;\n  if(list != NULL) {\n    n = list[0];\n    for(i = 1; i <= n; i++) {\n      ix = list[i];\n      if(isActiveLink(psdata->cols->varmap, ix)) {\n        if(presolve_colfixdual(psdata, ix, &fixValue, &status)) {\n          if(!presolve_colfix(psdata, ix, fixValue, TRUE, nVarRemove)) {\n            status = presolve_setstatus(psdata, INFEASIBLE);\n            break;\n          }\n          presolve_colremove(psdata, ix, FALSE);\n          countC++;\n        }\n        else if(SOS_is_member(SOS, 0, ix))\n          report(psdata->lp, DETAILED, \"presolve_shrink: Empty column %d is member of a SOS\\n\", ix);\n      }\n    }\n    list[0] = 0;\n  }\n\n  return( status );\n}\n\nSTATIC void presolve_rowremove(presolverec *psdata, int rownr, MYBOOL allowcoldelete)\n{\n  lprec    *lp = psdata->lp;\n  MATrec   *mat = lp->matA;\n  int      ix, ie, nx, jx, je, *cols, *rows, n, colnr;\n\n#ifdef Paranoia\n  if((rownr < 1) || (rownr > lp->rows))\n    report(lp, SEVERE, \"presolve_rowremove: Row %d out of range\\n\", rownr);\n#endif\n\n  /* Remove this row for each column that is active in the row */\n  cols = psdata->rows->next[rownr];\n  ie = *cols;\n  cols++;\n  for(ix = 1; ix <= ie; ix++, cols++) {\n    n = 0;\n    colnr = ROW_MAT_COLNR(*cols);\n    rows = psdata->cols->next[colnr];\n    je = rows[0];\n    /* See if we can narrow the search window */\n    jx = je / 2;\n    if((jx > 5) && (rownr >= COL_MAT_ROWNR(rows[jx])))\n      n = jx-1;\n    else\n      jx = 1;\n    /* Do the compression loop */\n    for(; jx <= je; jx++) {\n      nx = rows[jx];\n      if(COL_MAT_ROWNR(nx) != rownr) {\n        n++;\n        rows[n] = nx;\n      }\n    }\n    rows[0] = n;\n\n    /* Make sure we delete columns that have become empty */\n#if 1\n    if((n == 0) && allowcoldelete) {\n      int *list = psdata->cols->empty;\n      n = ++list[0];\n      list[n] = colnr;\n    }\n#endif\n\n  }\n  FREE(psdata->rows->next[rownr]);\n\n  removeLink(psdata->rows->varmap, rownr);\n  switch(get_constr_type(lp, rownr)) {\n    case LE: removeLink(psdata->LTmap, rownr);\n              break;\n    case EQ: removeLink(psdata->EQmap, rownr);\n              break;\n  }\n  if(isActiveLink(psdata->INTmap, rownr))\n    removeLink(psdata->INTmap, rownr);\n}\n\nSTATIC int presolve_colremove(presolverec *psdata, int colnr, MYBOOL allowrowdelete)\n{\n  lprec    *lp = psdata->lp;\n\n#ifdef Paranoia\n  if((colnr < 1) || (colnr > lp->columns))\n    report(lp, SEVERE, \"presolve_colremove: Column %d out of range\\n\", colnr);\n  if(!isActiveLink(psdata->cols->varmap, colnr) || !presolve_candeletevar(psdata, colnr))\n    colnr = -1;\n  else\n#endif\n  {\n    MATrec *mat = lp->matA;\n    int    ix, ie, nx, jx, je, *cols, *rows, n, rownr;\n\n    /* Remove this column for each row that is active in the column */\n    rows = psdata->cols->next[colnr];\n    je = *rows;\n    rows++;\n    for(jx = 1; jx <= je; jx++, rows++) {\n      n = 0;\n      rownr = COL_MAT_ROWNR(*rows);\n      cols = psdata->rows->next[rownr];\n      ie = cols[0];\n      /* See if we can narrow the search window */\n      ix = ie / 2;\n      if((ix > 5) && (colnr >= ROW_MAT_COLNR(cols[ix])))\n        n = ix-1;\n      else\n        ix = 1;\n      /* Do the compression loop */\n      for(; ix <= ie; ix++) {\n        nx = cols[ix];\n        if(ROW_MAT_COLNR(nx) != colnr) {\n          n++;\n          cols[n] = nx;\n        }\n      }\n      cols[0] = n;\n\n      /* Make sure we delete rows that become empty */\n#if 1\n      if((n == 0) && allowrowdelete) {\n        int *list = psdata->rows->empty;\n        n = ++list[0];\n        list[n] = rownr;\n      }\n#endif\n\n    }\n    FREE(psdata->cols->next[colnr]);\n\n    /* Update other counts */\n    if(SOS_is_member(lp->SOS, 0, colnr)) {\n      if(lp->sos_priority != NULL) {\n        lp->sos_vars--;\n        if(is_int(lp, colnr))\n          lp->sos_ints--;\n      }\n      SOS_member_delete(lp->SOS, 0, colnr);\n      clean_SOSgroup(lp->SOS, TRUE);\n      if(SOS_count(lp) == 0)\n        free_SOSgroup(&(lp->SOS));\n    }\n\n    /* Finally remove the column from the active column list */\n    colnr = removeLink(psdata->cols->varmap, colnr);\n  }\n  return( colnr );\n}\n\nSTATIC int presolve_redundantSOS(presolverec *psdata, int *nb, int *nSum)\n{\n  lprec    *lp = psdata->lp;\n  int      i, ii, k, kk, j, nrows = lp->rows, *fixed = NULL,\n           iBoundTighten = 0, status = RUNNING;\n  SOSrec   *SOS;\n\n  /* Is there anything to do? */\n  i = ii = SOS_count(lp);\n  if(ii == 0)\n    return( status );\n\n  /* Allocate working member list */\n  if(!allocINT(lp, &fixed, lp->columns+1, FALSE) )\n    return( lp->spx_status );\n\n  /* Check if we have SOS'es that are already satisfied or fixable/satisfiable */\n  while(i > 0) {\n    SOS = lp->SOS->sos_list[i-1];\n    kk = SOS->members[0];\n    fixed[0] = 0;\n    for(k = 1; k <= kk; k++) {\n      j = SOS->members[k];\n      if((get_lowbo(lp, j) > 0) && !is_semicont(lp, j)) {\n        fixed[++fixed[0]] = k;\n        /* Abort if we have identified SOS infeasibility */\n        if(fixed[0] > SOS->type) {\n          status = presolve_setstatus(psdata, INFEASIBLE);\n          goto Done;\n        }\n      }\n    }\n    /* If there were an exact number of non-zero SOS members, check their sequentiality */\n    if(fixed[0] == SOS->type) {\n      /* Check sequentiality of members with non-zero lower bounds */\n      for(k = 2; k <= fixed[0]; k++) {\n        if(fixed[k] != fixed[k-1]+1) {\n          status = presolve_setstatus(psdata, INFEASIBLE);\n          goto Done;\n        }\n      }\n      /* Fix other member variables to zero, if necessary */\n      for(k = kk; k > 0; k--) {\n        j = SOS->members[k];\n        if((get_lowbo(lp, j) > 0) && !is_semicont(lp, j))\n          continue;\n        if(!presolve_colfix(psdata, j, 0.0, AUTOMATIC, &iBoundTighten)) {\n          status = presolve_setstatus(psdata, INFEASIBLE);\n          goto Done;\n        }\n      }\n      /* Remove the SOS */\n      delete_SOSrec(lp->SOS, i /* , FALSE */);\n    }\n    /* Otherwise, try to fix variables outside the SOS type window */\n    else if(fixed[0] > 0) {\n      for(k = kk; k > 0; k--) {\n        if((k > fixed[fixed[0]]-SOS->type) && /* After leading entries   */\n           (k < fixed[1]+SOS->type))          /* Before trailing entries */\n          continue;\n        j = SOS->members[k];\n        SOS_member_delete(lp->SOS, i, j);\n        /* if(get_upbo(lp, j) - get_lowbo(lp, j) < lp->epsprimal) */\n        if(is_fixedvar(lp, nrows+j))\n          continue;\n        if(!presolve_colfix(psdata, j, 0.0, AUTOMATIC, &iBoundTighten)) {\n          status = presolve_setstatus(psdata, INFEASIBLE);\n          goto Done;\n        }\n      }\n    }\n    i--;\n  }\n\n  /* Update the sparse member map if there were SOS deletions;\n     Remember that delete_SOSrec() above specified deferred updating! */\n  i = SOS_count(lp);\n  if((i < ii) || (iBoundTighten > 0)) {\n    SOS_member_updatemap(lp->SOS);\n  }\n\n  /* Update tag orders */\n  for(; i > 0; i--)\n    lp->SOS->sos_list[i-1]->tagorder = i;\n\nDone:\n  FREE(fixed);\n  (*nb) += iBoundTighten;\n  (*nSum) += iBoundTighten;\n\n  return( status );\n}\n\nSTATIC MYBOOL presolve_fixSOS1(presolverec *psdata, int colnr, REAL fixvalue, int *nr, int *nv)\n{\n  (void)nr;\n  lprec    *lp = psdata->lp;\n  int      i, k, j;\n  SOSrec   *SOS;\n  REAL     newvalue;\n  MYBOOL   *fixed = NULL, status = FALSE;\n  (void)nr;\n\n  /* Allocate working member list */\n  if(!allocMYBOOL(lp, &fixed, lp->columns+1, TRUE) )\n    return(FALSE);\n\n  /* Fix variables in SOS's where colnr is a member */\n  i = SOS_count(lp);\n  while(i > 0) {\n    /* Set next SOS target (note that colnr has been tested earlier as not being a member of a higher order SOS) */\n    SOS = lp->SOS->sos_list[i-1];\n    if(SOS_is_member(lp->SOS, i, colnr)) {\n      for(k = SOS->members[0]; k > 0; k--) {\n        j = SOS->members[k];\n        if(fixed[j])\n          continue;\n        if(j == colnr) {\n          fixed[j] = TRUE;\n          newvalue = fixvalue;\n        }\n        else {\n          fixed[j] = AUTOMATIC;\n          newvalue = 0.0;\n        }\n        /* If it is a member of a higher order SOS then just change bounds */\n        if(!presolve_candeletevar(psdata, j)) {\n          set_bounds(lp, j, newvalue, newvalue);\n          fixed[j] = TRUE | AUTOMATIC;\n          psdata->forceupdate = TRUE;\n        }\n        /* Otherwise fix it in preparation for removal */\n        else if(!presolve_colfix(psdata, j, newvalue, TRUE, nv))\n          goto Done;\n      }\n    }\n    i--;\n  }\n\n  /* Delete SOS'es or SOS member variables where we can */\n  k = i = SOS_count(lp);\n  while(i > 0) {\n    /* Set next SOS target */\n    SOS = lp->SOS->sos_list[i-1];\n    if(SOS_is_member(lp->SOS, i, colnr)) {\n      /* Always delete SOS1's */\n      if(SOS->type == SOS1)\n        delete_SOSrec(lp->SOS, i /* , FALSE */);\n      /* Only delete leading or trailing SOS members in higher-order SOS'es that are fixed at 0;\n        (note that this section of the code will never be called in the current setup) */\n      else {\n        /* First the leading entries... */\n        for(j = 1; j <= SOS->members[0]; j++) {\n          if(fixed[SOS->members[j]] == AUTOMATIC)\n            SOS_member_delete(lp->SOS, i, SOS->members[j]);\n        }\n        /* ...then trailing entries */\n        for(j = SOS->members[0]; j > 0; j--) {\n          if(fixed[SOS->members[j]] == AUTOMATIC)\n            SOS_member_delete(lp->SOS, i, SOS->members[j]);\n        }\n      }\n    }\n    i--;\n  }\n\n  /* Update the sparse member map if there were SOS deletions; delete_SOSrec() above\n     specified deferred updating */\n  i = SOS_count(lp);\n  if(i < k)\n    SOS_member_updatemap(lp->SOS);\n\n  /* Delete the variables that have been fixed */\n  k = 0;\n  for(j = lp->columns; j > 0; j--) {\n    if((fixed[j] == TRUE) || (fixed[j] == AUTOMATIC)) {\n       presolve_colremove(psdata, j, TRUE);\n       k++;\n    }\n  }\n\n  /* Update tag orders */\n  i = SOS_count(lp);\n  for(; i > 0; i--)\n    lp->SOS->sos_list[i-1]->tagorder = i;\n\n  status = TRUE;\n\nDone:\n  FREE(fixed);\n  return( status );\n}\n\nSTATIC void presolve_setEQ(presolverec *psdata, int rownr)\n{\n  lprec *lp = psdata->lp;\n\n  if(is_constr_type(lp, rownr, LE))\n     removeLink(psdata->LTmap, rownr);\n   setLink(psdata->EQmap, rownr);\n   set_constr_type(lp, rownr, EQ);\n   psdata->dv_lobo[rownr] = -lp->infinite;\n   psdata->dv_upbo[rownr] = lp->infinite;\n}\n\nSTATIC MYBOOL presolve_singletonbounds(presolverec *psdata, int rownr, int colnr, REAL *lobound, REAL *upbound, REAL *aval)\n{\n  lprec  *lp = psdata->lp;\n  REAL   coeff_a, epsvalue = psdata->epsvalue;\n  MYBOOL isneg;\n\n  /* Compute row singleton variable range */\n  if(is_constr_type(lp, rownr, EQ) && (fabs(*lobound) < epsvalue))\n    *lobound = *upbound = 0;\n  else {\n    if(aval == NULL)\n      coeff_a = get_mat(lp, rownr, colnr);\n    else\n      coeff_a = *aval;\n    isneg = (MYBOOL) (coeff_a < 0);\n    if(*lobound > -lp->infinite)\n      *lobound /= coeff_a;\n    else if(isneg)\n      *lobound = -(*lobound);\n    if(*upbound < lp->infinite)\n      *upbound /= coeff_a;\n    else if(isneg)\n      *upbound = -(*upbound);\n    if(isneg)\n      swapREAL(lobound, upbound);\n  }\n\n  /* Check against bound - handle SC variables specially */\n  if(is_semicont(lp, colnr)) {\n    coeff_a = get_lowbo(lp, colnr);\n    if(coeff_a > 0) {\n      SETMAX(*lobound, 0.0);\n      SETMIN(*upbound, get_upbo(lp, colnr));\n    }\n    else {\n      coeff_a = get_upbo(lp, colnr);\n      if(coeff_a > 0) {\n        SETMAX(*lobound, get_lowbo(lp, colnr));\n        SETMIN(*upbound, 0.0);\n      }\n    }\n  }\n  else {\n    SETMAX(*lobound, get_lowbo(lp, colnr));\n    SETMIN(*upbound, get_upbo(lp, colnr));\n  }\n\n  /* Return with consistency status */\n#ifdef DoPresolveRelativeTest\n  isneg = (MYBOOL) (my_reldiff(*upbound, *lobound) >= - epsvalue);\n#else\n  isneg = (MYBOOL) (*upbound >= *lobound - epsvalue);\n#endif\n  if(!isneg) {\n    /* Attempt bound-related error correction */\n    if(fabs(my_reldiff(*lobound, get_upbo(lp, colnr))) < PRESOLVE_BOUNDSLACK*epsvalue)\n      *lobound = get_upbo(lp, colnr);\n    else if(fabs(my_reldiff(*upbound, get_lowbo(lp, colnr))) < PRESOLVE_BOUNDSLACK*epsvalue)\n      *upbound = get_lowbo(lp, colnr);\n#ifdef DoPresolveRelativeTest\n    isneg = (MYBOOL) (my_reldiff(*upbound, *lobound) >= - epsvalue);\n#else\n    isneg = (MYBOOL) (*upbound >= *lobound - epsvalue);\n#endif\n    if(!isneg)\n      report(lp, NORMAL, \"presolve_singletonbounds: Singleton variable %s in row %s infeasibility (%g << %g)\\n\",\n                         get_col_name(lp, colnr), get_row_name(lp, rownr), *lobound, *upbound);\n  }\n  return( isneg );\n}\n\nSTATIC MYBOOL presolve_altsingletonvalid(presolverec *psdata, int rownr, int colnr, REAL reflotest, REAL refuptest)\n{\n  lprec *lp = psdata->lp;\n  REAL  coeff_bl, coeff_bu, epsvalue = psdata->epsvalue;\n\n  coeff_bl = get_rh_lower(lp, rownr);\n  coeff_bu = get_rh_upper(lp, rownr);\n\n  /* Check base data validity */\n#ifdef DoPresolveRelativeTest\n  if((my_reldiff(refuptest, reflotest) < -epsvalue) ||\n#else\n  if((reflotest > refuptest + epsvalue) ||\n#endif\n     !presolve_singletonbounds(psdata, rownr, colnr, &coeff_bl, &coeff_bu, NULL))\n    return( FALSE );\n\n  /* Base data is Ok, now check against against each other */\n  epsvalue = MAX(reflotest-coeff_bu, coeff_bl-refuptest) / epsvalue;\n  if(epsvalue > PRESOLVE_BOUNDSLACK) {\n    report(lp, NORMAL, \"presolve_altsingletonvalid: Singleton variable %s in row %s infeasible (%g)\\n\",\n                       get_col_name(lp, colnr), get_row_name(lp, rownr), MAX(reflotest-coeff_bu, coeff_bl-refuptest));\n    return( FALSE );\n  }\n  else\n    return( TRUE );\n}\n\nSTATIC MYBOOL presolve_multibounds(presolverec *psdata, int rownr, int colnr,\n                                   REAL *lobound, REAL *upbound, REAL *aval, MYBOOL *rowbinds)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   rowbindsvar = FALSE, status = FALSE;\n  REAL     coeff_a, LHS, RHS, netX, Xupper, Xlower, epsvalue = psdata->epsvalue;\n\n  /* Get variable bounds for netting */\n  LHS = *lobound;\n  RHS = *upbound;\n  Xlower = get_lowbo(lp, colnr);\n  Xupper = get_upbo(lp, colnr);\n\n  /* Identify opportunity for bound tightening */\n  if(aval == NULL)\n    coeff_a = get_mat(lp, rownr, colnr);\n  else\n    coeff_a = *aval;\n\n  netX = presolve_sumplumin(lp, rownr, psdata->rows, TRUE);\n  if(!my_infinite(lp, LHS) && !my_infinite(lp, netX)) {\n    if(coeff_a > 0) {\n      LHS -= netX-coeff_a*Xupper;\n      LHS /= coeff_a;\n      if(LHS > Xlower + epsvalue) {\n        Xlower = presolve_roundrhs(lp, LHS, TRUE);\n        status = TRUE;\n      }\n      else if(LHS > Xlower - epsvalue)\n        rowbindsvar = TRUE;\n    }\n    else {\n      LHS -= netX-coeff_a*Xlower;\n      LHS /= coeff_a;\n      if(LHS < Xupper - epsvalue) {\n        Xupper = presolve_roundrhs(lp, LHS, FALSE);\n        status = AUTOMATIC;\n      }\n      else if(LHS < Xupper + epsvalue)\n        rowbindsvar = AUTOMATIC;\n    }\n  }\n\n  netX = presolve_sumplumin(lp, rownr, psdata->rows, FALSE);\n  if(!my_infinite(lp, RHS) && !my_infinite(lp, netX)) {\n    if(coeff_a < 0) {\n      if(!my_infinite(lp, Xupper)) {\n        RHS -= netX-coeff_a*Xupper;\n        RHS /= coeff_a;\n        if(RHS > Xlower + epsvalue) {\n          Xlower = presolve_roundrhs(lp, RHS, TRUE);\n          status |= TRUE;\n        }\n        else if(RHS > Xlower - epsvalue)\n          rowbindsvar |= TRUE;\n      }\n    }\n    else if(!my_infinite(lp, Xlower)) {\n      RHS -= netX-coeff_a*Xlower;\n      RHS /= coeff_a;\n      if(RHS < Xupper - epsvalue) {\n        Xupper = presolve_roundrhs(lp, RHS, FALSE);\n        status |= AUTOMATIC;\n      }\n      else if(RHS < Xupper + epsvalue)\n        rowbindsvar |= AUTOMATIC;\n    }\n  }\n\n  *lobound = Xlower;\n  *upbound = Xupper;\n  if(rowbinds != NULL)\n    *rowbinds = rowbindsvar;\n\n  return(status);\n}\n\nSTATIC MYBOOL isnz_origobj(lprec *lp, int colnr)\n{\n  return( (MYBOOL) (lp->orig_obj[colnr] != 0) );\n}\n\nSTATIC MYBOOL presolve_testrow(presolverec *psdata, int lastrow)\n{\n  (void)lastrow;\n  if(psdata->forceupdate) {\n    presolve_updatesums(psdata);\n    psdata->forceupdate = FALSE;\n  }\n  if(!presolve_rowfeasible(psdata, 0, TRUE))\n    return( FALSE );\n  else\n    return( TRUE );\n}\n\nSTATIC MYBOOL presolve_coltighten(presolverec *psdata, int colnr, REAL LOnew, REAL UPnew, int *count)\n{\n  lprec    *lp = psdata->lp;\n  int      elmnr, elmend, k, oldcount = 0, newcount = 0, deltainf;\n  REAL     LOold, UPold, Value, margin = psdata->epsvalue;\n  MATrec   *mat = lp->matA;\n  REAL     *value;\n  int      *rownr;\n\n  /* Attempt correction of marginally equal, but inconsistent input values */\n  Value = UPnew - LOnew;\n  if((Value <= -margin) && (Value > -lp->epsprimal)) {\n    if(fabs(fmod(UPnew, 1.0)) < margin)\n      LOnew = UPnew;\n    else\n      UPnew = LOnew;\n  }\n\n  /* Check if there is anything to do */\n  LOold = get_lowbo(lp, colnr);\n  UPold = get_upbo(lp, colnr);\n#ifdef Paranoia\n  if(((LOold > LOnew) && !is_semicont(lp, colnr)) || (UPold < UPnew)) {\n    report(lp, SEVERE, \"presolve_coltighten: Inconsistent new bounds requested for column %d\\n\", colnr);\n    return( FALSE );\n  }\n#endif\n  if(count != NULL)\n    newcount = *count;\n  oldcount = newcount;\n\n  /* Modify inf-count */\n  deltainf = 0;\n  if((UPold < lp->infinite) || (LOold > -lp->infinite))\n    deltainf -= 1;\n  if((UPnew < lp->infinite) || (LOnew > -lp->infinite))\n    deltainf += 1;\n  if(isnz_origobj(lp, colnr))\n    psdata->rows->infcount[0] += deltainf;\n  elmnr = mat->col_end[colnr-1];\n  elmend = mat->col_end[colnr];\n  rownr = &COL_MAT_ROWNR(elmnr);\n  for(; elmnr < elmend; elmnr++, rownr += matRowColStep) {\n    k = *rownr;\n    if(isActiveLink(psdata->rows->varmap, k))\n      psdata->rows->infcount[k] += deltainf;\n  }\n\n  /* Look for opportunity to tighten upper variable bound */\n  if((UPnew < lp->infinite) && (UPnew+margin < UPold)) {\n    if(is_int(lp, colnr))\n      UPnew = floor(UPnew+margin);\n    if(UPold < lp->infinite) {\n      /* First do OF */\n      k = 0;\n      Value = my_chsign(is_chsign(lp, k), lp->orig_obj[colnr]);\n      if((Value > 0) && (psdata->rows->pluupper[k] < lp->infinite))\n        psdata->rows->pluupper[k] += (UPnew-UPold)*Value;\n      else if((Value < 0) && (psdata->rows->negupper[k] < lp->infinite))\n        psdata->rows->negupper[k] += (LOnew-LOold)*Value;\n      psdata->rows->infcount[k] += deltainf;\n\n      /* Then scan the constraint rows */\n      elmnr = mat->col_end[colnr-1];\n      elmend = mat->col_end[colnr];\n      rownr = &COL_MAT_ROWNR(elmnr);\n      value = &COL_MAT_VALUE(elmnr);\n      for(; elmnr < elmend;\n          elmnr++, rownr += matRowColStep, value += matValueStep) {\n        k = *rownr;\n        if(!isActiveLink(psdata->rows->varmap, k))\n          continue;\n        Value = my_chsign(is_chsign(lp, k), *value);\n        if((Value > 0) && (psdata->rows->pluupper[k] < lp->infinite))\n          psdata->rows->pluupper[k] += (UPnew-UPold)*Value;\n        else if((Value < 0) && (psdata->rows->negupper[k] < lp->infinite))\n          psdata->rows->negupper[k] += (LOnew-LOold)*Value;\n      }\n    }\n    else\n      psdata->forceupdate = TRUE;\n    if(UPnew < UPold) {\n      UPold = UPnew;\n      newcount++;\n    }\n  }\n\n  /* Look for opportunity to tighten lower variable bound */\n  if((LOnew > -lp->infinite) && (LOnew-margin > LOold)) {\n    if(is_int(lp, colnr))\n       LOnew = ceil(LOnew-margin);\n    if(LOold > -lp->infinite) {\n      /* First do OF */\n      k = 0;\n      Value = my_chsign(is_chsign(lp, k), lp->orig_obj[colnr]);\n      if((Value > 0) && (psdata->rows->plulower[k] > -lp->infinite))\n        psdata->rows->plulower[k] += (LOnew-LOold)*Value;\n      else if((Value < 0) && (psdata->rows->neglower[k] > -lp->infinite))\n        psdata->rows->neglower[k] += (UPnew-UPold)*Value;\n\n      /* Then scan the constraint rows */\n      elmnr = mat->col_end[colnr-1];\n      elmend = mat->col_end[colnr];\n      rownr = &COL_MAT_ROWNR(elmnr);\n      value = &COL_MAT_VALUE(elmnr);\n      for(; elmnr < elmend;\n          elmnr++, rownr += matRowColStep, value += matValueStep) {\n        k = *rownr;\n        if(!isActiveLink(psdata->rows->varmap, k))\n          continue;\n        Value = my_chsign(is_chsign(lp, k), *value);\n        if((Value > 0) && (psdata->rows->plulower[k] > -lp->infinite))\n          psdata->rows->plulower[k] += (LOnew-LOold)*Value;\n        else if((Value < 0) && (psdata->rows->neglower[k] > -lp->infinite))\n          psdata->rows->neglower[k] += (UPnew-UPold)*Value;\n      }\n    }\n    else\n      psdata->forceupdate = TRUE;\n    if(LOnew > LOold) {\n      LOold = LOnew;\n      newcount++;\n    }\n  }\n\n  /* Now set the new variable bounds, if they are tighter */\n  if(newcount > oldcount) {\n    UPnew = presolve_roundval(lp, UPnew);\n    LOnew = presolve_roundval(lp, LOnew);\n    if(LOnew > UPnew) {\n      if(LOnew-UPnew < margin) {\n        LOnew = UPnew;\n      }\n      else {\n        report(lp, NORMAL, \"presolve_coltighten: Found column %s with LB %g > UB %g\\n\",\n                            get_col_name(lp, colnr), LOnew, UPnew);\n        return( FALSE );\n      }\n    }\n    if(lp->spx_trace || (lp->verbose > DETAILED))\n      report(lp, NORMAL, \"presolve_coltighten: Replaced bounds on column %s to [%g ... %g]\\n\",\n                         get_col_name(lp, colnr), LOnew, UPnew);\n    set_bounds(lp, colnr, LOnew, UPnew);\n  }\n  if(count != NULL)\n    *count = newcount;\n\n  return( TRUE );\n}\n\nSTATIC int presolve_rowtighten(presolverec *psdata, int rownr, int *tally, MYBOOL intsonly)\n{\n  lprec  *lp = psdata->lp;\n  MYBOOL rowbinds;\n  int    item = 0, jx, jjx, ix, idxn = 0, *idxbound = NULL, status = RUNNING;\n  REAL   *newbound = NULL, RHlo = get_rh_lower(lp, rownr), RHup = get_rh_upper(lp, rownr),\n         VARlo, VARup, Aval;\n  MATrec *mat = lp->matA;\n\n  jx = presolve_rowlength(psdata, rownr);\n  allocREAL(lp, &newbound, 2*jx, TRUE);\n  allocINT (lp, &idxbound, 2*jx, TRUE);\n\n  /* Identify bound tightening for each active variable in the constraint */\n  for(jx = presolve_nextcol(psdata, rownr, &item); jx >= 0;\n      jx = presolve_nextcol(psdata, rownr, &item)) {\n    jjx = ROW_MAT_COLNR(jx);\n    Aval = ROW_MAT_VALUE(jx);\n    Aval = my_chsign(rownr, Aval);\n\n    VARlo = RHlo;\n    VARup = RHup;\n    presolve_multibounds(psdata, rownr,jjx, &VARlo, &VARup, &Aval, &rowbinds);\n    if(rowbinds & TRUE) {\n      idxbound[idxn] = -jjx;\n      newbound[idxn] = VARlo;\n      idxn++;\n    }\n    if(rowbinds & AUTOMATIC) {\n      idxbound[idxn] = jjx;\n      newbound[idxn] = VARup;\n      idxn++;\n    }\n  }\n\n  /* Loop over the bounds identified for tightening and perform update */\n  ix = 0;\n  while(ix < idxn) {\n    jjx = idxbound[ix];\n    jx = abs(jjx);\n\n    /* Skip free variables and non-ints, if specified */\n    if(is_unbounded(lp, jx) ||\n       (intsonly && !is_int(lp, jx)))\n      continue;\n\n    VARlo = get_lowbo(lp, jx);\n    VARup = get_upbo(lp, jx);\n    /* while((ix < idxn) && (jx == abs(jjx))) { */\n    while((ix < idxn) && (jx == abs((jjx = idxbound[ix])))) {\n      if(jjx < 0)\n        VARlo = newbound[ix];\n      else\n        VARup = newbound[ix];\n      ix++;\n    }\n    if(!presolve_coltighten(psdata, jx, VARlo, VARup, tally)) {\n      status = presolve_setstatus(psdata, INFEASIBLE);\n      break;\n    }\n  }\n\n  FREE(newbound);\n  FREE(idxbound);\n\n  return(status);\n}\n\nSTATIC void set_dv_bounds(presolverec *psdata, int rownr, REAL lowbo, REAL upbo)\n{\n  psdata->dv_lobo[rownr] = lowbo;\n  psdata->dv_upbo[rownr] = upbo;\n}\nSTATIC REAL get_dv_lower(presolverec *psdata, int rownr)\n{\n  return( psdata->dv_lobo[rownr] );\n}\n\nSTATIC REAL get_dv_upper(presolverec *psdata, int rownr)\n{\n  return( psdata->dv_upbo[rownr] );\n}\n\nSTATIC MYBOOL presolve_rowfix(presolverec *psdata, int rownr, REAL newvalue, MYBOOL remove, int *tally)\n{\n  lprec    *lp = psdata->lp;\n  int      i, ix, ie;\n  MYBOOL   isneg, lofinite, upfinite, doupdate = FALSE, chsign = is_chsign(lp, rownr);\n  REAL     lobound, upbound, lovalue, upvalue,\n           Value, fixvalue, fixprod, mult;\n  MATrec   *mat = lp->matA;\n  psrec    *ps = psdata->cols;\n\n  /* Set \"fixed\" value in case we are deleting a variable */\n  upbound = get_dv_upper(psdata, rownr);\n  lobound = get_dv_lower(psdata, rownr);\n  if(remove) {\n    if(upbound-lobound < psdata->epsvalue) {\n      if((newvalue > lobound) && (newvalue < upbound))\n        fixvalue = newvalue;\n      else\n        fixvalue = lobound;\n    }\n    else {\n      if(my_infinite(lp, newvalue) && (get_rh(lp, rownr) == 0))\n        fixvalue = ((lobound <= 0) && (upbound >= 0) ? 0 : MIN(upbound, lobound));\n      else\n        fixvalue = newvalue;\n    }\n    set_dv_bounds(psdata, rownr, fixvalue, fixvalue);\n    if(fixvalue != 0)\n      addUndoPresolve(lp, FALSE, rownr, fixvalue, 0, 0);\n    mult = -1;\n  }\n  else {\n    mult = 1;\n    fixvalue = 0;\n  }\n\n  /* Loop over rows to update statistics */\n  ix = mat->row_end[rownr - 1];\n  ie = mat->row_end[rownr];\n  for(; ix < ie; ix++) {\n\n   /* Retrieve row data and adjust RHS if we are deleting a variable */\n    i     = ROW_MAT_COLNR(ix);\n    Value = ROW_MAT_VALUE(ix);\n    if(Value == 0)\n      continue;\n\n    if(remove && (fixvalue != 0)) {\n      fixprod = Value*fixvalue;\n      lp->orig_obj[i] -= fixprod;\n      my_roundzero(lp->orig_obj[i], psdata->epsvalue);\n      lp->presolve_undo->fixed_obj[i] += fixprod;\n    }\n\n   /* Prepare for further processing */\n    Value = my_chsign(chsign, Value);\n    isneg = (MYBOOL) (Value < 0);\n\n   /* Reduce row variable counts if we are removing the variable */\n    if(!isActiveLink(ps->varmap, i))\n      continue;\n    if(remove) {\n      if(isneg) {\n        ps->negcount[i]--;\n      }\n      else {\n        ps->plucount[i]--;\n      }\n      if((lobound < 0) && (upbound >= 0)) {\n        ps->pluneg[i]--;\n      }\n    }\n\n   /* Compute associated constraint contribution values */\n    upfinite = (MYBOOL) (upbound < lp->infinite);\n    lofinite = (MYBOOL) (lobound > -lp->infinite);\n    if(upfinite || lofinite) {\n      if(remove)\n        ps->infcount[i]--;\n      else\n        ps->infcount[i]++;\n    }\n    upvalue = my_if(upfinite, Value*upbound, my_chsign(isneg, lp->infinite));\n    lovalue = my_if(lofinite, Value*lobound, my_chsign(isneg, -lp->infinite));\n\n   /* Cumulate effective upper column bound (only bother with non-finite bound) */\n    if(isneg) {\n      if((ps->negupper[i] < lp->infinite) && lofinite) {\n        ps->negupper[i] += mult*lovalue;\n        ps->negupper[i] = presolve_roundrhs(lp, ps->negupper[i], FALSE);\n      }\n      else if(remove && !lofinite)\n        doupdate = TRUE;\n      else\n        ps->negupper[i] = lp->infinite;\n    }\n    else {\n      if((ps->pluupper[i] < lp->infinite) && upfinite) {\n        ps->pluupper[i] += mult*upvalue;\n        ps->pluupper[i] = presolve_roundrhs(lp, ps->pluupper[i], FALSE);\n      }\n      else if(remove && !upfinite)\n        doupdate = TRUE;\n      else\n        ps->pluupper[i] = lp->infinite;\n    }\n\n   /* Cumulate effective lower column bound (only bother with non-finite bound) */\n    if(isneg) {\n      if((ps->neglower[i] > -lp->infinite) && upfinite) {\n        ps->neglower[i] += mult*upvalue;\n        ps->neglower[i] = presolve_roundrhs(lp, ps->neglower[i], TRUE);\n      }\n      else if(remove && !upfinite)\n        doupdate = TRUE;\n      else\n        ps->neglower[i] = -lp->infinite;\n    }\n    else {\n      if((ps->plulower[i] > -lp->infinite) && lofinite) {\n        ps->plulower[i] += mult*lovalue;\n        ps->plulower[i] = presolve_roundrhs(lp, ps->plulower[i], TRUE);\n      }\n      else if(remove && !lofinite)\n        doupdate = TRUE;\n      else\n        ps->plulower[i] = -lp->infinite;\n    }\n\n   /* Validate consistency of eliminated singleton */\n    if(remove && ((i == 0) || (ps->next[i][0] == 1)) && !psdata->forceupdate) {\n      presolve_range(lp, i, ps, &lovalue, &upvalue);\n      Value = get_mat(lp, 0, i);\n      if((upvalue < Value) ||\n         (lovalue > Value)) {\n        report(lp, IMPORTANT, \"presolve: Row %s (%g << %g) infeasibility in column %s (OF=%g)\\n\",\n                              get_row_name(lp, rownr), lovalue, upvalue, get_col_name(lp, i), Value);\n        return( FALSE );\n      }\n    }\n  }\n  if(remove) {\n    psdata->forceupdate |= doupdate;\n    if(tally != NULL)\n      (*tally)++;\n  }\n  return( TRUE );\n}\n\n\nSTATIC int presolve_colsingleton(presolverec *psdata, int i, int j, int *count)\n{\n  lprec    *lp = psdata->lp;\n  REAL     RHlow, RHup, LObound, UPbound, Value;\n\n#ifdef Paranoia\n  if(!isActiveLink(psdata->cols->varmap, j))\n    report(lp, SEVERE, \"presolve_colsingleton: Nothing to do, column %d was eliminated earlier\\n\",\n                       j);\n#endif\n\n  Value = get_mat(lp,i,j);\n  if(Value == 0)\n    return( RUNNING );\n\n  /* Initialize and identify semicontinuous variable */\n  LObound = get_lowbo(lp, j);\n  UPbound = get_upbo(lp, j);\n  if(is_semicont(lp, j) && (UPbound > LObound)) {\n    if(LObound > 0)\n      LObound = 0;\n    else if(UPbound < 0)\n      UPbound = 0;\n  }\n\n  /* Get singleton variable bounds */\n  RHlow = get_rh_lower(lp, i);\n  RHup  = get_rh_upper(lp, i);\n  if(!presolve_singletonbounds(psdata, i,j, &RHlow, &RHup, &Value))\n    return( presolve_setstatus(psdata, INFEASIBLE) );\n\n  if(presolve_coltighten(psdata, j, RHlow, RHup, count))\n    return( RUNNING );\n  else\n    return( presolve_setstatus(psdata, INFEASIBLE) );\n}\n\nSTATIC MYBOOL presolve_colfix(presolverec *psdata, int colnr, REAL newvalue, MYBOOL remove, int *tally)\n{\n  lprec    *lp = psdata->lp;\n  int      i, ix, ie;\n  MYBOOL   isneg, lofinite, upfinite, doupdate = FALSE, doOF = TRUE;\n  REAL     lobound, upbound, lovalue, upvalue,\n           Value, fixvalue, mult;\n  MATrec   *mat = lp->matA;\n  psrec    *ps = psdata->rows;\n  REAL     *value;\n  int      *rownr;\n\n  /* Set \"fixed\" value in case we are deleting a variable */\n  upbound = get_upbo(lp, colnr);\n  lobound = get_lowbo(lp, colnr);\n  if(remove) {\n    if(upbound-lobound < psdata->epsvalue) {\n      if((newvalue > lobound) && (newvalue < upbound))\n        fixvalue = newvalue;\n      else\n        fixvalue = lobound;\n    }\n    else {\n      if(my_infinite(lp, newvalue) && (get_mat(lp, 0, colnr) == 0))\n        fixvalue = ((lobound <= 0) && (upbound >= 0) ? 0 : MIN(upbound, lobound));\n      else\n        fixvalue = newvalue;\n    }\n#if 1 /* Fast normal version */\n    set_bounds(lp, colnr, fixvalue, fixvalue);\n#else /* Slower version that can be used for debugging/control purposes */\n    presolve_coltighten(psdata, colnr, fixvalue, fixvalue, NULL);\n    lobound = fixvalue;\n    upbound = fixvalue;\n#endif\n    if(fixvalue != 0)\n      addUndoPresolve(lp, TRUE, colnr, fixvalue, 0, 0);\n    mult = -1;\n  }\n  else {\n    mult = 1;\n    fixvalue = 0;\n  }\n\n  /* Adjust semi-continuous variable bounds to zero-base */\n  if(is_semicont(lp, colnr) && (upbound > lobound)) {\n    if(lobound > 0)\n      lobound = 0;\n    else if(upbound < 0)\n      upbound = 0;\n  }\n\n  /* Loop over rows to update statistics */\n  ix = mat->col_end[colnr - 1];\n  ie = mat->col_end[colnr];\n  rownr = &COL_MAT_ROWNR(ix);\n  value = &COL_MAT_VALUE(ix);\n  for(; doOF || (ix < ie);\n      ix++, rownr += matRowColStep, value += matValueStep) {\n\n   /* Retrieve row data and adjust RHS if we are deleting a variable */\nRestart:\n    if(doOF) {\n      i = 0;\n      Value = lp->orig_obj[colnr];\n    }\n    else {\n      i = *rownr;\n      Value = *value;\n      if(!isActiveLink(ps->varmap, i))\n        continue;\n    }\n    if(Value == 0)\n      goto BlockEnd;\n\n    if(remove && (fixvalue != 0))\n      presolve_adjustrhs(psdata, i, Value*fixvalue, psdata->epsvalue);\n\n   /* Prepare for further processing */\n    Value = my_chsign(is_chsign(lp, i), Value);\n    isneg = (MYBOOL) (Value < 0);\n\n   /* Reduce row variable counts if we are removing the variable */\n    if(remove == TRUE) {\n      if(isneg) {\n        ps->negcount[i]--;\n      }\n      else {\n        ps->plucount[i]--;\n      }\n      if((lobound < 0) && (upbound >= 0)) {\n        ps->pluneg[i]--;\n      }\n    }\n\n   /* Compute associated constraint contribution values */\n    upfinite = (MYBOOL) (upbound < lp->infinite);\n    lofinite = (MYBOOL) (lobound > -lp->infinite);\n    if(upfinite || lofinite) {\n      if(remove)\n        ps->infcount[i]--;\n      else\n        ps->infcount[i]++;\n    }\n    upvalue = my_if(upfinite, Value*upbound, my_chsign(isneg, lp->infinite));\n    lovalue = my_if(lofinite, Value*lobound, my_chsign(isneg, -lp->infinite));\n\n   /* Cumulate effective upper row bound (only bother with non-finite bound) */\n    if(isneg) {\n      if((ps->negupper[i] < lp->infinite) && lofinite) {\n        ps->negupper[i] += mult*lovalue;\n        ps->negupper[i] = presolve_roundrhs(lp, ps->negupper[i], FALSE);\n      }\n      else if(remove && !lofinite)\n        doupdate = TRUE;\n      else\n        ps->negupper[i] = lp->infinite;\n    }\n    else {\n      if((ps->pluupper[i] < lp->infinite) && upfinite) {\n        ps->pluupper[i] += mult*upvalue;\n        ps->pluupper[i] = presolve_roundrhs(lp, ps->pluupper[i], FALSE);\n      }\n      else if(remove && !upfinite)\n        doupdate = TRUE;\n      else\n        ps->pluupper[i] = lp->infinite;\n    }\n\n   /* Cumulate effective lower row bound (only bother with non-finite bound) */\n    if(isneg) {\n      if((ps->neglower[i] > -lp->infinite) && upfinite) {\n        ps->neglower[i] += mult*upvalue;\n        ps->neglower[i] = presolve_roundrhs(lp, ps->neglower[i], TRUE);\n      }\n      else if(remove && !upfinite)\n        doupdate = TRUE;\n      else\n        ps->neglower[i] = -lp->infinite;\n    }\n    else {\n      if((ps->plulower[i] > -lp->infinite) && lofinite) {\n        ps->plulower[i] += mult*lovalue;\n        ps->plulower[i] = presolve_roundrhs(lp, ps->plulower[i], TRUE);\n      }\n      else if(remove && !lofinite)\n        doupdate = TRUE;\n      else\n        ps->plulower[i] = -lp->infinite;\n    }\n\n   /* Validate consistency of eliminated singleton */\n    if(remove && ((i == 0) || (ps->next[i][0] == 1)) && !psdata->forceupdate) {\n      if(i == 0) {\n        lovalue = get_rh_lower(lp, i);\n        upvalue = get_rh_upper(lp, i);\n        report(lp, DETAILED, \"presolve_colfix: Objective determined by presolve as %18g\\n\",\n                             (is_maxim(lp) ? upvalue : lovalue));\n      }\n      else {\n        presolve_range(lp, i, ps, &lovalue, &upvalue);\n#if 1\n        Value = 0;\n#else\n        Value = MAX(fabs(upvalue), fabs(lovalue));\n        Value = psdata->epsvalue * MAX(1, Value);\n#endif\n        if((upvalue < get_rh_lower(lp, i)-Value) ||\n           (lovalue > get_rh_upper(lp, i)+Value)) {\n          report(lp, NORMAL, \"presolve_colfix: Variable %s (%g << %g) infeasibility in row %s (%g << %g)\\n\",\n                              get_col_name(lp, colnr), lovalue, upvalue,\n                              get_row_name(lp, i), get_rh_lower(lp,i), get_rh_upper(lp, i));\n          return( FALSE );\n        }\n      }\n    }\nBlockEnd:\n    if(doOF) {\n      doOF = FALSE;\n      if(ix < ie)\n        goto Restart;\n    }\n\n  }\n  if(remove) {\n    psdata->forceupdate |= doupdate;\n    if(tally != NULL)\n      (*tally)++;\n  }\n  return( TRUE );\n}\n\n/* Delete the columns of the specified row, but make sure we don't delete SOS variables.\n   Note that we cannot use presolve_nextcol() here, since the variables are deleted. */\nSTATIC int presolve_rowfixzero(presolverec *psdata, int rownr, int *nv)\n{\n  lprec  *lp = psdata->lp;\n  MATrec *mat = lp->matA;\n  int    ix, jx, ib = mat->row_end[rownr-1];\n  for(ix = mat->row_end[rownr]-1; ix >= ib; ix--) {\n    jx = ROW_MAT_COLNR(ix);\n    if(isActiveLink(psdata->cols->varmap, jx)) {\n      if(!presolve_colfix(psdata, jx, 0.0, TRUE, nv))\n        return( presolve_setstatus(psdata, INFEASIBLE) );\n      if(presolve_candeletevar(psdata, jx))\n        presolve_colremove(psdata, jx, TRUE);\n    }\n  }\n#ifdef xxParanoia\n  if(!presolve_debugrowtallies(psdata))\n    return( INFEASIBLE );\n#endif\n  return( RUNNING );\n}\n\n/* Function to find if a variable can be fixed based on considering the dual */\nSTATIC MYBOOL presolve_colfixdual(presolverec *psdata, int colnr, REAL *fixValue, int *status)\n{\n  lprec   *lp = psdata->lp;\n  MYBOOL  hasOF, isMI, isDualFREE = TRUE;\n  int     i, ix, ie, *rownr, signOF;\n  REAL    *value, loX, upX, eps = psdata->epsvalue;\n  MATrec  *mat = lp->matA;\n\n  /* First check basic variable range */\n  loX = get_lowbo(lp, colnr);\n  upX = get_upbo(lp, colnr);\n  if(((loX < 0) && (upX > 0)) ||\n     (fabs(upX-loX) < lp->epsvalue) ||\n     SOS_is_member_of_type(lp->SOS, colnr, SOSn))\n    return( FALSE );\n  isMI = (MYBOOL) (upX <= 0);\n\n  /* Retrieve OF (standard form assuming maximization) */\n  ix = mat->col_end[colnr - 1];\n  ie = mat->col_end[colnr];\n  rownr = &COL_MAT_ROWNR(ix);\n  value = &COL_MAT_VALUE(ix);\n  hasOF = isnz_origobj(lp, colnr);\n  if(hasOF)\n    signOF = my_sign(lp->orig_obj[colnr]);\n  else\n    signOF = 0;\n\n  /* Loop over all constraints involving active variable (standard form with LE constraints)*/\n  for(; (ix < ie) && isDualFREE;\n      ix++, rownr += matRowColStep, value += matValueStep) {\n    i = *rownr;\n    if(!isActiveLink(psdata->rows->varmap, i))\n      continue;\n    if(presolve_rowlength(psdata, i) == 1) {\n      REAL val = my_chsign(is_chsign(lp, i), *value),\n           loR = get_rh_lower(lp, i),\n           upR = get_rh_upper(lp, i);\n      if(!presolve_singletonbounds(psdata, i, colnr, &loR, &upR, &val)) {\n        *status = presolve_setstatus(psdata, INFEASIBLE);\n        return( FALSE );\n      }\n      if(loR > loX + psdata->epsvalue)\n        loX = presolve_roundrhs(lp, loR, TRUE);\n      if(upR < upX - psdata->epsvalue)\n        upX = presolve_roundrhs(lp, upR, FALSE);\n      continue;\n    }\n    else\n      isDualFREE = my_infinite(lp, get_rh_range(lp, i)) ||                                          /* Explicitly free */\n                   ((presolve_sumplumin(lp, i, psdata->rows, TRUE)-eps <= get_rh_upper(lp, i)) &&   /* Implicitly free */\n                    (presolve_sumplumin(lp, i, psdata->rows, FALSE)+eps >= get_rh_lower(lp, i)));\n    if(isDualFREE) {\n      if(signOF == 0)  /* Test on the basis of identical signs in the constraints */\n        signOF = my_sign(*value);\n      else             /* Test on the basis of constraint sign equal to OF sign */\n        isDualFREE = (MYBOOL) (signOF == my_sign(*value));\n    }\n  }\n\n  /* Set fixing value if we were successful */\n  if(isDualFREE) {\n    if(signOF == 0) {\n      SETMAX(loX, 0);\n      *fixValue = MIN(loX, upX);\n    }\n    else if(signOF > 0) {\n      if(my_infinite(lp, loX))\n        isDualFREE = FALSE;\n      else {\n        if(is_int(lp, colnr))\n          *fixValue = ceil(loX-PRESOLVE_EPSVALUE);\n        else\n          *fixValue = loX;\n      }\n    }\n    else {\n      if(my_infinite(lp, upX))\n        isDualFREE = FALSE;\n      else {\n        if(is_int(lp, colnr) && (upX != 0))\n          *fixValue = floor(upX+PRESOLVE_EPSVALUE);\n        else\n          *fixValue = upX;\n      }\n    }\n    if((*fixValue != 0) && SOS_is_member(lp->SOS, 0, colnr))\n      return( FALSE );\n\n  }\n\n  return( isDualFREE );\n}\n\n#if 0\nSTATIC MYBOOL presolve_probefix01(presolverec *psdata, int colnr, REAL *fixvalue)\n{\n  lprec    *lp = psdata->lp;\n  int      i, ix, item;\n  REAL     loLim, absvalue, epsvalue = psdata->epsvalue;\n  MATrec   *mat = lp->matA;\n  MYBOOL   chsign, canfix = FALSE;\n\n  if(!is_binary(lp, colnr))\n    return( canfix );\n\n  /* Loop over all active rows to search for fixing opportunity */\n  item = 0;\n  for(ix = presolve_nextrow(psdata, colnr, &item);\n      (ix >= 0) && !canfix;\n      ix = presolve_nextrow(psdata, colnr, &item)) {\n    i = COL_MAT_ROWNR(ix);\n    *fixvalue = COL_MAT_VALUE(ix);\n    chsign = is_chsign(lp, i);\n\n    /* First check the lower bound of the normalized constraint */\n    loLim = presolve_sumplumin(lp, i, psdata->rows, chsign);\n    loLim = my_chsign(chsign, loLim);\n    absvalue = fabs(*fixvalue);\n    canfix = (MYBOOL) ((loLim + absvalue > lp->orig_rhs[i]+epsvalue*MAX(1, absvalue)));\n\n    /* If we were unsuccessful in fixing above, try the upper bound\n       of the normalized constraint - if it is finite */\n    if(!canfix && !my_infinite(lp, get_rh_range(lp, i))) {\n      loLim = presolve_sumplumin(lp, i, psdata->rows, (MYBOOL) !chsign);\n      loLim = my_chsign(!chsign, loLim);\n      *fixvalue = -(*fixvalue);\n      canfix = (MYBOOL) ((loLim + absvalue > get_rh_range(lp, i)-lp->orig_rhs[i]+epsvalue*MAX(1, absvalue)));\n    }\n  }\n\n  /* Check if we were successful in identifying fixing opportunity */\n  if(canfix) {\n    if(*fixvalue < 0)\n      *fixvalue = 1;\n    else\n      *fixvalue = 0;\n  }\n  return( canfix );\n}\n#else\nSTATIC MYBOOL presolve_probefix01(presolverec *psdata, int colnr, REAL *fixvalue)\n{\n  lprec    *lp = psdata->lp;\n  int      i, ix, item;\n  REAL     loLim, upLim, range, absvalue, epsvalue = psdata->epsvalue, tolgap;\n  MATrec   *mat = lp->matA;\n  MYBOOL   chsign, status = FALSE;\n\n  if(!is_binary(lp, colnr))\n    return( status );\n\n  /* Loop over all active rows to search for fixing opportunity.  The logic is that if a\n     constraint gets violated by setting a variable at one of its bounds, then it can be\n     fixed at its opposite bound. */\n  item = 0;\n\n  for(ix = presolve_nextrow(psdata, colnr, &item); (ix >= 0); ix = presolve_nextrow(psdata, colnr, &item)) {\n    i = COL_MAT_ROWNR(ix);\n    *fixvalue = COL_MAT_VALUE(ix);\n    absvalue = fabs(*fixvalue);\n    SETMIN(absvalue, 100);\n    tolgap = epsvalue*MAX(1, absvalue);\n    chsign = is_chsign(lp, i);\n\n    /* Get the constraint value limits based on variable bounds, normalized to LE constraint */\n    loLim = presolve_sumplumin(lp, i, psdata->rows, FALSE);\n    upLim = presolve_sumplumin(lp, i, psdata->rows, TRUE);\n    if(chsign) {\n      loLim = my_chsign(chsign, loLim);\n      upLim = my_chsign(chsign, upLim);\n      swapREAL(&loLim, &upLim);\n    }\n\n    /* Check the upper constraint bound for possible violation if the value were to be fixed at 1 */\n    if(loLim + *fixvalue > lp->orig_rhs[i]+tolgap) {\n      if(*fixvalue < 0)\n        presolve_setstatus(psdata, INFEASIBLE);\n      *fixvalue = 0;\n      break;\n    }\n\n    /* Check the lower constraint bound for possible violation if the value were to be fixed at 1 */\n    range = get_rh_range(lp, i);\n    if(!my_infinite(lp, range) &&\n       (upLim + *fixvalue < lp->orig_rhs[i]-range-tolgap)) {\n      if(*fixvalue > 0)\n        presolve_setstatus(psdata, INFEASIBLE);\n      *fixvalue = 0;\n      break;\n    }\n\n    /* Check if we have to fix the value at 1 to avoid constraint infeasibility */\n    if(psdata->rows->infcount[i] >= 1)\n      continue;\n    if(((*fixvalue < 0) && (upLim + *fixvalue >= loLim-tolgap) && (upLim > lp->orig_rhs[i]+tolgap)) ||\n       ((*fixvalue > 0) && (loLim + *fixvalue <= upLim+tolgap) && (loLim < lp->orig_rhs[i]-range-tolgap) && !my_infinite(lp, range))) {\n      *fixvalue = 1;\n      break;\n    }\n  }\n  status = (MYBOOL) (ix >= 0);\n\n  /* Returns TRUE if fixing opportunity was identified */\n  return( status );\n}\n#endif\n\nSTATIC int presolve_probetighten01(presolverec *psdata, int colnr)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   chsign;\n  int      i, ix, item, n = 0;\n  REAL     upLim, value, absvalue, epsvalue = psdata->epsvalue;\n  MATrec   *mat = lp->matA;\n\n#if 0 /* Handled in calling routine */\n  if(!is_binary(lp, colnr))\n    return( n );\n#endif\n\n  /* Loop over all active rows and do coefficient tightening for qualifying constraints */\n  item = 0;\n  for(ix = presolve_nextrow(psdata, colnr, &item); ix >= 0;\n      ix = presolve_nextrow(psdata, colnr, &item)) {\n    i = COL_MAT_ROWNR(ix);\n    value = COL_MAT_VALUE(ix);\n    chsign = is_chsign(lp, i);\n    upLim = presolve_sumplumin(lp, i, psdata->rows, (MYBOOL) !chsign);\n    upLim = my_chsign(chsign, upLim);\n\n    /* Does this constraint qualify for coefficient tightening? */\n    absvalue = fabs(value);\n    if(upLim - absvalue < lp->orig_rhs[i]-epsvalue*MAX(1, absvalue)) {\n      REAL delta = lp->orig_rhs[i] - upLim;\n      lp->orig_rhs[i] = upLim;\n      upLim = value - my_chsign(value < 0, delta);\n      COL_MAT_VALUE(ix) = upLim;\n      if(my_sign(value) != my_sign(upLim)) {\n        if(chsign) {\n          psdata->rows->negcount[i]--;\n          psdata->rows->plucount[i]++;\n        }\n        else {\n          psdata->rows->negcount[i]++;\n          psdata->rows->plucount[i]--;\n        }\n      }\n      n++;\n    }\n  }\n  return( n );\n}\n\nSTATIC int presolve_mergerows(presolverec *psdata, int *nRows, int *nSum)\n{\n  lprec *lp = psdata->lp;\n  MYBOOL candelete;\n  int    status = RUNNING, item1, item2,\n         firstix, RT1, RT2, i, ix, iix, j, jjx, n = 0;\n  REAL   Value1, Value2, bound;\n  MATrec *mat = lp->matA;\n\n  for(i = lastActiveLink(psdata->rows->varmap); (i > 0) && (status == RUNNING); ) {\n\n    /* First scan for rows with identical row lengths */\n    ix = prevActiveLink(psdata->rows->varmap, i);\n    if(ix == 0)\n      break;\n\n    /* Don't bother about empty rows or row singletons, since they are\n       handled by PRESOLVE_ROWS */\n    j = presolve_rowlength(psdata, i);\n    if(j <= 1) {\n      i = ix;\n      continue;\n    }\n\n#if 0\n    /* Enable this to scan all rows back */\n    RT2 = lp->rows;\n\n    /* Check abort since this section can be pretty \"expensive\" */\n    if(!presolve_statuscheck(psdata, &status))\n      return( status );\n#else\n    RT2 = 2+1;\n#endif\n    firstix = ix;\n    for(RT1 = 0; (ix > 0) && (RT1 < RT2) && (status == RUNNING);\n        ix = prevActiveLink(psdata->rows->varmap, ix), RT1++)  {\n      candelete = FALSE;\n      if(presolve_rowlength(psdata, ix) != j)\n        continue;\n\n      /* Check if the beginning columns are identical; if not, continue */\n      item1 = 0;\n      iix = presolve_nextcol(psdata, ix, &item1);\n      item2 = 0;\n      jjx = presolve_nextcol(psdata, i,  &item2);\n\n      if(ROW_MAT_COLNR(iix) != ROW_MAT_COLNR(jjx))\n        continue;\n\n      /* We have a candidate row; check if the entries have a fixed non-zero ratio */\n      Value1 = get_mat_byindex(lp, iix, TRUE, FALSE);\n      Value2 = get_mat_byindex(lp, jjx, TRUE, FALSE);\n      bound = Value1 / Value2;\n      Value1 = bound;\n\n      /* Loop over remaining entries */\n      jjx = presolve_nextcol(psdata, i, &item2);\n      for(; (jjx >= 0) && (Value1 == bound);\n          jjx = presolve_nextcol(psdata, i, &item2)) {\n        iix = presolve_nextcol(psdata, ix, &item1);\n        if(ROW_MAT_COLNR(iix) != ROW_MAT_COLNR(jjx))\n          break;\n        Value1 = get_mat_byindex(lp, iix, TRUE, FALSE);\n        Value2 = get_mat_byindex(lp, jjx, TRUE, FALSE);\n\n        /* If the ratio is different from the reference value we have a mismatch */\n        Value1 = Value1 / Value2;\n        if(bound == lp->infinite)\n          bound = Value1;\n        else if(fabs(Value1 - bound) > psdata->epsvalue)\n          break;\n      }\n\n      /* Check if we found a match (we traversed all active columns without a break) */\n      if(jjx < 0) {\n\n        /* Get main reference values */\n        Value1 = lp->orig_rhs[ix];\n        Value2 = lp->orig_rhs[i] * bound;\n\n        /* First check for inconsistent equalities */\n        if((fabs(Value1 - Value2) > psdata->epsvalue) &&\n           ((get_constr_type(lp, ix) == EQ) && (get_constr_type(lp, i) == EQ))) {\n          report(lp, NORMAL, \"presolve_mergerows: Inconsistent equalities %d and %d found\\n\",\n                             ix, i);\n          status = presolve_setstatus(psdata, INFEASIBLE);\n        }\n\n        else {\n\n          /* Update lower and upper bounds */\n          if(is_chsign(lp, i) != is_chsign(lp, ix))\n            bound = -bound;\n\n          Value1 = get_rh_lower(lp, i);\n          if(Value1 <= -lp->infinite)\n            Value1 *= my_sign(bound);\n          else\n            Value1 *= bound;\n          my_roundzero(Value1, lp->epsdual);      /* Extra rounding tolerance *** */\n\n          Value2 = get_rh_upper(lp, i);\n          if(Value2 >= lp->infinite)\n            Value2 *= my_sign(bound);\n          else\n            Value2 *= bound;\n          my_roundzero(Value2, lp->epsdual);      /* Extra rounding tolerance *** */\n\n          if((bound < 0))\n            swapREAL(&Value1, &Value2);\n\n          bound = get_rh_lower(lp, ix);\n          if(Value1 > bound + psdata->epsvalue)\n            set_rh_lower(lp, ix, Value1);\n          else\n            Value1 = bound;\n          bound = get_rh_upper(lp, ix);\n          if(Value2 < bound - psdata->epsvalue)\n            set_rh_upper(lp, ix, Value2);\n          else\n            Value2 = bound;\n\n          /* Check results and make equality if appropriate */\n          if(fabs(Value2-Value1) < psdata->epsvalue)\n            presolve_setEQ(psdata, ix);\n          else if(Value2 < Value1) {\n            status = presolve_setstatus(psdata, INFEASIBLE);\n          }\n\n          /* Verify if we can continue */\n          candelete = (MYBOOL) (status == RUNNING);\n          if(!candelete) {\n            report(lp, NORMAL, \"presolve: Range infeasibility found involving rows %s and %s\\n\",\n                                get_row_name(lp, ix), get_row_name(lp, i));\n          }\n        }\n      }\n      /* Perform i-row deletion if authorized */\n      if(candelete) {\n        presolve_rowremove(psdata, i, TRUE);\n        n++;\n        break;\n      }\n    }\n    i = firstix;\n  }\n  (*nRows) += n;\n  (*nSum)  += n;\n\n  return( status );\n}\n\nSTATIC MYBOOL presolve_reduceGCD(presolverec *psdata, int *nn, int *nb, int *nsum)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   status = TRUE;\n  int      i, jx, je, in = 0, ib = 0;\n  LLONG    GCDvalue;\n  REAL     *Avalue, Rvalue, epsvalue = psdata->epsvalue;\n  MATrec   *mat = lp->matA;\n\n  for(i = firstActiveLink(psdata->INTmap); i != 0; i = nextActiveLink(psdata->INTmap, i)) {\n\n    /* Obtain the row GCD */\n    jx = mat->row_end[i - 1];\n    je = mat->row_end[i];\n    Rvalue = ROW_MAT_VALUE(jx);\n    GCDvalue = abs((int) Rvalue);\n    jx++;\n    if(jx < je)\n    for(; (jx < je) && (GCDvalue > 1); jx++) {\n      Rvalue = fabs(ROW_MAT_VALUE(jx));\n      GCDvalue = gcd((LLONG) Rvalue, GCDvalue, NULL, NULL);\n    }\n\n    /* Reduce the coefficients, if possible */\n    if(GCDvalue > 1) {\n      jx = mat->row_end[i - 1];\n      je = mat->row_end[i];\n      for(; jx < je; jx++) {\n        Avalue = &ROW_MAT_VALUE(jx);\n        *Avalue /= GCDvalue;\n        in++;\n      }\n      Rvalue = (lp->orig_rhs[i] / GCDvalue) + epsvalue;\n      lp->orig_rhs[i] = floor(Rvalue);\n      Rvalue = fabs(lp->orig_rhs[i]-Rvalue);\n      if(is_constr_type(lp, i, EQ) && (Rvalue > epsvalue)) {\n        report(lp, NORMAL, \"presolve_reduceGCD: Infeasible equality constraint %d\\n\", i);\n        status = FALSE;\n        break;\n      }\n      if(!my_infinite(lp, lp->orig_upbo[i]))\n        lp->orig_upbo[i] = floor(lp->orig_upbo[i] / GCDvalue);\n      ib++;\n    }\n  }\n  if(status && (in > 0))\n    report(lp, DETAILED, \"presolve_reduceGCD: Did %d constraint coefficient reductions.\\n\", in);\n\n  (*nn)   += in;\n  (*nb)   += ib;\n  (*nsum) += in + ib;\n\n  return( status );\n}\n\nSTATIC int presolve_knapsack(presolverec *psdata, int *nn)\n{\n  lprec *lp = psdata->lp;\n  int    m, n, i, ix, j, jx, colnr, *rownr = NULL,\n         status = RUNNING;\n  REAL   *colOF = lp->orig_obj, value, *ratio = NULL;\n  LLrec  *map = psdata->EQmap;\n  MATrec *mat = lp->matA;\n\n  /* Check if it is worth trying */\n  m = mat->row_end[0];\n  if((map->count == 0) || (m < 2))\n    return( status );\n\n  /* Get the OF row */\n  allocINT(lp, &rownr,  map->count+1, FALSE);\n  allocREAL(lp, &ratio, map->count+1, FALSE);\n\n  /* Loop over each row trying to find equal entries in the OF */\n  rownr[0] = 0;\n  for(i = firstActiveLink(map); i != 0; i = nextActiveLink(map, i)) {\n    if(get_rh(lp, i) <= 0)\n      continue;\n    jx = mat->row_end[i];\n    n = 0;\n    for(j = mat->row_end[i-1]; j  < jx; j++, n++) {\n      colnr = ROW_MAT_COLNR(j);\n      value = ROW_MAT_VALUE(j);\n      if(colOF[colnr] == 0)\n        break;\n      if(n == 0) {\n        ratio[0] = colOF[colnr] / value;\n      }\n      else if(fabs(value * ratio[0] - colOF[colnr]) > psdata->epsvalue) {\n        n = -1;\n        break;\n      }\n    }\n    /* Register row if we were successful (and row long enough) */\n    if(n >= 2) {\n      ix = ++rownr[0];\n      rownr[ix] = i;\n      ratio[ix] = ratio[0];\n    }\n  }\n  n = rownr[0];\n  if(n == 0)\n    goto Finish;\n\n  /* Process the identified rows, eliminating the OF value */\n  for(ix = 1; ix <= n; ix++) {\n    i = rownr[ix];\n    jx = mat->row_end[i];\n    for(j = mat->row_end[i-1]; j  < jx; j++) {\n      colnr = ROW_MAT_COLNR(j);\n      colOF[colnr] = 0;\n    }\n  }\n\n  /* Update key mapper structures */\n  j = lp->columns;\n  psdata->cols->varmap = cloneLink(psdata->cols->varmap, j+n, TRUE);\n  psdata->forceupdate = TRUE;\n\n  /* Finally, add helper columns */\n  for(ix = 1; ix <= n; ix++) {\n    i = rownr[ix];\n    rownr[0] = 0;\n    colOF[0] = my_chsign(is_maxim(lp), ratio[ix]);\n    rownr[1] = i;\n    colOF[1] = -1;\n    value = get_rh(lp, i);\n/*    j = get_constr_type(lp, i); */\n    add_columnex(lp, 2, colOF, rownr);\n    set_bounds(lp, lp->columns, value, value);\n/*    presolve_setEQ(psdata, i); */\n    set_rh(lp, i, 0);\n    appendLink(psdata->cols->varmap, j+ix);\n  }\n  presolve_validate(psdata, TRUE);\n\n  /* Clean up before returning */\nFinish:\n  FREE(rownr);\n  FREE(ratio);\n  (*nn) += n;\n\n  return( status );\n}\n\nSTATIC MYBOOL presolve_invalideq2(lprec *lp, presolverec *psdata)\n{\n  int    jx, jjx, i = 0, item;\n  MATrec *mat = lp->matA;\n  MYBOOL error = FALSE;\n\n  do {\n\n    if(i == 0)\n      i = firstActiveLink(psdata->EQmap);\n    else\n      i = nextActiveLink(psdata->EQmap, i);\n    if(i == 0)\n      return( error );\n\n    /* Get the row index of the first 2-element equality */\n    for(; i > 0; i = nextActiveLink(psdata->EQmap, i))\n      if(presolve_rowlength(psdata, i) == 2)\n        break;\n    if(i == 0)\n      return( error );\n\n    /* Get the first column */\n    item = 0;\n    jx  = presolve_nextcol(psdata, i, &item);\n    if(jx < 0)\n      error = TRUE;\n    jx  = ROW_MAT_COLNR(jx);\n\n    /* Get the second column */\n    jjx = presolve_nextcol(psdata, i, &item);\n    if(jjx < 0)\n      error = AUTOMATIC;\n  } while(!error);\n\n  return( error );\n}\n\n/* Callback to obtain the non-zero rows of equality constraints */\nint BFP_CALLMODEL presolve_getcolumnEQ(lprec *lp, int colnr, REAL nzvalues[], int nzrows[], int mapin[])\n{\n  int    i, ib, ie, nn = 0;\n  MATrec *mat = lp->matA;\n\n  ib = mat->col_end[colnr-1];\n  ie = mat->col_end[colnr];\n  for(; ib < ie; ib++) {\n    i = COL_MAT_ROWNR(ib);\n    if(!is_constr_type(lp, i, EQ) ||  /* It has to be an equality constraint         */\n       (mapin[i] == 0))               /* And it should not already have been deleted */\n      continue;\n    if(nzvalues != NULL) {\n      nzrows[nn] = mapin[i];\n      nzvalues[nn] = COL_MAT_VALUE(ib);\n    }\n    nn++;\n  }\n  return( nn );\n}\nSTATIC int presolve_singularities(presolverec *psdata, int *nn, int *nr, int *nv, int *nSum)\n{\n  (void)nv;\n  lprec *lp = psdata->lp;\n  int i, j, n, *rmapin = NULL, *rmapout = NULL, *cmapout = NULL;\n  (void)nv;\n\n  if(lp->bfp_findredundant(lp, 0, NULL, NULL, NULL) == 0)\n    return( 0 );\n\n  /* Create condensed row map */\n  allocINT(lp, &rmapin, lp->rows+1, TRUE);\n  allocINT(lp, &rmapout, psdata->EQmap->count+1, FALSE);\n  allocINT(lp, &cmapout, lp->columns+1, FALSE);\n  n = 0;\n  for(i = firstActiveLink(psdata->EQmap); i != 0; i = nextActiveLink(psdata->EQmap, i)) {\n    n++;\n    rmapout[n] = i;\n    rmapin[i]  = n;\n  }\n  rmapout[0] = n;\n  n = 0;\n  for(i = firstActiveLink(psdata->cols->varmap); i != 0; i = nextActiveLink(psdata->cols->varmap, i)) {\n    n++;\n    cmapout[n]  = i;\n  }\n  cmapout[0] = n;\n\n  /* Do the rank-revealing factorization */\n  n = lp->bfp_findredundant(lp, psdata->EQmap->count, presolve_getcolumnEQ, rmapin, cmapout);\n\n  /* Delete the redundant rows */\n  for(i = 1; i <= n; i++) {\n    j = rmapin[i];\n    j = rmapout[j];\n    presolve_rowremove(psdata, j, TRUE);\n  }\n  (*nn)   += n;\n  (*nr)   += n;\n  (*nSum) += n;\n\n  /* Clean up */\n  FREE(rmapout);\n  FREE(rmapin);\n  FREE(cmapout);\n\n  return( n );\n}\n\nSTATIC int presolve_elimeq2(presolverec *psdata, int *nn, int *nr, int *nc, int *nSum)\n{\n  lprec     *lp = psdata->lp;\n  int       n, i, jx, jjx, k, item, *plucount, *negcount, colplu, colneg,\n            iCoeffChanged = 0, iRowsRemoved = 0, iVarsFixed = 0, nrows = lp->rows,\n            status = RUNNING, *colindex = NULL;\n  MYBOOL    freshupdate;\n  REAL      Coeff1, Coeff2, Value1, Value2, lobound, upbound, bound, test, product,\n            *colvalue = NULL, *delvalue = NULL, *colitem;\n  MATrec    *mat = lp->matA, *rev = NULL;\n  DeltaVrec *DV = NULL;\n  LLrec     *EQ2 = NULL;\n\n  /* See if there is anything to do */\n  if(psdata->EQmap->count == 0) {\n    (*nSum) = 0;\n    return( status );\n  }\n\n  /* Tally counts */\n  createLink(lp->rows, &EQ2, NULL);\n  if((EQ2 == NULL) || !allocREAL(lp, &colvalue, nrows+1, FALSE) ||\n                      !allocREAL(lp, &delvalue, nrows+1, FALSE))\n    goto Finish;\n  for(i = firstActiveLink(psdata->EQmap); i > 0; i = nextActiveLink(psdata->EQmap, i)) {\n    if(presolve_rowlength(psdata, i) == 2)\n      appendLink(EQ2, i);\n  }\n  if(EQ2->count == 0)\n    goto Finish;\n  n = 0;\n\n  /* Do the elimination loop for all identified 2-element equalities */\n  for(i = firstActiveLink(EQ2); i > 0; i = nextActiveLink(EQ2, i)) {\n\n    /* Check if the constraint has been modified by a previous elimination */\n    if(presolve_rowlength(psdata, i) != 2)\n      continue;\n\n    /* Get the column indeces of NZ-values of the \"pivot\" row */\n    item = 0;\n    jx  = presolve_nextcol(psdata, i, &item);   /* Eliminated variable coefficient    b */\n#ifdef Paranoia\n    if(jx < 0)\n      report(lp, SEVERE, \"presolve_elimeq2: No qualifying %dst column was found in row %s (ostensible length %d)\\n\",\n                         1, get_row_name(lp, i), presolve_rowlength(psdata, i));\n#endif\n    Coeff2 = ROW_MAT_VALUE(jx);\n    jx  = ROW_MAT_COLNR(jx);\n    jjx = presolve_nextcol(psdata, i, &item);  /* Non-eliminated variable coefficient a */\n#ifdef Paranoia\n    if(jjx < 0)\n      report(lp, SEVERE, \"presolve_elimeq2: No qualifying %dnd column was found in row %s (ostensible length %d)\\n\",\n                          2, get_row_name(lp, i), presolve_rowlength(psdata, i));\n#endif\n    Coeff1 = ROW_MAT_VALUE(jjx);\n    jjx = ROW_MAT_COLNR(jjx);\n\n    /* Check if at least one of the coefficients is large enough to preserve stability;\n       use opposing maximum column values for stability testing. */\n    if((fabs(Coeff1) < psdata->epspivot*mat->colmax[jx]) &&\n       ((fabs(Coeff1) != 1) && (fabs(Coeff2) != 1)) &&\n       (fabs(Coeff2) < psdata->epspivot*mat->colmax[jjx]))\n      continue;\n\n    /* Cannot eliminate a variable if both are SOS members or SC variables */\n    if((is_semicont(lp, jx) && is_semicont(lp, jjx)) ||\n        (SOS_is_member(lp->SOS, 0, jx) && SOS_is_member(lp->SOS, 0, jjx)))\n      continue;\n\n    /* First check if we are allowed to swap; set swap \"blockers\" */\n    k = 0;\n    if(!is_int(lp, jx) && is_int(lp, jjx))\n      k += 1;\n    else if(!is_semicont(lp, jx) && is_semicont(lp, jjx))\n      k += 2;\n    else if(!SOS_is_member(lp->SOS, 0, jx) && SOS_is_member(lp->SOS, 0, jjx))\n      k += 4;\n\n    /* If there were no blockers, determine if we MUST swap the variable to be eliminated */\n    if(k == 0) {\n      if(is_int(lp, jx) && !is_int(lp, jjx))\n        k += 8;\n      else if(is_semicont(lp, jx) && !is_semicont(lp, jjx))\n        k += 16;\n      else if(SOS_is_member(lp->SOS, 0, jx) && !SOS_is_member(lp->SOS, 0, jjx))\n        k += 32;\n\n      /* If we are not forced to swap, decide if it otherwise makes sense - high order */\n      if(k == 0) {\n        if((fabs(Coeff2) < psdata->epspivot*mat->colmax[jjx]) &&\n           (fabs(Coeff1) > psdata->epspivot*mat->colmax[jx]))\n          k += 64;\n        else if(presolve_collength(psdata, jx) > presolve_collength(psdata, jjx))\n          k += 128;\n      }\n\n      /* If we are not forced to swap, decide if it otherwise makes sense - low order */\n      if(k == 0) {\n        Value2 = Coeff1/Coeff2;\n#ifdef DualFeasibilityLogicEQ2\n        if((Value2*lp->orig_obj[jx] < 0) &&\n          (Value2*lp->orig_obj[jjx] > 0))                     /* Seek increased dual feasibility */\n          k += 256;\n#endif\n#ifdef DivisorIntegralityLogicEQ2\n        if((fabs(modf(Coeff2, &Value2)) >= lp->epsvalue) &&    /* Seek integrality of result */\n           (fabs(modf(Coeff1, &Value2)) < lp->epsvalue))\n          k += 512;\n        else if((fabs(fabs(Coeff2)-1) >= lp->epsvalue) &&    /* Seek integrality of divisor */\n                 (fabs(fabs(Coeff1)-1) < lp->epsvalue))\n          k += 1024;\n#endif\n      }\n\n    }\n    else\n      k = 0;\n\n    /* Perform variable index swap if indicated */\n    if(k != 0) {\n      swapINT(&jx, &jjx);\n      swapREAL(&Coeff1, &Coeff2);\n    }\n\n    Value1 = lp->orig_rhs[i]/Coeff2; /* Delta constant term */\n    Value2 = Coeff1/Coeff2;          /* Delta variable term */\n    upbound = lp->orig_upbo[lp->rows+jx];\n    lobound = lp->orig_lowbo[lp->rows+jx];\n    if(lp->spx_trace) {\n      report(lp, DETAILED, \"Row %3d : Elim %g %s - %d\\n\", i, Coeff2, get_col_name(lp, jx), jx);\n      report(lp, DETAILED, \"          Keep %g %s - %d\\n\",    Coeff1, get_col_name(lp, jjx), jjx);\n    }\n\n    /* Get the coefficient vectors of the independent (jjx) and dependent (jx) columns;\n      the dependent column will be deleted and reconstructed during postsolve. */\n    freshupdate = (MYBOOL) ((colindex == NULL) || (colindex[jjx] == 0));\n    if(freshupdate)\n      mat_expandcolumn(mat, jjx, colvalue, NULL, TRUE);\n    else\n      mat_expandcolumn(rev, colindex[jjx], colvalue, NULL, FALSE);\n    if((colindex == NULL) || (colindex[jx] == 0))\n      mat_expandcolumn(mat, jx, delvalue, NULL, TRUE);\n    else\n      mat_expandcolumn(rev, colindex[jx], delvalue, NULL, FALSE);\n\n    /* Add variable reconstruction information */\n    addUndoPresolve(lp, TRUE, jx, Value1, Value2, jjx);\n\n    /* If possible, tighten the bounds of the uneliminated variable based\n       on the bounds of the eliminated variable. Also handle roundings\n       and attempt precision management. */\n    bound = lobound;\n    k = nrows+jjx;\n    if(bound > -lp->infinite) {\n      bound = (lp->orig_rhs[i] - Coeff2*bound) / Coeff1;\n      if(Value2 > 0) {\n        test = lp->orig_upbo[k];\n        if(bound < test - psdata->epsvalue) {\n          if(is_int(lp, jjx))\n            lp->orig_upbo[k] = floor(bound + lp->epsint);\n          else\n            lp->orig_upbo[k] = presolve_roundrhs(lp, bound, FALSE);\n        }\n      }\n      else {\n        test = lp->orig_lowbo[k];\n        if(bound > test + psdata->epsvalue) {\n          if(is_int(lp, jjx))\n            lp->orig_lowbo[k] = ceil(bound - lp->epsint);\n          else\n            lp->orig_lowbo[k] = presolve_roundrhs(lp, bound, TRUE);\n        }\n      }\n    }\n    bound = upbound;\n    if(bound < lp->infinite) {\n      bound = (lp->orig_rhs[i] - Coeff2*bound) / Coeff1;\n      if(Value2 < 0) {\n        test = lp->orig_upbo[k];\n        if(bound < test - psdata->epsvalue) {\n          if(is_int(lp, jjx))\n            lp->orig_upbo[k] = floor(bound + lp->epsint);\n          else\n            lp->orig_upbo[k] = presolve_roundrhs(lp, bound, FALSE);\n        }\n      }\n      else {\n        test = lp->orig_lowbo[k];\n        if(bound > test + psdata->epsvalue) {\n          if(is_int(lp, jjx))\n            lp->orig_lowbo[k] = ceil(bound - lp->epsint);\n          else\n            lp->orig_lowbo[k] = presolve_roundrhs(lp, bound, TRUE);\n        }\n      }\n    }\n\n#ifdef Eq2Reldiff\n    test = 2*lp->epsvalue;\n#else\n    test = psdata->epsvalue;\n#endif\n    if(/*(lp->orig_upbo[k] < lp->orig_lowbo[k]) ||*/\n#ifdef Eq2Reldiff\n       (fabs(my_reldiff(lp->orig_upbo[k],lp->orig_lowbo[k])) < test)) {\n#else\n       (fabs(lp->orig_upbo[k] - lp->orig_lowbo[k]) < test)) {\n#endif\n      my_roundzero(lp->orig_lowbo[k], test);\n      lp->orig_upbo[k] = lp->orig_lowbo[k];\n    }\n    else {\n      my_roundzero(lp->orig_upbo[k], test);\n      my_roundzero(lp->orig_lowbo[k], test);\n    }\n\n    if(/*(upbound < lobound) ||*/\n#ifdef Eq2Reldiff\n       (fabs(my_reldiff(upbound, lobound)) < test)) {\n#else\n       (fabs(upbound - lobound) < test)) {\n#endif\n      my_roundzero(lobound, test);\n      lp->orig_upbo[nrows+jx] = lobound;\n      upbound = lobound;\n    }\n\n    /* Loop over the non-zero rows of the column (jx) to be eliminated;\n      substitute jx-variable by updating rhs and jjx coefficients */\n    colitem = colvalue;\n    plucount = psdata->rows->plucount;\n    negcount = psdata->rows->negcount;\n    colplu = 0;\n    colneg = 0;\n    /* Count of non-zeros in the independent column jjx */\n    item = presolve_collength(psdata, jjx) - 1;\n    if(isnz_origobj(lp, jjx))\n      item++;\n    for(k = 0; k <= nrows; k++, colitem++) {\n\n      bound = delvalue[k];\n      if((k == i) || (bound == 0) ||\n         ((k > 0) && !isActiveLink(psdata->rows->varmap, k)))\n        continue;\n\n      /* Do constraint and nz-count updates for the substituted variable */\n      product = bound*Value1;\n\n      /* \"Raw\"/unsigned data */\n      presolve_adjustrhs(psdata, k, my_chsign(is_chsign(lp, k), product), test);\n\n      /* Change back to signed part */\n      if(*colitem != 0) {\n        if(*colitem > 0) {\n          colplu--;\n          plucount[k]--;\n        }\n        else {\n          colneg--;\n          negcount[k]--;\n        }\n        if((lobound < 0) && (upbound >= 0)) {\n          psdata->cols->pluneg[jjx]--;\n          psdata->rows->pluneg[k]--;\n        }\n        item--;\n      }\n      (*colitem) -= bound*Value2;\n      iCoeffChanged++;\n\n      /* Update counts */\n      if(fabs(*colitem) >= mat->epsvalue) {\n        if(*colitem > 0) {\n          colplu++;\n          plucount[k]++;\n        }\n        else {\n          colneg++;\n          negcount[k]++;\n        }\n        if((lobound < 0) && (upbound >= 0)) {\n          psdata->cols->pluneg[jjx]++;\n          psdata->rows->pluneg[k]++;\n        }\n        item++;\n      }\n      else {\n        *colitem = 0;\n      }\n\n      /* Also reduce count if the row contains the deleted variable */\n      if(bound > 0)\n        plucount[k]--;\n      else\n        negcount[k]--;\n    }\n    psdata->cols->plucount[jjx] += colplu;\n    psdata->cols->negcount[jjx] += colneg;\n\n    /* Save the new column */\n    if(rev == NULL) {\n      DV = createUndoLadder(lp, nrows, lp->columns / RESIZEFACTOR);\n      rev = DV->tracker;\n      rev->epsvalue = mat->epsvalue;\n      allocINT(lp, &(rev->col_tag), mat->columns_alloc+1, FALSE);\n      allocINT(lp, &colindex, lp->columns+1, TRUE);\n      rev->col_tag[0] = 0;\n    }\n    n = rev->col_tag[0] = incrementUndoLadder(DV);\n    mat_setcol(rev, n, 0, colvalue, NULL, FALSE, FALSE);\n    rev->col_tag[n] = jjx;\n\n    /* Save index to updated vector, but specially handle case where we have\n      the same independent variable for multiple equations! */\n    if(!freshupdate)\n      rev->col_tag[colindex[jjx]] *= -1;\n    colindex[jjx] = n;\n\n    /* Delete the column dependent variable */\n    jx = presolve_colremove(psdata, jx, FALSE);\n    iVarsFixed++;\n\n    /* Check if we have been lucky enough to have eliminated the independent\n       variable via substitution of the dependent variable */\n    if(item == 0) {\n#ifdef Paranoia\n      report(lp, DETAILED, \"presolve_elimeq2: Was able to remove variables %d and %d in row %s\\n\",\n                         jx, jjx, get_row_name(lp, i));\n#endif\n      if(presolve_colfix(psdata, jjx, 0.0, TRUE, nc))\n        jjx = presolve_colremove(psdata, jjx, FALSE);\n    }\n\n    /* Delete the row */\n    presolve_rowremove(psdata, i, FALSE);\n    iRowsRemoved++;\n  }\n\n  /* Perform the column updates collected above */\n  if(n > 0) {\n    mat_mapreplace(mat, psdata->rows->varmap, psdata->cols->varmap, rev);\n    presolve_validate(psdata, TRUE);\n#ifdef PresolveForceUpdateMax\n    mat_computemax(mat /* , FALSE */);\n#endif\n    psdata->forceupdate = TRUE;\n  }\n\n  /* Free work arrays */\nFinish:\n  if(DV != NULL)\n    freeUndoLadder(&DV);\n  freeLink(&EQ2);\n  FREE(colvalue);\n  FREE(delvalue);\n  FREE(colindex);\n\n  /* Update counters */\n  (*nn)   += iCoeffChanged;\n  (*nr)   += iRowsRemoved;\n  (*nc)   += iVarsFixed;\n  (*nSum) += iCoeffChanged + iRowsRemoved + iVarsFixed;\n\n  return( status );\n}\n\nSTATIC MYBOOL presolve_impliedfree(lprec *lp, presolverec *psdata, int colnr)\n{\n  int    i, ix, ie;\n  REAL   Tlower, Tupper;\n  MYBOOL status, rowbinds, isfree = FALSE;\n  MATrec *mat = lp->matA;\n\n  if(my_infinite(lp, get_lowbo(lp, colnr)) && my_infinite(lp, get_upbo(lp, colnr)))\n    return( TRUE );\n\n  ie = mat->col_end[colnr];\n  for(ix = mat->col_end[colnr-1]; (isfree != (TRUE | AUTOMATIC)) && (ix < ie); ix++) {\n    i = COL_MAT_ROWNR(ix);\n    if(!isActiveLink(psdata->rows->varmap, i))\n      continue;\n    Tlower = get_rh_lower(lp, i);\n    Tupper = get_rh_upper(lp, i);\n    status = presolve_multibounds(psdata, i, colnr, &Tlower, &Tupper, NULL, &rowbinds);\n    isfree = isfree | status | rowbinds;\n  }\n\n  return( (MYBOOL) (isfree == (TRUE | AUTOMATIC)) );\n}\n\nSTATIC MYBOOL presolve_impliedcolfix(presolverec *psdata, int rownr, int colnr, MYBOOL isfree)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   signflip, undoadded = FALSE;\n  MATrec   *mat = lp->matA;\n  int      jx, i, ib, ie = mat->row_end[rownr];\n  REAL     varLo = 0, varHi = 0, varRange, conRange = 0, matValue = 0, dual, RHS = lp->orig_rhs[rownr],\n           pivot, matAij = mat_getitem(mat, rownr, colnr), *vecOF = lp->orig_obj;\n\n  /* We cannot have semi-continuous or non-qualifying integers */\n  if(is_semicont(lp, colnr) || is_SOS_var(lp, colnr))\n    return( FALSE );\n  if(is_int(lp, colnr)) {\n    if(!isActiveLink(psdata->INTmap, rownr) || !is_presolve(lp, PRESOLVE_KNAPSACK))\n      return( FALSE );\n    /* colnr must have a coefficient equal to the smallest in the row */\n    varRange = lp->infinite;\n    i = 0;\n    pivot = 0;\n    for(ib = presolve_nextcol(psdata, rownr, &i); i != 0; ib = presolve_nextcol(psdata, rownr, &i)) {\n      jx = ROW_MAT_COLNR(ib);\n      dual = fabs(ROW_MAT_VALUE(ib));\n      /* Check if we have the target column and save the pivot value */\n      if(jx == colnr) {\n        /* Always accept unit coefficient */\n        if(fabs(dual - 1) < psdata->epsvalue)\n          break;\n        pivot = dual;\n        /* Otherwise continue scan */\n      }\n      /* Cannot accept case where result can be fractional */\n      else if((pivot > dual + psdata->epsvalue) ||\n               ((pivot > 0) && (fabs(fmod(dual, pivot)) > psdata->epsvalue)))\n        return( FALSE );\n    }\n  }\n\n  /* Ascertain that the pivot value is large enough to preserve stability */\n  pivot = matAij;\n  if(fabs(pivot) < psdata->epspivot*mat->colmax[colnr])\n    return( FALSE );\n\n  /* Must ascertain that the row variables are not SOS'es; this is because\n     the eliminated variable will be a function of another variable. */\n  if(SOS_count(lp) > 0) {\n    for(ib = mat->row_end[rownr-1]; ib < ie; ib++)\n      if(SOS_is_member(lp->SOS, 0, ROW_MAT_COLNR(ib)))\n        return( FALSE );\n  }\n\n  /* Calculate the dual value */\n  dual = vecOF[colnr]/pivot;\n\n  /* Here we have free variable in an equality constraint; this means we can\n     can adjust the OF for the deleted variable and also delete the constraint. */\n  if(isfree && is_constr_type(lp, rownr, EQ)) {\n    matValue = RHS/pivot;\n    if(matValue != 0)\n      undoadded = addUndoPresolve(lp, TRUE, colnr, matValue, 0.0, 0);\n  }\n\n  else {\n\n    /* IMPLIEDFREE: For simplicity, ensure that we can keep the slack based at 0,\n                   and not its upper bound. Effectively, we consider the constraint\n                   an equality, using the information of the sign of the dual.\n       IMPLIEDSLK: Since we already have an equality constraint, we wish to make sure\n                   that the ensuing inequality constraint will have an RHS that is\n                   non-infinite. */\n    if(isfree) {\n      SETMIN(RHS, presolve_sumplumin(lp, rownr, psdata->rows, TRUE));\n      matValue = presolve_sumplumin(lp, rownr, psdata->rows, FALSE);\n      conRange = get_rh_lower(lp, rownr);\n      conRange = RHS - MAX(matValue, conRange);\n      signflip = (MYBOOL) ((dual > 0) &&\n                           !my_infinite(lp, conRange));\n    }\n    else {\n      varLo = get_lowbo(lp, colnr);\n      varLo *= (my_infinite(lp, varLo) ? my_sign(pivot) : pivot);\n      varHi = get_upbo(lp, colnr);\n      varHi *= (my_infinite(lp, varHi) ? my_sign(pivot) : pivot);\n      if(pivot < 0)\n        swapREAL(&varHi, &varLo);\n      signflip = my_infinite(lp, varLo);\n    }\n    if(signflip) {\n      mat_multrow(mat, rownr, -1);\n      RHS -= conRange;\n      RHS = -RHS;\n      lp->orig_rhs[rownr] = RHS;\n      pivot = -pivot;\n      dual  = -dual;\n      if(!isfree) {\n        varLo = -varLo;\n        varHi = -varHi;\n        swapREAL(&varHi, &varLo);\n      }\n    }\n    matValue = RHS/pivot;\n\n    /* Prepare for deleting free or implied free variable in inequality constraint.\n       Different strategies need to be used:\n\n       ACTUAL:  Find the proper constraint bound and store undo information for\n                recovering the value of the implied free variable.  The constraint\n                is then deleted.  We have to adjust the objective function if the\n                OF coefficient for the implied free variable is non-zero.\n       IMPLIED: Convert the constraint to an inequality at the proper bound.\n                For given models, the new equality constraint can later provide\n                an implied slack, which means that a further variable is eliminated,\n                and the constraint again becomes an inequality constraint.\n\n      Note that this version only implements the ACTUAL mode */\n    if(isfree) {\n      /* Add undo information connecting the deleted variable to the RHS */\n      if(matValue != 0)\n        undoadded = addUndoPresolve(lp, TRUE, colnr, matValue, 0.0, 0);\n      /* Add undo information for the dual of the deleted constraint */\n      if(dual != 0)\n        addUndoPresolve(lp, FALSE, rownr, dual, 0.0, 0);\n    }\n\n    /* Prepare for deleting implied slack variable.  The following two cases are\n      handled:\n\n      1. Equality constraint: Convert the constraint to an inequality constraint\n                              that is possibly ranged\n      2. Other constraints:   Expand existing slack variable / constraint\n                              range, if required. */\n    else {\n      if(my_infinite(lp, varHi))\n        varRange = lp->infinite;\n#ifdef Paranoia\n      else if(my_infinite(lp, varLo)) {\n        report(lp, SEVERE, \"presolve_impliedcolfix: Negative infinite limit for variable %d\\n\", colnr);\n        varRange = lp->infinite;\n      }\n#endif\n      else\n        varRange = my_precision(fabs(varHi - varLo) + lp->epsvalue, psdata->epsvalue);\n      presolve_adjustrhs(psdata, rownr, varLo, psdata->epsvalue);\n\n      /* Handle case 1 of an equality constraint */\n      if(is_constr_type(lp, rownr, EQ)) {\n        /* Make sure we actually have a ranged constraint */\n        if(varRange > 0) {\n          set_constr_type(lp, rownr, LE);\n          if(!my_infinite(lp, varRange))\n            lp->orig_upbo[rownr] = varRange;\n          setLink(psdata->LTmap, rownr);\n          removeLink(psdata->EQmap, rownr);\n        }\n      }\n      /* Handle case 2 of an inequality constraint (UNDER CONSTRUCTION!)*/\n      else {\n        if(!my_infinite(lp, lp->orig_upbo[rownr])) {\n          if(my_infinite(lp, varRange))\n            lp->orig_upbo[rownr] = lp->infinite;\n          else\n            lp->orig_upbo[rownr] += varHi - varLo;\n        }\n      }\n      /* Update counts */\n      if(matAij > 0)\n        psdata->rows->plucount[rownr]--;\n      else\n        psdata->rows->negcount[rownr]--;\n      if(my_sign(varLo) != my_sign(varHi))\n        psdata->rows->pluneg[rownr]--;\n\n      /* Add undo information for the deleted variable; note that we cannot link the\n        deleted variable to the slack, since it may not be available during undo.\n        We really should have a mini LP to compute this allocation ex-post. */\n      if(RHS != 0)\n        undoadded = addUndoPresolve(lp, TRUE, colnr, RHS/pivot, 0.0, 0);\n    }\n  }\n\n  /* Update the OF constant */\n  if(dual != 0) {\n    presolve_adjustrhs(psdata, 0, dual * RHS, 0);\n/*    lp->orig_rhs[0] -= dual * RHS; */\n    vecOF[colnr] = 0;\n  }\n\n  /* Do affine transformation with the constraint row */\n  i = 0;\n  for(ib = presolve_nextcol(psdata, rownr, &i); ib >= 0;\n      ib = presolve_nextcol(psdata, rownr, &i)) {\n\n    /* Get the constraint element */\n    jx = ROW_MAT_COLNR(ib);\n    if(jx == colnr)\n      continue;\n    matValue = ROW_MAT_VALUE(ib);\n\n    /* Adjust OF for the variable to be deleted */\n    if(dual != 0)\n      vecOF[jx] -= dual * matValue;\n\n    /* Add reconstruction/undo parameters for the deleted variable */\n    if(!undoadded)\n      undoadded = addUndoPresolve(lp, TRUE, colnr, 0.0, matValue/pivot, jx);\n    else\n      appendUndoPresolve(lp, TRUE, matValue/pivot, jx);\n  }\n\n  return( TRUE );\n}\n\nSTATIC psrec *presolve_initpsrec(lprec *lp, int size)\n{\n  psrec *ps = (psrec *) calloc(1, sizeof(*ps));\n\n  createLink(size, &ps->varmap, NULL);\n    fillLink(ps->varmap);\n\n  size++;\n\n  allocINT(lp, &ps->empty, size, FALSE);\n  ps->empty[0] = 0;\n\n  allocREAL(lp, &ps->pluupper,  size, FALSE);\n  allocREAL(lp, &ps->negupper,  size, FALSE);\n  allocREAL(lp, &ps->plulower,  size, FALSE);\n  allocREAL(lp, &ps->neglower,  size, FALSE);\n  allocINT(lp,  &ps->infcount,  size, FALSE);\n\n  ps->next = (int **) calloc(size, sizeof(*(ps->next)));\n\n  allocINT(lp,  &ps->plucount,  size, TRUE);\n  allocINT(lp,  &ps->negcount,  size, TRUE);\n  allocINT(lp,  &ps->pluneg,    size, TRUE);\n\n  ps->allocsize = size;\n\n  return( ps );\n}\nSTATIC void presolve_freepsrec(psrec **ps)\n{\n  FREE((*ps)->plucount);\n  FREE((*ps)->negcount);\n  FREE((*ps)->pluneg);\n  FREE((*ps)->infcount);\n\n  if((*ps)->next != NULL) {\n    int i, n = (*ps)->allocsize;\n    for(i = 0; i < n; i++)\n      FREE((*ps)->next[i]);\n    FREE((*ps)->next);\n  }\n\n  FREE((*ps)->plulower);\n  FREE((*ps)->neglower);\n  FREE((*ps)->pluupper);\n  FREE((*ps)->negupper);\n\n  FREE((*ps)->empty);\n\n  freeLink(&(*ps)->varmap);\n\n  FREE(*ps);\n}\n\nSTATIC presolverec *presolve_init(lprec *lp)\n{\n  int         k, i, ix, ixx, colnr,\n              ncols = lp->columns,\n              nrows = lp->rows;\n  REAL        hold;\n  MATrec      *mat = lp->matA;\n  presolverec *psdata = NULL;\n\n  /* Optimize memory usage if we have a very large model;\n     this is to reduce the risk of out-of-memory situations. */\n  ix  = get_nonzeros(lp);\n  ixx = lp->matA->mat_alloc;\n  if((ixx - ix > MAT_START_SIZE) && ((ixx - ix) * 20 > ixx))\n    mat_memopt(lp->matA, nrows / 20, ncols / 20, ix / 20);\n\n  psdata = (presolverec *) calloc(1, sizeof(*psdata));\n\n  psdata->lp   = lp;\n  psdata->rows = presolve_initpsrec(lp, nrows);\n  psdata->cols = presolve_initpsrec(lp, ncols);\n\n  psdata->epsvalue = PRESOLVE_EPSVALUE;\n  psdata->epspivot = PRESOLVE_EPSPIVOT;\n  psdata->forceupdate = TRUE;\n\n  /* Save incoming primal bounds */\n  k = lp->sum + 1;\n  allocREAL(lp, &psdata->pv_lobo, k, FALSE);\n  MEMCOPY(psdata->pv_lobo, lp->orig_lowbo, k);\n  allocREAL(lp, &psdata->pv_upbo, k, FALSE);\n  MEMCOPY(psdata->pv_upbo, lp->orig_upbo, k);\n\n  /* Create and initialize dual value (Langrangean and slack) limits */\n  allocREAL(lp, &psdata->dv_lobo, k, FALSE);\n  allocREAL(lp, &psdata->dv_upbo, k, FALSE);\n  for(i = 0; i <= nrows; i++) {\n    psdata->dv_lobo[i] = (is_constr_type(lp, i, EQ) ? -lp->infinite : 0);\n    psdata->dv_upbo[i] = lp->infinite;\n  }\n  k--;\n  for(; i <= k; i++) {\n    psdata->dv_lobo[i] = 0;\n    psdata->dv_upbo[i] = lp->infinite;\n  }\n\n /* Create NZ count and sign arrays, and do general initialization of row bounds */\n  createLink(nrows, &psdata->EQmap, NULL);\n  createLink(nrows, &psdata->LTmap, NULL);\n  createLink(nrows, &psdata->INTmap, NULL);\n  for(i = 1; i <= nrows; i++) {\n    switch (get_constr_type(lp, i)) {\n      case LE: appendLink(psdata->LTmap, i);\n                break;\n      case EQ: appendLink(psdata->EQmap, i);\n                break;\n    }\n    k = mat_rowlength(mat, i);\n    if((lp->int_vars > 0) && (k > 0))\n      appendLink(psdata->INTmap, i);\n  }\n\n  /* Seek to reduce set of sum(INT*INT) rows (mainly for GCD coefficient reductions) */\n  if(psdata->INTmap->count > 0)\n  for(i = 1; i <= nrows; i++) {\n    if(!isActiveLink(psdata->INTmap, i))\n      continue;\n    /* Disqualify if there is a non-int variable, otherwise find smallest absolute fractional row value */\n    ix = mat->row_end[i - 1];\n    ixx = mat->row_end[i];\n    colnr = 0;\n    for(; ix < ixx; ix++) {\n      if(!is_int(lp, ROW_MAT_COLNR(ix))) {\n        removeLink(psdata->INTmap, i);\n        break;\n      }\n      hold = fabs(ROW_MAT_VALUE(ix));\n      hold = fmod(hold, 1);\n      /* Adjust colnr to be a decimal scalar */\n      for(k = 0; (k <= MAX_FRACSCALE) && (hold+psdata->epsvalue < 1); k++)\n        hold *= 10;\n      if(k > MAX_FRACSCALE) {\n        removeLink(psdata->INTmap, i);\n        break;\n      }\n      SETMAX(colnr, k);\n    }\n    if(!isActiveLink(psdata->INTmap, i))\n      continue;\n    hold = pow(10.0, colnr);\n    /* Also disqualify if the RHS is fractional after scaling */\n    if(fabs(fmod(lp->orig_rhs[i] * hold, 1)) > psdata->epsvalue) {\n      removeLink(psdata->INTmap, i);\n      continue;\n    }\n    /* We have an all-int constraint, see if we should scale it up */\n    if(k > 0) {\n      ix = mat->row_end[i - 1];\n      for(; ix < ixx; ix++) {\n        ROW_MAT_VALUE(ix) *= hold;\n      }\n      lp->orig_rhs[i] *= hold;\n      if(!my_infinite(lp, lp->orig_upbo[i]))\n        lp->orig_upbo[i] *= hold; /* KE: Fix due to Andy Loto - 20070619 */\n    }\n  }\n\n  /* Do the real tallying and ordering work */\n  presolve_validate(psdata, TRUE);\n\n  return( psdata );\n}\n\nSTATIC void presolve_free(presolverec **psdata)\n{\n  presolve_freepsrec(&(*psdata)->rows);\n  presolve_freepsrec(&(*psdata)->cols);\n  FREE((*psdata)->dv_lobo);\n  FREE((*psdata)->dv_upbo);\n  FREE((*psdata)->pv_lobo);\n  FREE((*psdata)->pv_upbo);\n  freeLink(&(*psdata)->EQmap);\n  freeLink(&(*psdata)->LTmap);\n  freeLink(&(*psdata)->INTmap);\n  FREE(*psdata);\n}\n\nSTATIC int presolve_makefree(presolverec *psdata)\n{\n  lprec    *lp = psdata->lp;\n  int      i, ix, j, nn = 0;\n  REAL     Xlower, Xupper, losum, upsum, lorhs, uprhs, freeinf = lp->infinite / 10;\n  MATrec   *mat = lp->matA;\n  LLrec    *colLL = NULL;\n\n  /* First see if we can relax ranged constraints */\n  for(i = firstActiveLink(psdata->rows->varmap); i != 0; i = nextActiveLink(psdata->rows->varmap, i)) {\n    if(is_constr_type(lp, i, EQ))\n      continue;\n    presolve_range(lp, i, psdata->rows, &losum, &upsum);\n    lorhs = get_rh_lower(lp, i);\n    uprhs = get_rh_upper(lp, i);\n\n    /* Look for opportunity to relax constraint bounds */\n    if(presolve_rowlength(psdata, i) > 1) {\n      if((is_constr_type(lp, i, GE) && (upsum <= uprhs)) ||\n         (is_constr_type(lp, i, LE) && (losum >= lorhs)))\n        set_rh_range(lp, i, lp->infinite);\n    }\n  }\n\n  /* Collect columns available for bound relaxation (find implied free variables)\n     (consider sorting the list in decending order of column lengths or do call to\n      COLAMD to maximize impact) */\n  createLink(lp->columns, &colLL, NULL);\n  for(j = firstActiveLink(psdata->cols->varmap); j != 0; j = nextActiveLink(psdata->cols->varmap, j))\n    if(presolve_impliedfree(lp, psdata, j))\n      appendLink(colLL, j);\n\n  /* Find what columns to relax (ideally one per row) */\n  if(colLL->count > 0) {\n    LLrec  *rowLL = NULL;\n    MYBOOL canfree;\n\n    /* Create row tracker */\n    createLink(lp->rows, &rowLL, NULL);\n    fillLink(rowLL);\n\n    /* Loop over all column candidates */\n    for(j = firstActiveLink(colLL); (j > 0) && (rowLL->count > 0); j = nextActiveLink(colLL, j)) {\n\n      /* Verify that the variable is applicable */\n      canfree = TRUE;\n      for(ix = mat->col_end[j-1]; canfree && (ix < mat->col_end[j]); ix++)\n        canfree = isActiveLink(rowLL, COL_MAT_ROWNR(ix));\n\n      /* If so, then open the bounds and update the row availability mapper */\n      if(canfree) {\n        nn++;\n        Xlower = get_lowbo(lp, j);\n        Xupper = get_upbo(lp, j);\n        if(Xlower >= 0)\n          set_bounds(lp, j, 0, freeinf);\n        else if(Xupper <= 0)\n          set_bounds(lp, j, -freeinf, 0);\n        else\n/*          set_bounds(lo, j, -freeinf, freeinf); */\n          set_unbounded(lp, j);\n        for(ix = mat->col_end[j-1]; ix < mat->col_end[j]; ix++)\n          removeLink(rowLL, COL_MAT_ROWNR(ix));\n      }\n    }\n    freeLink(&rowLL);\n  }\n\n  /* Free list and return */\n  freeLink(&colLL);\n  return( nn );\n}\n\nSTATIC MYBOOL presolve_updatesums(presolverec *psdata)\n{\n  lprec    *lp = psdata->lp;\n  int      j;\n\n  /* Initialize row accumulation arrays */\n  MEMCLEAR(psdata->rows->pluupper, lp->rows + 1);\n  MEMCLEAR(psdata->rows->negupper, lp->rows + 1);\n  MEMCLEAR(psdata->rows->plulower, lp->rows + 1);\n  MEMCLEAR(psdata->rows->neglower, lp->rows + 1);\n  MEMCLEAR(psdata->rows->infcount, lp->rows + 1);\n\n  /* Loop over active columns */\n  for(j = firstActiveLink(psdata->cols->varmap); j != 0;\n      j = nextActiveLink(psdata->cols->varmap, j)) {\n    presolve_colfix(psdata, j, lp->infinite, FALSE, NULL);\n  }\n\n#ifdef UseDualPresolve\n  /* Initialize column accumulation arrays */\n  MEMCLEAR(psdata->cols->pluupper, lp->columns + 1);\n  MEMCLEAR(psdata->cols->negupper, lp->columns + 1);\n  MEMCLEAR(psdata->cols->plulower, lp->columns + 1);\n  MEMCLEAR(psdata->cols->neglower, lp->columns + 1);\n  MEMCLEAR(psdata->cols->infcount, lp->columns + 1);\n\n  /* Loop over active rows */\n  for(j = firstActiveLink(psdata->rows->varmap); j != 0;\n      j = nextActiveLink(psdata->rows->varmap, j)) {\n    presolve_rowfix(psdata, j, lp->infinite, FALSE, NULL);\n  }\n#endif\n\n  return( TRUE );\n}\n\nSTATIC MYBOOL presolve_finalize(presolverec *psdata)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   compactvars = FALSE;\n  int      ke, n;\n\n  /* Save eliminated rows and columns for restoration purposes */\n#ifdef SavePresolveEliminated\n  psdata->deletedA = mat_extractmat(lp->matA, rowmap, colmap, TRUE);\n  if(!mat_validate(psdata->deletedA))\n    report(lp, SEVERE, \"presolve_finalize: Could not validate matrix with undo data\\n\");\n#endif\n\n  /* Check if OF columns are to be deleted */\n  lp->presolve_undo->OFcolsdeleted = FALSE;\n  for(n = firstInactiveLink(psdata->cols->varmap); (n != 0) && !lp->presolve_undo->OFcolsdeleted;\n      n = nextInactiveLink(psdata->cols->varmap, n))\n    lp->presolve_undo->OFcolsdeleted = (MYBOOL) (lp->orig_obj[n] != 0);\n\n  /* Delete eliminated columns */\n  ke = lastInactiveLink(psdata->cols->varmap);\n  n = countInactiveLink(psdata->cols->varmap);\n  if((n > 0) && (ke > 0)) {\n    del_columnex(lp, psdata->cols->varmap);\n    mat_colcompact(lp->matA, lp->presolve_undo->orig_rows,\n                             lp->presolve_undo->orig_columns);\n    compactvars = TRUE;\n  }\n\n  /* Delete eliminated rows */\n  ke = lastInactiveLink(psdata->rows->varmap);\n  n = countInactiveLink(psdata->rows->varmap);\n  if((n > 0) && (ke > 0)) {\n    del_constraintex(lp, psdata->rows->varmap);\n    mat_rowcompact(lp->matA, TRUE);\n    compactvars = TRUE;\n  }\n  else if(psdata->nzdeleted > 0)\n    mat_zerocompact(lp->matA);\n\n  /* Do compacting and updating of variable maps */\n  if(compactvars)\n    varmap_compact(lp, lp->presolve_undo->orig_rows,\n                       lp->presolve_undo->orig_columns);\n\n  /* Reduce memory usage of postsolve matrices */\n  if(lp->presolve_undo->primalundo != NULL)\n    mat_memopt(lp->presolve_undo->primalundo->tracker, 0, 0, 0);\n  if(lp->presolve_undo->dualundo != NULL)\n    mat_memopt(lp->presolve_undo->dualundo->tracker, 0, 0, 0);\n\n  /* Round near-zero objective function coefficients and RHS values */\n  ke = lp->columns;\n  for(n = 1; n <= ke; n++)\n    my_roundzero(lp->orig_obj[n], lp->epsvalue);\n  ke = lp->rows;\n  for(n = 1; n <= ke; n++)\n    my_roundzero(lp->orig_rhs[n], lp->epsvalue);\n\n  /* Update the SOS sparse mapping */\n  if(SOS_count(lp) > 0)\n    SOS_member_updatemap(lp->SOS);\n\n  /* Validate matrix and reconstruct row indexation */\n  return(mat_validate(lp->matA));\n}\n\nSTATIC MYBOOL presolve_debugdump(lprec *lp, presolverec *psdata, const char *filename, MYBOOL doappend)\n{\n  FILE   *output = stdout;\n  int   size;\n  MYBOOL ok;\n\n  ok = (MYBOOL) ((filename == NULL) || ((output = fopen(filename, my_if(doappend, \"a\", \"w\"))) != NULL));\n  if(!ok)\n    return(ok);\n  if((filename == NULL) && (lp->outstream != NULL))\n    output = lp->outstream;\n\n  fprintf(output, \"\\nPRESOLVE - Status at loop %d:%d:%d\\n\",\n                  psdata->outerloops, psdata->middleloops, psdata->innerloops);\n  fprintf(output, \"Model size:     %d rows (%d equalities, %d less than), %d columns\\n\",\n                  psdata->rows->varmap->count, psdata->EQmap->count, psdata->LTmap->count, psdata->cols->varmap->count);\n\n  fprintf(output, \"\\nMAPPERS\\n-------\\n\\n\");\n  size = 1;\n  blockWriteINT(output,  \"colmap\", psdata->cols->varmap->map, 0, size*psdata->cols->varmap->size);\n  blockWriteINT(output,  \"rowmap\", psdata->rows->varmap->map, 0, size*psdata->rows->varmap->size);\n  blockWriteINT(output,  \"EQmap\",  psdata->EQmap->map,  0, size*psdata->EQmap->size);\n  blockWriteINT(output,  \"LTmap\",  psdata->LTmap->map,  0, size*psdata->LTmap->size);\n\n  fprintf(output, \"\\nCOUNTS\\n------\\n\\n\");\n  blockWriteINT(output, \"plucount\",  psdata->rows->plucount,  0, lp->rows);\n  blockWriteINT(output, \"negcount\",  psdata->rows->negcount,  0, lp->rows);\n  blockWriteINT(output, \"pluneg\",    psdata->rows->pluneg,    0, lp->rows);\n\n  fprintf(output, \"\\nSUMS\\n----\\n\\n\");\n  blockWriteREAL(output, \"pluupper\", psdata->rows->pluupper, 0, lp->rows);\n  blockWriteREAL(output, \"negupper\", psdata->rows->negupper, 0, lp->rows);\n  blockWriteREAL(output, \"plulower\", psdata->rows->pluupper, 0, lp->rows);\n  blockWriteREAL(output, \"neglower\", psdata->rows->negupper, 0, lp->rows);\n\n  if(filename != NULL)\n    fclose(output);\n  return(ok);\n}\n\nint CMP_CALLMODEL compRedundant(const UNIONTYPE QSORTrec *current, const UNIONTYPE QSORTrec *candidate)\n{\n  int start1 = (int) (current->int4.intpar1),\n      start2 = (int) (candidate->int4.intpar1),\n      result = CMP_COMPARE(start1, start2);\n\n  if(result == 0) {\n    start1 = (int) (current->int4.intpar2);\n    start2 = (int) (candidate->int4.intpar2);\n    result = -CMP_COMPARE(start1, start2);\n  }\n  return( result );\n}\nint CMP_CALLMODEL compSparsity(const UNIONTYPE QSORTrec *current, const UNIONTYPE QSORTrec *candidate)\n{\n  int start1 = (int) (current->int4.intpar1),\n      start2 = (int) (candidate->int4.intpar1),\n      result = CMP_COMPARE(start1, start2);\n\n  if(result == 0) {\n    start1 = (int) (current->int4.intpar2);\n    start2 = (int) (candidate->int4.intpar2);\n    result = -CMP_COMPARE(start1, start2);\n  }\n\n  if(result == 0) {\n    start1 = (int) (current->int4.intval);\n    start2 = (int) (candidate->int4.intval);\n    result = CMP_COMPARE(start1, start2);\n  }\n  return( result );\n}\nint CMP_CALLMODEL compAggregate(const UNIONTYPE QSORTrec *current, const UNIONTYPE QSORTrec *candidate)\n{\n  int  index1 = (int) (current->pvoidint2.intval),\n       index2 = (int) (candidate->pvoidint2.intval);\n  lprec *lp   = (lprec *) current->pvoidint2.ptr;\n  REAL value1 = lp->orig_obj[index1],\n       value2 = lp->orig_obj[index2];\n\n  /* Smallest objective coefficient (largest contribution to OF) */\n  int  result = CMP_COMPARE(value1, value2);\n\n  /* Smallest lower variable bound */\n  if(result == 0) {\n    index1 += lp->rows;\n    index2 += lp->rows;\n    value1 = lp->orig_lowbo[index1];\n    value2 = lp->orig_lowbo[index2];\n    result = CMP_COMPARE(value1, value2);\n  }\n\n  /* Largest upper variable bound */\n  if(result == 0) {\n    value1 = lp->orig_upbo[index1];\n    value2 = lp->orig_upbo[index2];\n    result = -CMP_COMPARE(value1, value2);\n  }\n  return( result );\n}\n\nSTATIC int presolve_rowdominance(presolverec *psdata, int *nCoeffChanged, int *nRowsRemoved, int *nVarsFixed, int *nSum)\n{\n  lprec    *lp = psdata->lp;\n  MATrec   *mat = lp->matA;\n  int      i, ii, ib, ie, n, jb, je, jx, *coldel = NULL, status = RUNNING, item,\n           iCoeffChanged = 0, iRowRemoved = 0, iVarFixed = 0;\n  REAL     ratio, *rowvalues = NULL;\n  UNIONTYPE QSORTrec *QS = (UNIONTYPE QSORTrec *) calloc(lp->rows+1, sizeof(*QS));\n\n  /* Check if we were able to obtain working memory */\n  if(QS == NULL)\n    return( status);\n\n  /* A dominating row of variables always satisfy the following criteria:\n      1) The starting column position is never lower, but could be the same\n      2) The non-zero row count is always lower */\n  n = 0;\n  for(i = firstActiveLink(psdata->EQmap); i != 0; i = nextActiveLink(psdata->EQmap, i)) {\n    /* Make sure we have no SOS or semi-continuous variables */\n    jb = je = 0;\n    if((SOS_count(lp) > 0) || (lp->sc_vars > 0)) {\n      item = 0;\n      for(jb = presolve_nextcol(psdata, i, &item); jb >= 0;\n          jb = presolve_nextcol(psdata, i, &item)) {\n        jx = ROW_MAT_COLNR(jb);\n        if(SOS_is_member(lp->SOS, 0, jx) || is_semicont(lp, jx))\n          break;\n      }\n    }\n\n    /* Add to list if we are Ok */\n    if(jb < 0) {\n      QS[n].int4.intval = i;\n      item = 0;\n      ii = presolve_nextcol(psdata, i, &item);\n      QS[n].int4.intpar1 = ROW_MAT_COLNR(ii);\n      QS[n].int4.intpar2 = presolve_rowlength(psdata, i);\n      n++;\n    }\n  }\n  if(n <= 1)\n    goto Finish;\n  QS_execute(QS, n, (findCompare_func *) compRedundant, NULL);\n\n  /* Let us start from the top of the list, going forward and looking\n    for the longest possible dominating row */\n  if(!allocREAL(lp, &rowvalues, lp->columns + 1, TRUE) ||\n     !allocINT(lp, &coldel, lp->columns + 1, FALSE))\n    goto Finish;\n\n  for(ib = 0; ib < n; ib++) {\n\n    /* Get row and check if it was previously eliminated */\n    i = QS[ib].int4.intval;\n    if(i < 0)\n      continue;\n\n    /* Load the non-zero row values */\n    item = 0;\n    for(jb = presolve_nextcol(psdata, i, &item); jb >= 0;\n        jb = presolve_nextcol(psdata, i, &item)) {\n      jx = ROW_MAT_COLNR(jb);\n      rowvalues[jx] = ROW_MAT_VALUE(jb);\n    }\n\n    for(ie = ib+1; ie < n; ie++) {\n\n      /* Get row and check if it was previously eliminated */\n      ii = QS[ie].int4.intval;\n      if(ii < 0)\n        continue;\n\n#ifdef Paranoia\n      if((QS[ib].int4.intpar1 > QS[ie].int4.intpar1) ||\n         ((QS[ib].int4.intpar1 == QS[ie].int4.intpar1) && (QS[ib].int4.intpar2 < QS[ie].int4.intpar2)))\n        report(lp, SEVERE, \"presolve_rowdominance: Invalid sorted row order\\n\");\n#endif\n\n      /* Loop over every row member to confirm that the candidate\n        actually dominates in every position */\n      if((lp->orig_rhs[i] == 0) && (lp->orig_rhs[ii] == 0))\n        ratio = 0;\n      else if((lp->orig_rhs[i] != 0) && (lp->orig_rhs[ii] != 0))\n        ratio = lp->orig_rhs[i] / lp->orig_rhs[ii];\n      else\n        continue;\n      item = 0;\n      for(jb = presolve_nextcol(psdata, ii, &item); jb >= 0;\n          jb = presolve_nextcol(psdata, ii, &item)) {\n        jx = ROW_MAT_COLNR(jb);\n        if(rowvalues[jx] == 0)\n          break;\n        if(ratio == 0)\n          ratio = rowvalues[jx] / ROW_MAT_VALUE(jb);\n        else if(fabs(rowvalues[jx] - ratio*ROW_MAT_VALUE(jb)) > psdata->epsvalue)\n          break;\n      }\n\n      /* \"We have contact\" */\n      if(jb < 0) {\n        int sign_1 = 0, sign_j = 0;\n\n        /* Need to fix any superset columns, but require that they have equal signs */\n        coldel[0] = 0;\n        item = 0;\n        for(jb = presolve_nextcol(psdata, i, &item); jb >= 0;\n            jb = presolve_nextcol(psdata, i, &item)) {\n          jx = ROW_MAT_COLNR(jb);\n          if(mat_findelm(mat, ii, jx) <= 0) {\n\n            /* Cancel if we detect a free or \"quasi-free\" variable */\n            if((lp->orig_lowbo[lp->rows + jx] < 0) &&\n               (lp->orig_upbo[lp->rows + jx] > 0)) {\n              coldel[0] = -1;\n              break;\n            }\n\n            /* Ensure that we are feasible */\n            else if((lp->orig_lowbo[lp->rows + jx] > 0) ||\n               (lp->orig_upbo[lp->rows + jx] < 0)) {\n              report(lp, DETAILED, \"presolve_rowdominate: Column %s is infeasible due to conflict in rows %s and %s\\n\",\n                                    get_col_name(lp, jx), get_row_name(lp, i), get_row_name(lp, ii));\n              coldel[0] = -1;\n              break;\n            }\n\n            /* Check consistency / uniformity of signs */\n            sign_j = my_sign(ROW_MAT_VALUE(jb));\n            sign_j = my_chsign(is_negative(lp, jx), sign_j);\n            if(coldel[0] == 0) {\n              sign_1 = sign_j;\n              coldel[++coldel[0]] = jx;\n            }\n            else if(sign_j == sign_1) {\n              coldel[++coldel[0]] = jx;\n            }\n            else {\n              coldel[0] = -1;\n              break;\n            }\n          }\n        }\n\n        /* Force break / continuation if the superset columns were incompatible */\n        if(coldel[0] < 0)\n          continue;\n\n        /* Do the column fixing and deletion (check for infeasibility in the process) */\n        for(jb = 1; jb <= coldel[0]; jb++) {\n          jx = coldel[jb];\n          if(!presolve_colfix(psdata, jx, 0, TRUE, &iVarFixed)) {\n             status = presolve_setstatus(psdata, INFEASIBLE);\n             goto Finish;\n          }\n          presolve_colremove(psdata, jx, TRUE);\n          rowvalues[jx] = 0;\n        }\n\n        /* Then delete the row */\n        presolve_rowremove(psdata, ii, TRUE);\n        iRowRemoved++;\n        QS[ie].int4.intval = -ii;\n      }\n    }\n\n    /* Clear the non-zero row values ahead of the next row candidate */\n    ie = mat->row_end[i-1];\n    ii = mat->row_end[i];\n    for(; ie < ii; ie++)\n      rowvalues[ROW_MAT_COLNR(ie)] = 0;\n\n  }\nFinish:\n  FREE(QS);\n  FREE(rowvalues);\n  FREE(coldel);\n\n  (*nCoeffChanged) += iCoeffChanged;\n  (*nRowsRemoved)  += iRowRemoved;\n  (*nVarsFixed)    += iVarFixed;\n  (*nSum)          += iCoeffChanged + iRowRemoved + iVarFixed;\n\n  return( status );\n}\n\n#if 0\nSTATIC int presolve_coldominance01(presolverec *psdata, int *nConRemoved, int *nVarsFixed, int *nSum)\n/* The current version of this routine eliminates binary variables\n   that are dominated via set coverage or unit knapsack constraints */\n{\n  lprec    *lp = psdata->lp;\n  MATrec   *mat = lp->matA;\n  MYBOOL   first;\n  int      i, ii, ib, ie, n, jb, je, jx, jj, item, item2,\n           *coldel = NULL, status = RUNNING, iVarFixed = 0;\n  REAL     scale, rhsval, *colvalues = NULL;\n  UNIONTYPE QSORTrec *QS = (UNIONTYPE QSORTrec *) calloc(lp->columns+1, sizeof(*QS));\n\n  /* Check if we were able to obtain working memory */\n  if(QS == NULL)\n    return( status);\n  if(lp->int_vars == 0)\n    goto Finish;\n\n  /* A column dominates another binary variable column with the following criteria:\n      1) The relative matrix non-zero entries are identical\n      2) The relative objective coefficient is worse than the other;\n         if the OF coefficients are identical, we can delete an arbitrary variable */\n  n = 0;\n  for(i = firstActiveLink(psdata->cols->varmap); i != 0; i = nextActiveLink(psdata->cols->varmap, i))\n    if(is_binary(lp, i) && !SOS_is_member(lp->SOS, 0, i)) {\n      /* Make sure we have an all-binary, unit-coefficient row */\n      je = mat->col_end[i];\n      item = 0;\n      for(jb = presolve_nextrow(psdata, i, &item); jb >= 0;\n          jb = presolve_nextrow(psdata, i, &item)) {\n        jx = COL_MAT_ROWNR(jb);\n        if(COL_MAT_VALUE(jb) != 1)\n          break;\n      }\n\n      /* Add to list if we are Ok */\n      if(jb < 0) {\n        QS[n].int4.intval = i;\n        item = 0;\n        ii = presolve_nextrow(psdata, i, &item);\n        QS[n].int4.intpar1 = COL_MAT_ROWNR(ii);\n        ii = presolve_collength(psdata, i);\n        QS[n].int4.intpar2 = ii;\n        n++;\n      }\n    }\n  if(n <= 1) {\n    FREE(QS);\n    return( status );\n  }\n  QS_execute(QS, n, (findCompare_func *) compRedundant, NULL);\n\n  /* Let us start from the top of the list, going forward and looking\n    for the longest possible dominated column */\n  if(!allocREAL(lp, &colvalues, lp->rows + 1, TRUE) ||\n     !allocINT(lp, &coldel, lp->columns + 1, FALSE))\n    goto Finish;\n\n  for(ib = 0; ib < n; ib++) {\n\n    /* Get column and check if it was previously eliminated */\n    i = QS[ib].int4.intval;\n    if(i < 0)\n      continue;\n\n    /* Load the non-zero column values */\n    item = 0;\n    for(jb = presolve_nextrow(psdata, i, &item); jb >= 0;\n        jb = presolve_nextrow(psdata, i, &item)) {\n      jx = COL_MAT_ROWNR(jb);\n      colvalues[jx] = COL_MAT_VALUE(jb);\n    }\n\n    coldel[0] = 0;\n    for(ie = ib+1; ie < n; ie++) {\n\n      /* Insist on identical column lengths (sort is decending in column lengths) */\n      ii = QS[ib].int4.intpar2 - QS[ie].int4.intpar2;\n      if(ii != 0)\n        break;\n\n      /* Also insist on identical starting positions */\n      ii = QS[ib].int4.intpar1 - QS[ie].int4.intpar1;\n      if(ii != 0)\n        break;\n\n      /* Get column and check if it was previously eliminated */\n      ii = QS[ie].int4.intval;\n      if(ii < 0)\n        continue;\n\n      /* Also make sure that the variables have \"compatible\" bounds */\n#if 1\n      if((fabs(my_reldiff(lp->orig_lowbo[lp->rows + i], lp->orig_lowbo[lp->rows + ii])) > psdata->epsvalue) ||\n         (fabs(my_reldiff(lp->orig_upbo[lp->rows + i],  lp->orig_upbo[lp->rows + ii] )) > psdata->epsvalue))\n        continue;\n#endif\n\n#ifdef Paranoia\n      if((QS[ib].int4.intpar1 > QS[ie].int4.intpar1) ||\n         ((QS[ib].int4.intpar1 == QS[ie].int4.intpar1) && (QS[ib].int4.intpar2 < QS[ie].int4.intpar2)))\n        report(lp, SEVERE, \"presolve_coldominance01: Invalid sorted column order\\n\");\n#endif\n\n      /* Loop over every column member to confirm that the candidate is\n        relatively identical in every position */\n      first = TRUE;\n      item = 0;\n      item2 = 0;\n      scale = 1;\n      for(jb = presolve_nextrow(psdata, ii, &item),\n          jj = presolve_nextrow(psdata, i, &item2); jb >= 0;\n          jb = presolve_nextrow(psdata, ii, &item),\n          jj = presolve_nextrow(psdata, i, &item2)) {\n        jx = COL_MAT_ROWNR(jb);\n        if(jx != COL_MAT_ROWNR(jj))\n          break;\n        if(first) {\n          first = !first;\n          scale = colvalues[jx] / COL_MAT_VALUE(jb);\n        }\n        else {\n          if(fabs(colvalues[jx] - scale * COL_MAT_VALUE(jb)) > psdata->epsvalue)\n            break;\n        }\n        /* Also make sure we have a compatible RHS (since this version of the\n          dominance logic only applies to \"sets\") */\n        rhsval = scale*lp->orig_rhs[jx] - 1.0;\n        /* if((rhsval < 0) || (rhsval > 1 + psdata->epsvalue)) */\n        if(fabs(rhsval) > psdata->epsvalue)\n          break;\n      }\n\n      /* \"We have contact\" */\n      if(jb < 0) {\n        coldel[++coldel[0]] = ii;\n        QS[ie].int4.intval = -ii;\n      }\n    }\n\n    /* Find the dominant column and delete / fix the others;\n       if there is a tie, simply delete the second candidate */\n    ii = i;\n    for(jb = 1; jb <= coldel[0]; jb++) {\n      jx = coldel[jb];\n      if(lp->orig_obj[jx] < lp->orig_obj[ii])\n        swapINT(&ii, &coldel[jb]);\n    }\n    for(jb = 1; jb <= coldel[0]; jb++) {\n      jx = coldel[jb];\n      if(!presolve_colfix(psdata, jx, lp->orig_lowbo[lp->rows+jx], TRUE, &iVarFixed)) {\n         status = presolve_setstatus(psdata, INFEASIBLE);\n         goto Finish;\n      }\n      presolve_colremove(psdata, jx, TRUE);\n    }\n\n    /* Clear the non-zero row values ahead of the next row candidate */\n    if(ib + 1 < n) {\n      ie = mat->col_end[i-1];\n      ii = mat->col_end[i];\n      for(; ie < ii; ie++)\n        colvalues[COL_MAT_ROWNR(ie)] = 0;\n    }\n  }\nFinish:\n  FREE(QS);\n  FREE(colvalues);\n  FREE(coldel);\n\n  (*nVarsFixed) += iVarFixed;\n  (*nSum)       += iVarFixed;\n\n  return( status );\n}\n#else\n\n/* DEVELOPMENT/TEST CODE FOR POSSIBLE REPLACEMENT OF SIMILAR FUNCTION IN lp_presolve.c */\n\n#define NATURAL int\n\nSTATIC int presolve_coldominance01(presolverec *psdata, NATURAL *nConRemoved, NATURAL *nVarsFixed, NATURAL *nSum)\n/* The current version of this routine eliminates binary variables\n   that are dominated via set coverage or unit knapsack constraints */\n{\n  (void)nConRemoved;\n  lprec    *lp = psdata->lp;\n  MATrec   *mat = lp->matA;\n  NATURAL  i, ib, ie, jx, item, item2,\n           n = lp->int_vars, iVarFixed = 0, nrows = lp->rows,\n           *coldel = NULL;\n  int      jb, jj, ii,\n           status = RUNNING;\n  REAL     rhsval = 0.0,\n           *colvalues = NULL, *colobj = NULL;\n  LLrec    *sets = NULL;\n  UNIONTYPE QSORTrec *QS = (UNIONTYPE QSORTrec *) calloc(n+1, sizeof(*QS));\n  (void)nConRemoved;\n\n  /* Check if we were able to obtain working memory */\n  if(QS == NULL)\n    return( status);\n  if(n == 0)\n    goto Finish;\n\n  /* Create list of set coverage and knapsack constraints */\n  createLink(nrows, &sets, NULL);\n  for(i = firstActiveLink(psdata->rows->varmap); i != 0; i = nextActiveLink(psdata->rows->varmap, i)) {\n    if((lp->orig_rhs[i] < 0) || (psdata->rows->negcount[i] > 0))\n      continue;\n    item = 0;\n    for(jb = presolve_nextcol(psdata, i, &item); jb >= 0;\n        jb = presolve_nextcol(psdata, i, &item)) {\n      jx = ROW_MAT_COLNR(jb);\n      if(!is_binary(lp, jx))\n        break;\n      rhsval = ROW_MAT_VALUE(jb) - 1;\n      if(fabs(rhsval) > lp->epsvalue)\n        break;\n    }\n    if(jb < 0)\n      setLink(sets, i);\n  }\n  if(countActiveLink(sets) == 0)\n    goto Finish;\n\n  /* A column dominates another binary variable column with the following criteria:\n      1) The relative matrix non-zero entries are identical\n      2) The relative objective coefficient is worse than the other;\n         if the OF coefficients are identical, we can delete an arbitrary variable */\n  n = 0;\n  for(i = firstActiveLink(psdata->cols->varmap); i != 0; i = nextActiveLink(psdata->cols->varmap, i))\n    if(is_binary(lp, i) && !SOS_is_member(lp->SOS, 0, i)) {\n      /* Make sure the column is member of at least one set */\n      item = 0;\n      for(jb = presolve_nextrow(psdata, i, &item); jb >= 0;\n          jb = presolve_nextrow(psdata, i, &item)) {\n        jx = COL_MAT_ROWNR(jb);\n        if(isActiveLink(sets, jx))\n          break;\n      }\n\n      /* Add to list if set membership test is Ok */\n      if(jb >= 0) {\n        QS[n].int4.intval = i;\n        item = 0;\n        ii = presolve_nextrow(psdata, i, &item);\n        QS[n].int4.intpar1 = COL_MAT_ROWNR(ii);\n        ii = presolve_collength(psdata, i);\n        QS[n].int4.intpar2 = ii;\n        n++;\n      }\n    }\n  if(n <= 1) {\n    FREE(QS);\n    return( status );\n  }\n  QS_execute(QS, n, (findCompare_func *) compRedundant, NULL);\n\n  /* Let us start from the top of the list, going forward and looking\n    for the longest possible dominated column */\n  if(!allocREAL(lp, &colvalues, nrows + 1, TRUE) ||\n     !allocREAL(lp, &colobj, n + 1, FALSE) ||\n     !allocINT(lp, &coldel, n + 1, FALSE))\n    goto Finish;\n\n  for(ib = 0; ib < n; ib++) {\n\n    /* Get column and check if it was previously eliminated */\n    i = QS[ib].int4.intval;\n    if(!isActiveLink(psdata->cols->varmap, i))\n      continue;\n\n    /* Load the non-zero column values */\n    item = 0;\n    for(jb = presolve_nextrow(psdata, i, &item); jb >= 0;\n        jb = presolve_nextrow(psdata, i, &item)) {\n      jx = COL_MAT_ROWNR(jb);\n      colvalues[jx] = COL_MAT_VALUE(jb);\n    }\n\n    /* Store data for current column */\n    coldel[0] = 1;\n    coldel[1] = i;\n    colobj[1] = lp->orig_obj[i];\n\n    /* Loop over all other columns to see if they have equal constraint coefficients */\n    for(ie = ib+1; ie < n; ie++) {\n\n      /* Check if this column was previously eliminated */\n      ii = QS[ie].int4.intval;\n      if(!isActiveLink(psdata->cols->varmap, ii))\n        continue;\n\n      /* Insist on identical column lengths (sort is decending in column lengths) */\n      ii = QS[ib].int4.intpar2 - QS[ie].int4.intpar2;\n      if(ii != 0)\n        break;\n\n      /* Also insist on identical starting positions */\n      ii = QS[ib].int4.intpar1 - QS[ie].int4.intpar1;\n      if(ii != 0)\n        break;\n\n      /* Get column and check if it was previously eliminated */\n      ii = QS[ie].int4.intval;\n\n#ifdef Paranoia\n      if((QS[ib].int4.intpar1 > QS[ie].int4.intpar1) ||\n         ((QS[ib].int4.intpar1 == QS[ie].int4.intpar1) && (QS[ib].int4.intpar2 < QS[ie].int4.intpar2)))\n        report(lp, SEVERE, \"presolve_coldominance01: Invalid sorted column order\\n\");\n#endif\n\n      /* Loop over every column member to confirm that the candidate is identical in every row;\n         we also compute the minimal set order */\n      rhsval = lp->infinite;\n      item = 0;\n      item2 = 0;\n      for(jb = presolve_nextrow(psdata, ii, &item),\n          jj = presolve_nextrow(psdata, i, &item2); jb >= 0;\n          jb = presolve_nextrow(psdata, ii, &item),\n          jj = presolve_nextrow(psdata, i, &item2)) {\n        jx = COL_MAT_ROWNR(jb);\n        if(jx != COL_MAT_ROWNR(jj))\n          break;\n        if(isActiveLink(sets, jx))\n          SETMIN(rhsval, lp->orig_rhs[jx]);\n      }\n\n      /* \"We have contact\" */\n      if(jb < 0) {\n        coldel[++coldel[0]] = ii;\n        colobj[coldel[0]] = lp->orig_obj[ii];\n      }\n    }\n\n    /* Find the dominant columns, fix and delete the others */\n    if(coldel[0] > 1) {\n      qsortex(colobj+1, coldel[0], 0, sizeof(*colobj), FALSE, compareREAL, coldel+1, sizeof(*coldel));\n      /* if(rhsval+lp->epsvalue < lp->infinite) { */\n        jb = (NATURAL) (rhsval+lp->epsvalue);\n        /* printf(\"%f / %d\\n\", rhsval, jb); */\n        for(jb++; jb <= coldel[0]; jb++) {\n          jx = coldel[jb];\n          if(!presolve_colfix(psdata, jx, lp->orig_lowbo[nrows+jx], TRUE, &iVarFixed)) {\n            status = presolve_setstatus(psdata, INFEASIBLE);\n            goto Finish;\n          }\n          presolve_colremove(psdata, jx, TRUE);\n        }\n      /*} */\n    }\n\n    /* Clear the non-zero row values ahead of the next row candidate */\n    if(ib + 1 < n) {\n      ie = mat->col_end[i-1];\n      ii = mat->col_end[i];\n      for(; ie < ii; ie++)\n        colvalues[COL_MAT_ROWNR(ie)] = 0;\n    }\n  }\nFinish:\n  freeLink(&sets);\n  FREE(QS);\n  FREE(colvalues);\n  FREE(coldel);\n  FREE(colobj);\n\n  (*nVarsFixed) += iVarFixed;\n  (*nSum)       += iVarFixed;\n\n  return( status );\n}\n\n#endif\n\nSTATIC int presolve_aggregate(presolverec *psdata, int *nConRemoved, int *nVarsFixed, int *nSum)\n/* This routine combines compatible or identical columns */\n{\n  (void)nConRemoved;\n  lprec    *lp = psdata->lp;\n  MATrec   *mat = lp->matA;\n  MYBOOL   first;\n  int      i, ii, ib, ie, ix, n, jb, je, jx, jj, item, item2,\n           *coldel = NULL, status = RUNNING, iVarFixed = 0;\n  REAL     scale, *colvalues = NULL;\n  UNIONTYPE QSORTrec *QScand = (UNIONTYPE QSORTrec *) calloc(lp->columns+1, sizeof(*QScand));\n  (void)nConRemoved;\n\n  /* Check if we were able to obtain working memory */\n  if(QScand == NULL)\n    return( status);\n\n  /* Obtain the list of qualifying columns to be sorted */\n  n = 0;\n  for(i = firstActiveLink(psdata->cols->varmap); i != 0; i = nextActiveLink(psdata->cols->varmap, i))\n    if(!is_semicont(lp, i) && !SOS_is_member(lp->SOS, 0, i)) {\n      QScand[n].int4.intval = i;\n      item = 0;\n      ii = presolve_nextrow(psdata, i, &item);\n      QScand[n].int4.intpar1 = COL_MAT_ROWNR(ii);\n      ii = presolve_collength(psdata, i);\n      QScand[n].int4.intpar2 = ii;\n      n++;\n    }\n  if(n <= 1) {\n    FREE(QScand);\n    return( status );\n  }\n  QS_execute(QScand, n, (findCompare_func *) compRedundant, NULL);\n\n  /* Let us start from the top of the list, going forward and looking\n    for the longest possible identical column */\n  if(!allocREAL(lp, &colvalues, lp->rows + 1, TRUE) ||\n     !allocINT(lp, &coldel, lp->columns + 1, FALSE))\n    goto Finish;\n\n  for(ib = 0; ib < n; ib++) {\n\n    /* Get column and check if it was previously eliminated */\n    i = QScand[ib].int4.intval;\n    if(i < 0)\n      continue;\n\n    /* Load the non-zero column values of this active/reference column */\n    item = 0;\n    for(jb = presolve_nextrow(psdata, i, &item); jb >= 0;\n        jb = presolve_nextrow(psdata, i, &item)) {\n      jx = COL_MAT_ROWNR(jb);\n      colvalues[jx] = COL_MAT_VALUE(jb);\n    }\n\n    coldel[0] = 0;\n    for(ie = ib+1; ie < n; ie++) {\n\n      /* Insist on identical column lengths (sort is decending in column lengths) */\n      ii = QScand[ib].int4.intpar2 - QScand[ie].int4.intpar2;\n      if(ii != 0)\n        break;\n\n      /* Also insist on identical starting positions */\n      ii = QScand[ib].int4.intpar1 - QScand[ie].int4.intpar1;\n      if(ii != 0)\n        break;\n\n      /* Get column and check if it was previously eliminated */\n      ii = QScand[ie].int4.intval;\n      if(ii < 0)\n        continue;\n\n      /* Loop over every column member to confirm that the candidate is\n        relatively identical in every position */\n      first = TRUE;\n      item = 0;\n      item2 = 0;\n      scale = 1;\n      for(jb = presolve_nextrow(psdata, ii, &item),\n          jj = presolve_nextrow(psdata, i, &item2); jb >= 0;\n          jb = presolve_nextrow(psdata, ii, &item),\n          jj = presolve_nextrow(psdata, i, &item2)) {\n        jx = COL_MAT_ROWNR(jb);\n        if(jx != COL_MAT_ROWNR(jj))\n          break;\n        if(first) {\n          first = !first;\n          scale = colvalues[jx] / COL_MAT_VALUE(jb);\n        }\n        else {\n          if(fabs(colvalues[jx] - scale * COL_MAT_VALUE(jb)) > psdata->epsvalue)\n            break;\n        }\n      }\n\n      /* \"We have contact\", store the column in the aggregation list */\n      if(jb < 0) {\n        coldel[++coldel[0]] = ii;\n        QScand[ie].int4.intval = -ii;\n      }\n    }\n\n    /* Sort the aggregation list if we have aggregation candidates */\n    if(coldel[0] > 1) {\n      REAL     of, ofelim, fixvalue;\n      MYBOOL   isint;\n      UNIONTYPE QSORTrec *QSagg = (UNIONTYPE QSORTrec *) calloc(coldel[0], sizeof(*QSagg));\n\n      for(jb = 1; jb <= coldel[0]; jb++) {\n        ii = jb - 1;\n        QSagg[ii].pvoidint2.intval = coldel[jb];\n        QSagg[ii].pvoidint2.ptr    = (void *) lp;\n      }\n      QS_execute(QSagg, coldel[0], (findCompare_func *) compAggregate, NULL);\n\n      /* Process columns with identical OF coefficients */\n      jb = 0;\n      while((status == RUNNING) && (jb < coldel[0])) {\n        ii = QSagg[jb].pvoidint2.intval;\n        of = lp->orig_obj[ii];\n        isint = is_int(lp, ii);\n        je = jb + 1;\n        while((status == RUNNING) && (je < coldel[0]) &&\n              (fabs(lp->orig_obj[ix = QSagg[je].pvoidint2.intval] - of) < psdata->epsvalue)) {\n           /* We now have two columns with equal OFs; the following cases are possible:\n\n             1) The first column has Inf upper bound, which means that it can\n                \"absorb\" compatible columns, which are then fixed at the appropriate\n                bounds (or zero in case of free variables).\n             2) The first column has a -Inf lower bound, and further columns are\n                Inf upper bounds, which means steps towards forming a free variable\n                can be made.\n             3) The first column is a non-Inf upper bound, in which case the bounds\n                are summed into a helper variable and the variable simply deleted.\n                The deleted variables' value are allocated/distributed via a simple\n                linear programming routine at postsolve.\n\n             In the current version of this code, we only handle case 1. */\n          if(is_int(lp, ix) == isint) {\n            ofelim = lp->orig_obj[ix];\n            if(of == 0)\n              scale = 1;\n            else\n              scale = ofelim / of;\n\n            if(my_infinite(lp, lp->orig_upbo[lp->rows+ii])) { /* Case 1 (recipe.mps) */\n              if(is_unbounded(lp, ix))\n                fixvalue = 0;\n              else if(ofelim < 0)\n                fixvalue = lp->orig_upbo[lp->rows+ix];\n              else\n                fixvalue = lp->orig_lowbo[lp->rows+ix];\n              if(my_infinite(lp, fixvalue))\n                status = presolve_setstatus(psdata, UNBOUNDED);\n              else if(!presolve_colfix(psdata, ix, fixvalue, TRUE, &iVarFixed))\n                status = presolve_setstatus(psdata, INFEASIBLE);\n              else\n                presolve_colremove(psdata, ix, TRUE);\n            }\n\n            else if(my_infinite(lp, lp->orig_lowbo[lp->rows+ii])) { /* Case 2 */\n              /* Do nothing */\n            }\n\n            else {                                            /* Case 3 */\n#if 0\n              /* Do nothing */\n#else\n              if(ofelim >= 0) {\n                fixvalue = lp->orig_lowbo[lp->rows+ix];\n                lp->orig_upbo[lp->rows+ii] += scale * (lp->orig_upbo[lp->rows+ix] - fixvalue);\n              }\n              else {\n                fixvalue = lp->orig_upbo[lp->rows+ix];\n                lp->orig_upbo[lp->rows+ii] -= scale * (fixvalue - lp->orig_lowbo[lp->rows+ix]);\n              }\n              if(my_infinite(lp, fixvalue))\n                status = presolve_setstatus(psdata, UNBOUNDED);\n              else if(!presolve_colfix(psdata, ix, fixvalue, TRUE, &iVarFixed))\n                status = presolve_setstatus(psdata, INFEASIBLE);\n              else\n                presolve_colremove(psdata, ix, TRUE);\n#ifdef xxParanoia\n              if(presolve_rowlengthdebug(psdata) > 0)\n                report(lp, SEVERE, \"presolve_aggregate: Invalid row count\\n\");\n#endif\n              psdata->forceupdate = TRUE;\n#endif\n            }\n          }\n          je++;\n        }\n        jb = je;\n      }\n      FREE(QSagg);\n    }\n\n    /* Clear the non-zero row values ahead of the next row candidate */\n    if(ib + 1 < n) {\n      ie = mat->col_end[i-1];\n      ii = mat->col_end[i];\n      for(; ie < ii; ie++)\n        colvalues[COL_MAT_ROWNR(ie)] = 0;\n    }\n  }\nFinish:\n  FREE(QScand);\n  FREE(colvalues);\n  FREE(coldel);\n\n  (*nVarsFixed) += iVarFixed;\n  (*nSum)       += iVarFixed;\n\n  return( status );\n}\n\nSTATIC int presolve_makesparser(presolverec *psdata, int *nCoeffChanged, int *nConRemove, int *nVarFixed, int *nSum)\n{\n  (void)nVarFixed;\n  lprec    *lp = psdata->lp;\n  MATrec   *mat = lp->matA;\n  MYBOOL   chsign;\n  int      i, ii, ib, ix, k, n, jb, je, jl, jjb, jje, jjl, jx, jjx, item, itemEQ,\n           *nzidx = NULL, status = RUNNING, iObjChanged = 0, iCoeffChanged = 0, iConRemove = 0;\n  REAL     test, ratio, value, valueEQ, *valptr;\n  LLrec    *EQlist = NULL;\n  UNIONTYPE QSORTrec *QS = (UNIONTYPE QSORTrec *) calloc(lp->rows, sizeof(*QS));\n  (void)nVarFixed;\n\n  /* Check if we were able to obtain working memory */\n  if((QS == NULL) || (psdata->rows->varmap->count == 0) || (psdata->EQmap->count == 0))\n    return( status);\n\n  /* Sort rows in 1) increasing order of start index, 2) decreasing length, and\n     3) non-equalities (i.e. equalities last) */\n  n = 0;\n  for(i = firstActiveLink(psdata->rows->varmap); i != 0; i = nextActiveLink(psdata->rows->varmap, i)) {\n    k = presolve_rowlength(psdata, i);\n    if(k >= 2) {\n      item = 0;\n      ii = presolve_nextcol(psdata, i, &item);\n#ifdef Paranoia\n      if((ii < 0) || (item == 0)) {\n        report(lp, SEVERE, \"presolve_makesparser: Unexpected zero-length row %d\\n\", i);\n        continue;\n      }\n#endif\n      QS[n].int4.intval  = my_chsign(is_constr_type(lp, i, EQ), i);\n      QS[n].int4.intpar1 = ROW_MAT_COLNR(ii);\n      QS[n].int4.intpar2 = k;\n      n++;\n    }\n  }\n  if(n <= 1) {\n    FREE(QS);\n    return( status );\n  }\n  QS_execute(QS, n, (findCompare_func *) compSparsity, NULL);\n\n  /* Create associated sorted map of indeces to equality constraints;\n     note that we need to have a unit offset for compatibility. */\n  allocINT(lp, &nzidx, lp->columns + 1, FALSE);\n  createLink(lp->rows, &EQlist, NULL);\n  for(ib = 0; ib < n; ib++) {\n    i = QS[ib].int4.intval;\n    if(i < 0)\n      appendLink(EQlist, ib + 1);\n  }\n\n  /* Loop over all equality masks */\n  for(ix = firstActiveLink(EQlist); ix != 0; ) {\n\n    /* Get row starting and ending positions of the mask */\n    ii = abs(QS[ix-1].int4.intval);\n    jjb = QS[ix-1].int4.intpar1;\n    jje = presolve_lastcol(psdata, ii);\n    jje = ROW_MAT_COLNR(jje);\n    jjl = QS[ix-1].int4.intpar2;\n\n    /* Scan the OF */\n    i = 0;\n    chsign = is_chsign(lp, i);\n    test = ratio = 0.0;\n    itemEQ = 0;\n    nzidx[0] = 0;\n    while(((jjx = presolve_nextcol(psdata, ii, &itemEQ)) >= 0) && /*(itemEQ > 0) && */\n           (fabs(test-ratio) < psdata->epsvalue)) {\n      valueEQ = ROW_MAT_VALUE(jjx);\n      if(valueEQ == 0)\n        continue;\n      k = ROW_MAT_COLNR(jjx);\n      value = lp->orig_obj[k];\n      if(fabs(value) < psdata->epsvalue)\n        break;\n      if(ratio == 0.0) {\n        test = ratio = value / valueEQ;\n      }\n      else\n        test = value / valueEQ;\n      /* Store nz index */\n      nzidx[++nzidx[0]] = k;\n    }\n\n    /* We were successful if the equality was completely traversed; we will\n      then zero-out the OF coefficients and update the constant term. */\n    if((itemEQ == 0) && (nzidx[0] > 0) && (fabs(test-ratio) < psdata->epsvalue)) {\n      for(k = 1; k <= nzidx[0]; k++) {\n        /* We should add recovery data for the zero'ed coefficient here */\n        jx = nzidx[k];\n        value = lp->orig_obj[jx];\n        lp->orig_obj[jx] = 0.0;\n        /* Update counts */\n        value = my_chsign(chsign, value);\n        if(value < 0) {\n          psdata->rows->negcount[i]--;\n          psdata->cols->negcount[jx]--;\n        }\n        else {\n          psdata->rows->plucount[i]--;\n          psdata->cols->plucount[jx]--;\n        }\n        iObjChanged++;\n      }\n      value = ratio * lp->orig_rhs[ii];\n      presolve_adjustrhs(psdata, i, value, psdata->epsvalue);\n    }\n\n    /* Scan for compatible constraints that can be masked for sparsity elimination */\n    for(ib = 1; ib < ix; ib++) {\n\n      /* Get row starting and ending positions of the target constraint */\n      i  = abs(QS[ib-1].int4.intval);\n      jb = QS[ib-1].int4.intpar1;\n      je = presolve_lastcol(psdata, i);\n      je = ROW_MAT_COLNR(je);\n      jl = QS[ib-1].int4.intpar2;\n\n      /* Check if there is a window mismatch */\n      if((jjb < jb) || (jje > je) || (jjl > jl))\n        goto NextEQ;\n\n      /* We have a window match; now check if there is a (scalar) member-by-member\n        match as well.  We approach this in the following manner:\n          1) Get first (or next) member of active equality\n          2) Loop to matching member in the target constraint, but abandon if no match\n          3) Set ratio if this is the first match, otherwise compare ratio and abandon\n             on mismatch\n          4) Go to 1) of there are more elements in the active equality\n          5) Proceed to do sparsity elimination if we were successful. */\n      chsign = is_chsign(lp, i);\n      test = ratio = 0.0;\n      itemEQ = 0;\n      item = 0;\n      nzidx[0] = 0;\n      while(((jjx = presolve_nextcol(psdata, ii, &itemEQ)) >= 0) && /*(itemEQ > 0) &&*/\n             (fabs(test-ratio) < psdata->epsvalue)) {\n        valueEQ = ROW_MAT_VALUE(jjx);\n        if(valueEQ == 0)\n          continue;\n        jx = 0;\n        jjx = ROW_MAT_COLNR(jjx);\n        for(k = presolve_nextcol(psdata, i, &item);\n            (jx < jjx) && (item > 0);\n            k = presolve_nextcol(psdata, i, &item)) {\n          jx = ROW_MAT_COLNR(k);\n          /* Do we have a column index match? */\n          if(jx == jjx) {\n            value = ROW_MAT_VALUE(k);\n            /* Abandon if we have a zero value */\n            if(value == 0)\n              goto NextEQ;\n            if(ratio == 0.0) {\n              test = ratio = value / valueEQ;\n            }\n            else\n              test = value / valueEQ;\n           /* Store nz index */\n            nzidx[++nzidx[0]] = k;\n            break;\n          }\n          /* Give up matching if there is overshooting */\n          else if(jx > jjx)\n            goto NextEQ;\n        }\n      }\n\n      /* We were successful if the equality was completely traversed */\n      if((itemEQ == 0) && (nzidx[0] > 0) && (fabs(test-ratio) < psdata->epsvalue)) {\n\n        /* Check if we have found parametrically indentical constraints */\n        if(presolve_rowlength(psdata, i) == presolve_rowlength(psdata,ii)) {\n\n          value = lp->orig_rhs[i];\n          valueEQ = lp->orig_rhs[ii];\n\n          /* Are they both equalities? */\n          if(is_constr_type(lp, i, EQ)) {\n            /* Determine applicable ratio for the RHS */\n            if(fabs(valueEQ) < psdata->epsvalue) {\n              if(fabs(value) < psdata->epsvalue)\n                test = ratio;\n              else\n                test = lp->infinite;\n            }\n            else\n              test = value / valueEQ;\n            /* Check for infeasibility */\n            if(fabs(test-ratio) > psdata->epsvalue) {\n              report(lp, NORMAL, \"presolve_sparser: Infeasibility of relatively equal constraints %d and %d\\n\",\n                                 i, ii);\n              status = presolve_setstatus(psdata, INFEASIBLE);\n              goto Finish;\n            }\n            /* Otherwise we can delete a redundant constraint */\n            else {\n              removeLink(EQlist, i);\n              presolve_rowremove(psdata, i, TRUE);\n              MEMCOPY(&QS[ib-1], &QS[ib], n-ib);\n              n--;\n              iConRemove++;\n            }\n          }\n          /* ... if not, then delete the inequality, since the equality dominates */\n          else {\n            /* First verify feasibility of the RHS */\n            if((value+psdata->epsvalue < valueEQ) ||\n               (value-get_rh_range(lp, i)-psdata->epsvalue > valueEQ)) {\n              report(lp, NORMAL, \"presolve_sparser: Infeasibility of relatively equal RHS values for %d and %d\\n\",\n                                 i, ii);\n              status = presolve_setstatus(psdata, INFEASIBLE);\n              goto Finish;\n            }\n            presolve_rowremove(psdata, i, TRUE);\n            MEMCOPY(&QS[ib-1], &QS[ib], n-ib);\n            n--;\n            iConRemove++;\n          }\n        }\n\n        /* Otherwise zero-out the target constraint coefficients and update the RHS */\n        else {\n          for(k = 1; k <= nzidx[0]; k++) {\n            /* We should add recovery data for the zero'ed coefficient here */\n            jjx = nzidx[k];\n            jx = ROW_MAT_COLNR(jjx);\n            valptr = &ROW_MAT_VALUE(jjx);\n            value  = *valptr;\n            *valptr = 0.0;\n            /* Update counts */\n            value = my_chsign(chsign, value);\n            if(value < 0) {\n              psdata->rows->negcount[i]--;\n              psdata->cols->negcount[jx]--;\n            }\n            else {\n              psdata->rows->plucount[i]--;\n              psdata->cols->plucount[jx]--;\n            }\n            iCoeffChanged++;\n          }\n          value = ratio * lp->orig_rhs[ii];\n          presolve_adjustrhs(psdata, i, value, psdata->epsvalue);\n        }\n      }\n\n    }\n    /* Get next equality index */\nNextEQ:\n    ix = nextActiveLink(EQlist, ix);\n  }\n\nFinish:\n  FREE(QS);\n  freeLink(&EQlist);\n  FREE(nzidx);\n\n  /* Let us condense the matrix if we modified the constraint matrix */\n  if(iCoeffChanged > 0) {\n    mat->row_end_valid = FALSE;\n    mat_zerocompact(mat);\n    presolve_validate(psdata, TRUE);\n#ifdef PresolveForceUpdateMax\n    mat_computemax(mat /* , FALSE */);\n#endif\n    psdata->forceupdate = TRUE;\n  }\n\n  (*nConRemove)    += iConRemove;\n  (*nCoeffChanged) += iCoeffChanged + iObjChanged;\n  (*nSum)          += iCoeffChanged + iObjChanged + iConRemove;\n\n  return( status );\n}\n\nSTATIC int presolve_SOS1(presolverec *psdata, int *nCoeffChanged, int *nConRemove, int *nVarFixed, int *nSOS, int *nSum)\n{\n  (void)nVarFixed;\n  lprec    *lp = psdata->lp;\n  MYBOOL   candelete, SOS_GUBactive = FALSE;\n  int      iCoeffChanged = 0, iConRemove = 0, iSOS = 0,\n           i,ix,iix, j,jx,jjx, status = RUNNING;\n  REAL     Value1;\n  MATrec   *mat = lp->matA;\n  (void)nVarFixed;\n\n  for(i = lastActiveLink(psdata->rows->varmap); i > 0; ) {\n    candelete = FALSE;\n    Value1 = get_rh(lp, i);\n    jx = get_constr_type(lp, i);\n    if((Value1 == 1) && (presolve_rowlength(psdata, i) >= MIN_SOS1LENGTH) &&\n       ((SOS_GUBactive && (jx != GE)) || (!SOS_GUBactive && (jx == LE)))) {\n      jjx = mat->row_end[i-1];\n      iix = mat->row_end[i];\n      for(; jjx < iix; jjx++) {\n        j = ROW_MAT_COLNR(jjx);\n        if(!isActiveLink(psdata->cols->varmap, j))\n          continue;\n        if(!is_binary(lp, j) || (ROW_MAT_VALUE(jjx) != 1))\n          break;\n      }\n      if(jjx >= iix) {\n        char SOSname[16];\n\n        /* Define a new SOS instance */\n        ix = SOS_count(lp) + 1;\n        sprintf(SOSname, \"SOS_%d\", ix);\n        ix = add_SOS(lp, SOSname, 1, ix, 0, NULL, NULL);\n        if(jx == EQ)\n          SOS_set_GUB(lp->SOS, ix, TRUE);\n        Value1 = 0;\n        jjx = mat->row_end[i-1];\n        for(; jjx < iix; jjx++) {\n          j = ROW_MAT_COLNR(jjx);\n          if(!isActiveLink(psdata->cols->varmap, j))\n            continue;\n          Value1 += 1;\n          append_SOSrec(lp->SOS->sos_list[ix-1], 1, &j, &Value1);\n        }\n        candelete = TRUE;\n        iSOS++;\n      }\n    }\n\n    /* Get next row and do the deletion of the previous, if indicated */\n    ix = i;\n    i = prevActiveLink(psdata->rows->varmap, i);\n    if(candelete) {\n      presolve_rowremove(psdata, ix, TRUE);\n      iConRemove++;\n    }\n  }\n  if(iSOS)\n    report(lp, DETAILED, \"presolve_SOS1: Converted %5d constraints to SOS1.\\n\", iSOS);\n  clean_SOSgroup(lp->SOS, (MYBOOL) (iSOS > 0));\n\n  (*nCoeffChanged) += iCoeffChanged;\n  (*nConRemove)    += iConRemove;\n  (*nSOS)          += iSOS;\n  (*nSum)          += iCoeffChanged+iConRemove+iSOS;\n\n  return( status );\n}\n\nSTATIC int presolve_boundconflict(presolverec *psdata, int baserowno, int colno)\n{\n  REAL   Value1, Value2;\n  lprec  *lp = psdata->lp;\n  MATrec *mat = lp->matA;\n  int    ix, item = 0,\n         status = RUNNING;\n\n  if(baserowno <= 0) do {\n    ix = presolve_nextrow(psdata, colno, &item);\n    if(ix < 0)\n      return( status );\n    baserowno = COL_MAT_ROWNR(ix);\n  } while(presolve_rowlength(psdata, baserowno) != 1);\n  Value1 = get_rh_upper(lp, baserowno),\n  Value2 = get_rh_lower(lp, baserowno);\n\n  if(presolve_singletonbounds(psdata, baserowno, colno, &Value2, &Value1, NULL)) {\n    int iix;\n    item = 0;\n    for(ix = presolve_nextrow(psdata, colno, &item);\n        ix >= 0; ix = presolve_nextrow(psdata, colno, &item)) {\n      iix = COL_MAT_ROWNR(ix);\n      if((iix != baserowno) &&\n         (presolve_rowlength(psdata, iix) == 1) &&\n         !presolve_altsingletonvalid(psdata, iix, colno, Value2, Value1)) {\n        status = presolve_setstatus(psdata, INFEASIBLE);\n        break;\n      }\n    }\n  }\n  else\n    status = presolve_setstatus(psdata, INFEASIBLE);\n  return( status );\n}\n\nSTATIC int presolve_columns(presolverec *psdata, int *nCoeffChanged, int *nConRemove, int *nVarFixed, int *nBoundTighten, int *nSum)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   candelete, isOFNZ, unbounded,\n           probefix = is_presolve(lp, PRESOLVE_PROBEFIX),\n#if 0\n           probereduce = is_presolve(lp, PRESOLVE_PROBEREDUCE),\n#endif\n           colfixdual = is_presolve(lp, PRESOLVE_COLFIXDUAL);\n  int      iCoeffChanged = 0, iConRemove = 0, iVarFixed = 0, iBoundTighten = 0,\n           status = RUNNING, ix, j, countNZ, item;\n  REAL     Value1;\n\n  for(j = firstActiveLink(psdata->cols->varmap); (j != 0) && (status == RUNNING); ) {\n\n    /* Don't presolve members SOS'es */\n    if(SOS_is_member(lp->SOS, 0, j)) {\n      j = nextActiveLink(psdata->cols->varmap, j);\n      continue;\n    }\n\n    /* Initialize */\n    countNZ = presolve_collength(psdata, j);\n    isOFNZ  = isnz_origobj(lp, j);\n    Value1  = get_lowbo(lp, j);\n    unbounded = is_unbounded(lp, j);\n\n    /* Clear unnecessary semicont-definitions */\n    if((lp->sc_vars > 0) && (Value1 == 0) && is_semicont(lp, j))\n      set_semicont(lp, j, FALSE);\n\n    candelete = FALSE;\n    item = 0;\n    ix = lp->rows + j;\n\n    /* Check if the variable is unused */\n    if((countNZ == 0) && !isOFNZ) {\n      if(Value1 != 0)\n        report(lp, DETAILED, \"presolve_columns: Eliminated unused variable %s\\n\",\n                              get_col_name(lp,j));\n      candelete = TRUE;\n    }\n\n    /* Check if the variable has a cost, but is not limited by constraints */\n    else if((countNZ == 0) && isOFNZ) {\n      if(lp->orig_obj[j] < 0)\n        Value1 = get_upbo(lp, j);\n      if(fabs(Value1) >= lp->infinite) {\n        report(lp, DETAILED, \"presolve_columns: Unbounded variable %s\\n\",\n                              get_col_name(lp,j));\n        status = presolve_setstatus(psdata, UNBOUNDED);\n      }\n      else {\n        /* Fix the value at its best bound */\n        report(lp, DETAILED, \"presolve_columns: Eliminated trivial variable %s fixed at %g\\n\",\n                              get_col_name(lp,j), Value1);\n        candelete = TRUE;\n      }\n    }\n\n    /* Check if the variable can be eliminated because it is fixed */\n    else if(isOrigFixed(lp, ix)) {\n      if(countNZ > 0) {\n        status = presolve_boundconflict(psdata, -1, j);\n        if(status != RUNNING)\n          break;\n      }\n      report(lp, DETAILED, \"presolve_columns: Eliminated variable %s fixed at %g\\n\",\n                            get_col_name(lp,j), Value1);\n      candelete = TRUE;\n    }\n\n#if 0\n    /* Merge OF-constraint column doubleton in equality constraint (if it has\n      not been captured by the singleton free variable rule above) */\n    else if((countNZ == 1) && isOFNZ &&\n             ((i = presolve_nextrow(psdata, j, &item)) >= 0) &&\n             is_constr_type(lp, i = COL_MAT_ROWNR(i), EQ)) {\n      MATrec *mat = lp->matA;\n\n      /* Merge the constraint into the OF */\n      Value1 = lp->orig_obj[j] / get_mat(lp, i, j);\n      for(jx = mat->row_end[i-1]; jx < mat->row_end[i]; jx++) {\n        jjx = ROW_MAT_COLNR(jx);\n        lp->orig_obj[jjx] -= Value1 * ROW_MAT_VALUE(jx);\n      }\n      Value2 = lp->orig_rhs[i];\n      presolve_adjustrhs(psdata, 0, Value1 * Value2, 0.0);\n\n      /* Verify feasibility */\n      Value2 /= get_mat(lp, i, j);\n      if((Value2 < get_lowbo(lp, j)) || (Value2 > get_upbo(lp, j))) {\n        status = presolve_setstatus(psdata, INFEASIBLE);\n        break;\n      }\n\n      /* Do column (and flag row) deletion */\n      presolve_rowremove(psdata, i, TRUE);\n      psdata->forceupdate = TRUE;\n      iConRemove++;\n      candelete = TRUE;\n    }\n#endif\n    /* Look for opportunity to fix column based on the dual */\n    else if(colfixdual && presolve_colfixdual(psdata, j, &Value1, &status)) {\n      if(my_infinite(lp, Value1)) {\n        report(lp, DETAILED, \"presolve_columns: Unbounded variable %s\\n\",\n                              get_col_name(lp,j));\n        status = presolve_setstatus(psdata, UNBOUNDED);\n      }\n      else {\n        /* Fix the value at its best bound */\n        report(lp, DETAILED, \"presolve_columns: Eliminated dual-zero variable %s fixed at %g\\n\",\n                              get_col_name(lp,j), Value1);\n        candelete = TRUE;\n      }\n    }\n\n    /* Do probing of binary variables to see if we can fix them */\n    else if(probefix && is_binary(lp, j) &&\n            presolve_probefix01(psdata, j, &Value1)) {\n      report(lp, DETAILED, \"presolve_columns: Fixed binary variable %s at %g\\n\",\n                            get_col_name(lp,j), Value1);\n      candelete = TRUE;\n    }\n#if 0\n    /* Do probing of binary variables to see if we can tighten their coefficients */\n    else if(probereduce && is_binary(lp, j) &&\n            (ix = presolve_probetighten01(psdata, j) > 0)) {\n      report(lp, DETAILED, \"presolve_columns: Tightened coefficients for binary variable %s in %d rows\\n\",\n                            get_col_name(lp,j), ix);\n      iCoeffChanged += ix;\n      psdata->forceupdate = TRUE;\n    }\n#endif\n\n    /* Perform fixing and deletion, if indicated */\n    if(candelete) {\n\n      /* If we have a SOS1 member variable fixed at a non-zero value, then we\n        must fix the other member variables at zero and delete the SOS(es) */\n      if((Value1 != 0) && SOS_is_member(lp->SOS, 0, j)) {\n        ix = iVarFixed;\n        if(!presolve_fixSOS1(psdata, j, Value1, &iConRemove, &iVarFixed))\n          status = presolve_setstatus(psdata, INFEASIBLE);\n        if(iVarFixed > ix)\n          psdata->forceupdate = TRUE;\n        break;\n      }\n      else {\n        if(!presolve_colfix(psdata, j, Value1, TRUE, &iVarFixed)) {\n          status = presolve_setstatus(psdata, INFEASIBLE);\n          break;\n        }\n        j = presolve_colremove(psdata, j, TRUE);\n      }\n    }\n    else\n      j = nextActiveLink(psdata->cols->varmap, j);\n  }\n\n  /* Remove any \"hanging\" empty row and columns */\n  if(status == RUNNING)\n    status = presolve_shrink(psdata, &iConRemove, &iVarFixed);\n\n  (*nCoeffChanged) += iCoeffChanged;\n  (*nConRemove)    += iConRemove;\n  (*nVarFixed)     += iVarFixed;\n  (*nBoundTighten) += iBoundTighten;\n  (*nSum)          += iCoeffChanged+iConRemove+iVarFixed+iBoundTighten;\n\n  return( status );\n}\n\nSTATIC int presolve_freeandslacks(presolverec *psdata, int *nCoeffChanged, int *nConRemove, int *nVarFixed, int *nSum)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   isOFNZ, unbounded,\n           impliedfree = is_presolve(lp, PRESOLVE_IMPLIEDFREE),\n           impliedslack = is_presolve(lp, PRESOLVE_IMPLIEDSLK);\n  int      iCoeffChanged = 0, iConRemove = 0, iVarFixed = 0,\n           status = RUNNING, i, ix, j, countNZ;\n  REAL     coeff_bl, coeff_bu;\n  MATrec   *mat = lp->matA;\n\n  if(impliedfree || impliedslack)\n  for(j = firstActiveLink(psdata->cols->varmap); j != 0; ) {\n\n    /* Check and initialize */\n    if((presolve_collength(psdata, j) != 1) ||\n       is_int(lp, j) || is_semicont(lp, j) ||\n       !presolve_candeletevar(psdata, j)) {\n      j = nextActiveLink(psdata->cols->varmap, j);\n      continue;\n    }\n    ix = 0;\n    i = COL_MAT_ROWNR(presolve_nextrow(psdata, j, &ix));\n    isOFNZ  = isnz_origobj(lp, j);\n    countNZ = presolve_rowlength(psdata, i);\n    coeff_bu = get_upbo(lp, j);\n    coeff_bl = get_lowbo(lp, j);\n    unbounded = my_infinite(lp, coeff_bl) && my_infinite(lp, coeff_bu);\n    ix = lp->rows + j;\n\n    /* Eliminate singleton free variable and its associated constraint */\n    if(impliedfree && unbounded &&\n       presolve_impliedcolfix(psdata, i, j, TRUE)) {\n      report(lp, DETAILED, \"presolve_freeandslacks: Eliminated free variable %s and row %s\\n\",\n                            get_col_name(lp, j), get_row_name(lp, i));\n      presolve_rowremove(psdata, i, TRUE);\n      iConRemove++;\n      j = presolve_colremove(psdata, j, TRUE);\n      iVarFixed++;\n    }\n\n    /* Check for implied slack variable in equality constraint */\n    else if(impliedslack &&\n             (countNZ > 1) &&\n             is_constr_type(lp, i, EQ) &&\n             presolve_impliedcolfix(psdata, i, j, FALSE)) {\n      report(lp, DETAILED, \"presolve_freeandslacks: Eliminated implied slack variable %s via row %s\\n\",\n                            get_col_name(lp, j), get_row_name(lp, i));\n      psdata->forceupdate = TRUE;\n      j = presolve_colremove(psdata, j, TRUE);\n      iVarFixed++;\n    }\n\n    /* Check for implied (generalized) slack variable in inequality constraint */\n    else if(impliedslack && !isOFNZ &&\n             my_infinite(lp, coeff_bu) &&                 /* Consider removing this test */\n#if 0 /* Force zero-bounded implicit slack  */\n             (coeff_bl == 0)) &&\n#else\n             !my_infinite(lp, coeff_bl) &&\n#endif\n             (countNZ > 1) &&\n             !is_constr_type(lp, i, EQ))  {\n      REAL *target,\n            ValueA   = COL_MAT_VALUE(presolve_lastrow(psdata, j));\n#if 0\n      coeff_bu = get_rh_upper(lp, i);\n      coeff_bl = get_rh_lower(lp, i);\n      if(!presolve_singletonbounds(psdata, i, j, &coeff_bl, &coeff_bu, &ValueA)) {\n        status = presolve_setstatus(psdata, INFEASIBLE);\n        break;\n      }\n#endif\n      if((coeff_bl != 0) && !my_infinite(lp, coeff_bl) && !my_infinite(lp, coeff_bu))\n        coeff_bu -= coeff_bl;\n\n      /* If the coefficient is negative, reduce the lower bound / increase range */\n      if(ValueA > 0) {\n        target = &lp->orig_upbo[i];\n        if(!my_infinite(lp, *target)) {\n          if(my_infinite(lp, coeff_bu)) {\n            *target = lp->infinite;\n            psdata->forceupdate = TRUE;\n          }\n          else {\n            *target += ValueA * coeff_bu;\n            *target = presolve_roundrhs(lp, *target, FALSE);\n          }\n        }\n      }\n      /* Otherwise see if the upper bound should be changed */\n      else {\n        target = &lp->orig_rhs[i];\n        if(my_infinite(lp, coeff_bu) || my_infinite(lp, *target)) {\n          /* Do we suddenly find that the constraint becomes redundant? (e226.mps) */\n          if(my_infinite(lp, lp->orig_upbo[i])) {\n            presolve_rowremove(psdata, i, TRUE);\n            iConRemove++;\n          }\n          /* Or does the upper bound of a ranged constraint become Inf? */\n          else {\n            *target -= lp->orig_upbo[i];\n            *target = -(*target);\n            mat_multrow(mat, i, -1);\n            lp->orig_upbo[i] = lp->infinite;\n            psdata->forceupdate = TRUE;\n          }\n        }\n        else {\n          *target -= ValueA * coeff_bu;\n          *target = presolve_roundrhs(lp, *target, FALSE);\n        }\n      }\n      presolve_colfix(psdata, j, coeff_bl, TRUE, &iVarFixed);\n      report(lp, DETAILED, \"presolve_freeandslacks: Eliminated duplicate slack variable %s via row %s\\n\",\n                            get_col_name(lp, j), get_row_name(lp, i));\n      j = presolve_colremove(psdata, j, TRUE);\n    }\n\n    /* Go to next column */\n    else\n      j = nextActiveLink(psdata->cols->varmap, j);\n  }\n\n  (*nCoeffChanged) += iCoeffChanged;\n  (*nConRemove)    += iConRemove;\n  (*nVarFixed)     += iVarFixed;\n  (*nSum)          += iCoeffChanged+iConRemove+iVarFixed;\n\n  return( status );\n}\n\nSTATIC int presolve_preparerows(presolverec *psdata, int *nBoundTighten, int *nSum)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   impliedfree = is_presolve(lp, PRESOLVE_IMPLIEDFREE),\n           tightenbounds  = is_presolve(lp, PRESOLVE_BOUNDS);\n  int      iRangeTighten = 0, iBoundTighten = 0, status = RUNNING, i, j;\n  REAL     losum, upsum, lorhs, uprhs, epsvalue = psdata->epsvalue;\n  MATrec   *mat = lp->matA;\n\n  for(i = lastActiveLink(psdata->rows->varmap); i > 0; i = prevActiveLink(psdata->rows->varmap, i)) {\n\n   /* First identify any full row infeasibilities */\n    j = presolve_rowlengthex(psdata, i);\n#ifdef Paranoia\n    if(!presolve_testrow(psdata, nextActiveLink(psdata->rows->varmap, i))) {\n#else\n    if((j > 1) && !psdata->forceupdate && !presolve_rowfeasible(psdata, i, FALSE)) {\n#endif\n      status = presolve_setstatus(psdata, INFEASIBLE);\n      break;\n    }\n\n    /* Do bound (LHS) or constraint range (RHS) tightening if we will later identify\n      implied free variables (tends to produce degeneracy otherwise) */\n    if(impliedfree && (j > 1) && mat_validate(mat)){\n\n      /* Look for opportunity to tighten constraint bounds (and check for feasibility again) */\n      presolve_range(lp, i, psdata->rows, &losum, &upsum);\n      lorhs = get_rh_lower(lp, i);\n      uprhs = get_rh_upper(lp, i);\n      if((losum > MIN(upsum, uprhs)+epsvalue) ||\n         (upsum < MAX(losum, lorhs)-epsvalue)) {\n        report(lp, NORMAL, \"presolve_preparerows: Variable bound / constraint value infeasibility in row %s.\\n\",\n                           get_row_name(lp, i));\n        status = presolve_setstatus(psdata, INFEASIBLE);\n        break;\n      }\n\n      if(losum > lorhs+epsvalue) {\n        set_rh_lower(lp, i, presolve_roundrhs(lp, losum, TRUE));\n        iRangeTighten++;\n      }\n      if(upsum < uprhs-epsvalue) {\n        set_rh_upper(lp, i, presolve_roundrhs(lp, upsum, FALSE));\n        iRangeTighten++;\n      }\n    }\n\n    /* Seek to tighten bounds on individual variables */\n    if(tightenbounds && mat_validate(mat)) {\n#if 1\n      if(j > 1)\n        status = presolve_rowtighten(psdata, i, &iBoundTighten, FALSE);\n#else\n      if((MIP_count(lp) > 0) && (j > 1))\n        status = presolve_rowtighten(psdata, i, &iBoundTighten, TRUE);\n#endif\n    }\n\n    /* Look for opportunity to convert ranged constraint to equality-type */\n    if(!is_constr_type(lp, i, EQ) && (get_rh_range(lp, i) < epsvalue)) {\n      presolve_setEQ(psdata, i);\n      iRangeTighten++;\n    }\n  }\n\n  psdata->forceupdate |= (MYBOOL) (iBoundTighten > 0);\n  (*nBoundTighten) += iBoundTighten+iRangeTighten;\n  (*nSum)          += iBoundTighten+iRangeTighten;\n\n  return( status );\n}\n\nSTATIC int presolve_rows(presolverec *psdata, int *nCoeffChanged, int *nConRemove, int *nVarFixed, int *nBoundTighten, int *nSum)\n{\n  lprec    *lp = psdata->lp;\n  MYBOOL   candelete;\n  int      iCoeffChanged = 0, iConRemove = 0, iVarFixed = 0, iBoundTighten = 0,\n           status = RUNNING, i,ix, j,jx, item;\n  REAL     Value1, Value2, losum, upsum, lorhs, uprhs, epsvalue = psdata->epsvalue;\n  MATrec   *mat = lp->matA;\n\n  for(i = lastActiveLink(psdata->rows->varmap); (i > 0) && (status == RUNNING); ) {\n\n    candelete = FALSE;\n\n   /* First identify any full row infeasibilities\n      Note: Handle singletons below to ensure that conflicting multiple singleton\n            rows with this variable do not provoke notice of infeasibility */\n    j = presolve_rowlengthex(psdata, i);\n    if((j > 1) &&\n       !psdata->forceupdate && !presolve_rowfeasible(psdata, i, FALSE)) {\n      status = presolve_setstatus(psdata, INFEASIBLE);\n      break;\n    }\n    presolve_range(lp, i, psdata->rows, &losum, &upsum);\n    lorhs = get_rh_lower(lp, i);\n    uprhs = get_rh_upper(lp, i);\n#ifdef Paranoia\n    if((losum>uprhs+epsvalue) || (upsum<lorhs-epsvalue)) {\n      status = presolve_setstatus(psdata, INFEASIBLE);\n      break;\n    }\n#endif\n\n    /* Delete empty rows */\n    if(j == 0)\n      candelete = TRUE;\n    else\n\n    /* Convert non-fixed row singletons to bounds */\n#if 0  /* Version that deletes bound-fixed columns in presolve_columns() */\n    if((j == 1) && (upsum-losum >= -epsvalue)) {\n#else  /* Version that deletes bound-fixed columns here */\n    if((j == 1) && (uprhs-lorhs >= -epsvalue)) {\n#endif\n      item = 0;\n      jx = presolve_nextcol(psdata, i, &item);\n      j = ROW_MAT_COLNR(jx);\n\n      /* Make sure we don't have conflicting other singleton rows with this variable */\n      Value1 = lp->infinite;\n      Value2 = -Value1;\n      if(presolve_collength(psdata, j) > 1)\n        status = presolve_boundconflict(psdata, i, j);\n      else if(is_constr_type(lp, i, EQ)) {\n        Value2 = ROW_MAT_VALUE(jx);\n        Value1 = lp->orig_rhs[i] / Value2;\n        if(Value2 < 0)\n          swapREAL(&losum, &upsum);\n        if((Value1 < losum / my_if(my_infinite(lp, losum), my_sign(Value2), Value2) - epsvalue) ||\n           (Value1 > upsum / my_if(my_infinite(lp, upsum), my_sign(Value2), Value2) + epsvalue))\n          status = presolve_setstatus(psdata, INFEASIBLE);\n        Value2 = Value1;\n      }\n\n      /* Proceed to fix and remove variable (if it is not a SOS member) */\n      if(status == RUNNING) {\n        if((fabs(Value2-Value1) < epsvalue) && (fabs(Value2) > epsvalue)) {\n          MYBOOL isSOS     = (MYBOOL) (SOS_is_member(lp->SOS, 0, j) != FALSE),\n                 deleteSOS = isSOS && presolve_candeletevar(psdata, j);\n          if((Value1 != 0) && deleteSOS) {\n            if(!presolve_fixSOS1(psdata, j, Value1, &iConRemove, &iVarFixed))\n              status = presolve_setstatus(psdata, INFEASIBLE);\n              psdata->forceupdate = TRUE;\n          }\n          else {\n            if(!presolve_colfix(psdata, j, Value1, (MYBOOL) !isSOS, NULL))\n              status = presolve_setstatus(psdata, INFEASIBLE);\n            else if(isSOS && !deleteSOS)\n              iBoundTighten++;\n            else {\n              presolve_colremove(psdata, j, TRUE);\n              iVarFixed++;\n            }\n          }\n        }\n        else\n          status = presolve_colsingleton(psdata, i, j, &iBoundTighten);\n      }\n      if(status == INFEASIBLE) {\n        break;\n      }\n      if(psdata->forceupdate != AUTOMATIC) {\n        /* Store dual recovery information and code for deletion */\n        presolve_storeDualUndo(psdata, i, j);\n        candelete = TRUE;\n      }\n    }\n\n    /* Delete non-empty rows and variables that are completely determined at zero */\n    else if((j > 0)                            /* Only examine non-empty rows, */\n       && (fabs(lp->orig_rhs[i]) < epsvalue)   /* .. and the current RHS is zero, */\n       && ((psdata->rows->plucount[i] == 0) ||\n           (psdata->rows->negcount[i] == 0))   /* .. and the parameter signs are all equal, */\n       && (psdata->rows->pluneg[i] == 0)       /* .. and no (quasi) free variables, */\n       && (is_constr_type(lp, i, EQ)\n#ifdef FindImpliedEqualities\n           || (fabs(lorhs-upsum) < epsvalue)   /* Convert to equalities */\n           || (fabs(uprhs-losum) < epsvalue)   /* Convert to equalities */\n#endif\n          )\n          ) {\n\n      /* Delete the columns we can delete */\n      status = presolve_rowfixzero(psdata, i, &iVarFixed);\n\n      /* Then delete the row, which is redundant */\n      if(status == RUNNING)\n        candelete = TRUE;\n    }\n\n\n    /* Check if we have a constraint made redundant through bounds on individual\n       variables; such constraints are often referred to as \"forcing constraints\" */\n    else if((losum >= lorhs-epsvalue) &&\n             (upsum <= uprhs+epsvalue)) {\n\n      /* Check if we can also fix all the variables */\n      if(fabs(losum-upsum) < epsvalue) {\n        item = 0;\n        jx = presolve_nextcol(psdata, i, &item);\n        while((status == RUNNING) && (jx >= 0)) {\n          j = ROW_MAT_COLNR(jx);\n          Value1 = get_lowbo(lp, j);\n          if(presolve_colfix(psdata, j, Value1, TRUE, &iVarFixed)) {\n            presolve_colremove(psdata, j, TRUE);\n            iVarFixed++;\n            jx = presolve_nextcol(psdata, i, &item);\n          }\n          else\n            status = presolve_setstatus(psdata, INFEASIBLE);\n        }\n      }\n      candelete = TRUE;\n    }\n\n    /* Get next row and do the deletion of the previous, if indicated */\n    ix = i;\n    i = prevActiveLink(psdata->rows->varmap, i);\n    if(candelete) {\n      presolve_rowremove(psdata, ix, TRUE);\n      iConRemove++;\n    }\n  }\n\n  /* Remove any \"hanging\" empty row and columns */\n  if(status == RUNNING)\n    status = presolve_shrink(psdata, &iConRemove, &iVarFixed);\n\n  (*nCoeffChanged) += iCoeffChanged;\n  (*nConRemove)    += iConRemove;\n  (*nVarFixed)     += iVarFixed;\n  (*nBoundTighten) += iBoundTighten;\n  (*nSum)          += iCoeffChanged+iConRemove+iVarFixed+iBoundTighten;\n\n  return( status );\n}\n\n/* Top level presolve routine */\nSTATIC int presolve(lprec *lp)\n{\n  int    status = RUNNING,\n         i, j = 0, jx = 0, jjx = 0, k, oSum,\n         iCoeffChanged = 0, iConRemove = 0, iVarFixed = 0, iBoundTighten = 0, iSOS = 0, iSum = 0,\n         nCoeffChanged = 0, nConRemove = 0, nVarFixed = 0, nBoundTighten = 0, nSOS = 0, nSum = 0;\n  REAL   Value1, Value2, initrhs0 = lp->orig_rhs[0];\n  presolverec *psdata = NULL;\n  MATrec *mat = lp->matA;\n\n#if 0\n  lp->do_presolve     = PRESOLVE_ROWS;\n  report(lp, IMPORTANT, \"presolve: Debug override of presolve setting to %d\\n\", lp->do_presolve);\n#endif\n\n /* Lock the variable mapping arrays and counts ahead of any row/column\n    deletion or creation in the course of presolve, solvelp or postsolve */\n  if(!lp->varmap_locked)\n    varmap_lock(lp);\n\n /* Check if we have already done presolve */\n  mat_validate(mat);\n  if(lp->wasPresolved) {\n    if(SOS_count(lp) > 0) {\n      SOS_member_updatemap(lp->SOS);\n      make_SOSchain(lp, (MYBOOL) ((lp->do_presolve & PRESOLVE_LASTMASKMODE) != PRESOLVE_NONE));\n    }\n    if((lp->solvecount > 1) && (lp->bb_level < 1) &&\n       ((lp->scalemode & SCALE_DYNUPDATE) != 0))\n      auto_scale(lp);\n    if(!lp->basis_valid) {\n      crash_basis(lp);\n      report(lp, DETAILED, \"presolve: Had to repair broken basis.\\n\");\n    }\n    lp->timepresolved = timeNow();\n    return(status);\n  }\n\n  /* Produce original model statistics (do hoops to produce correct stats if we have SOS'es) */\n  i = SOS_count(lp);\n  if(i > 0) {\n    SOS_member_updatemap(lp->SOS);\n    lp->sos_vars = SOS_memberships(lp->SOS, 0);\n  }\n  REPORT_modelinfo(lp, TRUE, \"SUBMITTED\");\n  report(lp, NORMAL, \" \\n\");\n  if(i > 0)\n    lp->sos_vars = 0;\n\n  /* Finalize basis indicators; if no basis was created earlier via\n     set_basis or crash_basis then simply set the default basis. */\n  if(!lp->basis_valid)\n    lp->var_basic[0] = AUTOMATIC; /* Flag that we are presolving */\n\n#if 0\nwrite_lp(lp, \"test_in.lp\");    /* Write to lp-formatted file for debugging */\n/*write_mps(lp, \"test_in.mps\");*/  /* Write to lp-formatted file for debugging */\n#endif\n\n  /* Update inf norms and check for potential factorization trouble */\n  mat_computemax(mat /*, FALSE */);\n#if 0\n  Value1 = fabs(lp->negrange);\n  if(is_obj_in_basis(lp) && (mat->dynrange < Value1) && vec_computeext(lp->orig_obj, 1, lp->columns, TRUE, &i, &j)) {\n\n    /* Compute relative scale metric */\n    Value2 = fabs(lp->orig_obj[j]/lp->orig_obj[i]) / mat->dynrange;\n    if(Value2 < 1.0)\n      Value2 = 1.0 / Value2;\n\n    /* Determine if we should alert modeler and possibly move the OF out of the coefficient matrix */\n    if((Value2 > Value1)           /* Case with extreme scale difference */\n#if 1\n        || (mat->dynrange == 1.0)  /* Case where we have an all-unit coefficient matrix, possibly totally unimodular */\n#endif\n      )\n      if((lp->simplex_strategy & SIMPLEX_DYNAMIC) > 0) {\n        clear_action(&lp->algopt, ALGOPT_OBJINBASIS);\n        report(lp, NORMAL, \"Moved objective function out of the basis matrix to enhance factorization accuracy.\\n\");\n      }\n      else if(mat->dynrange > 1.0)\n        report(lp, IMPORTANT, \"Warning: Objective/matrix coefficient magnitude differences will cause inaccuracy!\\n\");\n  }\n#endif\n\n  /* Do traditional simple presolve */\n  yieldformessages(lp);\n  if((lp->do_presolve & PRESOLVE_LASTMASKMODE) == PRESOLVE_NONE) {\n    mat_checkcounts(mat, NULL, NULL, TRUE);\n    i = 0;\n  }\n  else {\n\n    if(lp->full_solution == NULL)\n      allocREAL(lp, &lp->full_solution, lp->sum_alloc+1, TRUE);\n\n    /* Identify infeasible SOS'es prior to any pruning */\n    j = 0;\n    for(i = 1; i <= SOS_count(lp); i++) {\n      k = SOS_infeasible(lp->SOS, i);\n      if(k > 0) {\n        presolverec psdata2;\n\n        psdata2.lp = lp;\n        report(lp, NORMAL, \"presolve: Found SOS %d (type %d) to be range-infeasible on variable %d\\n\",\n                            i, SOS_get_type(lp->SOS, i), k);\n        status = presolve_setstatus(&psdata2, INFEASIBLE);\n        j++;\n      }\n    }\n    if(j > 0)\n      goto Finish;\n\n    /* Create and initialize the presolve data structures */\n    psdata = presolve_init(lp);\n\n    /* Reentry point for the outermost, computationally expensive presolve loop */\n    psdata->outerloops = 0;\n    do {\n      psdata->outerloops++;\n      iCoeffChanged = 0;\n      iConRemove    = 0;\n      iVarFixed     = 0;\n      iBoundTighten = 0;\n      iSOS          = 0;\n      oSum          = nSum;\n\n      /* Do the middle elimination loop */\n      do {\n        psdata->middleloops++;\n        nSum += iSum;\n        iSum = 0;\n\n        /* Accumulate constraint bounds based on bounds on individual variables. */\n        j = 0;\n        while(presolve_statuscheck(psdata, &status) && psdata->forceupdate) {\n          psdata->forceupdate = FALSE;\n          /* Update sums, but limit iteration count to avoid possible\n            \"endless\" loops with only marginal bound improvements */\n          if(presolve_updatesums(psdata) && (j < MAX_PSBOUNDTIGHTENLOOPS)) {\n            /* Do row preparation useful for subsequent column and row presolve operations */\n            if((psdata->outerloops == 1) && (psdata->middleloops == 1))\n              status = presolve_preparerows(psdata, &iBoundTighten, &iSum);\n            nBoundTighten += iBoundTighten;\n            iBoundTighten  = 0;\n            nSum          += iSum;\n            iSum           = 0;\n            j++;\n            if(status != RUNNING)\n              report(lp, NORMAL, \"presolve: Break after bound tightening iteration %d.\\n\", j);\n          }\n        }\n        if(status != RUNNING)\n          break;\n\n        /* Do the relatively cheap innermost elimination loop */\n        do {\n\n          psdata->innerloops++;\n          nSum += iSum;\n          iSum = 0;\n\n          /* Eliminate empty rows, convert row singletons to bounds,\n            tighten bounds, and remove always satisfied rows */\n          if(presolve_statuscheck(psdata, &status) &&\n             is_presolve(lp, PRESOLVE_ROWS))\n            status = presolve_rows(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iBoundTighten, &iSum);\n\n          /* Eliminate empty or fixed columns (including trivial OF column singletons) */\n          if(presolve_statuscheck(psdata, &status) &&\n             is_presolve(lp, PRESOLVE_COLS))\n            status = presolve_columns(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iBoundTighten, &iSum);\n\n          /* Presolve SOS'es if possible (always do this) */\n          if(presolve_statuscheck(psdata, &status))\n            status = presolve_redundantSOS(psdata, &iBoundTighten, &iSum);\n\n        } while((status == RUNNING) && (iSum > 0));\n        if(status != RUNNING)\n          break;\n\n        /* Merge compatible similar rows; loop backwards over every row */\n        if(presolve_statuscheck(psdata, &status) &&\n           (psdata->outerloops == 1) && (psdata->middleloops <= MAX_PSMERGELOOPS) &&\n           is_presolve(lp, PRESOLVE_MERGEROWS))\n          status = presolve_mergerows(psdata, &iConRemove, &iSum);\n\n        /* Eliminate dominated rows */\n        if(presolve_statuscheck(psdata, &status) &&\n           is_presolve(lp, PRESOLVE_ROWDOMINATE))\n          presolve_rowdominance(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iSum);\n\n        /* See if we can convert some constraints to SOSes (only SOS1 handled) */\n        if(presolve_statuscheck(psdata, &status) && (MIP_count(lp) > 0) &&\n           is_presolve(lp, PRESOLVE_SOS))\n          status = presolve_SOS1(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iSOS, &iSum);\n\n        /* Eliminate dominated columns in set coverage models */\n        if(presolve_statuscheck(psdata, &status) && (lp->int_vars > 1) &&\n           is_presolve(lp, PRESOLVE_COLDOMINATE))\n          presolve_coldominance01(psdata, &iConRemove, &iVarFixed, &iSum);\n\n        /* Aggregate compatible columns */\n        if(presolve_statuscheck(psdata, &status) && /*TRUE ||*/\n           is_presolve(lp, PRESOLVE_AGGREGATE))\n          presolve_aggregate(psdata, &iConRemove, &iVarFixed, &iSum);\n\n        /* Eliminate free variables and implied slacks */\n        if(presolve_statuscheck(psdata, &status) &&\n/*           !is_presolve(lp, PRESOLVE_ELIMEQ2) && */\n           is_presolve(lp, PRESOLVE_IMPLIEDSLK | PRESOLVE_IMPLIEDFREE))\n          status = presolve_freeandslacks(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iSum);\n\n      } while((status == RUNNING) && (iSum > 0));\n      if(status != RUNNING)\n        break;\n\n      /* Check if we can do elimination of rank-deficient equality constraints */\n      if(presolve_statuscheck(psdata, &status) && (psdata->EQmap->count > 1) &&\n         is_presolve(lp, PRESOLVE_LINDEP)) {\n#if 0\n        REPORT_mat_mmsave(lp, \"A.mtx\", NULL, FALSE, \"Constraint matrix A\");\n#endif\n        presolve_singularities(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iSum);\n      }\n\n      /* Eliminate variable and tighten bounds using 2-element EQs;\n        note that this involves modifying the coefficients of A and\n        can therefore be a slow operation. */\n      if(presolve_statuscheck(psdata, &status) &&\n         is_presolve(lp, PRESOLVE_ELIMEQ2)) {\n        jjx = 0;\n        do {\n          jjx += iSum;\n          status = presolve_elimeq2(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iSum);\n        } while((status == RUNNING) && (iSum > jjx));\n        iSum = jjx;\n\n#if 0\n        /* Eliminate free variables and implied slacks */\n        if(presolve_statuscheck(psdata, &status) &&\n           is_presolve(lp, PRESOLVE_IMPLIEDSLK | PRESOLVE_IMPLIEDFREE))\n          status = presolve_freeandslacks(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iSum);\n#endif\n      }\n\n      /* Increase A matrix sparsity by discovering common subsets using EQs */\n      if(presolve_statuscheck(psdata, &status) && (psdata->EQmap->count > 0) &&\n         is_presolve(lp, PRESOLVE_SPARSER))\n        status = presolve_makesparser(psdata, &iCoeffChanged, &iConRemove, &iVarFixed, &iSum);\n\n      /* Do GCD-based coefficient reductions (also does row scaling,\n        even if no rhs INT truncations are possible) */\n      if(presolve_statuscheck(psdata, &status) && (psdata->INTmap->count > 0) &&\n         is_presolve(lp, PRESOLVE_REDUCEGCD))\n        if(!presolve_reduceGCD(psdata, &iCoeffChanged, &iBoundTighten, &iSum))\n          status = presolve_setstatus(psdata, INFEASIBLE);\n\n      /* Simplify knapsack or set coverage models where OF coefficients are\n        duplicated in the constraints.  At the cost of adding helper columns, this\n        increases sparsity and facilitates identification of lower and upper bounds. */\n      if(presolve_statuscheck(psdata, &status) &&\n          is_presolve(lp, PRESOLVE_KNAPSACK)) {\n        i = iCoeffChanged;\n        status = presolve_knapsack(psdata, &iCoeffChanged);\n      }\n\n      /* Remove any \"hanging\" empty row and columns */\n      if(status == RUNNING)\n        status = presolve_shrink(psdata, &iConRemove, &iVarFixed);\n\n      nCoeffChanged += iCoeffChanged;\n      nConRemove    += iConRemove;\n      nVarFixed     += iVarFixed;\n      nBoundTighten += iBoundTighten;\n      nSOS          += iSOS;\n      nSum          += iSum;\n\n      iSum           = iConRemove + iVarFixed + iBoundTighten + iCoeffChanged;\n      if(iSum > 0)\n        report(lp, NORMAL, \"Presolve O:%d -> Reduced rows:%5d, cols:%5d --- changed bnds:%5d, Ab:%5d.\\n\",\n                           psdata->outerloops, iConRemove, iVarFixed, iBoundTighten, iCoeffChanged);\n\n   /* Do the outermost loop again if we were successful in this presolve sequences */\n    } while(presolve_statuscheck(psdata, &status) &&\n           (psdata->forceupdate || (oSum < nSum)) &&\n           (psdata->outerloops < get_presolveloops(lp)) &&\n           (psdata->rows->varmap->count+psdata->cols->varmap->count > 0));\n\n   /* Finalize presolve */\n#ifdef Paranoia\n    i = presolve_debugcheck(lp, psdata->rows->varmap, psdata->cols->varmap);\n    if(i > 0)\n      report(lp, SEVERE, \"presolve: %d internal consistency failure%s\\n\", i, my_plural_std(i));\n    if((SOS_count(lp) > 0) && !presolve_SOScheck(psdata))\n      report(lp, SEVERE, \"presolve: SOS sparse member mapping problem - part 1\\n\");\n#endif\n    /* Perform bound relaxation to reduce chance of degeneracy. */\n    if((status == RUNNING) && !is_presolve(lp, PRESOLVE_IMPLIEDFREE))\n      jjx = presolve_makefree(psdata);\n    else\n      jjx = 0;\n\n\n    /* Finalize the presolve */\n    if(!presolve_finalize(psdata))\n      report(lp, SEVERE, \"presolve: Unable to construct internal data representation\\n\");\n\n   /* Report summary information */\n    i = NORMAL;\n    iVarFixed  = lp->presolve_undo->orig_columns - psdata->cols->varmap->count;\n    iConRemove = lp->presolve_undo->orig_rows - psdata->rows->varmap->count;\n    if(nSum > 0)\n      report(lp, i, \"PRESOLVE             Elimination loops performed.......... O%d:M%d:I%d\\n\",\n                                  psdata->outerloops, psdata->middleloops, psdata->innerloops);\n    if(nVarFixed)\n      report(lp, i, \"            %8d empty or fixed variables............. %s.\\n\", nVarFixed, \"REMOVED\");\n    if(nConRemove)\n      report(lp, i, \"            %8d empty or redundant constraints....... %s.\\n\", nConRemove, \"REMOVED\");\n    if(nBoundTighten)\n      report(lp, i, \"            %8d bounds............................... %s.\\n\", nBoundTighten, \"TIGHTENED\");\n    if(nCoeffChanged)\n      report(lp, i, \"            %8d matrix coefficients.................. %s.\\n\", nCoeffChanged, \"CHANGED\");\n    if(jjx > 0)\n      report(lp, i, \"            %8d variables' final bounds.............. %s.\\n\", jjx, \"RELAXED\");\n    if(nSOS)\n      report(lp, i, \"            %8d constraints detected as SOS1......... %s.\\n\", nSOS, \"CONVERTED\");\n\n    /* Report optimality or infeasibility */\n    if(status == UNBOUNDED)\n      report(lp, NORMAL, \"%20s Solution status detected............. %s.\\n\", \"\", \"UNBOUNDED\");\n    else if(status == INFEASIBLE)\n      report(lp, NORMAL, \"%20s Solution status detected............. %s.\\n\", \"\", \"INFEASIBLE\");\n    else {\n      if(psdata->cols->varmap->count == 0)\n        Value1 = Value2 = lp->presolve_undo->fixed_rhs[0] -initrhs0;\n      else\n        presolve_rangeorig(lp, 0, psdata->rows, &Value1, &Value2, -initrhs0);\n      if((fabs(Value1 - Value2) < psdata->epsvalue) || (fabs(my_reldiff(Value1, Value2)) < psdata->epsvalue)) {\n        if((lp->rows == 0) && (lp->columns == 0)) {\n          status = PRESOLVED;\n          Value1 = my_chsign(is_maxim(lp), Value1);\n          lp->solution[0] = Value1;\n          lp->best_solution[0] = Value1;\n          lp->full_solution[0] = Value1;\n        }\n        report(lp, NORMAL, \"%20s OPTIMAL solution found............... %-g\", \"\", Value1);\n      }\n      else if((status == RUNNING) && (i >= NORMAL)) {\n        char lonum[20], upnum[20];\n        if(my_infinite(lp, Value1))\n          sprintf(lonum, \"%13s\", \"-Inf\");\n        else\n          sprintf(lonum, \"%+12g\", Value1);\n        if(my_infinite(lp, Value2))\n          sprintf(upnum, \"%-13s\", \"Inf\");\n        else\n          sprintf(upnum, \"%+-12g\", Value2);\n        report(lp, i,    \"%20s [ %s < Z < %s ]\\n\", \"\", lonum, upnum);\n      }\n\n      /* Update values for dual limit and best heuristic values */\n      if((MIP_count(lp) > 0) || (get_Lrows(lp) > 0)) {\n        if(is_maxim(lp)) {\n          SETMAX(lp->bb_heuristicOF, Value1);\n          SETMIN(lp->bb_limitOF, Value2);\n        }\n        else {\n          SETMIN(lp->bb_heuristicOF, Value2);\n          SETMAX(lp->bb_limitOF, Value1);\n        }\n      }\n    }\n    report(lp, NORMAL, \" \\n\");\n\n    /* Clean up (but save counts of constraint types for display later) */\n    j = psdata->LTmap->count;\n    jx = psdata->EQmap->count;\n    jjx = lp->rows - j - jx;\n    presolve_free(&psdata);\n\n  }\n\n  /* Signal that we are done presolving */\n  if((lp->usermessage != NULL) &&\n     ((lp->do_presolve & PRESOLVE_LASTMASKMODE) != 0) && (lp->msgmask & MSG_PRESOLVE))\n     lp->usermessage(lp, lp->msghandle, MSG_PRESOLVE);\n\n  /* Create master SOS variable list */\n  if(SOS_count(lp) > 0) {\n    /*SOS_member_updatemap(lp->SOS); */\n    make_SOSchain(lp, (MYBOOL) ((lp->do_presolve & PRESOLVE_LASTMASKMODE) != PRESOLVE_NONE));\n  }\n\n  /* Finalize model not identified as infeasible or unbounded */\n  if(status == RUNNING) {\n\n    /* Resolve GUBs */\n    if(is_bb_mode(lp, NODE_GUBMODE))\n      identify_GUB(lp, TRUE);\n\n#if 0\n    /* Mark rows containing hidden identity matrices so that supporting factorization\n      engines can use this structural information to boost efficiency */\n    if(is_algopt(lp, ALGOPT_COMPACTBPF))\n      lp->bfpoptimize = (MYBOOL) (assist_factorization(lp, ROWTYPE_LOGICAL,\n                                                       &lp->rowset1, &lp->rowno1) > 0);\n#endif\n\n    /* Scale the model based on current settings */\n    auto_scale(lp);\n\n    /* Crash the basis, if specified */\n    crash_basis(lp);\n\n    /* Produce presolved model statistics */\n    if(nConRemove+nVarFixed+nBoundTighten+nVarFixed+nCoeffChanged > 0) {\n      REPORT_modelinfo(lp, FALSE, \"REDUCED\");\n      if(nSum > 0) {\n        report(lp, NORMAL, \"Row-types:   %7d LE,          %7d GE,             %7d EQ.\\n\",\n                           j, jjx, jx);\n        report(lp, NORMAL, \" \\n\");\n      }\n    }\n  }\n\n  /* Optionally produce data on constraint classes */\n  if(lp->verbose > NORMAL) {\n    report(lp, NORMAL, \" \\n\");\n    REPORT_constraintinfo(lp, \"CONSTRAINT CLASSES\");\n    report(lp, NORMAL, \" \\n\");\n  }\n\nFinish:\n  lp->wasPresolved  = TRUE;\n  lp->timepresolved = timeNow();\n\n#if 0\n/*  write_mps(lp, \"test_out.mps\"); */ /* Must put here due to variable name mapping */\n  write_lp(lp, \"test_out.lp\");   /* Must put here due to variable name mapping */\n#endif\n#if 0\n  REPORT_debugdump(lp, \"testint2.txt\", FALSE);\n#endif\n\n  return( status );\n\n}\n\nSTATIC MYBOOL postsolve(lprec *lp, int status)\n{\n  /* Verify solution */\n  if(lp->lag_status != RUNNING) {\n    int itemp;\n\n    if(status == PRESOLVED)\n      status = OPTIMAL;\n\n    if((status == OPTIMAL) || (status == SUBOPTIMAL)) {\n      itemp = check_solution(lp, lp->columns, lp->best_solution,\n                                 lp->orig_upbo, lp->orig_lowbo, lp->epssolution);\n      if((itemp != OPTIMAL) && (lp->spx_status == OPTIMAL))\n        lp->spx_status = itemp;\n      else if((itemp == OPTIMAL) && ((status == SUBOPTIMAL) || (lp->spx_status == PRESOLVED)))\n        lp->spx_status = status;\n    }\n    else if(status != PRESOLVED) {\n      report(lp, NORMAL, \"lp_solve unsuccessful after %.0f iter and a last best value of %g\\n\",\n             (double) get_total_iter(lp), lp->best_solution[0]);\n      if(lp->bb_totalnodes > 0)\n        report(lp, NORMAL, \"lp_solve explored %.0f nodes before termination\\n\",\n               (double) get_total_nodes(lp));\n    }\n    else\n      lp->spx_status = OPTIMAL;\n\n    /* Only rebuild primal solution here, since the dual is only computed on request */\n    presolve_rebuildUndo(lp, TRUE);\n  }\n\n  /* Check if we can clear the variable map */\n  if(varmap_canunlock(lp))\n    lp->varmap_locked = FALSE;\n#if 0\n  REPORT_mat_mmsave(lp, \"basis.mtx\", NULL, FALSE);  /* Write the current basis matrix (no OF) */\n#endif\n\n  return( TRUE );\n}\n"
  },
  {
    "path": "utilities/lp_solve/lp_presolve.h",
    "content": "#ifndef HEADER_lp_presolve\n#define HEADER_lp_presolve\n\n#include \"lp_types.h\"\n#include \"lp_matrix.h\"\n\n/* -------------------------------------------------------------------------------------------- */\n/* Defines for various presolve options                                                         */\n/* -------------------------------------------------------------------------------------------- */\n\n#define MAX_PSMERGELOOPS                2                 /* Max loops to merge compatible constraints */\n#define MAX_PSLINDEPLOOPS               1   /* Max loops to detect linearly dependendent constraints */\n#define MAX_PSBOUNDTIGHTENLOOPS         5     /* Maximumn number of loops to allow bound tightenings */\n#define MIN_SOS1LENGTH                  4   /* Minimum length of a constraint for conversion to SOS1 */\n#if 1\n  #define PRESOLVE_EPSVALUE (0.1*lp->epsprimal)\n#else\n  #define PRESOLVE_EPSVALUE  lp->epsvalue\n#endif\n#define PRESOLVE_EPSPIVOT         1.0e-3        /* Looses robustness at values smaller than ~1.0e-3 */\n#define PRESOLVE_BOUNDSLACK           10                     /* Extra error recovery/tolerance margin */\n\n#define DoPresolveRounding              /* Use absolute and directed rounding (disable at own risk) */\n/*#define DoPresolveRelativeTest*/\n\n/*#define PresolveForceUpdateMax*/\n\n/*#define DualFeasibilityLogicEQ2*/              /* Add low-order feasibility/accuracy logic to elimEQ2 */\n#define DivisorIntegralityLogicEQ2                                   /* Always prefer integer divisors */\n#define FindImpliedEqualities                               /* Detect equalities (default is enabled) */\n#define Eq2Reldiff\n\n/*#define SavePresolveEliminated */        /* Enable to activate storage of eliminated matrix data */\n/*#define UseDualPresolve */                    /* Enable to use full dual information for presolve */\n\n\ntypedef struct _psrec\n{\n  LLrec *varmap;\n  int  **next;\n  int  *empty;\n  int  *plucount;\n  int  *negcount;\n  int  *pluneg;\n  int  *infcount;\n  REAL  *plulower;\n  REAL  *neglower;\n  REAL  *pluupper;\n  REAL  *negupper;\n  int  allocsize;\n} psrec;\n\ntypedef struct _presolverec\n{\n  psrec *rows;\n  psrec *cols;\n  LLrec *EQmap;\n  LLrec *LTmap;\n  LLrec *INTmap;\n  REAL  *pv_upbo;\n  REAL  *pv_lobo;\n  REAL  *dv_upbo;\n  REAL  *dv_lobo;\n  lprec *lp;\n  REAL  epsvalue;\n  REAL  epspivot;\n  int   innerloops;\n  int   middleloops;\n  int   outerloops;\n  int   nzdeleted;\n  MYBOOL forceupdate;\n} presolverec;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Put function headers here */\n\nSTATIC MYBOOL presolve_createUndo(lprec *lp);\nSTATIC MYBOOL presolve_rebuildUndo(lprec *lp, MYBOOL isprimal);\nSTATIC MYBOOL inc_presolve_space(lprec *lp, int delta, MYBOOL isrows);\nSTATIC MYBOOL presolve_setOrig(lprec *lp, int orig_rows, int orig_cols);\nSTATIC MYBOOL presolve_colfix(presolverec *psdata, int colnr, REAL newvalue, MYBOOL remove, int *tally);\nSTATIC MYBOOL presolve_fillUndo(lprec *lp, int orig_rows, int orig_cols, MYBOOL setOrig);\nSTATIC MYBOOL presolve_freeUndo(lprec *lp);\n\nSTATIC MYBOOL presolve_updatesums(presolverec *psdata);\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\nINLINE int presolve_nextrow(presolverec *psdata, int colnr, int *previtem);\nINLINE int presolve_nextcol(presolverec *psdata, int rownr, int *previtem);\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n\nSTATIC presolverec *presolve_init(lprec *lp);\nSTATIC void presolve_free(presolverec **psdata);\nSTATIC int presolve_shrink(presolverec *psdata, int *nConRemove, int *nVarRemove);\nSTATIC void presolve_rowremove(presolverec *psdata, int rownr, MYBOOL allowcoldelete);\nSTATIC int presolve_colremove(presolverec *psdata, int colnr, MYBOOL allowrowdelete);\n\nSTATIC MYBOOL presolve_colfixdual(presolverec *psdata, int colnr, REAL *fixValue, int *status);\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\nINLINE int presolve_rowlength(presolverec *psdata, int rownr)\n{\n  int *items = psdata->rows->next[rownr];\n\n  if(items == NULL)\n    return( 0 );\n  else\n    return( items[0] );\n}\nINLINE int presolve_collength(presolverec *psdata, int colnr)\n{\n  int *items = psdata->cols->next[colnr];\n  if(items == NULL)\n    return( 0 );\n  else\n    return( items[0] );\n}\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n\nSTATIC int presolve(lprec *lp);\nSTATIC MYBOOL postsolve(lprec *lp, int status);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_presolve */\n"
  },
  {
    "path": "utilities/lp_solve/lp_price.c",
    "content": "\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_report.h\"\n#include \"lp_pricePSE.h\"\n#include \"lp_price.h\"\n\n#if libBLAS > 0\n  #include \"myblas.h\"\n#endif\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n/* Simplex pricing utility module - w/interface for lp_solve v5.0+\n   -------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      lp_lib.h, commonlib.h\n\n    Release notes:\n    v1.0.0  1 July 2004         Routines extracted from lp_lib.\n    v1.0.1 10 July 2004         Added comparison operators for determination\n                                of entering and leaving variables.\n                                Added routines for multiple and partial\n                                pricing and made corresponding changes to\n                                colprim and rowdual.\n    v1.0.2 20 August 2004       Implemented relative pivot size control in\n                                rowprim and rowdual.\n    v1.1.0 15 October 2004      Added dual long step logic.\n    v1.1.1 22 October 2004      Added bound sort order to variable selections.\n    v1.2.0 24 March 2005        Completed multiple pricing logic.\n   ------------------------------------------------------------------------- */\n\n\n/* Comparison operators for entering and leaving variables for both the primal and\n   dual simplexes.  The functions compare a candidate variable with an incumbent. */\nint CMP_CALLMODEL compareImprovementVar(const pricerec *current, const pricerec *candidate)\n{\n  int   result = COMP_PREFERNONE;\n  lprec *lp = current->lp;\n  REAL  testvalue, margin = PREC_IMPROVEGAP;\n  int currentcolno, currentvarno = current->varno,\n      candidatecolno, candidatevarno = candidate->varno;\n  MYBOOL isdual = candidate->isdual;\n\n  if(isdual) {\n    candidatevarno = lp->var_basic[candidatevarno];\n    currentvarno   = lp->var_basic[currentvarno];\n  }\n  candidatecolno = candidatevarno - lp->rows;\n  currentcolno   = currentvarno - lp->rows;\n\n  /* Do pivot-based selection unless Bland's (first index) rule is active */\n  if(lp->_piv_rule_ != PRICER_FIRSTINDEX) {\n\n    MYBOOL candbetter;\n\n    /* Find the largest value - normalize in case of the dual, since\n       constraint violation is expressed as a negative number. */\n    /* Use absolute test for \"small numbers\", relative otherwise */\n    testvalue = candidate->pivot;\n    if(fabs(testvalue) < LIMIT_ABS_REL)\n      testvalue -= current->pivot;\n    else\n      testvalue = my_reldiff(testvalue, current->pivot);\n    if(isdual)\n      testvalue = -testvalue;\n\n    candbetter = (MYBOOL) (testvalue > 0);\n    if(candbetter) {\n      if(testvalue > margin)\n        result = COMP_PREFERCANDIDATE;\n    }\n#if 0 /* Give more opportunity to optimize on non-primary criteria */\n    else if (testvalue < -margin)\n#else /* Give reduced opportunity to optimize on non-primary criteria */\n    else if (testvalue < -lp->epsvalue)\n#endif\n      result = COMP_PREFERINCUMBENT;\n\n#ifdef UseSortOnBound\n      /* Extra selection criterion based on the variable's range;\n        variable with - DUAL: small bound out; PRIMAL: large bound in */\n    if(result == COMP_PREFERNONE) {\n      testvalue = lp->upbo[candidatevarno] - lp->upbo[currentvarno];\n      if(testvalue < -margin)\n        result = COMP_PREFERINCUMBENT;\n      else if(testvalue > margin)\n        result = COMP_PREFERCANDIDATE;\n      result = my_chsign(isdual, result);\n    }\n#endif\n\n#ifdef UseSortOnColumnLength\n    /* Prevent long columns from entering the basis */\n    if(result == COMP_PREFERNONE) {\n      if(candidatecolno > 0)\n        testvalue = mat_collength(lp->matA, candidatecolno) +\n                    (is_obj_in_basis(lp) && (lp->obj[candidatecolno] != 0) ? 1 : 0);\n      else\n        testvalue = 1;\n      if(currentcolno > 0)\n        testvalue -= mat_collength(lp->matA, currentcolno) +\n                     (is_obj_in_basis(lp) && (lp->obj[currentcolno] != 0) ? 1 : 0);\n      else\n        testvalue -= 1;\n      if(testvalue > 0)\n        result = COMP_PREFERINCUMBENT;\n      else if(testvalue < 0)\n        result = COMP_PREFERCANDIDATE;\n      result = my_chsign(isdual, result);\n    }\n#endif\n\n    /* Select absolute best if the non-primary criteria failed to separate */\n    if((result == COMP_PREFERNONE) && candbetter) {\n      result = COMP_PREFERCANDIDATE;\n      goto Finish;\n    }\n  }\n\n  /* Final tie-breakers */\n  if(result == COMP_PREFERNONE) {\n\n    /* Add randomization tie-braker */\n    if(lp->piv_strategy & PRICE_RANDOMIZE) {\n      result = my_sign(PRICER_RANDFACT - rand_uniform(lp, 1.0));\n      if(candidatevarno < currentvarno)\n        result = -result;\n    }\n\n    /* Resolve ties via index ordinal */\n    if(result == COMP_PREFERNONE) {\n      if(candidatevarno < currentvarno)\n        result = COMP_PREFERCANDIDATE;\n      else /* if(candidatevarno > currentvarno) */\n        result = COMP_PREFERINCUMBENT;\n      if(lp->_piv_left_)\n        result = -result;\n    }\n  }\n\nFinish:\n  return( result );\n\n}\n\nint CMP_CALLMODEL compareSubstitutionVar(const pricerec *current, const pricerec *candidate)\n{\n  int    result = COMP_PREFERNONE;\n  lprec  *lp = current->lp;\n  REAL   testvalue = candidate->theta,\n                  margin = current->theta;\n  MYBOOL isdual = candidate->isdual, candbetter;\n  int    currentcolno, currentvarno = current->varno,\n         candidatecolno, candidatevarno = candidate->varno;\n\n  if(!isdual) {\n    candidatevarno = lp->var_basic[candidatevarno];\n    currentvarno   = lp->var_basic[currentvarno];\n  }\n  candidatecolno = candidatevarno - lp->rows;\n  currentcolno   = currentvarno - lp->rows;\n\n  /* Compute the ranking test metric. */\n  if(isdual) {\n    testvalue = fabs(testvalue);\n    margin    = fabs(margin);\n  }\n\n  /* Use absolute test for \"small numbers\", relative otherwise */\n  if(fabs(testvalue) < LIMIT_ABS_REL)\n    testvalue -= margin;\n  else\n    testvalue = my_reldiff(testvalue, margin);\n\n  /* Find if the new Theta is smaller or near equal (i.e. testvalue <= eps)\n     compared to the previous best; ties will be broken by pivot size or index\n     NB! The margin below is essential in maintaining primal/dual feasibility\n         during the primal/dual simplex, respectively.  Sometimes a small\n         value prevents the selection of a suitable pivot, thereby weakening\n         the numerical stability of some models */\n  margin = PREC_SUBSTFEASGAP;\n  candbetter = (MYBOOL) (testvalue < 0);\n  if(candbetter) {\n    if(testvalue < -margin)\n      result = COMP_PREFERCANDIDATE;\n  }\n  else if(testvalue > margin)\n    result = COMP_PREFERINCUMBENT;\n\n  /* Resolve a tie */\n  if(result == COMP_PREFERNONE) {\n    REAL currentpivot = fabs(current->pivot),\n         candidatepivot = fabs(candidate->pivot);\n\n    /* Handle first index / Bland's rule specially */\n    if(lp->_piv_rule_ == PRICER_FIRSTINDEX) {\n#if 1\n      /* Special secondary selection by pivot size (limited stability protection) */\n      margin = candidate->epspivot;\n      if((candidatepivot >= margin) && (currentpivot < margin))\n        result = COMP_PREFERCANDIDATE;\n#endif\n    }\n\n    else {\n\n      /* General secondary selection based on pivot size */\n#if 0\n      if(candidatepivot > MIN_STABLEPIVOT)\n        testvalue = my_reldiff(testvalue, currentpivot);\n      else\n#endif\n        testvalue = candidatepivot - currentpivot;\n      if(testvalue > margin)\n        result = COMP_PREFERCANDIDATE;\n      else if(testvalue < -margin)\n        result = COMP_PREFERINCUMBENT;\n\n#ifdef UseSortOnBound\n      /* Extra selection criterion based on the variable's range;\n        variable with - PRIMAL: small bound out; DUAL: large bound in */\n      if(result == COMP_PREFERNONE) {\n        testvalue = lp->upbo[candidatevarno] - lp->upbo[currentvarno];\n        if(testvalue < -margin)\n          result = COMP_PREFERCANDIDATE;\n        else if(testvalue > margin)\n          result = COMP_PREFERINCUMBENT;\n        result = my_chsign(isdual, result);\n      }\n#endif\n\n#ifdef UseSortOnColumnLength\n      /* Prevent long columns from entering the basis */\n      if(result == COMP_PREFERNONE) {\n        if(candidatecolno > 0)\n          testvalue = mat_collength(lp->matA, candidatecolno) +\n                      (is_obj_in_basis(lp) && (lp->obj[candidatecolno] != 0) ? 1 : 0);\n        else\n          testvalue = 1;\n        if(currentcolno > 0)\n          testvalue -= mat_collength(lp->matA, currentcolno) +\n                       (is_obj_in_basis(lp) && (lp->obj[currentcolno] != 0) ? 1 : 0);\n        else\n          testvalue -= 1;\n        if(testvalue > 0)\n          result = COMP_PREFERCANDIDATE;\n        else if(testvalue < 0)\n          result = COMP_PREFERINCUMBENT;\n        result = my_chsign(isdual, result);\n      }\n#endif\n\n    }\n  }\n\n  /* Select absolute best if the non-primary criteria failed to separate */\n  if((result == COMP_PREFERNONE) && candbetter) {\n    result = COMP_PREFERCANDIDATE;\n    goto Finish;\n  }\n\n  /* Final tie-breakers */\n  if(result == COMP_PREFERNONE) {\n\n    /* Add randomization tie-braker */\n    if(lp->piv_strategy & PRICE_RANDOMIZE) {\n      result = my_sign(PRICER_RANDFACT - rand_uniform(lp, 1.0));\n      if(candidatevarno < currentvarno)\n        result = -result;\n    }\n\n    /* Resolve ties via index ordinal (also prefers slacks over user variables) */\n    if(result == COMP_PREFERNONE) {\n      if(candidatevarno < currentvarno)\n        result = COMP_PREFERCANDIDATE;\n      else /* if(candidatevarno > currentvarno) */\n        result = COMP_PREFERINCUMBENT;\n      if(lp->_piv_left_)\n        result = -result;\n    }\n  }\n\nFinish:\n  return( result );\n}\nint CMP_CALLMODEL compareBoundFlipVar(const pricerec *current, const pricerec *candidate)\n{\n  REAL  testvalue, margin;\n  int   result = COMP_PREFERNONE;\n  lprec *lp = current->lp;\n  MYBOOL    candbetter;\n  int currentvarno = current->varno,\n      candidatevarno = candidate->varno;\n\n  if(!current->isdual) {\n    candidatevarno = lp->var_basic[candidatevarno];\n    currentvarno   = lp->var_basic[currentvarno];\n  }\n\n  /* Compute the ranking test metric. */\n  testvalue = candidate->theta;\n  margin    = current->theta;\n  if(candidate->isdual) {\n    testvalue = fabs(testvalue);\n    margin    = fabs(margin);\n  }\n  if(fabs(margin) < LIMIT_ABS_REL)\n    testvalue -= margin;\n  else\n    testvalue = my_reldiff(testvalue, margin);\n\n  /* Find if the new Theta is smaller or near equal (i.e. testvalue <= eps)\n     compared to the previous best; ties will be broken by pivot size or index */\n  margin = PREC_SUBSTFEASGAP;\n  candbetter = (MYBOOL) (testvalue < 0);\n  if(candbetter) {\n    if(testvalue < -margin)\n      result = COMP_PREFERCANDIDATE;\n  }\n  else if(testvalue > margin)\n    result = COMP_PREFERINCUMBENT;\n\n  /* Resolve a tie */\n  if(result == COMP_PREFERNONE) {\n\n    /* Tertiary selection based on priority for large pivot sizes */\n    if(result == COMP_PREFERNONE) {\n      REAL currentpivot   = fabs(current->pivot),\n           candidatepivot = fabs(candidate->pivot);\n      if(candidatepivot > currentpivot+margin)\n        result = COMP_PREFERCANDIDATE;\n      else if(candidatepivot < currentpivot-margin)\n        result = COMP_PREFERINCUMBENT;\n    }\n\n    /* Secondary selection based on priority for narrow-bounded variables */\n    if(result == COMP_PREFERNONE)\n      result = compareREAL(&(lp->upbo[currentvarno]),\n                           &(lp->upbo[candidatevarno]));\n\n  }\n\n  /* Select absolute best if the non-primary criteria failed to separate */\n  if((result == COMP_PREFERNONE) && candbetter) {\n    result = COMP_PREFERCANDIDATE;\n    goto Finish;\n  }\n\n  /* Quaternary selection by index value */\n  if(result == COMP_PREFERNONE) {\n    if(candidatevarno < currentvarno)\n      result = COMP_PREFERCANDIDATE;\n    else\n      result = COMP_PREFERINCUMBENT;\n    if(lp->_piv_left_)\n      result = -result;\n  }\n\nFinish:\n  return( result );\n}\n\n/* Validity operators for entering and leaving columns for both the primal and dual\n   simplex.  All candidates must satisfy these tests to qualify to be allowed to be\n   a subject for the comparison functions/operators. */\nSTATIC MYBOOL validImprovementVar(pricerec *candidate)\n{\n  REAL candidatepivot = fabs(candidate->pivot);\n\n#ifdef Paranoia\n  return( (MYBOOL) ((candidate->varno > 0) && (candidatepivot > candidate->lp->epsvalue)) );\n#else\n  return( (MYBOOL) (candidatepivot > candidate->lp->epsvalue) );\n#endif\n}\n\nSTATIC MYBOOL validSubstitutionVar(pricerec *candidate)\n{\n  lprec *lp   = candidate->lp;\n  REAL  theta = (candidate->isdual ? fabs(candidate->theta) : candidate->theta);\n\n#ifdef Paranoia\n  if(candidate->varno <= 0)\n    return( FALSE );\n  else\n#endif\n  if(fabs(candidate->pivot) >= lp->infinite)\n    return( (MYBOOL) (theta < lp->infinite) );\n  else\n    return( (MYBOOL) ((theta < lp->infinite) &&\n                      (fabs(candidate->pivot) >= candidate->epspivot)) );\n}\n\nint CMP_CALLMODEL compareImprovementQS(const UNIONTYPE QSORTrec *current, const UNIONTYPE QSORTrec *candidate)\n{\n  return( compareImprovementVar((pricerec *) current->pvoidint2.ptr, (pricerec *) candidate->pvoidint2.ptr) );\n}\nint CMP_CALLMODEL compareSubstitutionQS(const UNIONTYPE QSORTrec *current, const UNIONTYPE QSORTrec *candidate)\n{\n  return( compareBoundFlipVar((pricerec *) current->pvoidint2.ptr, (pricerec *) candidate->pvoidint2.ptr) );\n/*  return( compareSubstitutionVar((pricerec *) current->self, (pricerec *) candidate->self) ); */\n}\n\n/* Function to add a valid pivot candidate into the specified list */\nSTATIC int addCandidateVar(pricerec *candidate, multirec *multi, findCompare_func findCompare, MYBOOL allowSortedExpand)\n{\n  int     insertpos, delta = 1;\n  pricerec *targetrec;\n\n  /* Find the insertion point (if any) */\n  if((multi->freeList[0] == 0) ||\n     (multi->sorted && allowSortedExpand) ||\n     (candidate->isdual && (multi->used == 1) && ((multi->step_last >= multi->epszero) ||\n                                                  multi_truncatingvar(multi, ((pricerec *) (multi->sortedList[0].pvoidreal.ptr))->varno)))\n     ) {\n    UNIONTYPE QSORTrec searchTarget;\n\n    /* Make sure that the list is sorted before the search for an insertion point */\n    if((multi->freeList[0] == 0) && !multi->sorted) {\n      multi->sorted = QS_execute(multi->sortedList, multi->used, findCompare, &insertpos);\n      multi->dirty  = (MYBOOL) (insertpos > 0);\n    }\n\n    /* Perform the search */\n    searchTarget.pvoidint2.ptr = (void *) candidate;\n    insertpos = sizeof(searchTarget);\n    insertpos = findIndexEx(&searchTarget, multi->sortedList-delta, multi->used, delta, insertpos, findCompare, TRUE);\n    if(insertpos > 0)\n      return( -1 );\n    insertpos = -insertpos - delta;\n\n    /* Check if the candidate is worse than the worst of the list */\n    if(((insertpos >= multi->size) && (multi->freeList[0] == 0)) ||\n       ((insertpos == multi->used) && (!allowSortedExpand ||\n                                       (multi->step_last >= multi->epszero))))\n      return( -1 );\n\n#ifdef Paranoia\n    /* Do validation */\n    if((insertpos < 0) || (insertpos > multi->used))\n      return( -1 );\n#endif\n\n    /* Define the target for storing the candidate;\n       Case 1: List is full and we must discard the previously worst candidate\n       Case 2: List is not full and we simply use the next free position */\n    if(multi->freeList[0] == 0)\n      targetrec = (pricerec *) multi->sortedList[multi->used-1].pvoidreal.ptr;\n    else {\n      delta = multi->freeList[0]--;\n      delta = multi->freeList[delta];\n      targetrec = &(multi->items[delta]);\n    }\n  }\n  else {\n    delta = multi->freeList[0]--;\n    delta = multi->freeList[delta];\n    targetrec = &(multi->items[delta]);\n    insertpos = multi->used;\n  }\n\n  /* Insert the new candidate record in the data store */\n  MEMCOPY(targetrec, candidate, 1);\n\n  /* Store the pointer data and handle tree cases:\n     Case 1: The list is unsorted and not full; simply append pointer to list,\n     Case 2: The list is sorted and full; insert the pointer by discarding previous last,\n     Case 3: The list is sorted and not full; shift the inferior items down, and increment count */\n  if((multi->used < multi->size) && (insertpos >= multi->used)) {\n    QS_append(multi->sortedList, insertpos, targetrec);\n    multi->used++;\n  }\n  else {\n    if(multi->used == multi->size)\n      QS_insert(multi->sortedList, insertpos, targetrec, multi->size-1); /* Discard previous last */\n    else {\n      QS_insert(multi->sortedList, insertpos, targetrec, multi->used);   /* Keep previous last    */\n      multi->used++;\n    }\n  }\n  multi->active = insertpos;\n\n#ifdef Paranoia\n  if((insertpos >= multi->size) || (insertpos >= multi->used))\n    report(multi->lp, SEVERE, \"addCandidateVar: Insertion point beyond limit!\\n\");\n#endif\n\n  return( insertpos );\n}\n\nSTATIC MYBOOL findImprovementVar(pricerec *current, pricerec *candidate, MYBOOL collectMP, int *candidatecount)\n/* PRIMAL: Find a variable to enter the basis\n   DUAL:   Find a variable to leave the basis\n\n   Allowed variable set: Any pivot PRIMAL:larger or DUAL:smaller than threshold value of 0 */\n{\n  MYBOOL Action = FALSE,\n#ifdef ExtractedValidityTest\n         Accept = TRUE;\n#else    /* Check for validity and compare result with previous best */\n         Accept = validImprovementVar(candidate);\n#endif\n  if(Accept) {\n    if(candidatecount != NULL)\n      (*candidatecount)++;\n    if(collectMP) {\n      if(addCandidateVar(candidate, current->lp->multivars, (findCompare_func *) compareImprovementQS, FALSE) < 0)\n        return(Action);\n    }\n    if(current->varno > 0)\n      Accept = (MYBOOL) (compareImprovementVar(current, candidate) > 0);\n  }\n\n /* Apply candidate if accepted */\n  if(Accept) {\n    (*current) = *candidate;\n\n    /* Force immediate acceptance for Bland's rule using the primal simplex */\n    if(!candidate->isdual)\n      Action = (MYBOOL) (candidate->lp->_piv_rule_ == PRICER_FIRSTINDEX);\n  }\n  return(Action);\n}\n\n/* Bound flip variable accumulation routine */\nSTATIC MYBOOL collectMinorVar(pricerec *candidate, multirec *longsteps, MYBOOL isphase2, MYBOOL isbatch)\n{\n  int   inspos;\n\n  /* 1. Check for ratio and pivot validity (to have the extra flexibility that all\n        bound-flip candidates are also possible as basis-entering variables */\n  if(!validSubstitutionVar(candidate))\n    return( FALSE );\n\n  /* 2. If the free-list is empty we need to see if we have a better candidate,\n        and for this the candidate list has to be sorted by merit */\n  if(!isbatch &&\n     !longsteps->sorted && (longsteps->used > 1) &&\n     ((longsteps->freeList[0] == 0) ||\n      multi_truncatingvar(longsteps, candidate->varno) ||\n      (longsteps->step_last >= longsteps->epszero) )) {\n    longsteps->sorted = QS_execute(longsteps->sortedList, longsteps->used,\n                                   (findCompare_func *) compareSubstitutionQS, &inspos);\n    longsteps->dirty  = (MYBOOL) (inspos > 0);\n    if(longsteps->dirty)\n      multi_recompute(longsteps, 0, isphase2, TRUE);\n  }\n\n  /* 3. Now handle three cases...\n        - Add to the list when the list is not full and there is opportunity for improvement,\n        - Check if we should replace an incumbent when the list is full,\n        - Check if we should replace an incumbent when the list is not full, there is no room\n          for improvement, but the current candidate is better than an incumbent. */\n  inspos = addCandidateVar(candidate, longsteps, (findCompare_func *) compareSubstitutionQS, TRUE);\n\n  /* 4. Recompute steps and objective, and (if relevant) determine if we\n        may be suboptimal in relation to an incumbent MILP solution. */\n  return( (MYBOOL) (inspos >= 0) &&\n           ((isbatch == TRUE) || multi_recompute(longsteps, inspos, isphase2, TRUE)) );\n}\n\nSTATIC MYBOOL findSubstitutionVar(pricerec *current, pricerec *candidate, int *candidatecount)\n/* PRIMAL: Find a variable to leave the basis\n   DUAL:   Find a variable to enter the basis\n\n   Allowed variable set: \"Equal-valued\" smallest thetas! */\n{\n  MYBOOL Action = FALSE,\n#ifdef ExtractedValidityTest\n         Accept = TRUE;\n#else  /* Check for validity and comparison result with previous best */\n         Accept = validSubstitutionVar(candidate);\n#endif\n  if(Accept) {\n    if(candidatecount != NULL)\n      (*candidatecount)++;\n    if(current->varno != 0)\n      Accept = (MYBOOL) (compareSubstitutionVar(current, candidate) > 0);\n  }\n\n /* Apply candidate if accepted */\n  if(Accept) {\n    (*current) = *candidate;\n\n    /* Force immediate acceptance for Bland's rule using the dual simplex */\n#ifdef ForceEarlyBlandRule\n    if(candidate->isdual)\n      Action = (MYBOOL) (candidate->lp->_piv_rule_ == PRICER_FIRSTINDEX);\n#endif\n  }\n  return(Action);\n}\n\n/* Partial pricing management routines */\nSTATIC partialrec *partial_createBlocks(lprec *lp, MYBOOL isrow)\n{\n  partialrec *blockdata;\n\n  blockdata = (partialrec *) calloc(1, sizeof(*blockdata));\n  blockdata->lp = lp;\n  blockdata->blockcount = 1;\n  blockdata->blocknow = 1;\n  blockdata->isrow = isrow;\n\n  return(blockdata);\n}\nSTATIC int partial_countBlocks(lprec *lp, MYBOOL isrow)\n{\n  partialrec *blockdata = IF(isrow, lp->rowblocks, lp->colblocks);\n\n  if(blockdata == NULL)\n    return( 1 );\n  else\n    return( blockdata->blockcount );\n}\nSTATIC int partial_activeBlocks(lprec *lp, MYBOOL isrow)\n{\n  partialrec *blockdata = IF(isrow, lp->rowblocks, lp->colblocks);\n\n  if(blockdata == NULL)\n    return( 1 );\n  else\n    return( blockdata->blocknow );\n}\nSTATIC void partial_freeBlocks(partialrec **blockdata)\n{\n  if((blockdata == NULL) || (*blockdata == NULL))\n    return;\n  FREE((*blockdata)->blockend);\n  FREE((*blockdata)->blockpos);\n  FREE(*blockdata);\n}\n\n\n/* Function to provide for left-right or right-left scanning of entering/leaving\n   variables; note that *end must have been initialized by the calling routine! */\nSTATIC void makePriceLoop(lprec *lp, int *start, int *end, int *delta)\n{\n  int offset = is_piv_mode(lp, PRICE_LOOPLEFT);\n\n  if((offset) ||\n     (((lp->total_iter+offset) % 2 == 0) && is_piv_mode(lp, PRICE_LOOPALTERNATE))) {\n    *delta = -1; /* Step backwards - \"left\" */\n    swapINT(start, end);\n    lp->_piv_left_ = TRUE;\n  }\n  else {\n    *delta = 1;  /* Step forwards - \"right\" */\n    lp->_piv_left_ = FALSE;\n  }\n}\n\n/* Routine to verify accuracy of the current basis factorization */\nSTATIC MYBOOL serious_facterror(lprec *lp, REAL *bvector, int maxcols, REAL tolerance)\n{\n  int    i, j, ib, ie, nz, nc;\n  REAL   sum, tsum = 0, err = 0;\n  MATrec *mat = lp->matA;\n\n  if(bvector == 0)\n    bvector = lp->bsolveVal;\n  nc =0;\n  nz = 0;\n  for(i = 1; (i <= lp->rows) && (nc <= maxcols); i++) {\n\n    /* Do we have a non-slack variable? (we choose to skip slacks,\n      since they have \"natural\" good accuracy properties) */\n    j = lp->var_basic[i] - lp->rows;\n    if(j <= 0)\n      continue;\n    nc++;\n\n    /* Compute cross product for basic, non-slack column */\n    ib = mat->col_end[j-1];\n    ie = mat->col_end[j];\n    nz += ie - ib;\n    sum = get_OF_active(lp, j+lp->rows, bvector[0]);\n    for(; ib < ie; ib++)\n      sum += COL_MAT_VALUE(ib)*bvector[COL_MAT_ROWNR(ib)];\n\n    /* Catch high precision early, so we don't to uneccessary work */\n    tsum += sum;\n    SETMAX(err, fabs(sum));\n    if((tsum / nc > tolerance / 100) && (err < tolerance / 100))\n      break;\n  }\n  err /= mat->infnorm;\n  return( (MYBOOL) (err >= tolerance) );\n}\n\n/* Computation of reduced costs */\nSTATIC void update_reducedcosts(lprec *lp, MYBOOL isdual, int leave_nr, int enter_nr, REAL *prow, REAL *drow)\n{\n  /* \"Fast\" update of the dual reduced cost vector; note that it must be called\n     after the pivot operation and only applies to a major \"true\" iteration */\n  int  i;\n  REAL hold;\n\n  if(isdual) {\n    hold = -drow[enter_nr]/prow[enter_nr];\n    for(i=1; i <= lp->sum; i++)\n      if(!lp->is_basic[i]) {\n        if(i == leave_nr)\n          drow[i] = hold;\n        else {\n          drow[i] += hold*prow[i];\n          my_roundzero(drow[i], lp->epsmachine);\n        }\n      }\n  }\n  else\n    report(lp, SEVERE, \"update_reducedcosts: Cannot update primal reduced costs!\\n\");\n}\n\n\nSTATIC void compute_reducedcosts(lprec *lp, MYBOOL isdual, int row_nr, int *coltarget, MYBOOL dosolve,\n                                            REAL *prow, int *nzprow,\n                                            REAL *drow, int *nzdrow,\n                                            int roundmode)\n{\n  REAL epsvalue = lp->epsvalue;  /* Any larger value can produce a suboptimal result */\n  roundmode |=  MAT_ROUNDRC;\n\n  if(isdual) {\n    bsolve_xA2(lp, coltarget,\n                   row_nr, prow, epsvalue, nzprow,  /* Calculate net sensitivity given a leaving variable */\n                        0, drow, epsvalue, nzdrow,  /* Calculate the net objective function values */\n                   roundmode);\n  }\n  else {\n    REAL *bVector;\n\n#if 1 /* Legacy mode, that is possibly a little faster */\n    if((lp->multivars == NULL) && (lp->P1extraDim == 0))\n      bVector = drow;\n    else\n#endif\n      bVector = lp->bsolveVal;\n    if(dosolve) {\n      bsolve(lp, 0, bVector, lp->bsolveIdx, epsvalue*DOUBLEROUND, 1.0);\n      if(!isdual && (row_nr == 0) && (lp->improve & IMPROVE_SOLUTION) && !refactRecent(lp) &&\n         serious_facterror(lp, bVector, lp->rows, lp->epsvalue))\n        set_action(&lp->spx_action, ACTION_REINVERT);\n    }\n    prod_xA(lp,   coltarget,\n                  bVector, lp->bsolveIdx, epsvalue, 1.0,\n                  drow, nzdrow, roundmode);\n  }\n}\n\n\n/* Primal: Prevent acceptance of an entering variable when the magnitude of\n           other candidates is also very small.\n   Dual:   Prevent acceptance of a leaving variable when the magnitude of\n           other candidates is also very small.\n\n   Both of these cases are associated with numerical stalling, which we could\n   argue should be detected and handled by the stalling monitor routine. */\nSTATIC MYBOOL verify_stability(lprec *lp, MYBOOL isprimal, REAL xfeas, REAL sfeas, int nfeas)\n{\n  MYBOOL testOK = TRUE;\n  return( testOK );\n\n#if 1\n  /* Try to make dual feasibility as tight as possible */\n  if(!isprimal)\n/*  if(lp->P1extraVal == 0) */\n  {\n    xfeas /= (1+lp->rhsmax);\n    sfeas /= (1+lp->rhsmax);\n  }\n#endif\n  xfeas = fabs(xfeas);             /* Maximum (positive) infeasibility */\n/*  if(xfeas < lp->epspivot) { */\n  if(xfeas < lp->epssolution) {\n    REAL f;\n    sfeas = fabs(sfeas);           /* Make sum of infeasibilities positive */\n    xfeas = (sfeas-xfeas)/nfeas;   /* Average \"residual\" feasibility */\n    f = 1 + log10((REAL) nfeas);   /* Some numerical complexity scalar */\n    /* Numerical errors can interact to cause non-convergence, and the\n      idea is to relax the tolerance to account for this and only\n      marginally weakening the (user-specified) tolerance. */\n    if((sfeas-xfeas) < f*lp->epsprimal)\n      testOK = FALSE;\n  }\n  return( testOK );\n}\n\n\n/* Find an entering column for the case that the specified basic variable\n   is fixed or zero - typically used for artificial variable elimination */\nSTATIC int find_rowReplacement(lprec *lp, int rownr, REAL *prow, int *nzprow)\n/* The logic in this section generally follows Chvatal: Linear Programming, p. 130\n   Basically, the function is a specialized coldual(). */\n{\n  int  i, bestindex;\n  REAL bestvalue;\n\n /* Solve for \"local reduced cost\" */\n  set_action(&lp->piv_strategy, PRICE_FORCEFULL);\n    compute_reducedcosts(lp, TRUE, rownr, NULL, TRUE,\n                             prow, nzprow, NULL, NULL, MAT_ROUNDDEFAULT);\n  clear_action(&lp->piv_strategy, PRICE_FORCEFULL);\n\n /* Find a suitably non-singular variable to enter (\"most orthogonal\") */\n  bestindex = 0;\n  bestvalue = 0;\n  for(i = 1; i <= lp->sum-abs(lp->P1extraDim); i++) {\n    if(!lp->is_basic[i] && !is_fixedvar(lp, i) &&\n      (fabs(prow[i]) > bestvalue)) {\n      bestindex = i;\n      bestvalue = fabs(prow[i]);\n    }\n  }\n\n  /* Prepare to update inverse and pivot/iterate (compute Bw=a) */\n  if(i > lp->sum-abs(lp->P1extraDim))\n    bestindex = 0;\n  else\n    fsolve(lp, bestindex, prow, nzprow, lp->epsmachine, 1.0, TRUE);\n\n  return( bestindex );\n}\n\n/* Find the primal simplex entering non-basic column variable */\nSTATIC int colprim(lprec *lp, REAL *drow, int *nzdrow, MYBOOL skipupdate, int partialloop, int *candidatecount, MYBOOL updateinfeas, REAL *xviol)\n{\n  int      i, ix, iy, iz, ninfeas, nloop = 0;\n  REAL     f, sinfeas, xinfeas, epsvalue = lp->epsdual;\n  pricerec current, candidate;\n  MYBOOL   collectMP = FALSE;\n  int      *coltarget = NULL;\n\n  /* Identify pivot column according to pricing strategy; set\n     entering variable initial threshold reduced cost value to \"0\" */\n  current.pivot    = lp->epsprimal;    /* Minimum acceptable improvement */\n  current.varno    = 0;\n  current.lp       = lp;\n  current.isdual   = FALSE;\n  candidate.lp     = lp;\n  candidate.isdual = FALSE;\n  *candidatecount  = 0;\n\n  /* Update local value of pivot setting and determine active multiple pricing set */\n  lp->_piv_rule_ = get_piv_rule(lp);\ndoLoop:\n  nloop++;\n  if((lp->multivars != NULL) && ((lp->simplex_mode & SIMPLEX_PRIMAL_PRIMAL) != 0)) {\n    collectMP = multi_mustupdate(lp->multivars);\n    if(collectMP) {\n      multi_restart(lp->multivars);\n      coltarget = NULL;\n    }\n    else\n      coltarget = multi_indexSet(lp->multivars, FALSE);\n  }\n\n  /* Compute reduced costs c - c*Inv(B), if necessary\n     (i.e. the previous iteration was not a \"minor\" iteration/bound flip) */\n  if(!skipupdate) {\n#ifdef UsePrimalReducedCostUpdate\n    /* Recompute from scratch only at the beginning, otherwise update */\n    if((lp->current_iter > 0) && (refactRecent(lp) == AUTOMATIC))\n#endif\n    compute_reducedcosts(lp, FALSE, 0, coltarget, (MYBOOL) ((nloop <= 1) || (partialloop > 1)),\n                             NULL, NULL,\n                             drow, nzdrow,\n                             MAT_ROUNDDEFAULT);\n  }\n\n  /* Loop over active partial column set; we presume that reduced costs\n     have only been updated for columns in the active partial range. */\n  ix = 1;\n  iy = nzdrow[0];\n  ninfeas = 0;\n  xinfeas = 0;\n  sinfeas = 0;\n  makePriceLoop(lp, &ix, &iy, &iz);\n  iy *= iz;\n  for(; ix*iz <= iy; ix += iz) {\n    i = nzdrow[ix];\n#if 0 /* Not necessary since we masked them out in compute_reducedcosts() */\n    if(i > lp->sum-abs(lp->P1extraDim))\n      continue;\n#endif\n\n    /* Check if the pivot candidate is on the block-list */\n    if(lp->rejectpivot[0] > 0) {\n      int kk;\n      for(kk = 1; (kk <= lp->rejectpivot[0]) && (i != lp->rejectpivot[kk]); kk++);\n      if(kk <= lp->rejectpivot[0])\n        continue;\n    }\n\n   /* Retrieve the applicable reduced cost - threshold should not be smaller than 0 */\n    f = my_chsign(lp->is_lower[i], drow[i]);\n    if(f <= epsvalue)\n      continue;\n\n   /* Find entering variable according to strategy (largest positive f) */\n    ninfeas++;\n    SETMAX(xinfeas, f);\n    sinfeas += f;\n    candidate.pivot = normalizeEdge(lp, i, f, FALSE);\n    candidate.varno = i;\n    if(findImprovementVar(&current, &candidate, collectMP, candidatecount))\n      break;\n  }\n\n  /* Check if we should loop again after a multiple pricing update */\n  if(lp->multivars != NULL) {\n    if(collectMP) {\n      if(!lp->multivars->sorted)\n        lp->multivars->sorted = QS_execute(lp->multivars->sortedList, lp->multivars->used,\n                                           (findCompare_func *) compareImprovementQS, NULL);\n      coltarget = multi_indexSet(lp->multivars, TRUE);\n    }\n    else if((current.varno == 0) && (lp->multivars->retries == 0)) {\n      ix = partial_blockStart(lp, FALSE);\n      iy = partial_blockEnd(lp, FALSE);\n      lp->multivars->used = 0;\n      lp->multivars->retries++;\n      goto doLoop;\n    }\n    /* Shrink the candidate list */\n    lp->multivars->retries = 0;\n    if(current.varno != 0)\n      multi_removevar(lp->multivars, current.varno);\n  }\n\n  /* Check for optimality */\n  if(xviol != NULL)\n    *xviol = xinfeas;\n  if(updateinfeas)\n    lp->suminfeas = fabs(sinfeas);\n  if((lp->multivars == NULL) && (current.varno > 0) &&\n     !verify_stability(lp, TRUE, xinfeas, sinfeas, ninfeas))\n    current.varno = 0;\n\n  /* Produce statistics */\n  if(lp->spx_trace) {\n    if(current.varno > 0)\n      report(lp, DETAILED, \"colprim: Column %d reduced cost = \" RESULTVALUEMASK \"\\n\",\n                          current.varno, current.pivot);\n    else\n      report(lp, DETAILED, \"colprim: No positive reduced costs found, optimality!\\n\");\n  }\n\n  return( current.varno );\n} /* colprim */\n\n/* Find the primal simplex leaving basic column variable */\nSTATIC int rowprim(lprec *lp, int colnr, LREAL *theta, REAL *pcol, int *nzpcol, MYBOOL forceoutEQ, REAL *xviol)\n{\n  int      i, ii, iy, iz, Hpass, k, *nzlist;\n  LREAL    f, savef;\n  REAL     Heps, Htheta, Hlimit, epsvalue, epspivot, p = 0.0;\n  pricerec current, candidate;\n  MYBOOL   isupper = !lp->is_lower[colnr], HarrisTwoPass = FALSE;\n\n  /* Update local value of pivot setting */\n  lp->_piv_rule_ = get_piv_rule(lp);\n  if(nzpcol == NULL)\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n    nzlist = (int *) mempool_obtainVector(lp->workarrays, lp->rows+1, sizeof(*nzlist));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n  else\n    nzlist = nzpcol;\n\n  /* Find unconditional non-zeros and optionally compute relative size of epspivot */\n  epspivot = lp->epspivot;\n  epsvalue = lp->epsvalue;\n  Hlimit = 0;\n  Htheta = 0;\n  k = 0;\n  for(i = 1; i <= lp->rows; i++) {\n    p = fabs(pcol[i]);\n    if(p > Hlimit)\n      Hlimit = p;\n    if(p > epsvalue) {\n      k++;\n      nzlist[k] = i;\n      SETMAX(Htheta, p);\n    }\n#ifdef Paranoia\n    else {\n      if(lp->spx_trace)\n        report(lp, FULL, \"rowprim: Row %d with pivot \" RESULTVALUEMASK \" rejected as too small\\n\",\n                         i, p);\n    }\n#endif\n  }\n  if(xviol != NULL)\n    *xviol = Htheta;\n  Htheta = 0;\n\n  /* Update non-zero list based on the new pivot threshold */\n#ifdef UseRelativePivot_Primal\n/*  epspivot *= sqrt(lp->matA->dynrange) / lp->matA->infnorm; */\n  epspivot /= MAX(1, sqrt(lp->matA->colmax[colnr]));\n  iy = k;\n  k = 0;\n  p = 0;\n  for(ii = 1; ii <= iy; ii++) {\n    i = nzlist[ii];\n    p = fabs(pcol[i]);\n\n    /* Compress the list of valid alternatives, if appropriate */\n    if(p > epspivot) {\n      k++;\n      nzlist[k] = i;\n    }\n#ifdef Paranoia\n    else {\n      if(lp->spx_trace)\n        report(lp, FULL, \"rowprim: Row %d with pivot \" RESULTVALUEMASK \" rejected as too small\\n\",\n                         i, p);\n    }\n#endif\n  }\n#endif\n\n  /* Initialize counters */\n  nzlist[0] = k;\n  k = 0;\n\nRetry:\n  k++;\n  HarrisTwoPass = is_piv_mode(lp, PRICE_HARRISTWOPASS);\n  if(HarrisTwoPass)\n    Hpass = 1;\n  else\n    Hpass = 2;\n  current.theta    = lp->infinite;\n  current.pivot    = 0;\n  current.varno    = 0;\n  current.isdual   = FALSE;\n  current.epspivot = epspivot;\n  current.lp       = lp;\n  candidate.epspivot = epspivot;\n  candidate.isdual = FALSE;\n  candidate.lp     = lp;\n  savef  = 0;\n  for(; Hpass <= 2; Hpass++) {\n    Htheta = lp->infinite;\n    if(Hpass == 1) {\n      Hlimit = lp->infinite;           /* Don't apply any limit in the first pass */\n      Heps   = epspivot/lp->epsprimal; /* Scaled to lp->epsprimal used in compute_theta() */\n    }\n    else {\n      Hlimit = current.theta;          /* This is the smallest Theta of the first pass */\n      Heps   = 0.0;\n    }\n    current.theta = lp->infinite;\n    current.pivot = 0;\n    current.varno = 0;\n    savef = 0;\n\n    ii = 1;\n    iy = nzlist[0];\n    makePriceLoop(lp, &ii, &iy, &iz);\n    iy *= iz;\n    for(; ii*iz <= iy; ii += iz) {\n      i = nzlist[ii];\n      f = pcol[i];\n      candidate.theta = f;\n      candidate.pivot = f;\n      candidate.varno = i;\n\n      /*i =*/ compute_theta(lp, i, &candidate.theta, isupper,\n                            my_if(lp->upbo[lp->var_basic[i]] < lp->epsprimal, Heps/10, Heps), TRUE);\n\n      if(fabs(candidate.theta) >= lp->infinite) {\n        savef = f;\n        candidate.theta = 2*lp->infinite;\n        continue;\n      }\n\n      /* Find the candidate leaving variable according to strategy (smallest theta) */\n      if((Hpass == 2) && (candidate.theta > Hlimit))\n        continue;\n\n      /* Give a slight preference to fixed variables (mainly equality slacks) */\n      if(forceoutEQ) {\n        p = candidate.pivot;\n        if(lp->upbo[lp->var_basic[i]] < lp->epsprimal) {\n          /* Give an extra early boost to equality slack elimination, if specified */\n          if(forceoutEQ == AUTOMATIC)\n            candidate.pivot *= 1.0+lp->epspivot;\n          else\n            candidate.pivot *= 10.0;\n\n        }\n      }\n      if(HarrisTwoPass) {\n        f = candidate.theta;\n        if(Hpass == 2)\n          candidate.theta = 1;\n        if(findSubstitutionVar(&current, &candidate, NULL))\n          break;\n        if((Hpass == 2) && (current.varno == candidate.varno))\n          Htheta = f;\n      }\n      else\n        if(findSubstitutionVar(&current, &candidate, NULL))\n          break;\n      /* Restore temporarily modified pivot */\n      if(forceoutEQ && (current.varno == candidate.varno))\n        current.pivot = p;\n    }\n  }\n  if(HarrisTwoPass)\n    current.theta = Htheta;\n\n  /* Handle case of no available leaving variable */\n  if(current.varno == 0) {\n    if(lp->upbo[colnr] >= lp->infinite) {\n      /* Optionally try again with reduced pivot threshold level */\n      if(k < 2) {\n        epspivot = epspivot / 10;\n        goto Retry;\n      }\n    }\n    else {\n#if 1\n      i = 1;\n      while((pcol[i] >= 0) && (i <= lp->rows))\n        i++;\n      if(i > lp->rows) { /* Empty column with upper bound! */\n        lp->is_lower[colnr] = !lp->is_lower[colnr];\n/*        lp->is_lower[colnr] = FALSE; */\n        lp->rhs[0] += lp->upbo[colnr]*pcol[0];\n      }\n      else /* if(pcol[i]<0) */\n      {\n        current.varno = i;\n      }\n#endif\n    }\n  }\n  else if(current.theta >= lp->infinite) {\n    report(lp, IMPORTANT, \"rowprim: Numeric instability pcol[%d] = %g, rhs[%d] = %g, upbo = %g\\n\",\n                          current.varno, savef, current.varno, lp->rhs[current.varno],\n                          lp->upbo[lp->var_basic[current.varno]]);\n  }\n\n /* Return working array to pool */\n  if(nzpcol == NULL)\n    mempool_releaseVector(lp->workarrays, (char *) nzlist, FALSE);\n\n  if(lp->spx_trace)\n    report(lp, DETAILED, \"row_prim: %d, pivot size = \" RESULTVALUEMASK \"\\n\",\n                         current.varno, current.pivot);\n\n/*  *theta = current.theta; */\n  *theta = fabs(current.theta);\n\n  return(current.varno);\n} /* rowprim */\n\n\n/* Find the dual simplex leaving basic variable */\nSTATIC int rowdual(lprec *lp, REAL *rhvec, MYBOOL forceoutEQ, MYBOOL updateinfeas, REAL *xviol)\n{\n  int       k, i, iy, iz, ii, ninfeas;\n  REAL     rh;\n  REAL      up, lo = 0,\n            epsvalue, sinfeas, xinfeas;\n  pricerec  current, candidate;\n  MYBOOL    collectMP = FALSE;\n\n  /* Initialize */\n  if(rhvec == NULL)\n    rhvec = lp->rhs;\n  epsvalue = lp->epsdual;\n  current.pivot    = -epsvalue;  /* Initialize leaving variable threshold; \"less than 0\" */\n  current.theta    = 0;\n  current.varno    = 0;\n  current.isdual   = TRUE;\n  current.lp       = lp;\n  candidate.isdual = TRUE;\n  candidate.lp     = lp;\n\n  /* Loop over active partial row set */\n  if(is_action(lp->piv_strategy, PRICE_FORCEFULL)) {\n    k  = 1;\n    iy = lp->rows;\n  }\n  else {\n    k = partial_blockStart(lp, TRUE);\n    iy = partial_blockEnd(lp, TRUE);\n  }\n  ninfeas = 0;\n  xinfeas = 0;\n  sinfeas = 0;\n  makePriceLoop(lp, &k, &iy, &iz);\n  iy *= iz;\n  for(; k*iz <= iy; k += iz) {\n\n    /* Map loop variable to target */\n    i = k;\n\n    /* Check if the pivot candidate is on the block-list */\n    if(lp->rejectpivot[0] > 0) {\n      int kk;\n      for(kk = 1; (kk <= lp->rejectpivot[0]) && (i != lp->rejectpivot[kk]); kk++);\n      if(kk <= lp->rejectpivot[0])\n        continue;\n    }\n\n    /* Set local variables - express violation as a negative number */\n    ii = lp->var_basic[i];\n    up = lp->upbo[ii];\n    lo = 0;\n    rh = rhvec[i];\n    if(rh > up)\n      rh = up - rh;\n    else\n      rh -= lo;\n    up -= lo;\n\n   /* Analyze relevant constraints ...\n      KE version skips uninteresting alternatives and gives a noticeable speedup */\n/*    if((rh < -epsvalue*sqrt(lp->matA->rowmax[i])) || */\n    if((rh < -epsvalue) ||\n       ((forceoutEQ == TRUE) && (up < epsvalue))) {  /* It causes instability to remove the \"TRUE\" test */\n\n     /* Accumulate stats */\n      ninfeas++;\n      SETMIN(xinfeas, rh);\n      sinfeas += rh;\n\n     /* Give a slight preference to fixed variables (mainly equality slacks) */\n      if(up < epsvalue) {\n        /* Break out immediately if we are directed to force slacks out of the basis */\n        if(forceoutEQ == TRUE) {\n          current.varno = i;\n          current.pivot = -1;\n          break;\n        }\n        /* Give an extra early boost to equality slack elimination, if specified */\n        if(forceoutEQ == AUTOMATIC)\n          rh *= 10.0;\n        else /* .. or just the normal. marginal boost */\n          rh *= 1.0+lp->epspivot;\n      }\n\n     /* Select leaving variable according to strategy (the most negative/largest violation) */\n      candidate.pivot = normalizeEdge(lp, i, rh, TRUE);\n      candidate.varno = i;\n      if(findImprovementVar(&current, &candidate, collectMP, NULL))\n        break;\n    }\n  }\n\n  /* Verify infeasibility */\n  if(updateinfeas)\n    lp->suminfeas = fabs(sinfeas);\n  if((ninfeas > 1) &&\n     !verify_stability(lp, FALSE, xinfeas, sinfeas, ninfeas)) {\n    report(lp, IMPORTANT, \"rowdual: Check for reduced accuracy and tolerance settings.\\n\");\n    current.varno = 0;\n  }\n\n  /* Produce statistics */\n  if(lp->spx_trace) {\n    report(lp, NORMAL, \"rowdual: Infeasibility sum \" RESULTVALUEMASK \" in %7d constraints.\\n\",\n                        sinfeas, ninfeas);\n    if(current.varno > 0) {\n      report(lp, DETAILED, \"rowdual: rhs[%d] = \" RESULTVALUEMASK \"\\n\",\n                           current.varno, lp->rhs[current.varno]);\n    }\n    else\n      report(lp, FULL, \"rowdual: Optimality - No primal infeasibilities found\\n\");\n  }\n  if(xviol != NULL)\n    *xviol = fabs(xinfeas);\n\n  return(current.varno);\n} /* rowdual */\n\n\nSTATIC void longdual_testset(lprec *lp, int which, int rownr, REAL *prow, int *nzprow,\n                                                    REAL *drow, int *nzdrow)\n{\n  (void)nzdrow;\n  int i,j;\n  REAL F = lp->infinite;\n  (void)nzdrow;\n\n  if(which == 0) {             /* Maros Example-1 - raw data */\n    j =  1; i = lp->rows+j; lp->upbo[i] = 0;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] =  2; drow[i] = -1;\n    j =  2; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -2; drow[i] =  2;\n    j =  3; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] =  1; drow[i] =  5;\n    j =  4; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] =  3; drow[i] = -6;\n    j =  5; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] = -4; drow[i] = -2;\n    j =  6; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -1; drow[i] =  0;\n    j =  7; i = lp->rows+j; lp->upbo[i] = 2;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] =  1; drow[i] =  0;\n    j =  8; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] = -2; drow[i] =  0;\n    j =  9; i = lp->rows+j; lp->upbo[i] = 5;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -1; drow[i] =  4;\n    j = 10; i = lp->rows+j; lp->upbo[i] = F;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -2; drow[i] = 10;\n    nzprow[0] = i-lp->rows;\n    lp->rhs[rownr] = -11;\n    lp->upbo[lp->var_basic[rownr]] = F;\n    lp->rhs[0] = 1;\n  }\n  else if(which == 1) {       /* Maros Example-1 - presorted in correct order */\n    j =  1; i = lp->rows+j; lp->upbo[i] = 0;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] =  2; drow[i] = -1;\n    j =  2; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] =  1; drow[i] =  5;\n    j =  3; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] = -4; drow[i] = -2;\n    j =  4; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] = -2; drow[i] =  0;\n\n    j =  5; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -1; drow[i] =  0;\n    j =  6; i = lp->rows+j; lp->upbo[i] = 2;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] =  1; drow[i] =  0;\n    j =  7; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -2; drow[i] =  2;\n    j =  8; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] =  3; drow[i] = -6;\n    j =  9; i = lp->rows+j; lp->upbo[i] = 5;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -1; drow[i] =  4;\n    j = 10; i = lp->rows+j; lp->upbo[i] = F;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -2; drow[i] = 10;\n    nzprow[0] = i-lp->rows;\n    lp->rhs[rownr] = -11;\n    lp->upbo[lp->var_basic[rownr]] = F;\n    lp->rhs[0] = 1;\n  }\n\n  else if(which == 10) {       /* Maros Example-2 - raw data */\n    j =  1; i = lp->rows+j; lp->upbo[i] = 5;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] = -2; drow[i] =  2;\n    j =  2; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] =  3; drow[i] =  3;\n    j =  3; i = lp->rows+j; lp->upbo[i] = 1;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] = -2; drow[i] =  0;\n    j =  4; i = lp->rows+j; lp->upbo[i] = 2;  lp->is_lower[i] = FALSE; nzprow[j] = i; prow[i] = -1; drow[i] = -2;\n    j =  5; i = lp->rows+j; lp->upbo[i] = 2;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] =  1; drow[i] =  0;\n    j =  6; i = lp->rows+j; lp->upbo[i] = F;  lp->is_lower[i] =  TRUE; nzprow[j] = i; prow[i] =  3; drow[i] =  9;\n    nzprow[0] = i-lp->rows;\n    lp->rhs[rownr] = 14;\n    lp->upbo[lp->var_basic[rownr]] = 2;\n    lp->rhs[0] = 6;\n  }\n}\n\n\n/* Find the dual simplex entering non-basic variable */\nSTATIC int coldual(lprec *lp, int row_nr, REAL *prow, int *nzprow,\n                                          REAL *drow, int *nzdrow,\n                                          MYBOOL dualphase1, MYBOOL skipupdate,\n                                          int *candidatecount, REAL *xviol)\n{\n  int      i, iy, iz, ix, k, nbound;\n  LREAL    w, g, quot;\n  REAL     viol, p, epspivot = lp->epspivot;\n#ifdef MachinePrecRoundRHS\n  REAL     epsvalue = lp->epsmachine;\n#else\n  REAL     epsvalue = lp->epsvalue;\n#endif\n  pricerec current, candidate;\n  MYBOOL   isbatch = FALSE, /* Requires that lp->longsteps->size > lp->sum */\n           dolongsteps = (MYBOOL) (lp->longsteps != NULL);\n\n  /* Initialize */\n  if(xviol != NULL)\n    *xviol = lp->infinite;\n  if(dolongsteps && !dualphase1)\n    dolongsteps = AUTOMATIC;  /* Sets Phase1 = TRUE, Phase2 = AUTOMATIC */\n  current.theta    = lp->infinite;\n  current.pivot    = 0;\n  current.varno    = 0;\n  current.epspivot = epspivot;\n  current.isdual   = TRUE;\n  current.lp       = lp;\n  candidate.epspivot = epspivot;\n  candidate.isdual = TRUE;\n  candidate.lp     = lp;\n  *candidatecount  = 0;\n\n  /* Compute reduced costs */\n  if(!skipupdate) {\n#ifdef UseDualReducedCostUpdate\n    /* Recompute from scratch only at the beginning, otherwise update */\n    if((lp->current_iter > 0) && (refactRecent(lp) < AUTOMATIC))\n      compute_reducedcosts(lp, TRUE, row_nr, NULL, TRUE,\n                               prow, nzprow,\n                               NULL, NULL,\n                               MAT_ROUNDDEFAULT);\n    else\n#endif\n      compute_reducedcosts(lp, TRUE, row_nr, NULL, TRUE,\n                               prow, nzprow,\n                               drow, nzdrow,\n                               MAT_ROUNDDEFAULT);\n  }\n\n#if 0\n  /* Override all above to do in-line testing with fixed test set */\n  if(lp->rows > 1 && lp->columns > 10)\n    longdual_testset(lp, 10, row_nr, prow, nzprow, drow, nzdrow);\n#endif\n\n  /* Compute the current violation of the bounds of the outgoing variable,\n     negative for violation of lower bound, positive for upper bound violation.\n     (Basic variables are always lower-bounded, by lp_solve convention) */\n  g = 1;\n  viol = lp->rhs[row_nr];\n  if(viol > 0) {   /* Check if the leaving variable is >= its upper bound */\n    p = lp->upbo[lp->var_basic[row_nr]];\n    if(p < lp->infinite) {\n      viol -= p;\n      my_roundzero(viol, epsvalue);\n      if(viol > 0)\n        g = -1;\n    }\n    /* Do validation of numerics */\n    if(g == 1) {\n      if(viol >= lp->infinite) {\n        report(lp, IMPORTANT, \"coldual: Large basic solution value %g at iter %.0f indicates numerical instability\\n\",\n                               lp->rhs[row_nr], (double) get_total_iter(lp));\n        lp->spx_status = NUMFAILURE;\n        return( 0 );\n\n      }\n      if(skipupdate)\n        report(lp, DETAILED, \"coldual: Inaccurate bound-flip accuracy at iter %.0f\\n\",\n                              (double) get_total_iter(lp));\n      else\n        report(lp, SEVERE,   \"coldual: Leaving variable %d does not violate bounds at iter %.0f\\n\",\n                              row_nr, (double) get_total_iter(lp));\n      return( -1 );\n    }\n  }\n\n  /* Update local value of pivot setting */\n  lp->_piv_rule_ = get_piv_rule(lp);\n\n  /* Condense list of relevant targets */\n  p = 0;\n  k = 0;\n  nbound = 0;\n  ix = 1;\n  iy = nzprow[0];\n  for(ix = 1; ix <= iy; ix++) {\n    i = nzprow[ix];\n    w = prow[i] * g;            /* Change sign if upper bound of the leaving variable is violated   */\n    /* Change sign if the non-basic variable is currently upper-bounded */\n    /* w *= 2*lp->is_lower[i] - 1; */ /* fails on AIX!!! */\n    w = my_chsign(!lp->is_lower[i], w);\n\n    /* Check if the candidate is worth using for anything */\n    if(w < -epsvalue) {\n      /* Tally bounded variables */\n      if(lp->upbo[i] < lp->infinite)\n        nbound++;\n\n      /* Update the nz-index */\n      k++;\n      nzprow[k] = i;\n      SETMAX(p, -w);\n    }\n#ifdef Paranoia\n    else {\n      if(lp->spx_trace) {\n        report(lp, FULL, \"coldual: Candidate variable prow[%d] rejected with %g too small\\n\",\n                         i, w);\n      }\n    }\n#endif\n\n  }\n  nzprow[0] = k;\n  if(xviol != NULL)\n    *xviol = p;\n\n#ifdef UseRelativePivot_Dual\n/*  epspivot *= sqrt(lp->matA->dynrange) / lp->matA->infnorm; */\n  epspivot /= MAX(1, sqrt(lp->matA->rowmax[row_nr]));\n#endif\n  current.epspivot   = epspivot;\n  candidate.epspivot = epspivot;\n\n  /* Initialize the long-step structures if indicated */\n  if(dolongsteps) {\n    if((nzprow[0] <= 1) || (nbound == 0)) {  /* Don't bother */\n      dolongsteps = FALSE;\n      lp->longsteps->indexSet[0] = 0;\n    }\n    else {\n      multi_restart(lp->longsteps);\n      multi_valueInit(lp->longsteps, g*viol, lp->rhs[0]);\n    }\n  }\n\n  /* Loop over all entering column candidates */\n  ix = 1;\n  iy = nzprow[0];\n  makePriceLoop(lp, &ix, &iy, &iz);\n  iy *= iz;\n  for(; ix*iz <= iy; ix += iz) {\n    i = nzprow[ix];\n\n    /* Compute the dual ratio (prow = w and drow = cbar in Chvatal's \"nomenclatura\") */\n    w    = prow[i] * g;         /* Change sign if upper bound of the leaving variable is violated   */\n    quot = -drow[i] / w;        /* Remember this sign-reversal in multi_recompute!                  */\n\n    /* Apply the selected pivot strategy (smallest theta) */\n    candidate.theta = quot;  /* Note that abs() is applied in findSubstitutionVar */\n    candidate.pivot = w;\n    candidate.varno = i;\n\n    /* Collect candidates for minor iterations/bound flips */\n    if(dolongsteps) {\n      if(isbatch && (ix == iy))\n        isbatch = AUTOMATIC;\n      if(collectMinorVar(&candidate, lp->longsteps, (MYBOOL) (dolongsteps == AUTOMATIC), isbatch) &&\n         lp->spx_trace)\n        report(lp, DETAILED, \"coldual: Long-dual break point with %d bound-flip variables\\n\",\n                             lp->longsteps->used);\n      if(lp->spx_status == FATHOMED)\n        return( 0 );\n    }\n\n    /* We have a candidate for entering the basis; check if it is better than the incumbent */\n    else if(findSubstitutionVar(&current, &candidate, candidatecount))\n      break;\n  }\n\n  /* Set entering variable and long-step bound swap variables */\n  if(dolongsteps) {\n    *candidatecount = lp->longsteps->used;\n    i = multi_enteringvar(lp->longsteps, NULL, 3);\n  }\n  else\n    i = current.varno;\n\n  if(lp->spx_trace)\n    report(lp, NORMAL, \"coldual: Entering column %d, reduced cost %g, pivot value %g, bound swaps %d\\n\",\n                       i, drow[i], prow[i], multi_used(lp->longsteps));\n\n  return( i );\n} /* coldual */\n\n\nINLINE REAL normalizeEdge(lprec *lp, int item, REAL edge, MYBOOL isdual)\n{\n#if 1\n  /* Don't use the pricer \"close to home\", since this can possibly\n    worsen the final feasibility picture (mainly a Devex issue?) */\n  if(fabs(edge) > lp->epssolution)\n#endif\n    edge /= getPricer(lp, item, isdual);\n  if((lp->piv_strategy & PRICE_RANDOMIZE) != 0)\n    edge *= (1.0-PRICER_RANDFACT) + PRICER_RANDFACT*rand_uniform(lp, 1.0);\n  return( edge );\n\n}\n\n/* Support routines for block detection and partial pricing */\nSTATIC int partial_findBlocks(lprec *lp, MYBOOL autodefine, MYBOOL isrow)\n{\n  int    i, jj, n, nb, ne, items;\n  REAL   hold, biggest, *sum = NULL;\n  MATrec *mat = lp->matA;\n  partialrec *blockdata;\n\n  if(!mat_validate(mat))\n    return( 1 );\n\n  blockdata = IF(isrow, lp->rowblocks, lp->colblocks);\n  items     = IF(isrow, lp->rows, lp->columns);\n  allocREAL(lp, &sum, items+1, FALSE);\n\n  /* Loop over items and compute the average column index for each */\n  sum[0] = 0;\n  for(i = 1; i <= items; i++) {\n    n = 0;\n    if(isrow) {\n      nb = mat->row_end[i-1];\n      ne = mat->row_end[i];\n    }\n    else {\n      nb = mat->col_end[i-1];\n      ne = mat->col_end[i];\n    }\n    n = ne-nb;\n    sum[i] = 0;\n    if(n > 0) {\n      if(isrow)\n        for(jj = nb; jj < ne; jj++)\n          sum[i] += ROW_MAT_COLNR(jj);\n      else\n        for(jj = nb; jj < ne; jj++)\n          sum[i] += COL_MAT_ROWNR(jj);\n      sum[i] /= n;\n    }\n    else\n      sum[i] = sum[i-1];\n  }\n\n  /* Loop over items again, find largest difference and make monotone */\n  hold = 0;\n  biggest = 0;\n  for(i = 2; i <= items; i++) {\n    hold = sum[i] - sum[i-1];\n    if(hold > 0) {\n      if(hold > biggest)\n        biggest = hold;\n    }\n    else\n      hold = 0;\n    sum[i-1] = hold;\n  }\n\n  /* Loop over items again and find differences exceeding threshold;\n     the discriminatory power of this routine depends strongly on the\n     magnitude of the scaling factor - from empirical evidence > 0.9 */\n  biggest = MAX(1, 0.9*biggest);\n  n = 0;\n  nb = 0;\n  ne = 0;\n  for(i = 1; i < items; i++)\n    if(sum[i] > biggest) {\n      ne += i-nb;        /* Compute sum of index gaps between maxima */\n      nb = i;\n      n++;               /* Increment count */\n    }\n\n  /* Clean up */\n  FREE(sum);\n\n  /* Require that the maxima are spread \"nicely\" across the columns,\n     otherwise return that there is only one monolithic block.\n     (This is probably an area for improvement in the logic!) */\n  if(n > 0) {\n    ne /= n;                 /* Average index gap between maxima */\n    i = IF(isrow, lp->columns, lp->rows);\n    nb = i / ne;             /* Another estimated block count */\n    if(abs(nb - n) > 2)      /* Probably Ok to require equality (nb==n)*/\n      n = 1;\n    else if(autodefine)      /* Generate row/column break-indeces for partial pricing */\n      set_partialprice(lp, nb, NULL, isrow);\n  }\n  else\n    n = 1;\n\n  return( n );\n}\nSTATIC int partial_blockStart(lprec *lp, MYBOOL isrow)\n{\n  partialrec *blockdata;\n\n  blockdata = IF(isrow, lp->rowblocks, lp->colblocks);\n  if(blockdata == NULL)\n    return( 1 );\n  else {\n    if((blockdata->blocknow < 1) || (blockdata->blocknow > blockdata->blockcount))\n      blockdata->blocknow = 1;\n    return( blockdata->blockend[blockdata->blocknow-1] );\n  }\n}\nSTATIC int partial_blockEnd(lprec *lp, MYBOOL isrow)\n{\n  partialrec *blockdata;\n\n  blockdata = IF(isrow, lp->rowblocks, lp->colblocks);\n  if(blockdata == NULL)\n    return( IF(isrow, lp->rows, lp->sum) );\n  else {\n    if((blockdata->blocknow < 1) || (blockdata->blocknow > blockdata->blockcount))\n      blockdata->blocknow = 1;\n    return( blockdata->blockend[blockdata->blocknow]-1 );\n  }\n}\nSTATIC int partial_blockNextPos(lprec *lp, int block, MYBOOL isrow)\n{\n  partialrec *blockdata;\n\n  blockdata = IF(isrow, lp->rowblocks, lp->colblocks);\n#ifdef Paranoia\n  if((blockdata == NULL) || (block <= 1) || (block > blockdata->blockcount)) {\n    report(lp, SEVERE, \"partial_blockNextPos: Invalid block %d specified.\\n\",\n                       block);\n    return( -1 );\n  }\n#endif\n  block--;\n  if(blockdata->blockpos[block] == blockdata->blockend[block+1])\n    blockdata->blockpos[block] = blockdata->blockend[block];\n  else\n    blockdata->blockpos[block]++;\n  return( blockdata->blockpos[block] );\n}\nSTATIC MYBOOL partial_blockStep(lprec *lp, MYBOOL isrow)\n{\n  partialrec *blockdata;\n\n  blockdata = IF(isrow, lp->rowblocks, lp->colblocks);\n  if(blockdata == NULL)\n    return( FALSE );\n  else if(blockdata->blocknow < blockdata->blockcount) {\n    blockdata->blocknow++;\n    return( TRUE);\n  }\n  else {\n    blockdata->blocknow = 1;\n    return( TRUE );\n  }\n}\nSTATIC MYBOOL partial_isVarActive(lprec *lp, int varno, MYBOOL isrow)\n{\n  partialrec *blockdata;\n\n  blockdata = IF(isrow, lp->rowblocks, lp->colblocks);\n  if(blockdata == NULL)\n    return( TRUE );\n  else {\n    return( (MYBOOL) ((varno >= blockdata->blockend[blockdata->blocknow-1]) &&\n                      (varno < blockdata->blockend[blockdata->blocknow])) );\n  }\n}\n\n\n/* Multiple pricing routines */\nSTATIC multirec *multi_create(lprec *lp, MYBOOL truncinf)\n{\n  multirec *multi;\n\n  multi = (multirec *) calloc(1, sizeof(*multi));\n  if(multi != NULL) {\n    multi->active = 1;\n    multi->lp = lp;\n    multi->epszero = lp->epsprimal;\n    multi->truncinf = truncinf;\n  }\n\n  return(multi);\n}\nSTATIC void multi_free(multirec **multi)\n{\n  if((multi == NULL) || (*multi == NULL))\n    return;\n  FREE((*multi)->items);\n  FREE((*multi)->valueList);\n  FREE((*multi)->indexSet);\n  FREE((*multi)->freeList);\n  FREE((*multi)->sortedList);\n  FREE(*multi);\n}\nSTATIC MYBOOL multi_mustupdate(multirec *multi)\n{\n  return( (MYBOOL) ((multi != NULL) &&\n                     (multi->used < multi->limit)) );\n}\nSTATIC MYBOOL multi_resize(multirec *multi, int blocksize, int blockdiv, MYBOOL doVlist, MYBOOL doIset)\n{\n  MYBOOL ok = TRUE;\n\n  if((blocksize > 1) && (blockdiv > 0)) {\n    int oldsize = multi->size;\n\n    multi->size = blocksize;\n    if(blockdiv > 1)\n      multi->limit += (multi->size-oldsize) / blockdiv;\n\n    multi->items = (pricerec *) realloc(multi->items, (multi->size+1)*sizeof(*(multi->items)));\n    multi->sortedList = (UNIONTYPE QSORTrec *) realloc(multi->sortedList, (multi->size+1)*sizeof(*(multi->sortedList)));\n    ok = (multi->items != NULL) && (multi->sortedList != NULL) &&\n         allocINT(multi->lp, &(multi->freeList), multi->size+1, AUTOMATIC);\n    if(ok) {\n      int i, n;\n\n      if(oldsize == 0)\n        i = 0;\n      else\n        i = multi->freeList[0];\n      multi->freeList[0] = i + (multi->size-oldsize);\n      for(n = multi->size - 1, i++; i <= multi->freeList[0]; i++, n--)\n        multi->freeList[i] = n;\n    }\n    if(doVlist)\n      ok &= allocREAL(multi->lp, &(multi->valueList), multi->size+1, AUTOMATIC);\n    if(doIset) {\n      ok &= allocINT(multi->lp, &(multi->indexSet), multi->size+1, AUTOMATIC);\n      if(ok && (oldsize == 0))\n        multi->indexSet[0] = 0;\n    }\n    if(!ok)\n      goto Undo;\n\n  }\n  else {\nUndo:\n    multi->size = 0;\n    FREE(multi->items);\n    FREE(multi->valueList);\n    FREE(multi->indexSet);\n    FREE(multi->freeList);\n    FREE(multi->sortedList);\n  }\n  multi->active = 1;\n\n  return( ok );\n}\n\nSTATIC int multi_size(multirec *multi)\n{\n  if(multi == NULL)\n    return( 0 );\n  else\n    return( multi->size );\n}\n\nSTATIC int multi_used(multirec *multi)\n{\n  if(multi == NULL)\n    return( 0 );\n  else\n    return( multi->used );\n}\n\nSTATIC int multi_restart(multirec *multi)\n{\n  int i, n = multi->used;\n\n  multi->used   = 0;\n  multi->sorted = FALSE;\n  multi->dirty  = FALSE;\n  if(multi->freeList != NULL) {\n    for(i = 1; i <= multi->size; i++)\n      multi->freeList[i] = multi->size - i;\n    multi->freeList[0] = multi->size;\n  }\n#if 0\n  if(multi->indexSet != NULL)\n    multi->indexSet[0] = 0;\n#endif\n  return( n );\n}\n\nSTATIC void multi_valueInit(multirec *multi, REAL step_base, REAL obj_base)\n{\n  multi->step_base = multi->step_last = step_base;\n  multi->obj_base  = multi->obj_last  = obj_base;\n#ifdef Paranoia\n  if(step_base > 0)\n    report(multi->lp, SEVERE, \"multi_valueInit: Positive constraint violation %g provided at iteration %6.0f\\n\",\n                              step_base, (double) get_total_iter(multi->lp));\n#endif\n}\n\nSTATIC REAL *multi_valueList(multirec *multi)\n{\n  return(multi->valueList);\n}\n\nSTATIC int *multi_indexSet(multirec *multi, MYBOOL regenerate)\n{\n  if(regenerate)\n    multi_populateSet(multi, NULL, -1);\n  return(multi->indexSet);\n}\n\nSTATIC int multi_getvar(multirec *multi, int item)\n{\n#ifdef Paranoia\n  if((item < 1) || (item >= multi->size))\n    return(-1);\n#endif\n  return( ((pricerec *) &(multi->sortedList[item].pvoidreal.ptr))->varno );\n}\n\nSTATIC MYBOOL multi_recompute(multirec *multi, int index, MYBOOL isphase2, MYBOOL fullupdate)\n{\n  int      i, n;\n  REAL     lB, uB, Alpha, this_theta, prev_theta;\n  lprec    *lp = multi->lp;\n  pricerec *thisprice;\n\n  /* Define target update window */\n  if(multi->dirty) {\n    index = 0;\n    n = multi->used - 1;\n  }\n  else if(fullupdate)\n    n = multi->used - 1;\n  else\n    n = index;\n\n  /* Initialize accumulators from the specified update index */\n  if(index == 0) {\n    multi->maxpivot = 0;\n    multi->maxbound = 0;\n    multi->step_last = multi->step_base;\n    multi->obj_last  = multi->obj_base;\n    thisprice  = NULL;\n    this_theta  = 0;\n  }\n  else {\n    multi->obj_last  = multi->valueList[index-1];\n    multi->step_last = multi->sortedList[index-1].pvoidreal.realval;\n    thisprice  = (pricerec *) (multi->sortedList[index-1].pvoidreal.ptr);\n    this_theta = thisprice->theta;\n  }\n\n  /* Update step lengths and objective values */\n  while((index <= n) && (multi->step_last < multi->epszero)) {\n\n    /* Update parameters for this loop */\n    prev_theta = this_theta;\n    thisprice  = (pricerec *) (multi->sortedList[index].pvoidreal.ptr);\n    this_theta = thisprice->theta;\n    Alpha = fabs(thisprice->pivot);\n    uB = lp->upbo[thisprice->varno];\n    lB = 0;\n    SETMAX(multi->maxpivot, Alpha);\n    SETMAX(multi->maxbound, uB);\n\n    /* Do the value updates */\n    if(isphase2) {\n      multi->obj_last += (this_theta - prev_theta) * multi->step_last; /* Sign-readjusted from coldual()/Maros */\n      if(uB >= lp->infinite)\n        multi->step_last  = lp->infinite;\n      else\n        multi->step_last += Alpha*(uB-lB);\n    }\n    else {\n      multi->obj_last += (this_theta - prev_theta) * multi->step_last; /* Sign-readjusted from coldual()/Maros */\n      multi->step_last += Alpha;\n    }\n\n    /* Store updated values at the indexed locations */\n    multi->sortedList[index].pvoidreal.realval = multi->step_last;\n    multi->valueList[index] = multi->obj_last;\n#ifdef Paranoia\n    if(lp->spx_trace &&\n       (multi->step_last > lp->infinite))\n      report(lp, SEVERE, \"multi_recompute: A very large step-size %g was generated at iteration %6.0f\\n\",\n                         multi->step_last, (double) get_total_iter(lp));\n#endif\n    index++;\n  }\n\n  /* Discard candidates entered earlier that now make the OF worsen, and\n     make sure that the released positions are added to the free list. */\n  n = index;\n  while(n < multi->used) {\n    i = ++multi->freeList[0];\n    multi->freeList[i] = (int) (((pricerec *) multi->sortedList[n].pvoidreal.ptr) - multi->items);\n    n++;\n  }\n  multi->used  = index;\n  if(multi->sorted && (index == 1))\n    multi->sorted = FALSE;\n  multi->dirty = FALSE;\n\n  /* Return TRUE if the step is now positive */\n  return( (MYBOOL) (multi->step_last >= multi->epszero) );\n}\n\nSTATIC MYBOOL multi_truncatingvar(multirec *multi, int varnr)\n{\n  return( multi->truncinf && is_infinite(multi->lp, multi->lp->upbo[varnr]) );\n}\n\nSTATIC MYBOOL multi_removevar(multirec *multi, int varnr)\n{\n  int i = 1;\n  int *coltarget = multi->indexSet;\n\n  if(coltarget == NULL)\n    return( FALSE );\n\n  while((i <= multi->used) && (coltarget[i] != varnr))\n    i++;\n  if(i > multi->used)\n    return( FALSE );\n\n  for(; i < multi->used; i++)\n    coltarget[i] = coltarget[i+1];\n  coltarget[0]--;\n  multi->used--;\n  multi->dirty = TRUE;\n  return( TRUE );\n}\n\nSTATIC int multi_enteringvar(multirec *multi, pricerec *current, int priority)\n{\n  lprec    *lp = multi->lp;\n  int      i = 0, bestindex, colnr;\n  REAL     bound, score, bestscore = -lp->infinite;\n  REAL     b1, b2, b3;\n  pricerec *candidate, *bestcand;\n\n  /* Check that we have a candidate */\n  multi->active = bestindex = 0;\n  if((multi == NULL) || (multi->used == 0))\n    return( bestindex );\n\n  /* Check for pruning possibility of the B&B tree */\n  if(multi->objcheck && (lp->solutioncount > 0) &&\n     bb_better(lp, OF_WORKING | OF_PROJECTED, OF_TEST_WE)) {\n    lp->spx_status = FATHOMED;\n    return( bestindex );\n  }\n\n  /* Check the trivial case */\n  if(multi->used == 1) {\n    bestcand = (pricerec *) (multi->sortedList[bestindex].pvoidreal.ptr);\n    goto Finish;\n  }\n\n  /* Set priority weights */\nRedo:\n  switch(priority) {\n    case 0:  b1 = 0.0, b2 = 0.0, b3 = 1.0;          /* Only OF          */\n              bestindex = multi->used - 2;   break;\n    case 1:  b1 = 0.2, b2 = 0.3, b3 = 0.5; break;  /* Emphasize OF     */\n    case 2:  b1 = 0.3, b2 = 0.5, b3 = 0.2; break;  /* Emphasize bound  */\n    case 3:  b1 = 0.6, b2 = 0.2, b3 = 0.2; break;  /* Emphasize pivot  */\n    case 4:  b1 = 1.0, b2 = 0.0, b3 = 0.0; break;  /* Only pivot       */\n    default: b1 = 0.4, b2 = 0.2, b3 = 0.4;         /* Balanced default */\n  }\n  bestcand = (pricerec *) (multi->sortedList[bestindex].pvoidreal.ptr);\n\n  /* Loop over all candidates to get the best entering candidate;\n     start at the end to try to maximize the chain length */\n  for(i = multi->used - 1; i >= 0; i--) {\n    candidate = (pricerec *) (multi->sortedList[i].pvoidreal.ptr);\n    colnr = candidate->varno;\n    bound = lp->upbo[colnr];\n    score = fabs(candidate->pivot) / multi->maxpivot;\n    score = pow(1.0 + score                           , b1) *\n            pow(1.0 + log(bound / multi->maxbound + 1), b2) *\n            pow(1.0 + (REAL) i / multi->used          , b3);\n    if(score > bestscore) {\n      bestscore = score;\n      bestindex = i;\n      bestcand  = candidate;\n    }\n  }\n\n  /* Do pivot protection */\n  if((priority < 4) && (fabs(bestcand->pivot) < lp->epssolution)) {\n    bestindex = 0;\n    priority++;\n    goto Redo;\n  }\n\nFinish:\n  /* Make sure we shrink the list and update */\n  multi->active = colnr = bestcand->varno;\n  if(bestindex < multi->used - 1) {\n#if 0\n/*    if(lp->upbo[colnr] >= lp->infinite) */\n    QS_swap(multi->sortedList, bestindex, multi->used-1);\n    multi_recompute(multi, bestindex, (bestcand->isdual == AUTOMATIC), TRUE);\n#else\n    multi->used = i + 1;\n#endif\n  }\n  multi_populateSet(multi, NULL, multi->active);\n\n  /* Compute the entering theta and update parameters */\n  score = (multi->used == 1 ? multi->step_base : multi->sortedList[multi->used-2].pvoidreal.realval);\n  score /= bestcand->pivot;\n  score = my_chsign(!lp->is_lower[multi->active], score);\n\n  if(lp->spx_trace &&\n     (fabs(score) > 1/lp->epsprimal))\n    report(lp, IMPORTANT, \"multi_enteringvar: A very large Theta %g was generated (pivot %g)\\n\",\n                       score, bestcand->pivot);\n  multi->step_base = score;\n  if(current != NULL)\n    *current = *bestcand;\n\n  return( multi->active );\n}\n\nSTATIC REAL multi_enteringtheta(multirec *multi)\n{\n  return( multi->step_base );\n}\n\nSTATIC int multi_populateSet(multirec *multi, int **list, int excludenr)\n{\n  int n = 0;\n  if(list == NULL)\n    list = &(multi->indexSet);\n  if((multi->used > 0) &&\n     ((*list != NULL) || allocINT(multi->lp, list, multi->size+1, FALSE))) {\n    int i, colnr;\n\n    for(i = 0; i < multi->used; i++) {\n      colnr = ((pricerec *) (multi->sortedList[i].pvoidreal.ptr))->varno;\n      if((colnr != excludenr) &&\n        /* Prevent an unbounded variable from \"bound-flip\"; this could\n          actually indicate that we should let the entering variable be\n          bound-swapped (in the case that it is bounded), but we\n          disregard this possibility here, since it brings with it\n          issues of pivot size, etc. */\n        ((excludenr > 0) && (multi->lp->upbo[colnr] < multi->lp->infinite))) {\n        n++;\n        (*list)[n] = colnr;\n      }\n    }\n    (*list)[0] = n;\n  }\n  return( n );\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_price.h",
    "content": "#ifndef HEADER_lp_price\n#define HEADER_lp_price\n\n/* Local defines                                                             */\n/* ------------------------------------------------------------------------- */\n#define UseSortOnBound_Improve\n/*#define UseSortOnBound_Substitute*/\n\n#if 0 /* Stricter feasibility-preserving tolerance; use w/ *_UseRejectionList */\n  #define UseRelativeFeasibility       /* Use machine-precision and A-scale data */\n#endif\n#if 0          /* Stricter pivot-selection criteria; use w/ *UseRejectionList */\n  #define UseRelativePivot_Primal             /* In rowprim based on A-scale data */\n  #define UseRelativePivot_Dual               /* In coldual based on A-scale data */\n#endif\n\n\n/* Include required library headers                                          */\n/* ------------------------------------------------------------------------- */\n#include \"lp_types.h\"\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Comparison and validity routines */\nint CMP_CALLMODEL compareImprovementVar(const pricerec *current, const pricerec *candidate);\nint CMP_CALLMODEL compareSubstitutionVar(const pricerec *current, const pricerec *candidate);\nint CMP_CALLMODEL compareBoundFlipVar(const pricerec *current, const pricerec *candidate);\nSTATIC int addCandidateVar(pricerec *candidate, multirec *multi, findCompare_func findCompare, MYBOOL allowSortedExpand);\nSTATIC MYBOOL collectMinorVar(pricerec *candidate, multirec *longsteps, MYBOOL isphase2, MYBOOL isbatch);\nSTATIC MYBOOL validImprovementVar(pricerec *candidate);\nSTATIC MYBOOL validSubstitutionVar(pricerec *candidate);\n\n/* Row+column selection routines */\nSTATIC MYBOOL findImprovementVar(pricerec *current, pricerec *candidate, MYBOOL collectMP, int *candidatecount);\nSTATIC MYBOOL findSubstitutionVar(pricerec *current, pricerec *candidate, int *candidatecount);\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\nINLINE REAL normalizeEdge(lprec *lp, int item, REAL edge, MYBOOL isdual);\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\nSTATIC void makePriceLoop(lprec *lp, int *start, int *end, int *delta);\n\n/* Computation of reduced costs */\nSTATIC void update_reducedcosts(lprec *lp, MYBOOL isdual, int leave_nr, int enter_nr, REAL *prow, REAL *drow);\nSTATIC void compute_reducedcosts(lprec *lp, MYBOOL isdual, int row_nr, int *coltarget, MYBOOL dosolve,\n                                                            REAL *prow, int *nzprow,\n                                                            REAL *drow, int *nzdrow,\n                                                            int roundmode);\n\n/* Leaving variable selection and entering column pricing loops */\nSTATIC int find_rowReplacement(lprec *lp, int rownr, REAL *prow, int *nzprow);\nSTATIC int colprim(lprec *lp, REAL *drow, int *nzdrow,\n                              MYBOOL skipupdate, int partialloop, int *candidatecount, MYBOOL updateinfeas, REAL *xviol);\nSTATIC int rowprim(lprec *lp, int colnr, LREAL *theta, REAL *pcol, int *nzpcol, MYBOOL forceoutEQ, REAL *xviol);\nSTATIC int rowdual(lprec *lp, REAL *rhvec, MYBOOL forceoutEQ, MYBOOL updateinfeas, REAL *xviol);\nSTATIC int coldual(lprec *lp, int row_nr,\n                              REAL *prow, int *nzprow, REAL *drow, int *nzdrow,\n                              MYBOOL dualphase1, MYBOOL skipupdate,\n                              int *candidatecount, REAL *xviol);\n\n/* Partial pricing management routines */\nSTATIC partialrec *partial_createBlocks(lprec *lp, MYBOOL isrow);\nSTATIC int partial_countBlocks(lprec *lp, MYBOOL isrow);\nSTATIC int partial_activeBlocks(lprec *lp, MYBOOL isrow);\nSTATIC void partial_freeBlocks(partialrec **blockdata);\n\n/* Partial pricing utility routines */\nSTATIC int partial_findBlocks(lprec *lp, MYBOOL autodefine, MYBOOL isrow);\nSTATIC int partial_blockStart(lprec *lp, MYBOOL isrow);\nSTATIC int partial_blockEnd(lprec *lp, MYBOOL isrow);\nSTATIC int partial_blockNextPos(lprec *lp, int block, MYBOOL isrow);\n\nSTATIC MYBOOL partial_blockStep(lprec *lp, MYBOOL isrow);\nSTATIC MYBOOL partial_isVarActive(lprec *lp, int varno, MYBOOL isrow);\n\n/* Multiple pricing / dual long step management routines */\nSTATIC multirec *multi_create(lprec *lp, MYBOOL truncinf);\nSTATIC MYBOOL multi_resize(multirec *multi, int blocksize, int blockdiv, MYBOOL doVlist, MYBOOL doIset);\nSTATIC int multi_restart(multirec *multi);\nSTATIC int multi_size(multirec *multi);\nSTATIC int multi_used(multirec *multi);\nSTATIC MYBOOL multi_truncatingvar(multirec *multi, int varnr);\nSTATIC MYBOOL multi_mustupdate(multirec *multi);\nSTATIC void multi_valueInit(multirec *multi, REAL step_base, REAL obj_base);\nSTATIC REAL *multi_valueList(multirec *multi);\nSTATIC int *multi_indexSet(multirec *multi, MYBOOL regenerate);\nSTATIC int multi_getvar(multirec *multi, int item);\nSTATIC MYBOOL multi_recompute(multirec *multi, int index, MYBOOL isphase2, MYBOOL fullupdate);\nSTATIC MYBOOL multi_removevar(multirec *multi, int varnr);\nSTATIC int multi_enteringvar(multirec *multi, pricerec *current, int priority);\nSTATIC REAL multi_enteringtheta(multirec *multi);\nSTATIC void multi_free(multirec **multi);\nSTATIC int multi_populateSet(multirec *multi, int **list, int excludenr);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_price */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_pricePSE.c",
    "content": "\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_report.h\"\n#include \"lp_pricePSE.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n/*\n    Advanced simplex price scaling modules - w/interface for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      lp_lib.h\n\n    Release notes:\n    v1.0.0  1 September 2003    Implementation of DEVEX and STEEPEST EDGE\n                                routines for the primal and dual simplex.\n    v1.0.1  1 January 2004      Made initial value of weight of ingoing\n                                variable for the standard mode of DEVEX\n                                consistent with the initialization at restart;\n                                original version could at worst contribute\n                                to cycling.\n    v1.0.2  23 March 2004       Added floors to Steepest Edge updates and\n                                moved tests for tiny update higher. Previous\n                                logic can be simulated by disabling the compiler\n                                define ApplySteepestEdgeMinimum.\n    v1.1.0  1 July 2004         Renamed from lp_pricerPSE to lp_pricePSE in\n                                conjuction with the creation of a separate\n                                price library.\n    v1.2.0  1 March 2005        Changed memory allocation routines to use\n                                standard lp_solve functions, improve error handling\n                                and return boolean status values.\n\n   ----------------------------------------------------------------------------------\n*/\n\nINLINE MYBOOL applyPricer(lprec *lp)\n{\n  int rule = get_piv_rule(lp);\n  return( (MYBOOL) ((rule == PRICER_DEVEX) || (rule == PRICER_STEEPESTEDGE)) );\n}\n\n\nSTATIC void simplexPricer(lprec *lp, MYBOOL isdual)\n{\n  if(lp->edgeVector != NULL)\n    lp->edgeVector[0] = (REAL) isdual;\n}\n\n\nSTATIC void freePricer(lprec *lp)\n{\n  FREE(lp->edgeVector);\n}\n\n\nSTATIC MYBOOL resizePricer(lprec *lp)\n{\n  if(!applyPricer(lp))\n    return( TRUE );\n\n  /* Reallocate vector for new size */\n  if(!allocREAL(lp, &(lp->edgeVector), lp->sum_alloc+1, AUTOMATIC))\n    return( FALSE );\n\n  /* Signal that we have not yet initialized the price vector */\n  MEMCLEAR(lp->edgeVector, lp->sum_alloc+1);\n  lp->edgeVector[0] = -1;\n  return( TRUE );\n}\n\n\nSTATIC MYBOOL initPricer(lprec *lp)\n{\n  if(!applyPricer(lp))\n    return( FALSE );\n\n  /* Free any pre-existing pricer */\n  freePricer(lp);\n\n  /* Allocate vector to fit current problem size */\n  return( resizePricer(lp) );\n}\n\n\nSTATIC REAL getPricer(lprec *lp, int item, MYBOOL isdual)\n{\n  REAL value = 1.0;\n\n  if(!applyPricer(lp))\n    return( value );\n\n  value = *lp->edgeVector;\n\n  /* Make sure we have a price vector to use */\n  if(value < 0) {\n#ifdef Paranoia\n    report(lp, SEVERE, \"getPricer: Called without having being initialized!\\n\");\n#endif\n    return( 1.0 );\n  }\n  /* We may be calling the primal from the dual (and vice-versa) for validation\n     of feasibility; ignore calling origin and simply return 1 */\n  else if(isdual != value) {\n    return( 1.0 );\n  }\n  /* Do the normal norm retrieval */\n  else {\n\n    if(isdual)\n      item = lp->var_basic[item];\n\n    value = lp->edgeVector[item];\n\n    if(value == 0) {\n      value = 1.0;\n      report(lp, SEVERE, \"getPricer: Detected a zero-valued price at index %d\\n\", item);\n    }\n#ifdef Paranoia\n    else if(value < 0)\n      report(lp, SEVERE, \"getPricer: Invalid %s reduced cost norm %g at index %d\\n\",\n                          my_if(isdual, \"dual\", \"primal\"), value, item);\n#endif\n\n  /* Return the norm */\n    return( sqrt(value) );\n  }\n}\n\nSTATIC MYBOOL restartPricer(lprec *lp, MYBOOL isdual)\n{\n  REAL   *sEdge = NULL, seNorm, hold;\n  int    i, j, m;\n  MYBOOL isDEVEX, ok = applyPricer(lp);\n\n  if(!ok)\n    return( ok );\n\n  /* Store the active/current pricing type */\n  if(isdual == AUTOMATIC)\n    isdual = (MYBOOL) lp->edgeVector[0];\n  else\n    lp->edgeVector[0] = isdual;\n\n  m = lp->rows;\n\n  /* Determine strategy and check if we have strategy fallback for the primal */\n  isDEVEX = is_piv_rule(lp, PRICER_DEVEX);\n  if(!isDEVEX && !isdual)\n    isDEVEX = is_piv_mode(lp, PRICE_PRIMALFALLBACK);\n\n  /* Check if we only need to do the simple DEVEX initialization */\n  if(!is_piv_mode(lp, PRICE_TRUENORMINIT)) {\n    if(isdual) {\n      for(i = 1; i <= m; i++)\n        lp->edgeVector[lp->var_basic[i]] = 1.0;\n    }\n    else {\n      for(i = 1; i <= lp->sum; i++)\n        if(!lp->is_basic[i])\n          lp->edgeVector[i] = 1.0;\n    }\n    return( ok );\n  }\n\n  /* Otherwise do the full Steepest Edge norm initialization */\n  ok = allocREAL(lp, &sEdge, m+1, FALSE);\n  if(!ok)\n    return( ok );\n\n  if(isdual) {\n\n   /* Extract the rows of the basis inverse and compute their squared norms */\n\n    for(i = 1; i <= m; i++) {\n\n      bsolve(lp, i, sEdge, NULL, 0, 0.0);\n\n      /* Compute the edge norm */\n      seNorm = 0;\n      for(j = 1; j <= m; j++) {\n        hold = sEdge[j];\n        seNorm += hold*hold;\n      }\n\n      j = lp->var_basic[i];\n      lp->edgeVector[j] = seNorm;\n    }\n\n  }\n  else {\n\n   /* Solve a=Bb for b over all non-basic variables and compute their squared norms */\n\n    for(i = 1; i <= lp->sum; i++) {\n      if(lp->is_basic[i])\n        continue;\n\n      fsolve(lp, i, sEdge, NULL, 0, 0.0, FALSE);\n\n      /* Compute the edge norm */\n      seNorm = 1;\n      for(j = 1; j <= m; j++) {\n        hold = sEdge[j];\n        seNorm += hold*hold;\n      }\n\n      lp->edgeVector[i] = seNorm;\n    }\n\n  }\n\n  FREE(sEdge);\n\n  return( ok );\n\n}\n\n\nSTATIC MYBOOL formWeights(lprec *lp, int colnr, REAL *pcol, REAL **w)\n/* This computes Bw = a, where B is the basis and a is a column of A */\n{\n  MYBOOL ok = allocREAL(lp, w, lp->rows+1, FALSE);\n\n  if(ok) {\n    if(pcol == NULL)\n      fsolve(lp, colnr, *w, NULL, 0.0, 0.0, FALSE);\n    else {\n      MEMCOPY(*w, pcol, lp->rows+1);\n/*    *w[0] = 0; */ /* Test */\n    }\n  }\n/*\n  if(pcol != NULL) {\n    REAL cEdge, hold;\n    int  i;\n\n    cEdge = 0;\n    for(i = 1; i <= m; i++) {\n      hold = *w[i]-pcol[i];\n      cEdge += hold*hold;\n    }\n    cEdge /= m;\n    cEdge = sqrt(cEdge);\n    if(cEdge > lp->epspivot)\n      report(lp, SEVERE, \"updatePricer: MRS error is %g\\n\", cEdge);\n  }\n*/\n  return(ok);\n}\nSTATIC void freeWeights(REAL *w)\n{\n  FREE(w);\n}\n\n\nSTATIC MYBOOL updatePricer(lprec *lp, int rownr, int colnr, REAL *pcol, REAL *prow, int *nzprow)\n{\n  (void)nzprow;\n  REAL   *vEdge = NULL, cEdge, hold, *newEdge, *w = NULL;\n  int    i, m, n, exitcol, errlevel = DETAILED;\n  MYBOOL forceRefresh = FALSE, isDual, isDEVEX, ok = FALSE;\n  (void)nzprow;\n\n  if(!applyPricer(lp))\n    return(ok);\n\n  /* Make sure we have something to update */\n  hold = lp->edgeVector[0];\n  if(hold < 0)\n    return(ok);\n  isDual = (MYBOOL) (hold > 0);\n\n  /* Do common initializations and computations */\n  m = lp->rows;\n  n = lp->sum;\n  isDEVEX = is_piv_rule(lp, PRICER_DEVEX);\n  exitcol = lp->var_basic[rownr];\n\n  /* Solve/copy Bw = a */\n#if 0\n  ok = formWeights(lp, colnr, NULL, &w);  /* Compute from scratch - Experimental */\n#else\n  ok = formWeights(lp, colnr, pcol, &w);  /* Use previously computed values */\n#endif\n  if(!ok)\n    return( ok );\n\n  /* Price norms for the dual simplex - the basic columns */\n  if(isDual) {\n    REAL rw;\n    int  targetcol;\n\n    /* Don't need to compute cross-products with DEVEX */\n    if(!isDEVEX) {\n      ok = allocREAL(lp, &vEdge, m+1, FALSE);\n      if(!ok)\n        return( ok );\n\n    /* Extract the row of the inverse containing the leaving variable\n       and then form the dot products against the other variables, i.e. \"Tau\" */\n#if 0 /* Extract row explicitly */\n      bsolve(lp, rownr, vEdge, 0, 0.0);\n#else /* Reuse previously extracted row data */\n      MEMCOPY(vEdge, prow, m+1);\n      vEdge[0] = 0;\n#endif\n      lp->bfp_ftran_normal(lp, vEdge, NULL);\n    }\n\n    /* Update the squared steepest edge norms; first store some constants */\n    cEdge = lp->edgeVector[exitcol];\n    rw = w[rownr];\n    if(fabs(rw) < lp->epspivot) {\n      forceRefresh = TRUE;\n      goto Finish2;\n    }\n\n   /* Deal with the variable entering the basis to become a new leaving candidate */\n    hold = 1 / rw;\n    lp->edgeVector[colnr] = (hold*hold) * cEdge;\n\n#ifdef Paranoia\n    if(lp->edgeVector[colnr] <= lp->epsmachine)\n      report(lp, errlevel, \"updatePricer: Invalid dual norm %g at entering index %d - iteration %.0f\\n\",\n                           lp->edgeVector[colnr], rownr, (double) (lp->total_iter+lp->current_iter));\n#endif\n\n   /* Then loop over all basic variables, but skip the leaving row */\n    for(i = 1; i <= m; i++) {\n      if(i == rownr)\n        continue;\n      targetcol = lp->var_basic[i];\n      hold = w[i];\n      if(hold == 0)\n        continue;\n      hold /= rw;\n      if(fabs(hold) < lp->epsmachine)\n        continue;\n\n      newEdge = &(lp->edgeVector[targetcol]);\n      *newEdge += (hold*hold) * cEdge;\n      if(isDEVEX) {\n        if((*newEdge) > DEVEX_RESTARTLIMIT) {\n          forceRefresh = TRUE;\n          break;\n        }\n      }\n      else {\n        *newEdge -= 2*hold*vEdge[i];\n#ifdef xxApplySteepestEdgeMinimum\n        SETMAX(*newEdge, hold*hold+1); /* Kludge; use the primal lower bound */\n#else\n        if(*newEdge <= 0) {\n          report(lp, errlevel, \"updatePricer: Invalid dual norm %g at index %d - iteration %.0f\\n\",\n                                *newEdge, i, (double) (lp->total_iter+lp->current_iter));\n          forceRefresh = TRUE;\n          break;\n        }\n#endif\n      }\n    }\n\n\n  }\n  /* Price norms for the primal simplex - the non-basic columns */\n  else {\n\n    REAL *vTemp = NULL, *vAlpha = NULL, cAlpha;\n    int  *coltarget;\n\n    ok = allocREAL(lp, &vTemp, m+1, TRUE) &&\n         allocREAL(lp, &vAlpha, n+1, TRUE);\n    if(!ok)\n      return( ok );\n\n    /* Check if we have strategy fallback for the primal */\n    if(!isDEVEX)\n      isDEVEX = is_piv_mode(lp, PRICE_PRIMALFALLBACK);\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n    /* Initialize column target array */\n    coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->sum+1, sizeof(*coltarget));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n    ok = get_colIndexA(lp, SCAN_SLACKVARS+SCAN_USERVARS+USE_NONBASICVARS, coltarget, FALSE);\n    if(!ok) {\n      mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n      return( ok );\n    }\n\n    /* Don't need to compute cross-products with DEVEX */\n    if(!isDEVEX) {\n      ok = allocREAL(lp, &vEdge, n+1, TRUE);\n      if(!ok)\n        return( ok );\n\n      /* Compute v and then N'v */\n      MEMCOPY(vTemp, w, m+1);\n      bsolve(lp, -1, vTemp, NULL, lp->epsmachine*DOUBLEROUND, 0.0);\n      vTemp[0] = 0;\n      prod_xA(lp, coltarget, vTemp, NULL, lp->epsmachine, 0.0,\n                             vEdge, NULL, MAT_ROUNDDEFAULT);\n    }\n\n    /* Compute Sigma and then Alpha */\n    bsolve(lp, rownr, vTemp, NULL, 0*DOUBLEROUND, 0.0);\n    vTemp[0] = 0;\n    prod_xA(lp, coltarget, vTemp, NULL, lp->epsmachine, 0.0,\n                           vAlpha, NULL, MAT_ROUNDDEFAULT);\n    mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n\n    /* Update the squared steepest edge norms; first store some constants */\n    cEdge = lp->edgeVector[colnr];\n    cAlpha = vAlpha[colnr];\n    if(fabs(cAlpha) < lp->epspivot) {\n      forceRefresh = TRUE;\n      goto Finish1;\n    }\n\n    /* Deal with the variable leaving the basis to become a new entry candidate */\n    hold = 1 / cAlpha;\n    lp->edgeVector[exitcol] = (hold*hold) * cEdge;\n\n#ifdef Paranoia\n    if(lp->edgeVector[exitcol] <= lp->epsmachine)\n      report(lp, errlevel, \"updatePricer: Invalid primal norm %g at leaving index %d - iteration %.0f\\n\",\n                          lp->edgeVector[exitcol], exitcol, (double) (lp->total_iter+lp->current_iter));\n#endif\n\n    /* Then loop over all non-basic variables, but skip the entering column */\n    for(i = 1; i <= lp->sum; i++) {\n      if(lp->is_basic[i] || (i == colnr))\n        continue;\n      hold = vAlpha[i];\n      if(hold == 0)\n        continue;\n      hold /= cAlpha;\n      if(fabs(hold) < lp->epsmachine)\n        continue;\n\n      newEdge = &(lp->edgeVector[i]);\n      *newEdge += (hold*hold) * cEdge;\n      if(isDEVEX) {\n        if((*newEdge) > DEVEX_RESTARTLIMIT) {\n          forceRefresh = TRUE;\n          break;\n        }\n      }\n      else {\n        *newEdge -= 2*hold*vEdge[i];\n#ifdef ApplySteepestEdgeMinimum\n        SETMAX(*newEdge, hold*hold+1);\n#else\n        if(*newEdge < 0) {\n          report(lp, errlevel, \"updatePricer: Invalid primal norm %g at index %d - iteration %.0f\\n\",\n                               *newEdge, i, (double) (lp->total_iter+lp->current_iter));\n          if(lp->spx_trace)\n            report(lp, errlevel, \"Error detail: (RelAlpha=%g, vEdge=%g, cEdge=%g)\\n\", hold, vEdge[i], cEdge);\n          forceRefresh = TRUE;\n          break;\n        }\n#endif\n      }\n    }\n\nFinish1:\n    FREE(vAlpha);\n    FREE(vTemp);\n\n  }\n\nFinish2:\n  FREE(vEdge);\n  freeWeights(w);\n\n  if(forceRefresh)\n    ok = restartPricer(lp, AUTOMATIC);\n  else\n    ok = TRUE;\n\n  return( ok );\n\n}\n\n\nSTATIC MYBOOL verifyPricer(lprec *lp)\n{\n  REAL value;\n  int  i, n;\n  MYBOOL ok = applyPricer(lp);\n\n  if(!ok)\n    return( ok );\n  ok = FALSE;\n\n  /* Verify */\n  if(lp->edgeVector == NULL)\n    return( ok );\n  value = *lp->edgeVector;\n  if(value < 0)\n    return( ok );\n\n  /* Check the primal */\n  n = 1;\n  if(value == 0) {\n\n    for(n = lp->sum; n > 0; n--) {\n      if(lp->is_basic[n])\n        continue;\n      value = lp->edgeVector[n];\n      if(value <= 0)\n        break;\n    }\n  }\n  /* Check the dual */\n  else {\n    for(i = lp->rows; i > 0; i--) {\n      n = lp->var_basic[i];\n      value = lp->edgeVector[n];\n      if(value <= 0)\n        break;\n    }\n  }\n\n  ok = (MYBOOL) (n == 0);\n#ifdef Paranoia\n  if(!ok)\n    report(lp, SEVERE, \"verifyPricer: Invalid norm %g at index %d\\n\",\n                       value, n);\n#endif\n  return( ok );\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_pricePSE.h",
    "content": "#ifndef HEADER_lp_pricePSE\n#define HEADER_lp_pricePSE\n\n#include \"lp_types.h\"\n\n#define ApplySteepestEdgeMinimum\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Price norm management routines */\nSTATIC MYBOOL initPricer(lprec *lp);\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wunused-function\"\n#endif\nINLINE MYBOOL applyPricer(lprec *lp);\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\nSTATIC void simplexPricer(lprec *lp, MYBOOL isdual);\nSTATIC void freePricer(lprec *lp);\nSTATIC MYBOOL resizePricer(lprec *lp);\nSTATIC REAL getPricer(lprec *lp, int item, MYBOOL isdual);\nSTATIC MYBOOL restartPricer(lprec *lp, MYBOOL isdual);\nSTATIC MYBOOL updatePricer(lprec *lp, int rownr, int colnr, REAL *pcol, REAL *prow, int *nzprow);\nSTATIC MYBOOL verifyPricer(lprec *lp);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_pricePSE */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_report.c",
    "content": "\n/*\n    Mixed integer programming optimization drivers for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Michel Berkelaar (to lp_solve v3.2),\n                   Kjell Eikland\n    Contact:\n    License terms: LGPL.\n\n    Requires:      stdarg.h, lp_lib.h\n\n    Release notes:\n    v5.0.0 3   1 January 2004      New unit isolating reporting routines.\n    v5.2.0.0   1 December 2005     Addition of Matrix Market writing function.\n\n   ----------------------------------------------------------------------------------\n*/\n\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n\n#include \"lp_lib.h\"\n#include \"lp_scale.h\"\n#include \"commonlib.h\"\n#include \"lp_report.h\"\n\n#include \"mmio.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n/* Define buffer-size controled function mapping */\n# if defined _MSC_VER\n#  define vsnprintf _vsnprintf\n# endif\n\n/* Various reporting functions for lp_solve                                  */\n/* ------------------------------------------------------------------------- */\n\n/* First define general utilties for reporting and output */\nconst char * __VACALL explain(lprec *lp, const char *format, ...)\n{\n  char buff[DEF_STRBUFSIZE+1];\n  va_list ap;\n\n  va_start(ap, format);\n  vsnprintf(buff, DEF_STRBUFSIZE, format, ap);\n  va_end(ap);\n  allocCHAR(lp, &(lp->ex_status), (int) strlen(buff), AUTOMATIC);\n  strcpy(lp->ex_status, buff);\n  return( lp->ex_status );\n}\nvoid __VACALL report(lprec *lp, int level, const char * format, ...)\n{\n  char buff[DEF_STRBUFSIZE+1];\n  va_list ap;\n\n  if(lp == NULL) {\n    va_start(ap, format);\n    vfprintf(stderr, format, ap);\n    va_end(ap);\n  }\n  else if(level <= lp->verbose) {\n    if(lp->writelog != NULL) {\n      va_start(ap, format);\n      vsnprintf(buff, DEF_STRBUFSIZE, format, ap);\n      va_end(ap);\n      lp->writelog(lp, lp->loghandle, buff);\n    }\n    if(lp->outstream != NULL) {\n      va_start(ap, format);\n      vfprintf(lp->outstream, format, ap);\n      va_end(ap);\n      if(lp->outstream != stdout)\n        fflush(lp->outstream);\n    }\n  }\n#ifdef xParanoia\n  if(level == CRITICAL)\n    raise(SIGSEGV);\n#endif\n}\n\nSTATIC void print_indent(lprec *lp)\n{\n  int i;\n\n  report(lp, NEUTRAL, \"%2d\", lp->bb_level);\n  if(lp->bb_level < 50) /* useless otherwise */\n    for(i = lp->bb_level; i > 0; i--)\n      report(lp, NEUTRAL, \"--\");\n  else\n    report(lp, NEUTRAL, \" *** too deep ***\");\n  report(lp, NEUTRAL, \"> \");\n} /* print_indent */\n\nSTATIC void debug_print(lprec *lp, const char *format, ...)\n{\n  va_list ap;\n\n  if(lp->bb_trace) {\n    print_indent(lp);\n    if (lp == NULL)\n    {\n      va_start(ap, format);\n      vfprintf(stderr, format, ap);\n      va_end(ap);\n      fputc('\\n', stderr);\n    }\n    else if(lp->debuginfo != NULL)\n    {\n      char buff[DEF_STRBUFSIZE+1];\n      va_start(ap, format);\n      vsnprintf(buff, DEF_STRBUFSIZE, format, ap);\n      va_end(ap);\n      lp->debuginfo(lp, lp->loghandle, buff);\n    }\n  }\n} /* debug_print */\n\nSTATIC void debug_print_solution(lprec *lp)\n{\n  int i;\n\n  if(lp->bb_trace)\n    for (i = lp->rows + 1; i <= lp->sum; i++) {\n      print_indent(lp);\n      report(lp, NEUTRAL, \"%s \" RESULTVALUEMASK \"\\n\",\n                 get_col_name(lp, i - lp->rows),\n                (double)lp->solution[i]);\n    }\n} /* debug_print_solution */\n\nSTATIC void debug_print_bounds(lprec *lp, REAL *upbo, REAL *lowbo)\n{\n  int i;\n\n  if(lp->bb_trace)\n    for(i = lp->rows + 1; i <= lp->sum; i++) {\n      if(lowbo[i] == upbo[i]) {\n        print_indent(lp);\n        report(lp, NEUTRAL, \"%s = \" RESULTVALUEMASK \"\\n\", get_col_name(lp, i - lp->rows),\n                             (double)lowbo[i]);\n      }\n      else {\n        if(lowbo[i] != 0) {\n          print_indent(lp);\n          report(lp, NEUTRAL, \"%s > \" RESULTVALUEMASK \"\\n\", get_col_name(lp, i - lp->rows),\n                               (double)lowbo[i]);\n        }\n        if(upbo[i] != lp->infinite) {\n          print_indent(lp);\n          report(lp, NEUTRAL, \"%s < \" RESULTVALUEMASK \"\\n\", get_col_name(lp, i - lp->rows),\n                               (double)upbo[i]);\n    }\n      }\n    }\n} /* debug_print_bounds */\n\n/* List a vector of LREAL values for the given index range */\nvoid blockWriteLREAL(FILE *output, const char *label, LREAL *vector, int first, int last)\n{\n  int i, k = 0;\n\n  fprintf(output, \"%s\", label);\n  fprintf(output, \"\\n\");\n  for(i = first; i <= last; i++) {\n    fprintf(output, \" %18g\", vector[i]);\n    k++;\n    if(my_mod(k, 4) == 0) {\n      fprintf(output, \"\\n\");\n      k = 0;\n    }\n  }\n  if(my_mod(k, 4) != 0)\n    fprintf(output, \"\\n\");\n}\n\n/* List the current user data matrix columns over the selected row range */\nvoid blockWriteAMAT(FILE *output, const char *label, lprec* lp, int first, int last)\n{\n  int    i, j, k = 0;\n  int    nzb, nze, jb;\n  double hold;\n  MATrec *mat = lp->matA;\n\n  if(!mat_validate(mat))\n    return;\n  if(first < 0)\n    first = 0;\n  if(last < 0)\n    last = lp->rows;\n\n  fprintf(output, \"%s\", label);\n  fprintf(output, \"\\n\");\n\n  if(first == 0) {\n    for(j = 1; j <= lp->columns; j++) {\n      hold = get_mat(lp, 0, j);\n      fprintf(output, \" %18g\", hold);\n      k++;\n      if(my_mod(k, 4) == 0) {\n        fprintf(output, \"\\n\");\n        k = 0;\n      }\n    }\n    if(my_mod(k, 4) != 0) {\n      fprintf(output, \"\\n\");\n      k = 0;\n    }\n    first++;\n  }\n  nze = mat->row_end[first-1];\n  for(i = first; i <= last; i++) {\n    nzb = nze;\n    nze = mat->row_end[i];\n    if(nzb >= nze)\n      jb = lp->columns+1;\n    else\n      jb = ROW_MAT_COLNR(nzb);\n    for(j = 1; j <= lp->columns; j++) {\n      if(j < jb)\n        hold = 0;\n      else {\n        hold = get_mat(lp, i, j);\n        nzb++;\n        if(nzb < nze)\n          jb = ROW_MAT_COLNR(nzb);\n        else\n          jb = lp->columns+1;\n      }\n      fprintf(output, \" %18g\", hold);\n      k++;\n      if(my_mod(k, 4) == 0) {\n        fprintf(output, \"\\n\");\n        k = 0;\n      }\n    }\n    if(my_mod(k, 4) != 0) {\n      fprintf(output, \"\\n\");\n      k = 0;\n    }\n  }\n  if(my_mod(k, 4) != 0)\n    fprintf(output, \"\\n\");\n}\n\n/* List the current basis matrix columns over the selected row range */\nvoid blockWriteBMAT(FILE *output, const char *label, lprec* lp, int first, int last)\n{\n  int    i, j, jb, k = 0;\n  double hold;\n\n  if(first < 0)\n    first = 0;\n  if(last < 0)\n    last = lp->rows;\n\n  fprintf(output, \"%s\", label);\n  fprintf(output, \"\\n\");\n\n  for(i = first; i <= last; i++) {\n    for(j = 1; j <= lp->rows; j++) {\n      jb = lp->var_basic[j];\n      if(jb <= lp->rows) {\n        if(jb == i)\n          hold = 1;\n        else\n          hold = 0;\n      }\n      else\n        hold = get_mat(lp, i, j);\n      if(i == 0)\n        modifyOF1(lp, jb, &hold, 1);\n      hold = unscaled_mat(lp, hold, i, jb);\n      fprintf(output, \" %18g\", hold);\n      k++;\n      if(my_mod(k, 4) == 0) {\n        fprintf(output, \"\\n\");\n        k = 0;\n      }\n    }\n    if(my_mod(k, 4) != 0) {\n      fprintf(output, \"\\n\");\n      k = 0;\n    }\n  }\n  if(my_mod(k, 4) != 0)\n    fprintf(output, \"\\n\");\n}\n\n/* Do a generic readable data dump of key lp_solve model variables;\n   principally for run difference and debugging purposes */\nMYBOOL REPORT_debugdump(lprec *lp, const char *filename, MYBOOL livedata)\n{\n  FILE   *output = stdout;\n  MYBOOL ok;\n\n  ok = (MYBOOL) ((filename == NULL) || ((output = fopen(filename,\"w\")) != NULL));\n  if(!ok)\n    return(ok);\n  if((filename == NULL) && (lp->outstream != NULL))\n    output = lp->outstream;\n\n  fprintf(output, \"\\nGENERAL INFORMATION\\n-------------------\\n\\n\");\n  fprintf(output, \"Model size:     %d rows (%d equalities, %d Lagrangean), %d columns (%d integers, %d SC, %d SOS, %d GUB)\\n\",\n                  lp->rows, lp->equalities, get_Lrows(lp), lp->columns,\n      lp->int_vars, lp->sc_vars, SOS_count(lp), GUB_count(lp));\n  fprintf(output, \"Data size:      %d model non-zeros, %d invB non-zeros (engine is %s)\\n\",\n                  get_nonzeros(lp), my_if(lp->invB == NULL, 0, lp->bfp_nonzeros(lp, FALSE)), lp->bfp_name());\n  fprintf(output, \"Internal sizes: %d rows allocated, %d columns allocated, %d columns used, %d eta length\\n\",\n                  lp->rows_alloc, lp->columns_alloc, lp->columns, my_if(lp->invB == NULL, 0, lp->bfp_colcount(lp)));\n  fprintf(output, \"Memory use:     %d sparse matrix, %d eta\\n\",\n                  lp->matA->mat_alloc, my_if(lp->invB == NULL, 0, lp->bfp_memallocated(lp)));\n  fprintf(output, \"Parameters:     Maximize=%d, Names used=%d, Scalingmode=%d, Presolve=%d, SimplexPivot=%d\\n\",\n                  is_maxim(lp), lp->names_used, lp->scalemode, lp->do_presolve, lp->piv_strategy);\n  fprintf(output, \"Precision:      EpsValue=%g, EpsPrimal=%g, EpsDual=%g, EpsPivot=%g, EpsPerturb=%g\\n\",\n                  lp->epsvalue, lp->epsprimal, lp->epsdual, lp->epspivot, lp->epsperturb);\n  fprintf(output, \"Stability:      AntiDegen=%d, Improvement=%d, Split variables at=%g\\n\",\n                  lp->improve, lp->anti_degen, lp->negrange);\n  fprintf(output, \"B&B settings:   BB pivot rule=%d, BB branching=%s, BB strategy=%d, Integer precision=%g, MIP gaps=%g,%g\\n\",\n                  lp->bb_rule, my_boolstr(lp->bb_varbranch), lp->bb_floorfirst, lp->epsint, lp->mip_absgap, lp->mip_relgap);\n\n  fprintf(output, \"\\nCORE DATA\\n---------\\n\\n\");\n  blockWriteINT(output,  \"Column starts\", lp->matA->col_end, 0, lp->columns);\n  blockWriteINT(output,  \"row_type\", lp->row_type, 0, lp->rows);\n  blockWriteREAL(output, \"orig_rhs\", lp->orig_rhs, 0, lp->rows);\n  blockWriteREAL(output, \"orig_lowbo\", lp->orig_lowbo, 0, lp->sum);\n  blockWriteREAL(output, \"orig_upbo\", lp->orig_upbo, 0, lp->sum);\n  blockWriteINT(output,  \"row_type\", lp->row_type, 0, lp->rows);\n  blockWriteBOOL(output, \"var_type\", lp->var_type, 0, lp->columns, TRUE);\n  blockWriteAMAT(output, \"A\", lp, 0, lp->rows);\n\n  if(livedata) {\n    fprintf(output, \"\\nPROCESS DATA\\n------------\\n\\n\");\n    blockWriteREAL(output,  \"Active rhs\", lp->rhs, 0, lp->rows);\n    blockWriteINT(output,  \"Basic variables\", lp->var_basic, 0, lp->rows);\n    blockWriteBOOL(output, \"is_basic\", lp->is_basic, 0, lp->sum, TRUE);\n    blockWriteREAL(output, \"lowbo\", lp->lowbo, 0, lp->sum);\n    blockWriteREAL(output, \"upbo\", lp->upbo, 0, lp->sum);\n    if(lp->scalars != NULL)\n      blockWriteREAL(output, \"scalars\", lp->scalars, 0, lp->sum);\n  }\n\n  if(filename != NULL)\n    fclose(output);\n  return(ok);\n}\n\n\n/* High level reports for model results */\n\nvoid REPORT_objective(lprec *lp)\n{\n  if(lp->outstream == NULL)\n    return;\n  if(fabs(lp->best_solution[0]) < 1e-5)\n    fprintf(lp->outstream, \"\\nValue of objective function: %g\\n\", (double)lp->best_solution[0]);\n  else\n    fprintf(lp->outstream, \"\\nValue of objective function: %.8f\\n\", (double)lp->best_solution[0]);\n  fflush(lp->outstream);\n}\n\nvoid REPORT_solution(lprec *lp, int columns)\n{\n  int i, j, n;\n  REAL value;\n  presolveundorec *psundo = lp->presolve_undo;\n  MYBOOL NZonly = (MYBOOL) ((lp->print_sol & AUTOMATIC) > 0);\n\n  if(lp->outstream == NULL)\n    return;\n\n  fprintf(lp->outstream, \"\\nActual values of the variables:\\n\");\n  if(columns <= 0)\n    columns = 2;\n  n = 0;\n  for(i = 1; i <= psundo->orig_columns; i++) {\n    j = psundo->orig_rows + i;\n    value = get_var_primalresult(lp, j);\n    if(NZonly && (fabs(value) < lp->epsprimal))\n      continue;\n    n = (n+1) % columns;\n    fprintf(lp->outstream, \"%-20s %12g\", get_origcol_name(lp, i), (double) value);\n    if(n == 0)\n      fprintf(lp->outstream, \"\\n\");\n    else\n      fprintf(lp->outstream, \"       \");\n  }\n\n  fflush(lp->outstream);\n} /* REPORT_solution */\n\nvoid REPORT_constraints(lprec *lp, int columns)\n{\n  int i, n;\n  REAL value;\n  MYBOOL NZonly = (MYBOOL) ((lp->print_sol & AUTOMATIC) > 0);\n\n  if(lp->outstream == NULL)\n    return;\n\n  if(columns <= 0)\n    columns = 2;\n\n  fprintf(lp->outstream, \"\\nActual values of the constraints:\\n\");\n  n = 0;\n  for(i = 1; i <= lp->rows; i++) {\n    value = (double)lp->best_solution[i];\n    if(NZonly && (fabs(value) < lp->epsprimal))\n      continue;\n    n = (n+1) % columns;\n    fprintf(lp->outstream, \"%-20s %12g\", get_row_name(lp, i), value);\n    if(n == 0)\n      fprintf(lp->outstream, \"\\n\");\n    else\n      fprintf(lp->outstream, \"       \");\n  }\n\n  fflush(lp->outstream);\n}\n\nvoid REPORT_duals(lprec *lp)\n{\n  int i;\n  REAL *duals, *dualsfrom, *dualstill, *objfrom, *objtill, *objfromvalue;\n  MYBOOL ret;\n\n  if(lp->outstream == NULL)\n    return;\n\n  ret = get_ptr_sensitivity_objex(lp, &objfrom, &objtill, &objfromvalue, NULL);\n  if(ret) {\n    fprintf(lp->outstream, \"\\nObjective function limits:\\n\");\n    fprintf(lp->outstream, \"                                 From            Till       FromValue\\n\");\n    for(i = 1; i <= lp->columns; i++)\n      if(!is_splitvar(lp, i))\n        fprintf(lp->outstream, \"%-20s  %15.7g %15.7g %15.7g\\n\", get_col_name(lp, i),\n         (double)objfrom[i - 1], (double)objtill[i - 1], (double)objfromvalue[i - 1]);\n  }\n\n  ret = get_ptr_sensitivity_rhs(lp, &duals, &dualsfrom, &dualstill);\n  if(ret) {\n    fprintf(lp->outstream, \"\\nDual values with from - till limits:\\n\");\n    fprintf(lp->outstream, \"                           Dual value            From            Till\\n\");\n    for(i = 1; i <= lp->sum; i++)\n      fprintf(lp->outstream, \"%-20s  %15.7g %15.7g %15.7g\\n\",\n              (i <= lp->rows) ? get_row_name(lp, i) : get_col_name(lp, i - lp->rows),\n              (double)duals[i - 1], (double)dualsfrom[i - 1], (double)dualstill[i - 1]);\n    fflush(lp->outstream);\n  }\n}\n\n/* Printing of sensitivity analysis reports */\nvoid REPORT_extended(lprec *lp)\n{\n  int  i, j;\n  REAL hold;\n  REAL *duals, *dualsfrom, *dualstill, *objfrom, *objtill;\n  MYBOOL ret;\n\n  ret = get_ptr_sensitivity_obj(lp, &objfrom, &objtill);\n  report(lp, NORMAL, \" \\n\");\n  report(lp, NORMAL, \"Primal objective:\\n\");\n  report(lp, NORMAL, \" \\n\");\n  report(lp, NORMAL, \"  Column name                      Value   Objective         Min         Max\\n\");\n  report(lp, NORMAL, \"  --------------------------------------------------------------------------\\n\");\n  for(j = 1; j <= lp->columns; j++) {\n    hold = get_mat(lp,0,j);\n    report(lp, NORMAL, \"  %-25s \" MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK \"\\n\",\n           get_col_name(lp,j),\n           my_precision(hold,lp->epsprimal),\n           my_precision(hold*lp->best_solution[lp->rows+j],lp->epsprimal),\n           my_precision((ret) ? objfrom[j - 1] : 0.0,lp->epsprimal),\n           my_precision((ret) ? objtill[j - 1] : 0.0,lp->epsprimal));\n  }\n  report(lp, NORMAL, \" \\n\");\n\n  ret = get_ptr_sensitivity_rhs(lp, &duals, &dualsfrom, &dualstill);\n  report(lp, NORMAL, \"Primal variables:\\n\");\n  report(lp, NORMAL, \" \\n\");\n  report(lp, NORMAL, \"  Column name                      Value       Slack         Min         Max\\n\");\n  report(lp, NORMAL, \"  --------------------------------------------------------------------------\\n\");\n  for(j = 1; j <= lp->columns; j++)\n    report(lp, NORMAL, \"  %-25s \" MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK \"\\n\",\n           get_col_name(lp,j),\n           my_precision(lp->best_solution[lp->rows+j],lp->epsprimal),\n           my_precision(my_inflimit(lp, (ret) ? duals[lp->rows+j-1] : 0.0),lp->epsprimal),\n           my_precision((ret) ? dualsfrom[lp->rows+j-1] : 0.0,lp->epsprimal),\n           my_precision((ret) ? dualstill[lp->rows+j-1] : 0.0,lp->epsprimal));\n\n  report(lp, NORMAL, \" \\n\");\n  report(lp, NORMAL, \"Dual variables:\\n\");\n  report(lp, NORMAL, \" \\n\");\n  report(lp, NORMAL, \"  Row name                         Value       Slack         Min         Max\\n\");\n  report(lp, NORMAL, \"  --------------------------------------------------------------------------\\n\");\n  for(i = 1; i <= lp->rows; i++)\n    report(lp, NORMAL, \"  %-25s \" MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK MPSVALUEMASK \"\\n\",\n           get_row_name(lp,i),\n           my_precision((ret) ? duals[i - 1] : 0.0, lp->epsprimal),\n           my_precision(lp->best_solution[i], lp->epsprimal),\n           my_precision((ret) ? dualsfrom[i - 1] : 0.0,lp->epsprimal),\n           my_precision((ret) ? dualstill[i - 1] : 0.0,lp->epsprimal));\n\n  report(lp, NORMAL, \" \\n\");\n}\n\n/* A more readable lp-format report of the model; antiquated and not updated */\nvoid REPORT_lp(lprec *lp)\n{\n  int  i, j;\n\n  if(lp->outstream == NULL)\n    return;\n\n  fprintf(lp->outstream, \"Model name: %s\\n\", get_lp_name(lp));\n  fprintf(lp->outstream, \"          \");\n\n  for(j = 1; j <= lp->columns; j++)\n    fprintf(lp->outstream, \"%8s \", get_col_name(lp,j));\n\n  fprintf(lp->outstream, \"\\n%simize  \", (is_maxim(lp) ? \"Max\" : \"Min\"));\n  for(j = 1; j <= lp->columns; j++)\n      fprintf(lp->outstream, \"%8g \", get_mat(lp, 0, j));\n  fprintf(lp->outstream, \"\\n\");\n\n  for(i = 1; i <= lp->rows; i++) {\n    fprintf(lp->outstream, \"%-9s \", get_row_name(lp, i));\n    for(j = 1; j <= lp->columns; j++)\n      fprintf(lp->outstream, \"%8g \", get_mat(lp, i, j));\n    if(is_constr_type(lp, i, GE))\n      fprintf(lp->outstream, \">= \");\n    else if(is_constr_type(lp, i, LE))\n      fprintf(lp->outstream, \"<= \");\n    else\n      fprintf(lp->outstream, \" = \");\n    fprintf(lp->outstream, \"%8g\", get_rh(lp, i));\n\n    if(is_constr_type(lp, i, GE)) {\n      if(get_rh_upper(lp, i) < lp->infinite)\n        fprintf(lp->outstream, \"  %s = %8g\", \"upbo\", get_rh_upper(lp, i));\n    }\n    else if(is_constr_type(lp, i, LE)) {\n      if(get_rh_lower(lp, i) > -lp->infinite)\n        fprintf(lp->outstream, \"  %s = %8g\", \"lowbo\", get_rh_lower(lp, i));\n    }\n    fprintf(lp->outstream, \"\\n\");\n  }\n\n  fprintf(lp->outstream, \"Type      \");\n  for(i = 1; i <= lp->columns; i++) {\n    if(is_int(lp,i))\n      fprintf(lp->outstream, \"     Int \");\n    else\n      fprintf(lp->outstream, \"    Real \");\n  }\n\n  fprintf(lp->outstream, \"\\nupbo      \");\n  for(i = 1; i <= lp->columns; i++)\n    if(get_upbo(lp, i) >= lp->infinite)\n      fprintf(lp->outstream, \"     Inf \");\n    else\n      fprintf(lp->outstream, \"%8g \", get_upbo(lp, i));\n  fprintf(lp->outstream, \"\\nlowbo     \");\n  for(i = 1; i <= lp->columns; i++)\n    if(get_lowbo(lp, i) <= -lp->infinite)\n      fprintf(lp->outstream, \"    -Inf \");\n    else\n      fprintf(lp->outstream, \"%8g \", get_lowbo(lp, i));\n  fprintf(lp->outstream, \"\\n\");\n\n  fflush(lp->outstream);\n}\n\n/* Report the scaling factors used; extremely rarely used */\nvoid REPORT_scales(lprec *lp)\n{\n  int i, colMax;\n\n  colMax = lp->columns;\n\n  if(lp->outstream == NULL)\n    return;\n\n  if(lp->scaling_used) {\n    fprintf(lp->outstream, \"\\nScale factors:\\n\");\n    for(i = 0; i <= lp->rows + colMax; i++)\n      fprintf(lp->outstream, \"%-20s scaled at %g\\n\",\n              (i <= lp->rows) ? get_row_name(lp, i) : get_col_name(lp, i - lp->rows),\n        (double)lp->scalars[i]);\n  }\n  fflush(lp->outstream);\n}\n\n/* Report the traditional tableau corresponding to the current basis */\nMYBOOL REPORT_tableau(lprec *lp)\n{\n  int  j, row_nr, *coltarget;\n  REAL *prow = NULL;\n  FILE *stream = lp->outstream;\n\n  if(lp->outstream == NULL)\n    return(FALSE);\n\n  if(!lp->model_is_valid || !has_BFP(lp) ||\n     (get_total_iter(lp) == 0) || (lp->spx_status == NOTRUN)) {\n    lp->spx_status = NOTRUN;\n    return(FALSE);\n  }\n  if(!allocREAL(lp, &prow,lp->sum + 1, TRUE)) {\n    lp->spx_status = NOMEMORY;\n    return(FALSE);\n  }\n\n  fprintf(stream, \"\\n\");\n  fprintf(stream, \"Tableau at iter %.0f:\\n\", (double) get_total_iter(lp));\n\n  for(j = 1; j <= lp->sum; j++)\n    if (!lp->is_basic[j])\n      fprintf(stream, \"%15d\", (j <= lp->rows ?\n                               (j + lp->columns) * ((lp->orig_upbo[j] == 0) ||\n                                                    (is_chsign(lp, j)) ? 1 : -1) : j - lp->rows) *\n                              (lp->is_lower[j] ? 1 : -1));\n  fprintf(stream, \"\\n\");\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n  coltarget = (int *) mempool_obtainVector(lp->workarrays, lp->columns+1, sizeof(*coltarget));\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n  if(!get_colIndexA(lp, SCAN_USERVARS+USE_NONBASICVARS, coltarget, FALSE)) {\n    mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n    return(FALSE);\n  }\n  for(row_nr = 1; (row_nr <= lp->rows + 1); row_nr++) {\n    if (row_nr <= lp->rows)\n      fprintf(stream, \"%3d\", (lp->var_basic[row_nr] <= lp->rows ?\n                              (lp->var_basic[row_nr] + lp->columns) * ((lp->orig_upbo[lp->var_basic [row_nr]] == 0) ||\n                                                                       (is_chsign(lp, lp->var_basic[row_nr])) ? 1 : -1) : lp->var_basic[row_nr] - lp->rows) *\n                             (lp->is_lower[lp->var_basic [row_nr]] ? 1 : -1));\n    else\n      fprintf(stream, \"   \");\n    bsolve(lp, row_nr <= lp->rows ? row_nr : 0, prow, NULL, lp->epsmachine*DOUBLEROUND, 1.0);\n    prod_xA(lp, coltarget, prow, NULL, lp->epsmachine, 1.0,\n                                       prow, NULL, MAT_ROUNDDEFAULT);\n\n    for(j = 1; j <= lp->rows + lp->columns; j++)\n      if (!lp->is_basic[j])\n        fprintf(stream, \"%15.7f\", prow[j] * (lp->is_lower[j] ? 1 : -1) *\n                                            (row_nr <= lp->rows ? 1 : -1));\n    fprintf(stream, \"%15.7f\", lp->rhs[row_nr <= lp->rows ? row_nr : 0] *\n                              (double) ((row_nr <= lp->rows) || (is_maxim(lp)) ? 1 : -1));\n    fprintf(stream, \"\\n\");\n  }\n  fflush(stream);\n\n  mempool_releaseVector(lp->workarrays, (char *) coltarget, FALSE);\n  FREE(prow);\n  return(TRUE);\n}\n\nvoid REPORT_constraintinfo(lprec *lp, const char *datainfo)\n{\n  int i, tally[ROWCLASS_MAX+1];\n\n  MEMCLEAR(tally, ROWCLASS_MAX+1);\n  for(i = 1; i <= lp->rows; i++)\n    tally[get_constr_class(lp, i)]++;\n\n  if(datainfo != NULL)\n    report(lp, NORMAL, \"%s\\n\", datainfo);\n\n  for(i = 0; i <= ROWCLASS_MAX; i++)\n    if(tally[i] > 0)\n      report(lp, NORMAL, \"%-15s %4d\\n\", get_str_constr_class(lp, i), tally[i]);\n}\n\nvoid REPORT_modelinfo(lprec *lp, MYBOOL doName, const char *datainfo)\n{\n  if(doName) {\n    report(lp, NORMAL, \"\\nModel name:  '%s' - run #%-5d\\n\",\n                       get_lp_name(lp), lp->solvecount);\n    report(lp, NORMAL, \"Objective:   %simize(%s)\\n\",\n                       my_if(is_maxim(lp), \"Max\", \"Min\"), get_row_name(lp, 0));\n    report(lp, NORMAL, \" \\n\");\n  }\n  if(datainfo != NULL)\n    report(lp, NORMAL, \"%s\\n\", datainfo);\n\n  report(lp, NORMAL, \"Model size:  %7d constraints, %7d variables, %12d non-zeros.\\n\",\n         lp->rows, lp->columns, get_nonzeros(lp));\n  if(GUB_count(lp)+SOS_count(lp) > 0)\n  report(lp, NORMAL, \"Var-types:   %7d integer,     %7d semi-cont.,     %7d SOS.\\n\",\n         lp->int_vars, lp->sc_vars, lp->sos_vars);\n  report(lp, NORMAL, \"Sets:                             %7d GUB,            %7d SOS.\\n\",\n                         GUB_count(lp), SOS_count(lp));\n}\n\n/* Save a matrix column subset to a MatrixMarket formatted file,\n   say to export the basis matrix for further numerical analysis.\n   If colndx is NULL, then the full constraint matrix is assumed. */\nMYBOOL REPORT_mat_mmsave(lprec *lp, const char *filename, int *colndx, MYBOOL includeOF, const char *infotext)\n{\n  int         n, m, nz, i, j, k, kk;\n  MATrec      *mat = lp->matA;\n  MM_typecode matcode;\n  FILE        *output = stdout;\n  MYBOOL      ok;\n  REAL        *acol = NULL;\n  int         *nzlist = NULL;\n\n  /* Open file */\n  ok = (MYBOOL) ((filename == NULL) || ((output = fopen(filename,\"w\")) != NULL));\n  if(!ok)\n    return(ok);\n  if((filename == NULL) && (lp->outstream != NULL))\n    output = lp->outstream;\n\n  /* Compute column and non-zero counts */\n  if(colndx == lp->var_basic) {\n    if(!lp->basis_valid)\n      return( FALSE );\n    m = lp->rows;\n  }\n  else if(colndx != NULL)\n    m = colndx[0];\n  else\n    m = lp->columns;\n  n = lp->rows;\n  nz = 0;\n\n  for(j = 1; j <= m; j++) {\n    k = (colndx == NULL ? n + j : colndx[j]);\n    if(k > n) {\n      k -= lp->rows;\n      nz += mat_collength(mat, k);\n      if(includeOF && is_OF_nz(lp, k))\n        nz++;\n    }\n    else\n      nz++;\n  }\n  kk = 0;\n  if(includeOF) {\n    n++;   /* Row count */\n    kk++;  /* Row index offset */\n  }\n\n  /* Initialize */\n  mm_initialize_typecode(&matcode);\n  mm_set_matrix(&matcode);\n  mm_set_coordinate(&matcode);\n  mm_set_real(&matcode);\n\n  mm_write_banner(output, matcode);\n  mm_write_mtx_crd_size(output, n+kk, m, nz+(colndx == lp->var_basic ? 1 : 0));\n\n  /* Allocate working arrays for sparse column storage */\n  allocREAL(lp, &acol, n+2, FALSE);\n  allocINT(lp, &nzlist, n+2, FALSE);\n\n  /* Write the matrix non-zero values column-by-column.\n     NOTE: matrixMarket files use 1-based indeces,\n     i.e. first row of a vector has index 1, not 0. */\n  if(infotext != NULL) {\n    fprintf(output, \"%%\\n\");\n    fprintf(output, \"%% %s\\n\", infotext);\n    fprintf(output, \"%%\\n\");\n  }\n  if(includeOF && (colndx == lp->var_basic))\n    fprintf(output, \"%d %d %g\\n\", 1, 1, 1.0);\n  for(j = 1; j <= m; j++) {\n    k = (colndx == NULL ? lp->rows + j : colndx[j]);\n    if(k == 0)\n      continue;\n    nz = obtain_column(lp, k, acol, nzlist, NULL);\n    for(i = 1; i <= nz; i++) {\n      if(!includeOF && (nzlist[i] == 0))\n        continue;\n      fprintf(output, \"%d %d %g\\n\", nzlist[i]+kk, j+kk, acol[i]);\n    }\n  }\n  fprintf(output, \"%% End of MatrixMarket file\\n\");\n\n  /* Finish */\n  FREE(acol);\n  FREE(nzlist);\n  fclose(output);\n\n  return(ok);\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_report.h",
    "content": "#ifndef HEADER_lp_report\n#define HEADER_lp_report\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* General information functions */\nconst char * __VACALL explain(lprec *lp, const char *format, ...);\nvoid __VACALL report(lprec *lp, int level, const char * format, ...);\n\n/* Prototypes for debugging and general data dumps */\nvoid debug_print(lprec *lp, const char *format, ...);\nvoid debug_print_solution(lprec *lp);\nvoid debug_print_bounds(lprec *lp, REAL *upbo, REAL *lowbo);\nvoid blockWriteLREAL(FILE *output, const char *label, LREAL *vector, int first, int last);\nvoid blockWriteAMAT(FILE *output, const char *label, lprec* lp, int first, int last);\nvoid blockWriteBMAT(FILE *output, const char *label, lprec* lp, int first, int last);\n\n\n/* Model reporting headers */\nvoid REPORT_objective(lprec *lp);\nvoid REPORT_solution(lprec *lp, int columns);\nvoid REPORT_constraints(lprec *lp, int columns);\nvoid REPORT_duals(lprec *lp);\nvoid REPORT_extended(lprec *lp);\n\n/* Other rarely used, but sometimes extremely useful reports */\nvoid REPORT_constraintinfo(lprec *lp, const char *datainfo);\nvoid REPORT_modelinfo(lprec *lp, MYBOOL doName, const char *datainfo);\nvoid REPORT_lp(lprec *lp);\nMYBOOL REPORT_tableau(lprec *lp);\nvoid REPORT_scales(lprec *lp);\nMYBOOL REPORT_debugdump(lprec *lp, const char *filename, MYBOOL livedata);\nMYBOOL REPORT_mat_mmsave(lprec *lp, const char *filename, int *colndx, MYBOOL includeOF, const char *infotext);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_report */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_rlp.c",
    "content": "/* A Bison parser, made by GNU Bison 2.3.  */\n\n/* Skeleton implementation for Bison's Yacc-like parsers in C\n\n   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006\n   Free Software Foundation, Inc.\n\n   This program is free software; you can redistribute it and/or modify\n   it under the terms of the GNU General Public License as published by\n   the Free Software Foundation; either version 2, or (at your option)\n   any later version.\n\n   This program is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n   GNU General Public License for more details.\n\n   You should have received a copy of the GNU General Public License\n   along with this program; if not, write to the Free Software\n   Foundation, Inc., 51 Franklin Street, Fifth Floor,\n   Boston, MA 02110-1301, USA.  */\n\n/* As a special exception, you may create a larger work that contains\n   part or all of the Bison parser skeleton and distribute that work\n   under terms of your choice, so long as that work isn't itself a\n   parser generator using the skeleton or a modified version thereof\n   as a parser skeleton.  Alternatively, if you modify or redistribute\n   the parser skeleton itself, you may (at your option) remove this\n   special exception, which will cause the skeleton and the resulting\n   Bison output files to be licensed under the GNU General Public\n   License without this special exception.\n\n   This special exception was added by the Free Software Foundation in\n   version 2.2 of Bison.  */\n\n/* C LALR(1) parser skeleton written by Richard Stallman, by\n   simplifying the original so-called \"semantic\" parser.  */\n\n/* All symbols defined below should begin with lp_yy or YY, to avoid\n   infringing on user name space.  This should be done even for local\n   variables, as they might otherwise be expanded by user macros.\n   There are some unavoidable exceptions within include files to\n   define necessary library symbols; they are noted \"INFRINGES ON\n   USER NAME SPACE\" below.  */\n\n/* Identify Bison output.  */\n#define YYBISON 1\n\n/* Bison version.  */\n#define YYBISON_VERSION \"2.3\"\n\n/* Skeleton name.  */\n#define YYSKELETON_NAME \"yacc.c\"\n\n/* Pure parsers.  */\n#define YYPURE 1\n\n/* Using locations.  */\n#define YYLSP_NEEDED 0\n\n\n\n/* Tokens.  */\n#ifndef YYTOKENTYPE\n# define YYTOKENTYPE\n   /* Put the tokens into the symbol table, so that GDB and other debuggers\n      know about them.  */\n   enum lp_yytokentype {\n     VAR = 258,\n     CONS = 259,\n     INTCONS = 260,\n     VARIABLECOLON = 261,\n     INF = 262,\n     SEC_INT = 263,\n     SEC_BIN = 264,\n     SEC_SEC = 265,\n     SEC_SOS = 266,\n     SOSDESCR = 267,\n     SEC_FREE = 268,\n     TOK_SIGN = 269,\n     AR_M_OP = 270,\n     RE_OPEQ = 271,\n     RE_OPLE = 272,\n     RE_OPGE = 273,\n     END_C = 274,\n     COMMA = 275,\n     COLON = 276,\n     MINIMISE = 277,\n     MAXIMISE = 278,\n     UNDEFINED = 279\n   };\n#endif\n/* Tokens.  */\n#define VAR 258\n#define CONS 259\n#define INTCONS 260\n#define VARIABLECOLON 261\n#define INF 262\n#define SEC_INT 263\n#define SEC_BIN 264\n#define SEC_SEC 265\n#define SEC_SOS 266\n#define SOSDESCR 267\n#define SEC_FREE 268\n#define TOK_SIGN 269\n#define AR_M_OP 270\n#define RE_OPEQ 271\n#define RE_OPLE 272\n#define RE_OPGE 273\n#define END_C 274\n#define COMMA 275\n#define COLON 276\n#define MINIMISE 277\n#define MAXIMISE 278\n#define UNDEFINED 279\n\n\n\n\n/* Copy the first part of user declarations.  */\n\n\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n\n#define scanner lp_yyscanner\n#define PARM lp_yyget_extra(lp_yyscanner)\n#define YYSTYPE int\n#define YY_EXTRA_TYPE parse_parm *\n#define YY_FATAL_ERROR(msg) lex_fatal_error(PARM, lp_yyscanner, msg)\n#undef YY_INPUT\n#define YY_INPUT(buf,result,max_size) result = lp_input((void *) PARM, buf, max_size);\n#define lp_yyerror read_error\n\n#include \"lpkit.h\"\n#include \"yacc_read.h\"\n\ntypedef struct parse_vars_s\n{\n  read_modeldata_func *lp_input;\n  void *userhandle;\n  char HadVar, HadVar0, HadVar1, HadVar2, HasAR_M_OP, HadConstraint, Had_lineair_sum, Had_lineair_sum0, do_add_row, HadSign, OP, Sign, isign, isign0, make_neg;\n  char state, state0;\n  char Within_int_decl;  /* TRUE when we are within an char declaration */\n  char Within_bin_decl;  /* TRUE when we are within an bin declaration */\n  char Within_sec_decl;  /* TRUE when we are within a sec declaration */\n  char Within_sos_decl;  /* TRUE when we are within a sos declaration */\n  char Within_sos_decl1;\n  char Within_free_decl; /* TRUE when we are within a free declaration */\n  short SOStype, SOStype0;        /* SOS type */\n  int SOSNr;\n  int SOSweight;         /* SOS weight */\n  char *Last_var, *Last_var0;\n  REAL f, f0, f1;\n} parse_vars;\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n/* let's please C++ users */\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if defined MSDOS || defined __MSDOS__ || defined WINDOWS || defined _WINDOWS || defined WIN32 || defined _WIN32\n#define YY_NO_UNISTD_H\n\nstatic int isatty(int f)\n{\n  return(FALSE);\n}\n\n#if !defined _STDLIB_H\n# define _STDLIB_H\n#endif\n#endif\n\nstatic int __WINAPI lp_input_lp_yyin(void *fpin, char *buf, int max_size)\n{\n  int result;\n\n  result = fread( (char*)buf, sizeof(char), max_size, (FILE *)fpin);\n\n  return(result);\n}\n\nstatic int __WINAPI lp_input(void *vpp, char *buf, int max_size)\n{\n  parse_parm *pp = (parse_parm *) vpp;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n  int result;\n\n  result = pv->lp_input(pv->userhandle, buf, max_size);\n  if (result < 0)\n    lex_fatal_error(pp, pp->scanner, \"read() in flex scanner failed\");\n  return(result);\n}\n\n#ifdef __cplusplus\n};\n#endif\n\n#include \"lp_rlp.h\"\n\n#undef lp_yylval\n\n\n\n/* Enabling traces.  */\n#ifndef YYDEBUG\n# define YYDEBUG 0\n#endif\n\n/* Enabling verbose error messages.  */\n#ifdef YYERROR_VERBOSE\n# undef YYERROR_VERBOSE\n# define YYERROR_VERBOSE 1\n#else\n# define YYERROR_VERBOSE 0\n#endif\n\n/* Enabling the token table.  */\n#ifndef YYTOKEN_TABLE\n# define YYTOKEN_TABLE 0\n#endif\n\n#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED\ntypedef int YYSTYPE;\n# define lp_yystype YYSTYPE /* obsolescent; will be withdrawn */\n# define YYSTYPE_IS_DECLARED 1\n# define YYSTYPE_IS_TRIVIAL 1\n#endif\n\n\n\n/* Copy the second part of user declarations.  */\n\n\n/* Line 216 of yacc.c.  */\n\n\n#ifdef short\n# undef short\n#endif\n\n#ifdef YYTYPE_UINT8\ntypedef YYTYPE_UINT8 lp_yytype_uint8;\n#else\ntypedef unsigned char lp_yytype_uint8;\n#endif\n\n#ifdef YYTYPE_INT8\ntypedef YYTYPE_INT8 lp_yytype_int8;\n#elif (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\ntypedef signed char lp_yytype_int8;\n#else\ntypedef short int lp_yytype_int8;\n#endif\n\n#ifdef YYTYPE_UINT16\ntypedef YYTYPE_UINT16 lp_yytype_uint16;\n#else\ntypedef unsigned short int lp_yytype_uint16;\n#endif\n\n#ifdef YYTYPE_INT16\ntypedef YYTYPE_INT16 lp_yytype_int16;\n#else\ntypedef short int lp_yytype_int16;\n#endif\n\n#ifndef YYSIZE_T\n# ifdef __SIZE_TYPE__\n#  define YYSIZE_T __SIZE_TYPE__\n# elif defined size_t\n#  define YYSIZE_T size_t\n# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\n#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */\n#  define YYSIZE_T size_t\n# else\n#  define YYSIZE_T unsigned int\n# endif\n#endif\n\n#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)\n\n#ifndef YY_\n# if YYENABLE_NLS\n#  if ENABLE_NLS\n#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */\n#   define YY_(msgid) dgettext (\"bison-runtime\", msgid)\n#  endif\n# endif\n# ifndef YY_\n#  define YY_(msgid) msgid\n# endif\n#endif\n\n/* Suppress unused-variable warnings by \"using\" E.  */\n#if ! defined lint || defined __GNUC__\n# define YYUSE(e) ((void) (e))\n#else\n# define YYUSE(e) /* empty */\n#endif\n\n/* Identity function, used to suppress warnings about constant conditions.  */\n#ifndef lint\n# define YYID(n) (n)\n#else\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic int\nYYID (int i)\n#else\nstatic int\nYYID (i)\n    int i;\n#endif\n{\n  return i;\n}\n#endif\n\n#if ! defined lp_yyoverflow || YYERROR_VERBOSE\n\n/* The parser invokes alloca or malloc; define the necessary symbols.  */\n\n# ifdef YYSTACK_USE_ALLOCA\n#  if YYSTACK_USE_ALLOCA\n#   ifdef __GNUC__\n#    define YYSTACK_ALLOC __builtin_alloca\n#   elif defined __BUILTIN_VA_ARG_INCR\n#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */\n#   elif defined _AIX\n#    define YYSTACK_ALLOC __alloca\n#   elif defined _MSC_VER\n#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */\n#    define alloca _alloca\n#   else\n#    define YYSTACK_ALLOC alloca\n#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\n#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */\n#     ifndef _STDLIB_H\n#      define _STDLIB_H 1\n#     endif\n#    endif\n#   endif\n#  endif\n# endif\n\n# ifdef YYSTACK_ALLOC\n   /* Pacify GCC's `empty if-body' warning.  */\n#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))\n#  ifndef YYSTACK_ALLOC_MAXIMUM\n    /* The OS might guarantee only one guard page at the bottom of the stack,\n       and a page size can be as small as 4096 bytes.  So we cannot safely\n       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number\n       to allow for a few compiler-allocated temporary stack slots.  */\n#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */\n#  endif\n# else\n#  define YYSTACK_ALLOC YYMALLOC\n#  define YYSTACK_FREE YYFREE\n#  ifndef YYSTACK_ALLOC_MAXIMUM\n#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM\n#  endif\n#  if (defined __cplusplus && ! defined _STDLIB_H \\\n       && ! ((defined YYMALLOC || defined malloc) \\\n\t     && (defined YYFREE || defined free)))\n#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */\n#   ifndef _STDLIB_H\n#    define _STDLIB_H 1\n#   endif\n#  endif\n#  ifndef YYMALLOC\n#   define YYMALLOC malloc\n#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nvoid *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */\n#   endif\n#  endif\n#  ifndef YYFREE\n#   define YYFREE free\n#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nvoid free (void *); /* INFRINGES ON USER NAME SPACE */\n#   endif\n#  endif\n# endif\n#endif /* ! defined lp_yyoverflow || YYERROR_VERBOSE */\n\n\n#if (! defined lp_yyoverflow \\\n     && (! defined __cplusplus \\\n\t || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))\n\n/* A type that is properly aligned for any stack member.  */\nunion lp_yyalloc\n{\n  lp_yytype_int16 lp_yyss;\n  YYSTYPE lp_yyvs;\n  };\n\n/* The size of the maximum gap between one aligned stack and the next.  */\n# define YYSTACK_GAP_MAXIMUM (sizeof (union lp_yyalloc) - 1)\n\n/* The size of an array large to enough to hold all stacks, each with\n   N elements.  */\n# define YYSTACK_BYTES(N) \\\n     ((N) * (sizeof (lp_yytype_int16) + sizeof (YYSTYPE)) \\\n      + YYSTACK_GAP_MAXIMUM)\n\n/* Copy COUNT objects from FROM to TO.  The source and destination do\n   not overlap.  */\n# ifndef YYCOPY\n#  if defined __GNUC__ && 1 < __GNUC__\n#   define YYCOPY(To, From, Count) \\\n      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))\n#  else\n#   define YYCOPY(To, From, Count)\t\t\\\n      do\t\t\t\t\t\\\n\t{\t\t\t\t\t\\\n\t  YYSIZE_T lp_yyi;\t\t\t\t\\\n\t  for (lp_yyi = 0; lp_yyi < (Count); lp_yyi++)\t\\\n\t    (To)[lp_yyi] = (From)[lp_yyi];\t\t\\\n\t}\t\t\t\t\t\\\n      while (YYID (0))\n#  endif\n# endif\n\n/* Relocate STACK from its old location to the new one.  The\n   local variables YYSIZE and YYSTACKSIZE give the old and new number of\n   elements in the stack, and YYPTR gives the new location of the\n   stack.  Advance YYPTR to a properly aligned location for the next\n   stack.  */\n# define YYSTACK_RELOCATE(Stack)\t\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n      {\t\t\t\t\t\t\t\t\t\\\n\tYYSIZE_T lp_yynewbytes;\t\t\t\t\t\t\\\n\tYYCOPY (&lp_yyptr->Stack, Stack, lp_yysize);\t\t\t\t\\\n\tStack = &lp_yyptr->Stack;\t\t\t\t\t\t\\\n\tlp_yynewbytes = lp_yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \\\n\tlp_yyptr += lp_yynewbytes / sizeof (*lp_yyptr);\t\t\t\t\\\n      }\t\t\t\t\t\t\t\t\t\\\n    while (YYID (0))\n\n#endif\n\n/* YYFINAL -- State number of the termination state.  */\n#define YYFINAL  3\n/* YYLAST -- Last index in YYTABLE.  */\n#define YYLAST   115\n\n/* YYNTOKENS -- Number of terminals.  */\n#define YYNTOKENS  25\n/* YYNNTS -- Number of nonterminals.  */\n#define YYNNTS  56\n/* YYNRULES -- Number of rules.  */\n#define YYNRULES  89\n/* YYNRULES -- Number of states.  */\n#define YYNSTATES  123\n\n/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */\n#define YYUNDEFTOK  2\n#define YYMAXUTOK   279\n\n#define YYTRANSLATE(YYX)\t\t\t\t\t\t\\\n  ((unsigned int) (YYX) <= YYMAXUTOK ? lp_yytranslate[YYX] : YYUNDEFTOK)\n\n/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */\nstatic const lp_yytype_uint8 lp_yytranslate[] =\n{\n       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,\n       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,\n       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,\n      15,    16,    17,    18,    19,    20,    21,    22,    23,    24\n};\n\n#if YYDEBUG\n/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in\n   YYRHS.  */\nstatic const lp_yytype_uint8 lp_yyprhs[] =\n{\n       0,     0,     3,     4,     5,    10,    13,    16,    18,    21,\n      23,    25,    27,    29,    31,    34,    36,    37,    41,    42,\n      43,    44,    53,    55,    56,    57,    63,    65,    67,    69,\n      70,    74,    75,    78,    80,    83,    86,    88,    89,    93,\n      95,    97,    99,   102,   104,   106,   108,   110,   112,   114,\n     116,   118,   120,   122,   124,   127,   129,   131,   133,   135,\n     137,   138,   142,   143,   149,   151,   154,   156,   157,   161,\n     163,   164,   169,   171,   174,   176,   178,   180,   184,   186,\n     188,   190,   191,   193,   195,   198,   202,   205,   208,   211\n};\n\n/* YYRHS -- A `-1'-separated list of the rules' RHS.  */\nstatic const lp_yytype_int8 lp_yyrhs[] =\n{\n      27,     0,    -1,    -1,    -1,    28,    29,    32,    58,    -1,\n      23,    30,    -1,    22,    30,    -1,    30,    -1,    31,    19,\n      -1,    26,    -1,    46,    -1,    26,    -1,    33,    -1,    34,\n      -1,    33,    34,    -1,    36,    -1,    -1,     6,    35,    36,\n      -1,    -1,    -1,    -1,    43,    37,    52,    38,    44,    39,\n      40,    19,    -1,    26,    -1,    -1,    -1,    52,    41,    53,\n      42,    57,    -1,    26,    -1,    44,    -1,    46,    -1,    -1,\n       7,    45,    57,    -1,    -1,    47,    48,    -1,    49,    -1,\n      48,    49,    -1,    55,    50,    -1,    54,    -1,    -1,    56,\n      51,     3,    -1,    16,    -1,    17,    -1,    18,    -1,    55,\n      54,    -1,     7,    -1,     5,    -1,     4,    -1,    26,    -1,\n      14,    -1,    26,    -1,    15,    -1,    26,    -1,    26,    -1,\n      59,    -1,    61,    -1,    59,    61,    -1,     8,    -1,     9,\n      -1,    10,    -1,    11,    -1,    13,    -1,    -1,    60,    62,\n      65,    -1,    -1,    64,    66,    71,    68,    19,    -1,    63,\n      -1,    65,    63,    -1,    26,    -1,    -1,    12,    67,    77,\n      -1,    26,    -1,    -1,    17,     5,    69,    70,    -1,    26,\n      -1,    21,     5,    -1,    26,    -1,    72,    -1,    78,    -1,\n      72,    73,    78,    -1,    26,    -1,    20,    -1,    26,    -1,\n      -1,    26,    -1,    26,    -1,     3,    74,    -1,     6,    75,\n      79,    -1,    54,    76,    -1,    77,    80,    -1,     3,    74,\n      -1,     6,    75,    54,    76,    -1\n};\n\n/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */\nstatic const lp_yytype_uint16 lp_yyrline[] =\n{\n       0,   116,   116,   120,   120,   145,   149,   153,   156,   170,\n     171,   201,   202,   205,   206,   210,   212,   211,   224,   232,\n     242,   223,   288,   298,   311,   297,   342,   355,   364,   366,\n     365,   376,   376,   400,   401,   405,   444,   452,   451,   470,\n     470,   470,   473,   475,   489,   489,   492,   500,   510,   517,\n     526,   547,   548,   551,   552,   555,   555,   555,   555,   555,\n     560,   559,   570,   570,   598,   599,   602,   604,   603,   614,\n     626,   624,   643,   650,   660,   661,   664,   665,   670,   671,\n     674,   703,   724,   749,   770,   772,   777,   779,   784,   786\n};\n#endif\n\n#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE\n/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.\n   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */\nstatic const char *const lp_yytname[] =\n{\n  \"$end\", \"error\", \"$undefined\", \"VAR\", \"CONS\", \"INTCONS\",\n  \"VARIABLECOLON\", \"INF\", \"SEC_INT\", \"SEC_BIN\", \"SEC_SEC\", \"SEC_SOS\",\n  \"SOSDESCR\", \"SEC_FREE\", \"TOK_SIGN\", \"AR_M_OP\", \"RE_OPEQ\", \"RE_OPLE\",\n  \"RE_OPGE\", \"END_C\", \"COMMA\", \"COLON\", \"MINIMISE\", \"MAXIMISE\",\n  \"UNDEFINED\", \"$accept\", \"EMPTY\", \"inputfile\", \"@1\", \"objective_function\",\n  \"real_of\", \"lineair_sum\", \"constraints\", \"x_constraints\", \"constraint\",\n  \"@2\", \"real_constraint\", \"@3\", \"@4\", \"@5\", \"optionalrange\", \"@6\", \"@7\",\n  \"x_lineair_sum2\", \"x_lineair_sum3\", \"@8\", \"x_lineair_sum\", \"@9\",\n  \"x_lineair_sum1\", \"x_lineair_term\", \"x_lineair_term1\", \"@10\", \"RE_OP\",\n  \"cons_term\", \"REALCONS\", \"x_SIGN\", \"optional_AR_M_OP\", \"RHS_STORE\",\n  \"int_bin_sec_sos_free_declarations\", \"real_int_bin_sec_sos_free_decls\",\n  \"SEC_INT_BIN_SEC_SOS_FREE\", \"int_bin_sec_sos_free_declaration\", \"@11\",\n  \"xx_int_bin_sec_sos_free_declaration\", \"@12\",\n  \"x_int_bin_sec_sos_free_declaration\", \"optionalsos\", \"@13\",\n  \"optionalsostype\", \"@14\", \"optionalSOSweight\", \"vars\", \"x_vars\",\n  \"optionalcomma\", \"variable\", \"variablecolon\", \"sosweight\", \"sosdescr\",\n  \"onevarwithoptionalweight\", \"INTCONSorVARIABLE\",\n  \"x_onevarwithoptionalweight\", 0\n};\n#endif\n\n# ifdef YYPRINT\n/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to\n   token YYLEX-NUM.  */\nstatic const lp_yytype_uint16 lp_yytoknum[] =\n{\n       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,\n     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,\n     275,   276,   277,   278,   279\n};\n# endif\n\n/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */\nstatic const lp_yytype_uint8 lp_yyr1[] =\n{\n       0,    25,    26,    28,    27,    29,    29,    29,    30,    31,\n      31,    32,    32,    33,    33,    34,    35,    34,    37,    38,\n      39,    36,    40,    41,    42,    40,    43,    43,    44,    45,\n      44,    47,    46,    48,    48,    49,    50,    51,    50,    52,\n      52,    52,    53,    53,    54,    54,    55,    55,    56,    56,\n      57,    58,    58,    59,    59,    60,    60,    60,    60,    60,\n      62,    61,    64,    63,    65,    65,    66,    67,    66,    68,\n      69,    68,    70,    70,    71,    71,    72,    72,    73,    73,\n      74,    75,    76,    77,    78,    78,    79,    79,    80,    80\n};\n\n/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */\nstatic const lp_yytype_uint8 lp_yyr2[] =\n{\n       0,     2,     0,     0,     4,     2,     2,     1,     2,     1,\n       1,     1,     1,     1,     2,     1,     0,     3,     0,     0,\n       0,     8,     1,     0,     0,     5,     1,     1,     1,     0,\n       3,     0,     2,     1,     2,     2,     1,     0,     3,     1,\n       1,     1,     2,     1,     1,     1,     1,     1,     1,     1,\n       1,     1,     1,     1,     2,     1,     1,     1,     1,     1,\n       0,     3,     0,     5,     1,     2,     1,     0,     3,     1,\n       0,     4,     1,     2,     1,     1,     1,     3,     1,     1,\n       1,     0,     1,     1,     2,     3,     2,     2,     2,     4\n};\n\n/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state\n   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero\n   means the default is an error.  */\nstatic const lp_yytype_uint8 lp_yydefact[] =\n{\n       3,     0,    31,     1,    31,    31,     9,     2,     7,     0,\n      10,     2,     6,     5,    16,    29,    11,     2,    12,    13,\n      15,    18,    27,    28,     8,    47,    46,     2,    33,     2,\n      31,     2,    55,    56,    57,    58,    59,    51,     4,    52,\n      60,    53,    26,    14,     0,    34,    45,    44,    49,    48,\n      35,    36,    37,    17,    50,    30,    54,    62,    39,    40,\n      41,    19,     0,    64,     2,    61,    31,    38,    67,    66,\n       2,    65,    20,     2,     2,    81,    74,     2,     2,    76,\n       2,    83,    68,    80,    84,     2,     0,    69,     0,    79,\n      78,     0,    22,     0,    23,     2,     0,    85,    70,    63,\n      77,    21,     2,    82,    86,     2,    81,    87,     2,    43,\n      24,     0,    88,     0,     0,    72,    71,     2,    42,     2,\n      73,    25,    89\n};\n\n/* YYDEFGOTO[NTERM-NUM].  */\nstatic const lp_yytype_int8 lp_yydefgoto[] =\n{\n      -1,     6,     1,     2,     7,     8,     9,    17,    18,    19,\n      30,    20,    44,    66,    80,    93,   102,   117,    21,    22,\n      31,    23,    11,    27,    28,    50,    62,    61,   110,    51,\n      29,    52,    55,    38,    39,    40,    41,    57,    63,    64,\n      65,    70,    73,    88,   108,   116,    77,    78,    91,    84,\n      85,   104,    82,    79,    97,   107\n};\n\n/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing\n   STATE-NUM.  */\n#define YYPACT_NINF -85\nstatic const lp_yytype_int8 lp_yypact[] =\n{\n     -85,    13,    46,   -85,     2,     2,   -85,    32,   -85,     7,\n     -85,    26,   -85,   -85,   -85,   -85,    64,    40,    27,   -85,\n     -85,   -85,   -85,   -85,   -85,   -85,   -85,    42,   -85,     3,\n      -2,   -85,   -85,   -85,   -85,   -85,   -85,   -85,   -85,    40,\n     -85,   -85,   -85,   -85,    67,   -85,   -85,   -85,   -85,   -85,\n     -85,   -85,   -85,   -85,   -85,   -85,   -85,   -85,   -85,   -85,\n     -85,   -85,    59,   -85,    52,     0,    84,   -85,   -85,   -85,\n      22,   -85,   -85,   -85,   -85,   -85,   -85,    60,    35,   -85,\n      67,   -85,   -85,   -85,   -85,    82,    87,   -85,    74,   -85,\n     -85,    22,   -85,    75,   -85,   -85,    73,   -85,   -85,   -85,\n     -85,   -85,    -5,   -85,   -85,   -85,   -85,   -85,    76,   -85,\n     -85,    82,   -85,    82,    91,   -85,   -85,   -85,   -85,   -85,\n     -85,   -85,   -85\n};\n\n/* YYPGOTO[NTERM-NUM].  */\nstatic const lp_yytype_int8 lp_yypgoto[] =\n{\n     -85,    -7,   -85,   -85,   -85,    85,   -85,   -85,   -85,    81,\n     -85,    72,   -85,   -85,   -85,   -85,   -85,   -85,   -85,    34,\n     -85,    70,   -85,   -85,    77,   -85,   -85,    23,   -85,   -84,\n       4,   -85,   -12,   -85,   -85,   -85,    68,   -85,    43,   -85,\n     -85,   -85,   -85,   -85,   -85,   -85,   -85,   -85,   -85,     6,\n       8,   -10,    28,    24,   -85,   -85\n};\n\n/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If\n   positive, shift that token.  If negative, reduce the rule which\n   number is the opposite.  If zero, do what YYDEFACT says.\n   If YYTABLE_NINF, syntax error.  */\n#define YYTABLE_NINF -76\nstatic const lp_yytype_int8 lp_yytable[] =\n{\n      16,    95,   109,   -62,    26,    15,   -62,    46,    47,    25,\n      37,    42,   -62,     3,    -2,    -2,    -2,   -62,    48,   -62,\n      26,    -2,    49,    42,    54,    74,    24,   118,    75,   119,\n     -31,   -31,   -31,    14,    15,   -31,   -31,   -31,    14,    15,\n      25,   -31,   -31,    -2,    -2,    -2,   -31,   -31,    32,    33,\n      34,    35,   -75,    36,   -75,    89,    25,    69,   -32,   -32,\n     -32,   -32,    67,    76,    68,    -2,    81,    83,     4,     5,\n      87,    90,    10,    92,    10,    10,   105,    86,    81,   106,\n     -26,   -26,   -26,    58,    59,    60,    46,    47,   103,    12,\n      13,    15,    98,    99,   101,    26,   120,   114,    83,    43,\n      72,   115,    53,    94,    45,   121,   111,    56,    71,   122,\n      54,   112,   103,    96,   113,   100\n};\n\nstatic const lp_yytype_uint8 lp_yycheck[] =\n{\n       7,    85,     7,     3,    11,     7,     6,     4,     5,    14,\n      17,    18,    12,     0,    16,    17,    18,    17,    15,    19,\n      27,    19,    29,    30,    31,     3,    19,   111,     6,   113,\n       3,     4,     5,     6,     7,     3,     4,     5,     6,     7,\n      14,    14,    15,    16,    17,    18,    14,    15,     8,     9,\n      10,    11,    17,    13,    19,    20,    14,    64,    16,    17,\n      18,    19,     3,    70,    12,    19,    73,    74,    22,    23,\n      77,    78,     2,    80,     4,     5,     3,    17,    85,     6,\n      16,    17,    18,    16,    17,    18,     4,     5,    95,     4,\n       5,     7,     5,    19,    19,   102,     5,    21,   105,    18,\n      66,   108,    30,    80,    27,   117,   102,    39,    65,   119,\n     117,   105,   119,    85,   106,    91\n};\n\n/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing\n   symbol of state STATE-NUM.  */\nstatic const lp_yytype_uint8 lp_yystos[] =\n{\n       0,    27,    28,     0,    22,    23,    26,    29,    30,    31,\n      46,    47,    30,    30,     6,     7,    26,    32,    33,    34,\n      36,    43,    44,    46,    19,    14,    26,    48,    49,    55,\n      35,    45,     8,     9,    10,    11,    13,    26,    58,    59,\n      60,    61,    26,    34,    37,    49,     4,     5,    15,    26,\n      50,    54,    56,    36,    26,    57,    61,    62,    16,    17,\n      18,    52,    51,    63,    64,    65,    38,     3,    12,    26,\n      66,    63,    44,    67,     3,     6,    26,    71,    72,    78,\n      39,    26,    77,    26,    74,    75,    17,    26,    68,    20,\n      26,    73,    26,    40,    52,    54,    77,    79,     5,    19,\n      78,    19,    41,    26,    76,     3,     6,    80,    69,     7,\n      53,    55,    74,    75,    21,    26,    70,    42,    54,    54,\n       5,    57,    76\n};\n\n#define lp_yyerrok\t\t(lp_yyerrstatus = 0)\n#define lp_yyclearin\t(lp_yychar = YYEMPTY)\n#define YYEMPTY\t\t(-2)\n#define YYEOF\t\t0\n\n#define YYACCEPT\tgoto lp_yyacceptlab\n#define YYABORT\t\tgoto lp_yyabortlab\n#define YYERROR\t\tgoto lp_yyerrorlab\n\n\n/* Like YYERROR except do call lp_yyerror.  This remains here temporarily\n   to ease the transition to the new meaning of YYERROR, for GCC.\n   Once GCC version 2 has supplanted version 1, this can go.  */\n\n#define YYFAIL\t\tgoto lp_yyerrlab\n\n#define YYRECOVERING()  (!!lp_yyerrstatus)\n\n#define YYBACKUP(Token, Value)\t\t\t\t\t\\\ndo\t\t\t\t\t\t\t\t\\\n  if (lp_yychar == YYEMPTY && lp_yylen == 1)\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      lp_yychar = (Token);\t\t\t\t\t\t\\\n      lp_yylval = (Value);\t\t\t\t\t\t\\\n      lp_yytoken = YYTRANSLATE (lp_yychar);\t\t\t\t\\\n      YYPOPSTACK (1);\t\t\t\t\t\t\\\n      goto lp_yybackup;\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\\\n  else\t\t\t\t\t\t\t\t\\\n    {\t\t\t\t\t\t\t\t\\\n      lp_yyerror (parm, scanner, YY_(\"syntax error: cannot back up\")); \\\n      YYERROR;\t\t\t\t\t\t\t\\\n    }\t\t\t\t\t\t\t\t\\\nwhile (YYID (0))\n\n\n#define YYTERROR\t1\n#define YYERRCODE\t256\n\n\n/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].\n   If N is 0, then set CURRENT to the empty location which ends\n   the previous symbol: RHS[0] (always defined).  */\n\n#define YYRHSLOC(Rhs, K) ((Rhs)[K])\n#ifndef YYLLOC_DEFAULT\n# define YYLLOC_DEFAULT(Current, Rhs, N)\t\t\t\t\\\n    do\t\t\t\t\t\t\t\t\t\\\n      if (YYID (N))                                                    \\\n\t{\t\t\t\t\t\t\t\t\\\n\t  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;\t\\\n\t  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;\t\\\n\t  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;\t\t\\\n\t  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;\t\\\n\t}\t\t\t\t\t\t\t\t\\\n      else\t\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\\\n\t  (Current).first_line   = (Current).last_line   =\t\t\\\n\t    YYRHSLOC (Rhs, 0).last_line;\t\t\t\t\\\n\t  (Current).first_column = (Current).last_column =\t\t\\\n\t    YYRHSLOC (Rhs, 0).last_column;\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\\\n    while (YYID (0))\n#endif\n\n\n/* YY_LOCATION_PRINT -- Print the location on the stream.\n   This macro was not mandated originally: define only if we know\n   we won't break user code: when these are the locations we know.  */\n\n#ifndef YY_LOCATION_PRINT\n# if YYLTYPE_IS_TRIVIAL\n#  define YY_LOCATION_PRINT(File, Loc)\t\t\t\\\n     fprintf (File, \"%d.%d-%d.%d\",\t\t\t\\\n\t      (Loc).first_line, (Loc).first_column,\t\\\n\t      (Loc).last_line,  (Loc).last_column)\n# else\n#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)\n# endif\n#endif\n\n\n/* YYLEX -- calling `lp_yylex' with the right arguments.  */\n\n#ifdef YYLEX_PARAM\n# define YYLEX lp_yylex (&lp_yylval, YYLEX_PARAM)\n#else\n# define YYLEX lp_yylex (&lp_yylval, scanner)\n#endif\n\n/* Enable debugging if requested.  */\n#if YYDEBUG\n\n# ifndef YYFPRINTF\n#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */\n#  define YYFPRINTF fprintf\n# endif\n\n# define YYDPRINTF(Args)\t\t\t\\\ndo {\t\t\t\t\t\t\\\n  if (lp_yydebug)\t\t\t\t\t\\\n    YYFPRINTF Args;\t\t\t\t\\\n} while (YYID (0))\n\n# define YY_SYMBOL_PRINT(Title, Type, Value, Location)\t\t\t  \\\ndo {\t\t\t\t\t\t\t\t\t  \\\n  if (lp_yydebug)\t\t\t\t\t\t\t\t  \\\n    {\t\t\t\t\t\t\t\t\t  \\\n      YYFPRINTF (stderr, \"%s \", Title);\t\t\t\t\t  \\\n      lp_yy_symbol_print (stderr,\t\t\t\t\t\t  \\\n\t\t  Type, Value, parm, scanner); \\\n      YYFPRINTF (stderr, \"\\n\");\t\t\t\t\t\t  \\\n    }\t\t\t\t\t\t\t\t\t  \\\n} while (YYID (0))\n\n\n/*--------------------------------.\n| Print this symbol on YYOUTPUT.  |\n`--------------------------------*/\n\n/*ARGSUSED*/\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nlp_yy_symbol_value_print (FILE *lp_yyoutput, int lp_yytype, YYSTYPE const * const lp_yyvaluep, parse_parm *parm, void *scanner)\n#else\nstatic void\nlp_yy_symbol_value_print (lp_yyoutput, lp_yytype, lp_yyvaluep, parm, scanner)\n    FILE *lp_yyoutput;\n    int lp_yytype;\n    YYSTYPE const * const lp_yyvaluep;\n    parse_parm *parm;\n    void *scanner;\n#endif\n{\n  if (!lp_yyvaluep)\n    return;\n  YYUSE (parm);\n  YYUSE (scanner);\n# ifdef YYPRINT\n  if (lp_yytype < YYNTOKENS)\n    YYPRINT (lp_yyoutput, lp_yytoknum[lp_yytype], *lp_yyvaluep);\n# else\n  YYUSE (lp_yyoutput);\n# endif\n  switch (lp_yytype)\n    {\n      default:\n\tbreak;\n    }\n}\n\n\n/*--------------------------------.\n| Print this symbol on YYOUTPUT.  |\n`--------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nlp_yy_symbol_print (FILE *lp_yyoutput, int lp_yytype, YYSTYPE const * const lp_yyvaluep, parse_parm *parm, void *scanner)\n#else\nstatic void\nlp_yy_symbol_print (lp_yyoutput, lp_yytype, lp_yyvaluep, parm, scanner)\n    FILE *lp_yyoutput;\n    int lp_yytype;\n    YYSTYPE const * const lp_yyvaluep;\n    parse_parm *parm;\n    void *scanner;\n#endif\n{\n  if (lp_yytype < YYNTOKENS)\n    YYFPRINTF (lp_yyoutput, \"token %s (\", lp_yytname[lp_yytype]);\n  else\n    YYFPRINTF (lp_yyoutput, \"nterm %s (\", lp_yytname[lp_yytype]);\n\n  lp_yy_symbol_value_print (lp_yyoutput, lp_yytype, lp_yyvaluep, parm, scanner);\n  YYFPRINTF (lp_yyoutput, \")\");\n}\n\n/*------------------------------------------------------------------.\n| lp_yy_stack_print -- Print the state stack from its BOTTOM up to its |\n| TOP (included).                                                   |\n`------------------------------------------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nlp_yy_stack_print (lp_yytype_int16 *bottom, lp_yytype_int16 *top)\n#else\nstatic void\nlp_yy_stack_print (bottom, top)\n    lp_yytype_int16 *bottom;\n    lp_yytype_int16 *top;\n#endif\n{\n  YYFPRINTF (stderr, \"Stack now\");\n  for (; bottom <= top; ++bottom)\n    YYFPRINTF (stderr, \" %d\", *bottom);\n  YYFPRINTF (stderr, \"\\n\");\n}\n\n# define YY_STACK_PRINT(Bottom, Top)\t\t\t\t\\\ndo {\t\t\t\t\t\t\t\t\\\n  if (lp_yydebug)\t\t\t\t\t\t\t\\\n    lp_yy_stack_print ((Bottom), (Top));\t\t\t\t\\\n} while (YYID (0))\n\n\n/*------------------------------------------------.\n| Report that the YYRULE is going to be reduced.  |\n`------------------------------------------------*/\n\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nlp_yy_reduce_print (YYSTYPE *lp_yyvsp, int lp_yyrule, parse_parm *parm, void *scanner)\n#else\nstatic void\nlp_yy_reduce_print (lp_yyvsp, lp_yyrule, parm, scanner)\n    YYSTYPE *lp_yyvsp;\n    int lp_yyrule;\n    parse_parm *parm;\n    void *scanner;\n#endif\n{\n  int lp_yynrhs = lp_yyr2[lp_yyrule];\n  int lp_yyi;\n  unsigned long int lp_yylno = lp_yyrline[lp_yyrule];\n  YYFPRINTF (stderr, \"Reducing stack by rule %d (line %lu):\\n\",\n\t     lp_yyrule - 1, lp_yylno);\n  /* The symbols being reduced.  */\n  for (lp_yyi = 0; lp_yyi < lp_yynrhs; lp_yyi++)\n    {\n      fprintf (stderr, \"   $%d = \", lp_yyi + 1);\n      lp_yy_symbol_print (stderr, lp_yyrhs[lp_yyprhs[lp_yyrule] + lp_yyi],\n\t\t       &(lp_yyvsp[(lp_yyi + 1) - (lp_yynrhs)])\n\t\t       \t\t       , parm, scanner);\n      fprintf (stderr, \"\\n\");\n    }\n}\n\n# define YY_REDUCE_PRINT(Rule)\t\t\\\ndo {\t\t\t\t\t\\\n  if (lp_yydebug)\t\t\t\t\\\n    lp_yy_reduce_print (lp_yyvsp, Rule, parm, scanner); \\\n} while (YYID (0))\n\n/* Nonzero means print parse trace.  It is left uninitialized so that\n   multiple parsers can coexist.  */\nint lp_yydebug;\n#else /* !YYDEBUG */\n# define YYDPRINTF(Args)\n# define YY_SYMBOL_PRINT(Title, Type, Value, Location)\n# define YY_STACK_PRINT(Bottom, Top)\n# define YY_REDUCE_PRINT(Rule)\n#endif /* !YYDEBUG */\n\n\n/* YYINITDEPTH -- initial size of the parser's stacks.  */\n#ifndef\tYYINITDEPTH\n# define YYINITDEPTH 200\n#endif\n\n/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only\n   if the built-in stack extension method is used).\n\n   Do not make this value too large; the results are undefined if\n   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)\n   evaluated with infinite-precision integer arithmetic.  */\n\n#ifndef YYMAXDEPTH\n# define YYMAXDEPTH 10000\n#endif\n\n\f\n\n#if YYERROR_VERBOSE\n\n# ifndef lp_yystrlen\n#  if defined __GLIBC__ && defined _STRING_H\n#   define lp_yystrlen strlen\n#  else\n/* Return the length of YYSTR.  */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic YYSIZE_T\nlp_yystrlen (const char *lp_yystr)\n#else\nstatic YYSIZE_T\nlp_yystrlen (lp_yystr)\n    const char *lp_yystr;\n#endif\n{\n  YYSIZE_T lp_yylen;\n  for (lp_yylen = 0; lp_yystr[lp_yylen]; lp_yylen++)\n    continue;\n  return lp_yylen;\n}\n#  endif\n# endif\n\n# ifndef lp_yystpcpy\n#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE\n#   define lp_yystpcpy stpcpy\n#  else\n/* Copy YYSRC to YYDEST, returning the address of the terminating '\\0' in\n   YYDEST.  */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic char *\nlp_yystpcpy (char *lp_yydest, const char *lp_yysrc)\n#else\nstatic char *\nlp_yystpcpy (lp_yydest, lp_yysrc)\n    char *lp_yydest;\n    const char *lp_yysrc;\n#endif\n{\n  char *lp_yyd = lp_yydest;\n  const char *lp_yys = lp_yysrc;\n\n  while ((*lp_yyd++ = *lp_yys++) != '\\0')\n    continue;\n\n  return lp_yyd - 1;\n}\n#  endif\n# endif\n\n# ifndef lp_yytnamerr\n/* Copy to YYRES the contents of YYSTR after stripping away unnecessary\n   quotes and backslashes, so that it's suitable for lp_yyerror.  The\n   heuristic is that double-quoting is unnecessary unless the string\n   contains an apostrophe, a comma, or backslash (other than\n   backslash-backslash).  YYSTR is taken from lp_yytname.  If YYRES is\n   null, do not copy; instead, return the length of what the result\n   would have been.  */\nstatic YYSIZE_T\nlp_yytnamerr (char *lp_yyres, const char *lp_yystr)\n{\n  if (*lp_yystr == '\"')\n    {\n      YYSIZE_T lp_yyn = 0;\n      char const *lp_yyp = lp_yystr;\n\n      for (;;)\n\tswitch (*++lp_yyp)\n\t  {\n\t  case '\\'':\n\t  case ',':\n\t    goto do_not_strip_quotes;\n\n\t  case '\\\\':\n\t    if (*++lp_yyp != '\\\\')\n\t      goto do_not_strip_quotes;\n\t    /* Fall through.  */\n\t  default:\n\t    if (lp_yyres)\n\t      lp_yyres[lp_yyn] = *lp_yyp;\n\t    lp_yyn++;\n\t    break;\n\n\t  case '\"':\n\t    if (lp_yyres)\n\t      lp_yyres[lp_yyn] = '\\0';\n\t    return lp_yyn;\n\t  }\n    do_not_strip_quotes: ;\n    }\n\n  if (! lp_yyres)\n    return lp_yystrlen (lp_yystr);\n\n  return lp_yystpcpy (lp_yyres, lp_yystr) - lp_yyres;\n}\n# endif\n\n/* Copy into YYRESULT an error message about the unexpected token\n   YYCHAR while in state YYSTATE.  Return the number of bytes copied,\n   including the terminating null byte.  If YYRESULT is null, do not\n   copy anything; just return the number of bytes that would be\n   copied.  As a special case, return 0 if an ordinary \"syntax error\"\n   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during\n   size calculation.  */\nstatic YYSIZE_T\nlp_yysyntax_error (char *lp_yyresult, int lp_yystate, int lp_yychar)\n{\n  int lp_yyn = lp_yypact[lp_yystate];\n\n  if (! (YYPACT_NINF < lp_yyn && lp_yyn <= YYLAST))\n    return 0;\n  else\n    {\n      int lp_yytype = YYTRANSLATE (lp_yychar);\n      YYSIZE_T lp_yysize0 = lp_yytnamerr (0, lp_yytname[lp_yytype]);\n      YYSIZE_T lp_yysize = lp_yysize0;\n      YYSIZE_T lp_yysize1;\n      int lp_yysize_overflow = 0;\n      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };\n      char const *lp_yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];\n      int lp_yyx;\n\n# if 0\n      /* This is so xgettext sees the translatable formats that are\n\t constructed on the fly.  */\n      YY_(\"syntax error, unexpected %s\");\n      YY_(\"syntax error, unexpected %s, expecting %s\");\n      YY_(\"syntax error, unexpected %s, expecting %s or %s\");\n      YY_(\"syntax error, unexpected %s, expecting %s or %s or %s\");\n      YY_(\"syntax error, unexpected %s, expecting %s or %s or %s or %s\");\n# endif\n      char *lp_yyfmt;\n      char const *lp_yyf;\n      static char const lp_yyunexpected[] = \"syntax error, unexpected %s\";\n      static char const lp_yyexpecting[] = \", expecting %s\";\n      static char const lp_yyor[] = \" or %s\";\n      char lp_yyformat[sizeof lp_yyunexpected\n\t\t    + sizeof lp_yyexpecting - 1\n\t\t    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)\n\t\t       * (sizeof lp_yyor - 1))];\n      char const *lp_yyprefix = lp_yyexpecting;\n\n      /* Start YYX at -YYN if negative to avoid negative indexes in\n\t YYCHECK.  */\n      int lp_yyxbegin = lp_yyn < 0 ? -lp_yyn : 0;\n\n      /* Stay within bounds of both lp_yycheck and lp_yytname.  */\n      int lp_yychecklim = YYLAST - lp_yyn + 1;\n      int lp_yyxend = lp_yychecklim < YYNTOKENS ? lp_yychecklim : YYNTOKENS;\n      int lp_yycount = 1;\n\n      lp_yyarg[0] = lp_yytname[lp_yytype];\n      lp_yyfmt = lp_yystpcpy (lp_yyformat, lp_yyunexpected);\n\n      for (lp_yyx = lp_yyxbegin; lp_yyx < lp_yyxend; ++lp_yyx)\n\tif (lp_yycheck[lp_yyx + lp_yyn] == lp_yyx && lp_yyx != YYTERROR)\n\t  {\n\t    if (lp_yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)\n\t      {\n\t\tlp_yycount = 1;\n\t\tlp_yysize = lp_yysize0;\n\t\tlp_yyformat[sizeof lp_yyunexpected - 1] = '\\0';\n\t\tbreak;\n\t      }\n\t    lp_yyarg[lp_yycount++] = lp_yytname[lp_yyx];\n\t    lp_yysize1 = lp_yysize + lp_yytnamerr (0, lp_yytname[lp_yyx]);\n\t    lp_yysize_overflow |= (lp_yysize1 < lp_yysize);\n\t    lp_yysize = lp_yysize1;\n\t    lp_yyfmt = lp_yystpcpy (lp_yyfmt, lp_yyprefix);\n\t    lp_yyprefix = lp_yyor;\n\t  }\n\n      lp_yyf = YY_(lp_yyformat);\n      lp_yysize1 = lp_yysize + lp_yystrlen (lp_yyf);\n      lp_yysize_overflow |= (lp_yysize1 < lp_yysize);\n      lp_yysize = lp_yysize1;\n\n      if (lp_yysize_overflow)\n\treturn YYSIZE_MAXIMUM;\n\n      if (lp_yyresult)\n\t{\n\t  /* Avoid sprintf, as that infringes on the user's name space.\n\t     Don't have undefined behavior even if the translation\n\t     produced a string with the wrong number of \"%s\"s.  */\n\t  char *lp_yyp = lp_yyresult;\n\t  int lp_yyi = 0;\n\t  while ((*lp_yyp = *lp_yyf) != '\\0')\n\t    {\n\t      if (*lp_yyp == '%' && lp_yyf[1] == 's' && lp_yyi < lp_yycount)\n\t\t{\n\t\t  lp_yyp += lp_yytnamerr (lp_yyp, lp_yyarg[lp_yyi++]);\n\t\t  lp_yyf += 2;\n\t\t}\n\t      else\n\t\t{\n\t\t  lp_yyp++;\n\t\t  lp_yyf++;\n\t\t}\n\t    }\n\t}\n      return lp_yysize;\n    }\n}\n#endif /* YYERROR_VERBOSE */\n\f\n\n/*-----------------------------------------------.\n| Release the memory associated to this symbol.  |\n`-----------------------------------------------*/\n\n/*ARGSUSED*/\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nstatic void\nlp_yydestruct (const char *lp_yymsg, int lp_yytype, YYSTYPE *lp_yyvaluep, parse_parm *parm, void *scanner)\n#else\nstatic void\nlp_yydestruct (lp_yymsg, lp_yytype, lp_yyvaluep, parm, scanner)\n    const char *lp_yymsg;\n    int lp_yytype;\n    YYSTYPE *lp_yyvaluep;\n    parse_parm *parm;\n    void *scanner;\n#endif\n{\n  YYUSE (lp_yyvaluep);\n  YYUSE (parm);\n  YYUSE (scanner);\n\n  if (!lp_yymsg)\n    lp_yymsg = \"Deleting\";\n  YY_SYMBOL_PRINT (lp_yymsg, lp_yytype, lp_yyvaluep, lp_yylocationp);\n\n  switch (lp_yytype)\n    {\n\n      default:\n\tbreak;\n    }\n}\n\f\n\n/* Prevent warnings from -Wmissing-prototypes.  */\n\n#ifdef YYPARSE_PARAM\n#if defined __STDC__ || defined __cplusplus\nint lp_yyparse (void *YYPARSE_PARAM);\n#else\nint lp_yyparse ();\n#endif\n#else /* ! YYPARSE_PARAM */\n#if defined __STDC__ || defined __cplusplus\nint lp_yyparse (parse_parm *parm, void *scanner);\n#else\nint lp_yyparse ();\n#endif\n#endif /* ! YYPARSE_PARAM */\n\n\n\n\n\n\n/*----------.\n| lp_yyparse.  |\n`----------*/\n\n#ifdef YYPARSE_PARAM\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nint\nlp_yyparse (void *YYPARSE_PARAM)\n#else\nint\nlp_yyparse (YYPARSE_PARAM)\n    void *YYPARSE_PARAM;\n#endif\n#else /* ! YYPARSE_PARAM */\n#if (defined __STDC__ || defined __C99__FUNC__ \\\n     || defined __cplusplus || defined _MSC_VER)\nint\nlp_yyparse (parse_parm *parm, void *scanner)\n#else\nint\nlp_yyparse (parm, scanner)\n    parse_parm *parm;\n    void *scanner;\n#endif\n#endif\n{\n  /* The look-ahead symbol.  */\nint lp_yychar;\n\n/* The semantic value of the look-ahead symbol.  */\nYYSTYPE lp_yylval;\n\n/* Number of syntax errors so far.  */\nint lp_yynerrs;\n\n  int lp_yystate;\n  int lp_yyn;\n  int lp_yyresult;\n  /* Number of tokens to shift before error messages enabled.  */\n  int lp_yyerrstatus;\n  /* Look-ahead token as an internal (translated) token number.  */\n  int lp_yytoken = 0;\n#if YYERROR_VERBOSE\n  /* Buffer for error messages, and its allocated size.  */\n  char lp_yymsgbuf[128];\n  char *lp_yymsg = lp_yymsgbuf;\n  YYSIZE_T lp_yymsg_alloc = sizeof lp_yymsgbuf;\n#endif\n\n  /* Three stacks and their tools:\n     `lp_yyss': related to states,\n     `lp_yyvs': related to semantic values,\n     `lp_yyls': related to locations.\n\n     Refer to the stacks thru separate pointers, to allow lp_yyoverflow\n     to reallocate them elsewhere.  */\n\n  /* The state stack.  */\n  lp_yytype_int16 lp_yyssa[YYINITDEPTH];\n  lp_yytype_int16 *lp_yyss = lp_yyssa;\n  lp_yytype_int16 *lp_yyssp;\n\n  /* The semantic value stack.  */\n  YYSTYPE lp_yyvsa[YYINITDEPTH];\n  YYSTYPE *lp_yyvs = lp_yyvsa;\n  YYSTYPE *lp_yyvsp;\n\n\n\n#define YYPOPSTACK(N)   (lp_yyvsp -= (N), lp_yyssp -= (N))\n\n  YYSIZE_T lp_yystacksize = YYINITDEPTH;\n\n  /* The variables used to return semantic value and location from the\n     action routines.  */\n  YYSTYPE lp_yyval;\n\n\n  /* The number of symbols on the RHS of the reduced rule.\n     Keep to zero when no symbol should be popped.  */\n  int lp_yylen = 0;\n\n  YYDPRINTF ((stderr, \"Starting parse\\n\"));\n\n  lp_yystate = 0;\n  lp_yyerrstatus = 0;\n  lp_yynerrs = 0;\n  lp_yychar = YYEMPTY;\t\t/* Cause a token to be read.  */\n\n  /* Initialize stack pointers.\n     Waste one element of value and location stack\n     so that they stay on the same level as the state stack.\n     The wasted elements are never initialized.  */\n\n  lp_yyssp = lp_yyss;\n  lp_yyvsp = lp_yyvs;\n\n  goto lp_yysetstate;\n\n/*------------------------------------------------------------.\n| lp_yynewstate -- Push a new state, which is found in lp_yystate.  |\n`------------------------------------------------------------*/\n lp_yynewstate:\n  /* In all cases, when you get here, the value and location stacks\n     have just been pushed.  So pushing a state here evens the stacks.  */\n  lp_yyssp++;\n\n lp_yysetstate:\n  *lp_yyssp = lp_yystate;\n\n  if (lp_yyss + lp_yystacksize - 1 <= lp_yyssp)\n    {\n      /* Get the current used size of the three stacks, in elements.  */\n      YYSIZE_T lp_yysize = lp_yyssp - lp_yyss + 1;\n\n#ifdef lp_yyoverflow\n      {\n\t/* Give user a chance to reallocate the stack.  Use copies of\n\t   these so that the &'s don't force the real ones into\n\t   memory.  */\n\tYYSTYPE *lp_yyvs1 = lp_yyvs;\n\tlp_yytype_int16 *lp_yyss1 = lp_yyss;\n\n\n\t/* Each stack pointer address is followed by the size of the\n\t   data in use in that stack, in bytes.  This used to be a\n\t   conditional around just the two extra args, but that might\n\t   be undefined if lp_yyoverflow is a macro.  */\n\tlp_yyoverflow (YY_(\"memory exhausted\"),\n\t\t    &lp_yyss1, lp_yysize * sizeof (*lp_yyssp),\n\t\t    &lp_yyvs1, lp_yysize * sizeof (*lp_yyvsp),\n\n\t\t    &lp_yystacksize);\n\n\tlp_yyss = lp_yyss1;\n\tlp_yyvs = lp_yyvs1;\n      }\n#else /* no lp_yyoverflow */\n# ifndef YYSTACK_RELOCATE\n      goto lp_yyexhaustedlab;\n# else\n      /* Extend the stack our own way.  */\n      if (YYMAXDEPTH <= lp_yystacksize)\n\tgoto lp_yyexhaustedlab;\n      lp_yystacksize *= 2;\n      if (YYMAXDEPTH < lp_yystacksize)\n\tlp_yystacksize = YYMAXDEPTH;\n\n      {\n\tlp_yytype_int16 *lp_yyss1 = lp_yyss;\n\tunion lp_yyalloc *lp_yyptr =\n\t  (union lp_yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (lp_yystacksize));\n\tif (! lp_yyptr)\n\t  goto lp_yyexhaustedlab;\n\tYYSTACK_RELOCATE (lp_yyss);\n\tYYSTACK_RELOCATE (lp_yyvs);\n\n#  undef YYSTACK_RELOCATE\n\tif (lp_yyss1 != lp_yyssa)\n\t  YYSTACK_FREE (lp_yyss1);\n      }\n# endif\n#endif /* no lp_yyoverflow */\n\n      lp_yyssp = lp_yyss + lp_yysize - 1;\n      lp_yyvsp = lp_yyvs + lp_yysize - 1;\n\n\n      YYDPRINTF ((stderr, \"Stack size increased to %lu\\n\",\n\t\t  (unsigned long int) lp_yystacksize));\n\n      if (lp_yyss + lp_yystacksize - 1 <= lp_yyssp)\n\tYYABORT;\n    }\n\n  YYDPRINTF ((stderr, \"Entering state %d\\n\", lp_yystate));\n\n  goto lp_yybackup;\n\n/*-----------.\n| lp_yybackup.  |\n`-----------*/\nlp_yybackup:\n\n  /* Do appropriate processing given the current state.  Read a\n     look-ahead token if we need one and don't already have one.  */\n\n  /* First try to decide what to do without reference to look-ahead token.  */\n  lp_yyn = lp_yypact[lp_yystate];\n  if (lp_yyn == YYPACT_NINF)\n    goto lp_yydefault;\n\n  /* Not known => get a look-ahead token if don't already have one.  */\n\n  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */\n  if (lp_yychar == YYEMPTY)\n    {\n      YYDPRINTF ((stderr, \"Reading a token: \"));\n      lp_yychar = YYLEX;\n    }\n\n  if (lp_yychar <= YYEOF)\n    {\n      lp_yychar = lp_yytoken = YYEOF;\n      YYDPRINTF ((stderr, \"Now at end of input.\\n\"));\n    }\n  else\n    {\n      lp_yytoken = YYTRANSLATE (lp_yychar);\n      YY_SYMBOL_PRINT (\"Next token is\", lp_yytoken, &lp_yylval, &lp_yylloc);\n    }\n\n  /* If the proper action on seeing token YYTOKEN is to reduce or to\n     detect an error, take that action.  */\n  lp_yyn += lp_yytoken;\n  if (lp_yyn < 0 || YYLAST < lp_yyn || lp_yycheck[lp_yyn] != lp_yytoken)\n    goto lp_yydefault;\n  lp_yyn = lp_yytable[lp_yyn];\n  if (lp_yyn <= 0)\n    {\n      if (lp_yyn == 0 || lp_yyn == YYTABLE_NINF)\n\tgoto lp_yyerrlab;\n      lp_yyn = -lp_yyn;\n      goto lp_yyreduce;\n    }\n\n  if (lp_yyn == YYFINAL)\n    YYACCEPT;\n\n  /* Count tokens shifted since error; after three, turn off error\n     status.  */\n  if (lp_yyerrstatus)\n    lp_yyerrstatus--;\n\n  /* Shift the look-ahead token.  */\n  YY_SYMBOL_PRINT (\"Shifting\", lp_yytoken, &lp_yylval, &lp_yylloc);\n\n  /* Discard the shifted token unless it is eof.  */\n  if (lp_yychar != YYEOF)\n    lp_yychar = YYEMPTY;\n\n  lp_yystate = lp_yyn;\n  *++lp_yyvsp = lp_yylval;\n\n  goto lp_yynewstate;\n\n\n/*-----------------------------------------------------------.\n| lp_yydefault -- do the default action for the current state.  |\n`-----------------------------------------------------------*/\nlp_yydefault:\n  lp_yyn = lp_yydefact[lp_yystate];\n  if (lp_yyn == 0)\n    goto lp_yyerrlab;\n  goto lp_yyreduce;\n\n\n/*-----------------------------.\n| lp_yyreduce -- Do a reduction.  |\n`-----------------------------*/\nlp_yyreduce:\n  /* lp_yyn is the number of a rule to reduce with.  */\n  lp_yylen = lp_yyr2[lp_yyn];\n\n  /* If YYLEN is nonzero, implement the default value of the action:\n     `$$ = $1'.\n\n     Otherwise, the following line sets YYVAL to garbage.\n     This behavior is undocumented and Bison\n     users should not rely upon it.  Assigning to YYVAL\n     unconditionally makes the parser a bit smaller, and it avoids a\n     GCC warning that YYVAL may be used uninitialized.  */\n  lp_yyval = lp_yyvsp[1-lp_yylen];\n\n\n  YY_REDUCE_PRINT (lp_yyn);\n  switch (lp_yyn)\n    {\n        case 3:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->isign = 0;\n  pv->make_neg = 0;\n  pv->Sign = 0;\n  pv->HadConstraint = FALSE;\n  pv->HadVar = pv->HadVar0 = FALSE;\n}\n    break;\n\n  case 5:\n\n    {\n  set_obj_dir(PARM, TRUE);\n}\n    break;\n\n  case 6:\n\n    {\n  set_obj_dir(PARM, FALSE);\n}\n    break;\n\n  case 8:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  add_row(pp);\n  pv->HadConstraint = FALSE;\n  pv->HadVar = pv->HadVar0 = FALSE;\n  pv->isign = 0;\n  pv->make_neg = 0;\n}\n    break;\n\n  case 16:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if(!add_constraint_name(pp, pv->Last_var))\n    YYABORT;\n  pv->HadConstraint = TRUE;\n}\n    break;\n\n  case 18:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->HadVar1 = pv->HadVar0;\n  pv->HadVar0 = FALSE;\n}\n    break;\n\n  case 19:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if(!store_re_op(pp, pv->OP, (int) pv->HadConstraint, (int) pv->HadVar, (int) pv->Had_lineair_sum))\n    YYABORT;\n  pv->make_neg = 1;\n  pv->f1 = 0;\n}\n    break;\n\n  case 20:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->Had_lineair_sum0 = pv->Had_lineair_sum;\n  pv->Had_lineair_sum = TRUE;\n  pv->HadVar2 = pv->HadVar0;\n  pv->HadVar0 = FALSE;\n  pv->do_add_row = FALSE;\n  if(pv->HadConstraint && !pv->HadVar ) {\n    /* it is a range */\n    /* already handled */\n  }\n  else if(!pv->HadConstraint && pv->HadVar) {\n    /* it is a bound */\n\n    if(!store_bounds(pp, TRUE))\n      YYABORT;\n  }\n  else {\n    /* it is a row restriction */\n    if(pv->HadConstraint && pv->HadVar)\n      store_re_op(pp, '\\0', (int) pv->HadConstraint, (int) pv->HadVar, (int) pv->Had_lineair_sum); /* makes sure that data stored in temporary buffers is treated correctly */\n    pv->do_add_row = TRUE;\n  }\n}\n    break;\n\n  case 21:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if((!pv->HadVar) && (!pv->HadConstraint)) {\n    lp_yyerror(pp, pp->scanner, \"parse error\");\n    YYABORT;\n  }\n  if(pv->do_add_row)\n    add_row(pp);\n  pv->HadConstraint = FALSE;\n  pv->HadVar = pv->HadVar0 = FALSE;\n  pv->isign = 0;\n  pv->make_neg = 0;\n  null_tmp_store(pp, TRUE);\n}\n    break;\n\n  case 22:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if((!pv->HadVar1) && (pv->Had_lineair_sum0))\n    if(!negate_constraint(pp))\n      YYABORT;\n}\n    break;\n\n  case 23:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->make_neg = 0;\n  pv->isign = 0;\n  if(pv->HadConstraint)\n    pv->HadVar = pv->Had_lineair_sum = FALSE;\n  pv->HadVar0 = FALSE;\n  if(!store_re_op(pp, (char) ((pv->OP == '<') ? '>' : (pv->OP == '>') ? '<' : pv->OP), (int) pv->HadConstraint, (int) pv->HadVar, (int) pv->Had_lineair_sum))\n    YYABORT;\n}\n    break;\n\n  case 24:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->f -= pv->f1;\n}\n    break;\n\n  case 25:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if((pv->HadVar1) || (!pv->HadVar2) || (pv->HadVar0)) {\n    lp_yyerror(pp, pp->scanner, \"parse error\");\n    YYABORT;\n  }\n\n  if(pv->HadConstraint && !pv->HadVar ) {\n    /* it is a range */\n    /* already handled */\n    if(!negate_constraint(pp))\n      YYABORT;\n  }\n  else if(!pv->HadConstraint && pv->HadVar) {\n    /* it is a bound */\n\n    if(!store_bounds(pp, TRUE))\n      YYABORT;\n  }\n}\n    break;\n\n  case 26:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  /* to allow a range */\n  /* constraint: < max */\n  if(!pv->HadConstraint) {\n    lp_yyerror(pp, pp->scanner, \"parse error\");\n    YYABORT;\n  }\n  pv->Had_lineair_sum = FALSE;\n}\n    break;\n\n  case 27:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->Had_lineair_sum = TRUE;\n}\n    break;\n\n  case 29:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->isign = pv->Sign;\n}\n    break;\n\n  case 31:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->state = pv->state0 = 0;\n}\n    break;\n\n  case 32:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if (pv->state == 1) {\n    /* RHS_STORE */\n    if (    (pv->isign0 || !pv->make_neg)\n        && !(pv->isign0 && !pv->make_neg)) /* but not both! */\n      pv->f0 = -pv->f0;\n    if(pv->make_neg)\n      pv->f1 += pv->f0;\n    if(!rhs_store(pp, pv->f0, (int) pv->HadConstraint, (int) pv->HadVar, (int) pv->Had_lineair_sum))\n      YYABORT;\n  }\n}\n    break;\n\n  case 35:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if ((pv->HadSign || pv->state == 1) && (pv->state0 == 1)) {\n    /* RHS_STORE */\n    if (    (pv->isign0 || !pv->make_neg)\n        && !(pv->isign0 && !pv->make_neg)) /* but not both! */\n      pv->f0 = -pv->f0;\n    if(pv->make_neg)\n      pv->f1 += pv->f0;\n    if(!rhs_store(pp, pv->f0, (int) pv->HadConstraint, (int) pv->HadVar, (int) pv->Had_lineair_sum))\n      YYABORT;\n  }\n  if (pv->state == 1) {\n    pv->f0 = pv->f;\n    pv->isign0 = pv->isign;\n  }\n  if (pv->state == 2) {\n    if((pv->HadSign) || (pv->state0 != 1)) {\n     pv->isign0 = pv->isign;\n     pv->f0 = 1.0;\n    }\n    if (    (pv->isign0 || pv->make_neg)\n        && !(pv->isign0 && pv->make_neg)) /* but not both! */\n      pv->f0 = -pv->f0;\n    if(!var_store(pp, pv->Last_var, pv->f0, (int) pv->HadConstraint, (int) pv->HadVar, (int) pv->Had_lineair_sum)) {\n      lp_yyerror(pp, pp->scanner, \"var_store failed\");\n      YYABORT;\n    }\n    pv->HadConstraint |= pv->HadVar;\n    pv->HadVar = pv->HadVar0 = TRUE;\n  }\n  pv->state0 = pv->state;\n}\n    break;\n\n  case 36:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->state = 1;\n}\n    break;\n\n  case 37:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if ((pv->HasAR_M_OP) && (pv->state != 1)) {\n    lp_yyerror(pp, pp->scanner, \"parse error\");\n    YYABORT;\n  }\n}\n    break;\n\n  case 38:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->state = 2;\n}\n    break;\n\n  case 43:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->isign = pv->Sign;\n}\n    break;\n\n  case 46:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->isign = 0;\n  pv->HadSign = FALSE;\n}\n    break;\n\n  case 47:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->isign = pv->Sign;\n  pv->HadSign = TRUE;\n}\n    break;\n\n  case 48:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->HasAR_M_OP = FALSE;\n}\n    break;\n\n  case 49:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->HasAR_M_OP = TRUE;\n}\n    break;\n\n  case 50:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if (    (pv->isign || !pv->make_neg)\n      && !(pv->isign && !pv->make_neg)) /* but not both! */\n    pv->f = -pv->f;\n  if(!rhs_store(pp, pv->f, (int) pv->HadConstraint, (int) pv->HadVar, (int) pv->Had_lineair_sum))\n    YYABORT;\n  pv->isign = 0;\n}\n    break;\n\n  case 60:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pv->Within_sos_decl1 = pv->Within_sos_decl;\n}\n    break;\n\n  case 62:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if((!pv->Within_int_decl) && (!pv->Within_sec_decl) && (!pv->Within_sos_decl1) && (!pv->Within_free_decl)) {\n    lp_yyerror(pp, pp->scanner, \"parse error\");\n    YYABORT;\n  }\n  pv->SOStype = pv->SOStype0;\n  check_int_sec_sos_free_decl(pp, (int) pv->Within_int_decl, (int) pv->Within_sec_decl, (int) (pv->Within_sos_decl1 = (pv->Within_sos_decl1 ? 1 : 0)), (int) pv->Within_free_decl);\n}\n    break;\n\n  case 63:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if((pv->Within_sos_decl1) && (pv->SOStype == 0))\n  {\n    lp_yyerror(pp, pp->scanner, \"Unsupported SOS type (0)\");\n    YYABORT;\n  }\n}\n    break;\n\n  case 67:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  FREE(pv->Last_var0);\n  pv->Last_var0 = strdup(pv->Last_var);\n}\n    break;\n\n  case 69:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if(pv->Within_sos_decl1) {\n    set_sos_type(pp, pv->SOStype);\n    set_sos_weight(pp, (double) pv->SOSweight, 1);\n  }\n}\n    break;\n\n  case 70:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if((pv->Within_sos_decl1) && (!pv->SOStype))\n  {\n    set_sos_type(pp, pv->SOStype = (short) (pv->f + .1));\n  }\n  else\n  {\n    lp_yyerror(pp, pp->scanner, \"SOS type not expected\");\n    YYABORT;\n  }\n}\n    break;\n\n  case 72:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  set_sos_weight(pp, (double) pv->SOSweight, 1);\n}\n    break;\n\n  case 73:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  set_sos_weight(pp, pv->f, 1);\n}\n    break;\n\n  case 80:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if(pv->Within_sos_decl1 == 1)\n  {\n    char buf[16];\n\n    pv->SOSweight++;\n    sprintf(buf, \"SOS%d\", pv->SOSweight);\n    storevarandweight(pp, buf);\n\n    check_int_sec_sos_free_decl(pp, (int) pv->Within_int_decl, (int) pv->Within_sec_decl, 2, (int) pv->Within_free_decl);\n    pv->Within_sos_decl1 = 2;\n    pv->SOSNr = 0;\n  }\n\n  storevarandweight(pp, pv->Last_var);\n\n  if(pv->Within_sos_decl1 == 2)\n  {\n    pv->SOSNr++;\n    set_sos_weight(pp, (double) pv->SOSNr, 2);\n  }\n}\n    break;\n\n  case 81:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if(!pv->Within_sos_decl1) {\n    lp_yyerror(pp, pp->scanner, \"parse error\");\n    YYABORT;\n  }\n  if(pv->Within_sos_decl1 == 1) {\n    FREE(pv->Last_var0);\n    pv->Last_var0 = strdup(pv->Last_var);\n  }\n  if(pv->Within_sos_decl1 == 2)\n  {\n    storevarandweight(pp, pv->Last_var);\n    pv->SOSNr++;\n    set_sos_weight(pp, (double) pv->SOSNr, 2);\n  }\n}\n    break;\n\n  case 82:\n\n    {\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if(pv->Within_sos_decl1 == 1)\n  {\n    char buf[16];\n\n    pv->SOSweight++;\n    sprintf(buf, \"SOS%d\", pv->SOSweight);\n    storevarandweight(pp, buf);\n\n    check_int_sec_sos_free_decl(pp, (int) pv->Within_int_decl, (int) pv->Within_sec_decl, 2, (int) pv->Within_free_decl);\n    pv->Within_sos_decl1 = 2;\n    pv->SOSNr = 0;\n\n    storevarandweight(pp, pv->Last_var0);\n    pv->SOSNr++;\n  }\n\n  set_sos_weight(pp, pv->f, 2);\n}\n    break;\n\n  case 83:\n\n    { /* SOS name */\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  if(pv->Within_sos_decl1 == 1)\n  {\n    parse_parm *pp2 = PARM;\n    parse_vars *pv2 = (parse_vars *) pp2->parse_vars;\n\n    storevarandweight(pp2, pv2->Last_var0);\n    set_sos_type(pp2, pv2->SOStype);\n    check_int_sec_sos_free_decl(pp2, (int) pv2->Within_int_decl, (int) pv2->Within_sec_decl, 2, (int) pv2->Within_free_decl);\n    pv2->Within_sos_decl1 = 2;\n    pv2->SOSNr = 0;\n    pv2->SOSweight++;\n  }\n}\n    break;\n\n\n/* Line 1267 of yacc.c.  */\n\n      default: break;\n    }\n  YY_SYMBOL_PRINT (\"-> $$ =\", lp_yyr1[lp_yyn], &lp_yyval, &lp_yyloc);\n\n  YYPOPSTACK (lp_yylen);\n  lp_yylen = 0;\n  YY_STACK_PRINT (lp_yyss, lp_yyssp);\n\n  *++lp_yyvsp = lp_yyval;\n\n\n  /* Now `shift' the result of the reduction.  Determine what state\n     that goes to, based on the state we popped back to and the rule\n     number reduced by.  */\n\n  lp_yyn = lp_yyr1[lp_yyn];\n\n  lp_yystate = lp_yypgoto[lp_yyn - YYNTOKENS] + *lp_yyssp;\n  if (0 <= lp_yystate && lp_yystate <= YYLAST && lp_yycheck[lp_yystate] == *lp_yyssp)\n    lp_yystate = lp_yytable[lp_yystate];\n  else\n    lp_yystate = lp_yydefgoto[lp_yyn - YYNTOKENS];\n\n  goto lp_yynewstate;\n\n\n/*------------------------------------.\n| lp_yyerrlab -- here on detecting error |\n`------------------------------------*/\nlp_yyerrlab:\n  /* If not already recovering from an error, report this error.  */\n  if (!lp_yyerrstatus)\n    {\n      ++lp_yynerrs;\n#if ! YYERROR_VERBOSE\n      lp_yyerror (parm, scanner, YY_(\"syntax error\"));\n#else\n      {\n\tYYSIZE_T lp_yysize = lp_yysyntax_error (0, lp_yystate, lp_yychar);\n\tif (lp_yymsg_alloc < lp_yysize && lp_yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)\n\t  {\n\t    YYSIZE_T lp_yyalloc = 2 * lp_yysize;\n\t    if (! (lp_yysize <= lp_yyalloc && lp_yyalloc <= YYSTACK_ALLOC_MAXIMUM))\n\t      lp_yyalloc = YYSTACK_ALLOC_MAXIMUM;\n\t    if (lp_yymsg != lp_yymsgbuf)\n\t      YYSTACK_FREE (lp_yymsg);\n\t    lp_yymsg = (char *) YYSTACK_ALLOC (lp_yyalloc);\n\t    if (lp_yymsg)\n\t      lp_yymsg_alloc = lp_yyalloc;\n\t    else\n\t      {\n\t\tlp_yymsg = lp_yymsgbuf;\n\t\tlp_yymsg_alloc = sizeof lp_yymsgbuf;\n\t      }\n\t  }\n\n\tif (0 < lp_yysize && lp_yysize <= lp_yymsg_alloc)\n\t  {\n\t    (void) lp_yysyntax_error (lp_yymsg, lp_yystate, lp_yychar);\n\t    lp_yyerror (parm, scanner, lp_yymsg);\n\t  }\n\telse\n\t  {\n\t    lp_yyerror (parm, scanner, YY_(\"syntax error\"));\n\t    if (lp_yysize != 0)\n\t      goto lp_yyexhaustedlab;\n\t  }\n      }\n#endif\n    }\n\n\n\n  if (lp_yyerrstatus == 3)\n    {\n      /* If just tried and failed to reuse look-ahead token after an\n\t error, discard it.  */\n\n      if (lp_yychar <= YYEOF)\n\t{\n\t  /* Return failure if at end of input.  */\n\t  if (lp_yychar == YYEOF)\n\t    YYABORT;\n\t}\n      else\n\t{\n\t  lp_yydestruct (\"Error: discarding\",\n\t\t      lp_yytoken, &lp_yylval, parm, scanner);\n\t  lp_yychar = YYEMPTY;\n\t}\n    }\n\n  /* Else will try to reuse look-ahead token after shifting the error\n     token.  */\n  goto lp_yyerrlab1;\n\n\n/*---------------------------------------------------.\n| lp_yyerrorlab -- error raised explicitly by YYERROR.  |\n`---------------------------------------------------*/\nlp_yyerrorlab:\n\n  /* Pacify compilers like GCC when the user code never invokes\n     YYERROR and the label lp_yyerrorlab therefore never appears in user\n     code.  */\n  if (/*CONSTCOND*/ 0)\n     goto lp_yyerrorlab;\n\n  /* Do not reclaim the symbols of the rule which action triggered\n     this YYERROR.  */\n  YYPOPSTACK (lp_yylen);\n  lp_yylen = 0;\n  YY_STACK_PRINT (lp_yyss, lp_yyssp);\n  lp_yystate = *lp_yyssp;\n  goto lp_yyerrlab1;\n\n\n/*-------------------------------------------------------------.\n| lp_yyerrlab1 -- common code for both syntax error and YYERROR.  |\n`-------------------------------------------------------------*/\nlp_yyerrlab1:\n  lp_yyerrstatus = 3;\t/* Each real token shifted decrements this.  */\n\n  for (;;)\n    {\n      lp_yyn = lp_yypact[lp_yystate];\n      if (lp_yyn != YYPACT_NINF)\n\t{\n\t  lp_yyn += YYTERROR;\n\t  if (0 <= lp_yyn && lp_yyn <= YYLAST && lp_yycheck[lp_yyn] == YYTERROR)\n\t    {\n\t      lp_yyn = lp_yytable[lp_yyn];\n\t      if (0 < lp_yyn)\n\t\tbreak;\n\t    }\n\t}\n\n      /* Pop the current state because it cannot handle the error token.  */\n      if (lp_yyssp == lp_yyss)\n\tYYABORT;\n\n\n      lp_yydestruct (\"Error: popping\",\n\t\t  lp_yystos[lp_yystate], lp_yyvsp, parm, scanner);\n      YYPOPSTACK (1);\n      lp_yystate = *lp_yyssp;\n      YY_STACK_PRINT (lp_yyss, lp_yyssp);\n    }\n\n  if (lp_yyn == YYFINAL)\n    YYACCEPT;\n\n  *++lp_yyvsp = lp_yylval;\n\n\n  /* Shift the error token.  */\n  YY_SYMBOL_PRINT (\"Shifting\", lp_yystos[lp_yyn], lp_yyvsp, lp_yylsp);\n\n  lp_yystate = lp_yyn;\n  goto lp_yynewstate;\n\n\n/*-------------------------------------.\n| lp_yyacceptlab -- YYACCEPT comes here.  |\n`-------------------------------------*/\nlp_yyacceptlab:\n  lp_yyresult = 0;\n  goto lp_yyreturn;\n\n/*-----------------------------------.\n| lp_yyabortlab -- YYABORT comes here.  |\n`-----------------------------------*/\nlp_yyabortlab:\n  lp_yyresult = 1;\n  goto lp_yyreturn;\n\n#ifndef lp_yyoverflow\n/*-------------------------------------------------.\n| lp_yyexhaustedlab -- memory exhaustion comes here.  |\n`-------------------------------------------------*/\nlp_yyexhaustedlab:\n  lp_yyerror (parm, scanner, YY_(\"memory exhausted\"));\n  lp_yyresult = 2;\n  /* Fall through.  */\n#endif\n\nlp_yyreturn:\n  if (lp_yychar != YYEOF && lp_yychar != YYEMPTY)\n     lp_yydestruct (\"Cleanup: discarding lookahead\",\n\t\t lp_yytoken, &lp_yylval, parm, scanner);\n  /* Do not reclaim the symbols of the rule which action triggered\n     this YYABORT or YYACCEPT.  */\n  YYPOPSTACK (lp_yylen);\n  YY_STACK_PRINT (lp_yyss, lp_yyssp);\n  while (lp_yyssp != lp_yyss)\n    {\n      lp_yydestruct (\"Cleanup: popping\",\n\t\t  lp_yystos[*lp_yyssp], lp_yyvsp, parm, scanner);\n      YYPOPSTACK (1);\n    }\n#ifndef lp_yyoverflow\n  if (lp_yyss != lp_yyssa)\n    YYSTACK_FREE (lp_yyss);\n#endif\n#if YYERROR_VERBOSE\n  if (lp_yymsg != lp_yymsgbuf)\n    YYSTACK_FREE (lp_yymsg);\n#endif\n  /* Make sure YYID is used.  */\n  return YYID (lp_yyresult);\n}\n\n\n\n\n\nstatic void lp_yy_delete_allocated_memory(parse_parm *pp)\n{\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n  /* free memory allocated by flex. Otherwise some memory is not freed.\n     This is a bit tricky. There is not much documentation about this, but a lot of\n     reports of memory that keeps allocated */\n\n  /* If you get errors on this function call, just comment it. This will only result\n     in some memory that is not being freed. */\n\n# if defined YY_CURRENT_BUFFER\n    /* flex defines the macro YY_CURRENT_BUFFER, so you should only get here if lp_rlp.h is\n       generated by flex */\n    /* lex doesn't define this macro and thus should not come here, but lex doesn't has\n       this memory leak also ...*/\n\n#  if 0\n    /* older versions of flex */\n    lp_yy_delete_buffer(YY_CURRENT_BUFFER); /* comment this line if you have problems with it */\n    lp_yy_init = 1; /* make sure that the next time memory is allocated again */\n    lp_yy_start = 0;\n#  else\n    /* As of version 2.5.9 Flex  */\n    lp_yylex_destroy(pp->scanner); /* comment this line if you have problems with it */\n#  endif\n# endif\n\n  FREE(pv->Last_var);\n  FREE(pv->Last_var0);\n}\n\nstatic int parse(parse_parm *pp)\n{\n  return(lp_yyparse(pp, pp->scanner));\n}\n\nlprec *read_lp1(lprec *lp, void *userhandle, read_modeldata_func read_modeldata, int verbose, char *lp_name)\n{\n  parse_vars *pv;\n  lprec *lp1 = NULL;\n\n  CALLOC(pv, 1, parse_vars);\n  if (pv != NULL) {\n    parse_parm pp;\n\n    memset(&pp, 0, sizeof(pp));\n    pp.parse_vars = (void *) pv;\n\n    lp_yylex_init(&pp.scanner);\n    lp_yyset_extra(&pp, pp.scanner);\n\n    lp_yyset_in((FILE *) userhandle, pp.scanner);\n    lp_yyset_out(NULL, pp.scanner);\n    pv->lp_input = read_modeldata;\n    pv->userhandle = userhandle;\n    lp1 = yacc_read(lp, verbose, lp_name, parse, &pp, lp_yy_delete_allocated_memory);\n    FREE(pv);\n  }\n  return(lp1);\n}\n\nlprec * __WINAPI read_lp(FILE *filename, int verbose, char *lp_name)\n{\n  return(read_lp1(NULL, filename, lp_input_lp_yyin, verbose, lp_name));\n}\n\nlprec * __WINAPI read_lpex(void *userhandle, read_modeldata_func read_modeldata, int verbose, char *lp_name)\n{\n  return(read_lp1(NULL, userhandle, read_modeldata, verbose, lp_name));\n}\n\nlprec *read_LP1(lprec *lp, const char *filename, int verbose, char *lp_name)\n{\n  FILE *fpin;\n\n  if((fpin = fopen(filename, \"r\")) != NULL) {\n    lp = read_lp1(lp, fpin, lp_input_lp_yyin, verbose, lp_name);\n    fclose(fpin);\n  }\n  else\n    lp = NULL;\n  return(lp);\n}\n\nlprec * __WINAPI read_LP(char *filename, int verbose, char *lp_name)\n{\n  return(read_LP1(NULL, filename, verbose, lp_name));\n}\n\nMYBOOL __WINAPI LP_readhandle(lprec **lp, FILE *filename, int verbose, char *lp_name)\n{\n  if(lp != NULL)\n    *lp = read_lp1(*lp, filename, lp_input_lp_yyin, verbose, lp_name);\n\n  return((lp != NULL) && (*lp != NULL));\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_rlp.h",
    "content": "\n\n\n#define  YY_INT_ALIGNED short int\n\n/* A lexical scanner generated by flex */\n\n#define FLEX_SCANNER\n#define YY_FLEX_MAJOR_VERSION 2\n#define YY_FLEX_MINOR_VERSION 5\n#define YY_FLEX_SUBMINOR_VERSION 35\n#if YY_FLEX_SUBMINOR_VERSION > 0\n#define FLEX_BETA\n#endif\n\n/* First, we deal with  platform-specific or compiler-specific issues. */\n\n/* begin standard C headers. */\n#include <stdio.h>\n#include <string.h>\n#include <errno.h>\n#include <stdlib.h>\n\n/* end standard C headers. */\n\n/* flex integer type definitions */\n\n#ifndef FLEXINT_H\n#define FLEXINT_H\n\n/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */\n\n#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n\n/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,\n * if you want the limit (max/min) macros for int types.\n */\n#ifndef __STDC_LIMIT_MACROS\n#define __STDC_LIMIT_MACROS 1\n#endif\n\n#include <inttypes.h>\ntypedef int8_t flex_int8_t;\ntypedef uint8_t flex_uint8_t;\ntypedef int16_t flex_int16_t;\ntypedef uint16_t flex_uint16_t;\ntypedef int32_t flex_int32_t;\ntypedef uint32_t flex_uint32_t;\n#else\ntypedef signed char flex_int8_t;\ntypedef short int flex_int16_t;\ntypedef int flex_int32_t;\ntypedef unsigned char flex_uint8_t;\ntypedef unsigned short int flex_uint16_t;\ntypedef unsigned int flex_uint32_t;\n#endif /* ! C99 */\n\n/* Limits of integral types. */\n#ifndef INT8_MIN\n#define INT8_MIN               (-128)\n#endif\n#ifndef INT16_MIN\n#define INT16_MIN              (-32767-1)\n#endif\n#ifndef INT32_MIN\n#define INT32_MIN              (-2147483647-1)\n#endif\n#ifndef INT8_MAX\n#define INT8_MAX               (127)\n#endif\n#ifndef INT16_MAX\n#define INT16_MAX              (32767)\n#endif\n#ifndef INT32_MAX\n#define INT32_MAX              (2147483647)\n#endif\n#ifndef UINT8_MAX\n#define UINT8_MAX              (255U)\n#endif\n#ifndef UINT16_MAX\n#define UINT16_MAX             (65535U)\n#endif\n#ifndef UINT32_MAX\n#define UINT32_MAX             (4294967295U)\n#endif\n\n#endif /* ! FLEXINT_H */\n\n#ifdef __cplusplus\n\n/* The \"const\" storage-class-modifier is valid. */\n#define YY_USE_CONST\n\n#else\t/* ! __cplusplus */\n\n/* C99 requires __STDC__ to be defined as 1. */\n#if defined (__STDC__)\n\n#define YY_USE_CONST\n\n#endif\t/* defined (__STDC__) */\n#endif\t/* ! __cplusplus */\n\n#ifdef YY_USE_CONST\n#define lp_yyconst const\n#else\n#define lp_yyconst\n#endif\n\n/* Returned upon end-of-file. */\n#define YY_NULL 0\n\n/* Promotes a possibly negative, possibly signed char to an unsigned\n * integer for use as an array index.  If the signed char is negative,\n * we want to instead treat it as an 8-bit unsigned char, hence the\n * double cast.\n */\n#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)\n\n/* An opaque pointer. */\n#ifndef YY_TYPEDEF_YY_SCANNER_T\n#define YY_TYPEDEF_YY_SCANNER_T\ntypedef void* lp_yyscan_t;\n#endif\n\n/* For convenience, these vars (plus the bison vars far below)\n   are macros in the reentrant scanner. */\n#define lp_yyin lp_yyg->lp_yyin_r\n#define lp_yyout lp_yyg->lp_yyout_r\n#define lp_yyextra lp_yyg->lp_yyextra_r\n#define lp_yyleng lp_yyg->lp_yyleng_r\n#define lp_yytext lp_yyg->lp_yytext_r\n#define lp_yylineno (YY_CURRENT_BUFFER_LVALUE->lp_yy_bs_lineno)\n#define lp_yycolumn (YY_CURRENT_BUFFER_LVALUE->lp_yy_bs_column)\n#define lp_yy_flex_debug lp_yyg->lp_yy_flex_debug_r\n\n/* Enter a start condition.  This macro really ought to take a parameter,\n * but we do it the disgusting crufty way forced on us by the ()-less\n * definition of BEGIN.\n */\n#define BEGIN lp_yyg->lp_yy_start = 1 + 2 *\n\n/* Translate the current start state into a value that can be later handed\n * to BEGIN to return to the state.  The YYSTATE alias is for lex\n * compatibility.\n */\n#define YY_START ((lp_yyg->lp_yy_start - 1) / 2)\n#define YYSTATE YY_START\n\n/* Action number for EOF rule of a given start state. */\n#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)\n\n/* Special action meaning \"start processing a new file\". */\n#define YY_NEW_FILE lp_yyrestart(lp_yyin ,lp_yyscanner )\n\n#define YY_END_OF_BUFFER_CHAR 0\n\n/* Size of default input buffer. */\n#ifndef YY_BUF_SIZE\n#define YY_BUF_SIZE 16384\n#endif\n\n/* The state buf must be large enough to hold one state per character in the main buffer.\n */\n#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(lp_yy_state_type))\n\n#ifndef YY_TYPEDEF_YY_BUFFER_STATE\n#define YY_TYPEDEF_YY_BUFFER_STATE\ntypedef struct lp_yy_buffer_state *YY_BUFFER_STATE;\n#endif\n\n#define EOB_ACT_CONTINUE_SCAN 0\n#define EOB_ACT_END_OF_FILE 1\n#define EOB_ACT_LAST_MATCH 2\n\n    /* Note: We specifically omit the test for lp_yy_rule_can_match_eol because it requires\n     *       access to the local variable lp_yy_act. Since lp_yyless() is a macro, it would break\n     *       existing scanners that call lp_yyless() from OUTSIDE lp_yylex.\n     *       One obvious solution it to make lp_yy_act a global. I tried that, and saw\n     *       a 5% performance hit in a non-lp_yylineno scanner, because lp_yy_act is\n     *       normally declared as a variable-- so it is not worth it.\n     */\n    #define  YY_LESS_LINENO(n) \\\n            do { \\\n                int lp_yyl;\\\n                for ( lp_yyl = n; lp_yyl < lp_yyleng; ++lp_yyl )\\\n                    if ( lp_yytext[lp_yyl] == '\\n' )\\\n                        --lp_yylineno;\\\n            }while(0)\n\n/* Return all but the first \"n\" matched characters back to the input stream. */\n#define lp_yyless(n) \\\n\tdo \\\n\t\t{ \\\n\t\t/* Undo effects of setting up lp_yytext. */ \\\n        int lp_yyless_macro_arg = (n); \\\n        YY_LESS_LINENO(lp_yyless_macro_arg);\\\n\t\t*lp_yy_cp = lp_yyg->lp_yy_hold_char; \\\n\t\tYY_RESTORE_YY_MORE_OFFSET \\\n\t\tlp_yyg->lp_yy_c_buf_p = lp_yy_cp = lp_yy_bp + lp_yyless_macro_arg - YY_MORE_ADJ; \\\n\t\tYY_DO_BEFORE_ACTION; /* set up lp_yytext again */ \\\n\t\t} \\\n\twhile ( 0 )\n\n#define unput(c) lp_yyunput( c, lp_yyg->lp_yytext_ptr , lp_yyscanner )\n\n#ifndef YY_TYPEDEF_YY_SIZE_T\n#define YY_TYPEDEF_YY_SIZE_T\ntypedef size_t lp_yy_size_t;\n#endif\n\n#ifndef YY_STRUCT_YY_BUFFER_STATE\n#define YY_STRUCT_YY_BUFFER_STATE\nstruct lp_yy_buffer_state\n\t{\n\tFILE *lp_yy_input_file;\n\n\tchar *lp_yy_ch_buf;\t\t/* input buffer */\n\tchar *lp_yy_buf_pos;\t\t/* current position in input buffer */\n\n\t/* Size of input buffer in bytes, not including room for EOB\n\t * characters.\n\t */\n\tlp_yy_size_t lp_yy_buf_size;\n\n\t/* Number of characters read into lp_yy_ch_buf, not including EOB\n\t * characters.\n\t */\n\tint lp_yy_n_chars;\n\n\t/* Whether we \"own\" the buffer - i.e., we know we created it,\n\t * and can realloc() it to grow it, and should free() it to\n\t * delete it.\n\t */\n\tint lp_yy_is_our_buffer;\n\n\t/* Whether this is an \"interactive\" input source; if so, and\n\t * if we're using stdio for input, then we want to use getc()\n\t * instead of fread(), to make sure we stop fetching input after\n\t * each newline.\n\t */\n\tint lp_yy_is_interactive;\n\n\t/* Whether we're considered to be at the beginning of a line.\n\t * If so, '^' rules will be active on the next match, otherwise\n\t * not.\n\t */\n\tint lp_yy_at_bol;\n\n    int lp_yy_bs_lineno; /**< The line count. */\n    int lp_yy_bs_column; /**< The column count. */\n\n\t/* Whether to try to fill the input buffer when we reach the\n\t * end of it.\n\t */\n\tint lp_yy_fill_buffer;\n\n\tint lp_yy_buffer_status;\n\n#define YY_BUFFER_NEW 0\n#define YY_BUFFER_NORMAL 1\n\t/* When an EOF's been seen but there's still some text to process\n\t * then we mark the buffer as YY_EOF_PENDING, to indicate that we\n\t * shouldn't try reading from the input source any more.  We might\n\t * still have a bunch of tokens to match, though, because of\n\t * possible backing-up.\n\t *\n\t * When we actually see the EOF, we change the status to \"new\"\n\t * (via lp_yyrestart()), so that the user can continue scanning by\n\t * just pointing lp_yyin at a new input file.\n\t */\n#define YY_BUFFER_EOF_PENDING 2\n\n\t};\n#endif /* !YY_STRUCT_YY_BUFFER_STATE */\n\n/* We provide macros for accessing buffer states in case in the\n * future we want to put the buffer states in a more general\n * \"scanner state\".\n *\n * Returns the top of the stack, or NULL.\n */\n#define YY_CURRENT_BUFFER ( lp_yyg->lp_yy_buffer_stack \\\n                          ? lp_yyg->lp_yy_buffer_stack[lp_yyg->lp_yy_buffer_stack_top] \\\n                          : NULL)\n\n/* Same as previous macro, but useful when we know that the buffer stack is not\n * NULL or when we need an lvalue. For internal use only.\n */\n#define YY_CURRENT_BUFFER_LVALUE lp_yyg->lp_yy_buffer_stack[lp_yyg->lp_yy_buffer_stack_top]\n\nvoid lp_yyrestart (FILE *input_file ,lp_yyscan_t lp_yyscanner );\nvoid lp_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,lp_yyscan_t lp_yyscanner );\nYY_BUFFER_STATE lp_yy_create_buffer (FILE *file,int size ,lp_yyscan_t lp_yyscanner );\nvoid lp_yy_delete_buffer (YY_BUFFER_STATE b ,lp_yyscan_t lp_yyscanner );\nvoid lp_yy_flush_buffer (YY_BUFFER_STATE b ,lp_yyscan_t lp_yyscanner );\nvoid lp_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,lp_yyscan_t lp_yyscanner );\nvoid lp_yypop_buffer_state (lp_yyscan_t lp_yyscanner );\n\nstatic void lp_yyensure_buffer_stack (lp_yyscan_t lp_yyscanner );\nstatic void lp_yy_load_buffer_state (lp_yyscan_t lp_yyscanner );\nstatic void lp_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,lp_yyscan_t lp_yyscanner );\n\n#define YY_FLUSH_BUFFER lp_yy_flush_buffer(YY_CURRENT_BUFFER ,lp_yyscanner)\n\nYY_BUFFER_STATE lp_yy_scan_buffer (char *base,lp_yy_size_t size ,lp_yyscan_t lp_yyscanner );\nYY_BUFFER_STATE lp_yy_scan_string (lp_yyconst char *lp_yy_str ,lp_yyscan_t lp_yyscanner );\nYY_BUFFER_STATE lp_yy_scan_bytes (lp_yyconst char *bytes,int len ,lp_yyscan_t lp_yyscanner );\n\nvoid *lp_yyalloc (lp_yy_size_t ,lp_yyscan_t lp_yyscanner );\nvoid *lp_yyrealloc (void *,lp_yy_size_t ,lp_yyscan_t lp_yyscanner );\nvoid lp_yyfree (void * ,lp_yyscan_t lp_yyscanner );\n\n#define lp_yy_new_buffer lp_yy_create_buffer\n\n#define lp_yy_set_interactive(is_interactive) \\\n\t{ \\\n\tif ( ! YY_CURRENT_BUFFER ){ \\\n        lp_yyensure_buffer_stack (lp_yyscanner); \\\n\t\tYY_CURRENT_BUFFER_LVALUE =    \\\n            lp_yy_create_buffer(lp_yyin,YY_BUF_SIZE ,lp_yyscanner); \\\n\t} \\\n\tYY_CURRENT_BUFFER_LVALUE->lp_yy_is_interactive = is_interactive; \\\n\t}\n\n#define lp_yy_set_bol(at_bol) \\\n\t{ \\\n\tif ( ! YY_CURRENT_BUFFER ){\\\n        lp_yyensure_buffer_stack (lp_yyscanner); \\\n\t\tYY_CURRENT_BUFFER_LVALUE =    \\\n            lp_yy_create_buffer(lp_yyin,YY_BUF_SIZE ,lp_yyscanner); \\\n\t} \\\n\tYY_CURRENT_BUFFER_LVALUE->lp_yy_at_bol = at_bol; \\\n\t}\n\n#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->lp_yy_at_bol)\n\n/* Begin user sect3 */\n\n#define lp_yywrap(n) 1\n#define YY_SKIP_YYWRAP\n\ntypedef unsigned char YY_CHAR;\n\ntypedef int lp_yy_state_type;\n\n#define lp_yytext_ptr lp_yytext_r\n\nstatic lp_yy_state_type lp_yy_get_previous_state (lp_yyscan_t lp_yyscanner );\nstatic lp_yy_state_type lp_yy_try_NUL_trans (lp_yy_state_type current_state  ,lp_yyscan_t lp_yyscanner);\nstatic int lp_yy_get_next_buffer (lp_yyscan_t lp_yyscanner );\nstatic void lp_yy_fatal_error (lp_yyconst char msg[] ,lp_yyscan_t lp_yyscanner );\n\n/* Done after the current pattern has been matched and before the\n * corresponding action - sets up lp_yytext.\n */\n#define YY_DO_BEFORE_ACTION \\\n\tlp_yyg->lp_yytext_ptr = lp_yy_bp; \\\n\tlp_yyleng = (size_t) (lp_yy_cp - lp_yy_bp); \\\n\tlp_yyg->lp_yy_hold_char = *lp_yy_cp; \\\n\t*lp_yy_cp = '\\0'; \\\n\tlp_yyg->lp_yy_c_buf_p = lp_yy_cp;\n\n#define YY_NUM_RULES 33\n#define YY_END_OF_BUFFER 34\n/* This struct is not used in this scanner,\n   but its presence is necessary. */\nstruct lp_yy_trans_info\n\t{\n\tflex_int32_t lp_yy_verify;\n\tflex_int32_t lp_yy_nxt;\n\t};\nstatic lp_yyconst flex_int16_t lp_yy_accept[144] =\n    {   0,\n        0,    0,    0,    0,    0,    0,   34,   32,   10,   10,\n       27,   17,   11,   32,   32,   14,   26,   31,   29,   28,\n       30,   25,   25,   10,   25,   25,   25,   25,    3,    4,\n        3,    3,    9,    7,    8,   10,   17,   17,    0,   15,\n        1,    6,   15,   14,    0,   29,   30,    0,   25,   24,\n        0,   25,   25,   10,    0,    0,    0,    0,   25,   25,\n       25,   25,   25,    2,    0,   15,    0,   15,   22,    0,\n       25,   25,    0,    0,    0,    0,    0,   19,   25,   18,\n       20,   25,   25,   21,    0,   25,    0,   13,   25,    0,\n       12,   25,   19,    0,   18,   20,   21,   25,   23,   25,\n\n       20,   21,   21,   16,   16,    0,   25,   25,    0,   23,\n        0,   21,   25,   25,    0,    0,   25,   25,    0,    0,\n       19,   25,    0,    0,   25,   25,   19,    0,   18,    0,\n        0,   25,   25,   18,    0,    0,    0,    0,    0,    0,\n        0,    0,    0\n    } ;\n\nstatic lp_yyconst flex_int32_t lp_yy_ec[256] =\n    {   0,\n        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,\n        1,    1,    4,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    2,    1,    1,    5,    6,    5,    5,    5,    1,\n        1,    7,    8,    9,   10,   11,   12,   13,   14,   14,\n       13,   13,   13,   13,   13,   13,   13,   15,   16,   17,\n       18,   19,    1,    5,   20,   21,   22,   23,   24,   25,\n       26,   23,   27,   23,   23,   23,   28,   29,   30,   23,\n       23,   31,   32,   33,   34,   23,   23,   35,   36,   37,\n        5,    1,    5,    5,    5,    1,   20,   21,   22,   23,\n\n       24,   25,   26,   23,   27,   23,   23,   23,   28,   29,\n       30,   23,   23,   31,   32,   33,   34,   23,   23,   35,\n       36,   37,    5,    1,    5,    5,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1\n    } ;\n\nstatic lp_yyconst flex_int32_t lp_yy_meta[38] =\n    {   0,\n        1,    2,    3,    3,    4,    5,    6,    3,    6,    3,\n        5,    5,    5,    5,    7,    6,    7,    6,    6,    4,\n        4,    4,    4,    4,    4,    4,    8,    4,    4,    4,\n        4,    4,    4,    4,    4,    4,    4\n    } ;\n\nstatic lp_yyconst flex_int16_t lp_yy_base[150] =\n    {   0,\n        0,   36,   36,   38,   43,   45,  366,  388,   48,   62,\n      388,  338,  388,   40,   48,   60,  388,  388,  346,  388,\n      326,   60,   65,   91,   81,   74,   85,  102,  388,  388,\n      388,  330,  388,  388,  388,  125,  313,  134,  308,   96,\n      388,  388,  117,  132,  139,  388,  388,   88,  146,  320,\n        0,  149,  152,    0,  307,  301,  294,   83,  153,  156,\n      157,  189,  160,  388,  286,  126,   65,  108,  388,  289,\n      181,  185,  272,  273,  250,  249,  220,  199,  203,  208,\n      192,  211,  219,  227,  243,  109,  163,  225,  202,  174,\n      224,  215,  213,  207,  191,  388,  189,  227,  228,  231,\n\n      244,  240,  253,  276,  388,  170,  260,  262,  166,  388,\n      169,  179,  263,  241,  166,  159,  270,  272,  149,  155,\n      284,  288,  130,  124,  296,  303,  388,  103,  300,   96,\n       45,  324,  328,  388,   82,  311,   79,   68,   54,   56,\n       25,   12,  388,  345,  353,  360,  367,  372,  379\n    } ;\n\nstatic lp_yyconst flex_int16_t lp_yy_def[150] =\n    {   0,\n      143,    1,  144,  144,  145,  145,  143,  143,  143,  143,\n      143,  146,  143,  143,  143,  143,  143,  143,  143,  143,\n      143,  147,  147,  143,  147,  147,  147,  147,  143,  143,\n      143,  143,  143,  143,  143,  143,  146,  143,  143,  143,\n      143,  143,  143,  143,  143,  143,  143,  143,  147,  143,\n      148,  147,  147,   24,  143,  143,  143,  143,  147,  147,\n      147,  147,  147,  143,  143,  143,  143,  143,  143,  148,\n      147,  147,  143,  143,  143,  143,  143,  147,  147,  147,\n      147,  147,  147,  147,  149,  143,  143,  143,   62,  143,\n      143,   62,  143,  143,  143,  143,  143,   62,   62,   62,\n\n       62,   62,   62,  143,  143,  143,   62,   62,  143,  143,\n      143,  143,   62,   62,  143,  143,   62,   62,  143,  143,\n       62,   62,  143,  143,   62,   62,  143,  143,   62,  143,\n      143,  147,  147,  143,  143,  149,  143,  143,  143,  143,\n      143,  143,    0,  143,  143,  143,  143,  143,  143\n    } ;\n\nstatic lp_yyconst flex_int16_t lp_yy_nxt[426] =\n    {   0,\n        8,    9,   10,    9,    8,    8,   11,   12,   13,   12,\n       14,   15,   16,   16,   17,   18,   19,   20,   21,   22,\n       22,   22,   22,   22,   22,   22,   22,   23,   22,   22,\n       22,   22,   22,   22,   22,   22,   22,   24,   30,   31,\n       30,   31,   32,   96,   32,   34,   35,   34,   35,   36,\n       36,   36,   40,   40,   41,   37,   25,   37,  142,   42,\n       26,   48,   27,   36,   36,   36,   48,   28,  136,   37,\n       43,   37,   44,   44,   50,   48,   51,   68,   68,   50,\n      136,   51,   48,   45,   52,  141,   48,  140,   50,   48,\n       51,   53,   54,   36,   36,   50,  139,   51,   37,   50,\n\n       37,   51,   50,   48,   60,  138,   76,   59,   40,   40,\n       48,   55,   77,   61,  137,   56,   50,   57,   51,   45,\n       68,   68,   58,   50,  135,   62,   36,   36,   36,   66,\n       66,   63,   37,  134,   37,   38,   38,   38,   66,   66,\n       45,   38,   43,   38,   44,   44,   67,   48,   67,   45,\n       48,   68,   68,   48,   48,   45,  131,   48,   48,  130,\n       50,   48,   51,   50,   87,   51,   50,   50,   51,   51,\n       50,   50,   51,   51,   50,   90,   51,   88,  128,   79,\n       72,   78,   87,   71,  127,  124,   90,  123,   91,   80,\n       48,   84,  112,   48,  120,   88,  119,   51,  116,   91,\n\n       48,   51,  112,   50,   48,   51,   50,   89,   51,   48,\n       81,   92,   48,   50,  111,   51,   82,   50,   98,   51,\n       48,   83,   50,   49,   51,   50,   99,   51,   48,  107,\n      110,  100,  109,   50,   49,   51,   49,  101,   69,   69,\n      103,   50,  108,   51,  104,  104,  104,   49,   49,   49,\n      102,   97,   49,  115,   49,   49,  114,  113,   49,   49,\n       49,   49,   49,   49,  122,   49,  103,   49,   49,  106,\n       96,   49,   49,   49,   49,   81,   49,  104,  104,  104,\n       49,   49,   95,   49,   49,   49,  117,   49,  118,   49,\n       49,   49,   49,   49,   49,   49,   94,   49,  121,   49,\n\n       93,  125,   49,  126,   49,   49,  125,   86,  126,   49,\n       85,   49,  104,  104,  104,   49,   49,   49,  129,  132,\n       49,   49,   75,   49,   49,   87,  133,   49,   49,   90,\n       49,   74,   49,   73,   69,   49,   65,  143,   88,   39,\n       51,   64,   91,   47,   51,   29,   29,   29,   29,   29,\n       29,   29,   29,   33,   33,   33,   33,   33,   33,   33,\n       33,   38,   38,   46,   39,  143,  143,   38,   49,  143,\n       49,   49,  143,   49,   49,   70,   70,  143,  143,   70,\n      105,  105,  143,  105,  105,  105,  105,    7,  143,  143,\n      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,\n\n      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,\n      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,\n      143,  143,  143,  143,  143\n    } ;\n\nstatic lp_yyconst flex_int16_t lp_yy_chk[426] =\n    {   0,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,\n        1,    1,    1,    1,    1,    1,    1,    2,    3,    3,\n        4,    4,    3,  142,    4,    5,    5,    6,    6,    9,\n        9,    9,   14,   14,   15,    9,    2,    9,  141,   15,\n        2,   22,    2,   10,   10,   10,   23,    2,  131,   10,\n       16,   10,   16,   16,   22,   26,   22,   67,   67,   23,\n      131,   23,   25,   16,   23,  140,   27,  139,   26,   48,\n       26,   23,   24,   24,   24,   25,  138,   25,   24,   27,\n\n       24,   27,   48,   28,   26,  137,   58,   25,   40,   40,\n       86,   24,   58,   27,  135,   24,   28,   24,   28,   40,\n       68,   68,   24,   86,  130,   28,   36,   36,   36,   43,\n       43,   28,   36,  128,   36,   38,   38,   38,   66,   66,\n       43,   38,   44,   38,   44,   44,   45,   49,   45,   66,\n       52,   45,   45,   53,   59,   44,  124,   60,   61,  123,\n       49,   63,   49,   52,   87,   52,   53,   59,   53,   59,\n       60,   61,   60,   61,   63,   90,   63,   87,  120,   60,\n       53,   59,   71,   52,  119,  116,   72,  115,   90,   61,\n       62,   63,  112,   81,  111,   71,  109,   71,  106,   72,\n\n       78,   72,   97,   62,   79,   62,   81,   71,   81,   80,\n       62,   72,   82,   78,   95,   78,   62,   79,   78,   79,\n       83,   62,   80,   89,   80,   82,   79,   82,   84,   89,\n       94,   80,   93,   83,   89,   83,   92,   82,   91,   88,\n       84,   84,   92,   84,   85,   85,   85,   92,   98,   99,\n       83,   77,  100,  101,   98,   99,  100,   98,  100,   98,\n       99,  102,  114,  100,  114,  101,  103,  102,  114,   85,\n       76,  101,  102,  114,  103,  101,  101,  104,  104,  104,\n      103,  107,   75,  108,  113,  103,  107,  107,  108,  108,\n      113,  117,  107,  118,  108,  113,   74,  117,  113,  118,\n\n       73,  117,  117,  118,  118,  121,  117,   70,  118,  122,\n       65,  121,  136,  136,  136,  122,  121,  125,  122,  125,\n      122,  129,   57,  125,  126,  132,  126,  129,  125,  133,\n      126,   56,  129,   55,   50,  126,   39,  136,  132,   37,\n      132,   32,  133,   21,  133,  144,  144,  144,  144,  144,\n      144,  144,  144,  145,  145,  145,  145,  145,  145,  145,\n      145,  146,  146,   19,   12,    7,    0,  146,  147,    0,\n      147,  147,    0,  147,  147,  148,  148,    0,    0,  148,\n      149,  149,    0,  149,  149,  149,  149,  143,  143,  143,\n      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,\n\n      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,\n      143,  143,  143,  143,  143,  143,  143,  143,  143,  143,\n      143,  143,  143,  143,  143\n    } ;\n\n/* Table of booleans, true if rule could match eol. */\nstatic lp_yyconst flex_int32_t lp_yy_rule_can_match_eol[34] =\n    {   0,\n0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     };\n\n/* The intent behind this definition is that it'll catch\n * any uses of REJECT which flex missed.\n */\n#define REJECT reject_used_but_not_detected\n#define lp_yymore() lp_yymore_used_but_not_detected\n#define YY_MORE_ADJ 0\n#define YY_RESTORE_YY_MORE_OFFSET\n/*\n   made reentrant with help of\n   http://www.usualcoding.eu/post/2007/09/03/Building-a-reentrant-parser-in-C-with-Flex/Bison\n*/\n/*\n   Note that a minimum version of flex is needed to be able to compile this.\n   Older version don't know the reentrant code.\n   Version 2.5.4 is not enough. Probably at least v2.5.31 is needed. Tested with v2.5.35\n*/\n/*\n** We want the scanner to be reentrant, therefore generate no global variables.\n** That what the 'reentrant' option is for.\n** 'bison-bridge' is used to create a bison compatible scanner and share lp_yylval\n*/\n\n#define INITIAL 0\n#define COMMENT 1\n#define LINECOMMENT 2\n\n#ifndef YY_NO_UNISTD_H\n/* Special case for \"unistd.h\", since it is non-ANSI. We include it way\n * down here because we want the user's section 1 to have been scanned first.\n * The user has a chance to override it with an option.\n */\n#include <unistd.h>\n#endif\n\n#ifndef YY_EXTRA_TYPE\n#define YY_EXTRA_TYPE void *\n#endif\n\n/* Holds the entire state of the reentrant scanner. */\nstruct lp_yyguts_t\n    {\n\n    /* User-defined. Not touched by flex. */\n    YY_EXTRA_TYPE lp_yyextra_r;\n\n    /* The rest are the same as the globals declared in the non-reentrant scanner. */\n    FILE *lp_yyin_r, *lp_yyout_r;\n    size_t lp_yy_buffer_stack_top; /**< index of top of stack. */\n    size_t lp_yy_buffer_stack_max; /**< capacity of stack. */\n    YY_BUFFER_STATE * lp_yy_buffer_stack; /**< Stack as an array. */\n    char lp_yy_hold_char;\n    int lp_yy_n_chars;\n    int lp_yyleng_r;\n    char *lp_yy_c_buf_p;\n    int lp_yy_init;\n    int lp_yy_start;\n    int lp_yy_did_buffer_switch_on_eof;\n    int lp_yy_start_stack_ptr;\n    int lp_yy_start_stack_depth;\n    int *lp_yy_start_stack;\n    lp_yy_state_type lp_yy_last_accepting_state;\n    char* lp_yy_last_accepting_cpos;\n\n    int lp_yylineno_r;\n    int lp_yy_flex_debug_r;\n\n    char *lp_yytext_r;\n    int lp_yy_more_flag;\n    int lp_yy_more_len;\n\n    YYSTYPE * lp_yylval_r;\n\n    }; /* end struct lp_yyguts_t */\n\nstatic int lp_yy_init_globals (lp_yyscan_t lp_yyscanner );\n\n    /* This must go here because YYSTYPE and YYLTYPE are included\n     * from bison output in section 1.*/\n    #    define lp_yylval lp_yyg->lp_yylval_r\n\nint lp_yylex_init (lp_yyscan_t* scanner);\n\nint lp_yylex_init_extra (YY_EXTRA_TYPE user_defined,lp_yyscan_t* scanner);\n\n/* Accessor methods to globals.\n   These are made visible to non-reentrant scanners for convenience. */\n\nint lp_yylex_destroy (lp_yyscan_t lp_yyscanner );\n\nint lp_yyget_debug (lp_yyscan_t lp_yyscanner );\n\nvoid lp_yyset_debug (int debug_flag ,lp_yyscan_t lp_yyscanner );\n\nYY_EXTRA_TYPE lp_yyget_extra (lp_yyscan_t lp_yyscanner );\n\nvoid lp_yyset_extra (YY_EXTRA_TYPE user_defined ,lp_yyscan_t lp_yyscanner );\n\nFILE *lp_yyget_in (lp_yyscan_t lp_yyscanner );\n\nvoid lp_yyset_in  (FILE * in_str ,lp_yyscan_t lp_yyscanner );\n\nFILE *lp_yyget_out (lp_yyscan_t lp_yyscanner );\n\nvoid lp_yyset_out  (FILE * out_str ,lp_yyscan_t lp_yyscanner );\n\nint lp_yyget_leng (lp_yyscan_t lp_yyscanner );\n\nchar *lp_yyget_text (lp_yyscan_t lp_yyscanner );\n\nint lp_yyget_lineno (lp_yyscan_t lp_yyscanner );\n\nvoid lp_yyset_lineno (int line_number ,lp_yyscan_t lp_yyscanner );\n\nYYSTYPE * lp_yyget_lval (lp_yyscan_t lp_yyscanner );\n\nvoid lp_yyset_lval (YYSTYPE * lp_yylval_param ,lp_yyscan_t lp_yyscanner );\n\n/* Macros after this point can all be overridden by user definitions in\n * section 1.\n */\n\n#ifndef YY_SKIP_YYWRAP\n#ifdef __cplusplus\nextern \"C\" int lp_yywrap (lp_yyscan_t lp_yyscanner );\n#else\nextern int lp_yywrap (lp_yyscan_t lp_yyscanner );\n#endif\n#endif\n\n    static void lp_yyunput (int c,char *buf_ptr  ,lp_yyscan_t lp_yyscanner);\n\n#ifndef lp_yytext_ptr\nstatic void lp_yy_flex_strncpy (char *,lp_yyconst char *,int ,lp_yyscan_t lp_yyscanner);\n#endif\n\n#ifdef YY_NEED_STRLEN\nstatic int lp_yy_flex_strlen (lp_yyconst char * ,lp_yyscan_t lp_yyscanner);\n#endif\n\n#ifndef YY_NO_INPUT\n\n#ifdef __cplusplus\nstatic int lp_yyinput (lp_yyscan_t lp_yyscanner );\n#else\nstatic int input (lp_yyscan_t lp_yyscanner );\n#endif\n\n#endif\n\n/* Amount of stuff to slurp up with each read. */\n#ifndef YY_READ_BUF_SIZE\n#define YY_READ_BUF_SIZE 8192\n#endif\n\n/* Copy whatever the last rule matched to the standard output. */\n#ifndef ECHO\n/* This used to be an fputs(), but since the string might contain NUL's,\n * we now use fwrite().\n */\n#define ECHO fwrite( lp_yytext, lp_yyleng, 1, lp_yyout )\n#endif\n\n/* Gets input and stuffs it into \"buf\".  number of characters read, or YY_NULL,\n * is returned in \"result\".\n */\n#ifndef YY_INPUT\n#define YY_INPUT(buf,result,max_size) \\\n\tif ( YY_CURRENT_BUFFER_LVALUE->lp_yy_is_interactive ) \\\n\t\t{ \\\n\t\tint c = '*'; \\\n\t\tint n; \\\n\t\tfor ( n = 0; n < max_size && \\\n\t\t\t     (c = getc( lp_yyin )) != EOF && c != '\\n'; ++n ) \\\n\t\t\tbuf[n] = (char) c; \\\n\t\tif ( c == '\\n' ) \\\n\t\t\tbuf[n++] = (char) c; \\\n\t\tif ( c == EOF && ferror( lp_yyin ) ) \\\n\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\\n\t\tresult = n; \\\n\t\t} \\\n\telse \\\n\t\t{ \\\n\t\terrno=0; \\\n\t\twhile ( (result = fread(buf, 1, max_size, lp_yyin))==0 && ferror(lp_yyin)) \\\n\t\t\t{ \\\n\t\t\tif( errno != EINTR) \\\n\t\t\t\t{ \\\n\t\t\t\tYY_FATAL_ERROR( \"input in flex scanner failed\" ); \\\n\t\t\t\tbreak; \\\n\t\t\t\t} \\\n\t\t\terrno=0; \\\n\t\t\tclearerr(lp_yyin); \\\n\t\t\t} \\\n\t\t}\\\n\\\n\n#endif\n\n/* No semi-colon after return; correct usage is to write \"lp_yyterminate();\" -\n * we don't want an extra ';' after the \"return\" because that will cause\n * some compilers to complain about unreachable statements.\n */\n#ifndef lp_yyterminate\n#define lp_yyterminate() return YY_NULL\n#endif\n\n/* Number of entries by which start-condition stack grows. */\n#ifndef YY_START_STACK_INCR\n#define YY_START_STACK_INCR 25\n#endif\n\n/* Report a fatal error. */\n#ifndef YY_FATAL_ERROR\n#define YY_FATAL_ERROR(msg) lp_yy_fatal_error( msg , lp_yyscanner)\n#endif\n\n/* end tables serialization structures and prototypes */\n\n/* Default declaration of generated scanner - a define so the user can\n * easily add parameters.\n */\n#ifndef YY_DECL\n#define YY_DECL_IS_OURS 1\n\nextern int lp_yylex \\\n               (YYSTYPE * lp_yylval_param ,lp_yyscan_t lp_yyscanner);\n\n#define YY_DECL int lp_yylex \\\n               (YYSTYPE * lp_yylval_param , lp_yyscan_t lp_yyscanner)\n#endif /* !YY_DECL */\n\n/* Code executed at the beginning of each rule, after lp_yytext and lp_yyleng\n * have been set up.\n */\n#ifndef YY_USER_ACTION\n#define YY_USER_ACTION\n#endif\n\n/* Code executed at the end of each rule. */\n#ifndef YY_BREAK\n#define YY_BREAK break;\n#endif\n\n#define YY_RULE_SETUP \\\n\tif ( lp_yyleng > 0 ) \\\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_at_bol = \\\n\t\t\t\t(lp_yytext[lp_yyleng - 1] == '\\n'); \\\n\tYY_USER_ACTION\n\n/** The main scanner function which does all the work.\n */\nYY_DECL\n{\n\tlp_yy_state_type lp_yy_current_state;\n\tchar *lp_yy_cp, *lp_yy_bp;\n\tint lp_yy_act;\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n    lp_yylval = lp_yylval_param;\n\n\tif ( !lp_yyg->lp_yy_init )\n\t\t{\n\t\tlp_yyg->lp_yy_init = 1;\n\n#ifdef YY_USER_INIT\n\t\tYY_USER_INIT;\n#endif\n\n\t\tif ( ! lp_yyg->lp_yy_start )\n\t\t\tlp_yyg->lp_yy_start = 1;\t/* first start state */\n\n\t\tif ( ! lp_yyin )\n\t\t\tlp_yyin = stdin;\n\n\t\tif ( ! lp_yyout )\n\t\t\tlp_yyout = stdout;\n\n\t\tif ( ! YY_CURRENT_BUFFER ) {\n\t\t\tlp_yyensure_buffer_stack (lp_yyscanner);\n\t\t\tYY_CURRENT_BUFFER_LVALUE =\n\t\t\t\tlp_yy_create_buffer(lp_yyin,YY_BUF_SIZE ,lp_yyscanner);\n\t\t}\n\n\t\tlp_yy_load_buffer_state(lp_yyscanner );\n\t\t}\n\n\twhile ( 1 )\t\t/* loops until end-of-file is reached */\n\t\t{\n\t\tlp_yy_cp = lp_yyg->lp_yy_c_buf_p;\n\n\t\t/* Support of lp_yytext. */\n\t\t*lp_yy_cp = lp_yyg->lp_yy_hold_char;\n\n\t\t/* lp_yy_bp points to the position in lp_yy_ch_buf of the start of\n\t\t * the current run.\n\t\t */\n\t\tlp_yy_bp = lp_yy_cp;\n\n\t\tlp_yy_current_state = lp_yyg->lp_yy_start;\n\t\tlp_yy_current_state += YY_AT_BOL();\nlp_yy_match:\n\t\tdo\n\t\t\t{\n\t\t\tYY_CHAR lp_yy_c = lp_yy_ec[YY_SC_TO_UI(*lp_yy_cp)];\n\t\t\tif ( lp_yy_accept[lp_yy_current_state] )\n\t\t\t\t{\n\t\t\t\tlp_yyg->lp_yy_last_accepting_state = lp_yy_current_state;\n\t\t\t\tlp_yyg->lp_yy_last_accepting_cpos = lp_yy_cp;\n\t\t\t\t}\n\t\t\twhile ( lp_yy_chk[lp_yy_base[lp_yy_current_state] + lp_yy_c] != lp_yy_current_state )\n\t\t\t\t{\n\t\t\t\tlp_yy_current_state = (int) lp_yy_def[lp_yy_current_state];\n\t\t\t\tif ( lp_yy_current_state >= 144 )\n\t\t\t\t\tlp_yy_c = lp_yy_meta[(unsigned int) lp_yy_c];\n\t\t\t\t}\n\t\t\tlp_yy_current_state = lp_yy_nxt[lp_yy_base[lp_yy_current_state] + (unsigned int) lp_yy_c];\n\t\t\t++lp_yy_cp;\n\t\t\t}\n\t\twhile ( lp_yy_base[lp_yy_current_state] != 388 );\n\nlp_yy_find_action:\n\t\tlp_yy_act = lp_yy_accept[lp_yy_current_state];\n\t\tif ( lp_yy_act == 0 )\n\t\t\t{ /* have to back up */\n\t\t\tlp_yy_cp = lp_yyg->lp_yy_last_accepting_cpos;\n\t\t\tlp_yy_current_state = lp_yyg->lp_yy_last_accepting_state;\n\t\t\tlp_yy_act = lp_yy_accept[lp_yy_current_state];\n\t\t\t}\n\n\t\tYY_DO_BEFORE_ACTION;\n\n\t\tif ( lp_yy_act != YY_END_OF_BUFFER && lp_yy_rule_can_match_eol[lp_yy_act] )\n\t\t\t{\n\t\t\tint lp_yyl;\n\t\t\tfor ( lp_yyl = 0; lp_yyl < lp_yyleng; ++lp_yyl )\n\t\t\t\tif ( lp_yytext[lp_yyl] == '\\n' )\n\t\t\t\t\t\n    do{ lp_yylineno++;\n        lp_yycolumn=0;\n    }while(0)\n;\n\t\t\t}\n\ndo_action:\t/* This label is used only to access EOF actions. */\n\n\t\tswitch ( lp_yy_act )\n\t{ /* beginning of action switch */\n\t\t\tcase 0: /* must back up */\n\t\t\t/* undo the effects of YY_DO_BEFORE_ACTION */\n\t\t\t*lp_yy_cp = lp_yyg->lp_yy_hold_char;\n\t\t\tlp_yy_cp = lp_yyg->lp_yy_last_accepting_cpos;\n\t\t\tlp_yy_current_state = lp_yyg->lp_yy_last_accepting_state;\n\t\t\tgoto lp_yy_find_action;\n\ncase 1:\nYY_RULE_SETUP\n{\n  BEGIN COMMENT;\n} /* begin skip comment */\n\tYY_BREAK\ncase 2:\nYY_RULE_SETUP\n{\n  BEGIN INITIAL;\n} /* end skip comment */\n\tYY_BREAK\ncase 3:\nYY_RULE_SETUP\n{\n}\n\tYY_BREAK\ncase 4:\n/* rule 4 can match eol */\nYY_RULE_SETUP\n{\n}\n\tYY_BREAK\ncase 5:\nYY_RULE_SETUP\n{\n}\n\tYY_BREAK\ncase 6:\nYY_RULE_SETUP\n{\n  BEGIN LINECOMMENT;\n} /* begin skip LINECOMMENT */\n\tYY_BREAK\ncase 7:\n/* rule 7 can match eol */\nYY_RULE_SETUP\n{\n  BEGIN INITIAL;\n} /* end skip LINECOMMENT */\n\tYY_BREAK\ncase 8:\nYY_RULE_SETUP\n{\n  BEGIN INITIAL;\n} /* end skip LINECOMMENT */\n\tYY_BREAK\ncase 9:\nYY_RULE_SETUP\n{\n}\n\tYY_BREAK\ncase 10:\n/* rule 10 can match eol */\nYY_RULE_SETUP\n{\n}\n\tYY_BREAK\ncase 11:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n\n  pp->lineno = lp_yylineno;\n  return(COMMA);\n}\n\tYY_BREAK\ncase 12:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n\n  pp->lineno = lp_yylineno;\n  return(MINIMISE);\n}\n\tYY_BREAK\ncase 13:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n\n  pp->lineno = lp_yylineno;\n  return(MAXIMISE);\n}\n\tYY_BREAK\ncase 14:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  pv->f = atof((char *)lp_yytext);\n  return(INTCONS);\n} /* f contains the last float */\n\tYY_BREAK\ncase 15:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  pv->f = atof((char *)lp_yytext);\n  return(CONS);\n} /* f contains the last float */\n\tYY_BREAK\ncase 16:\n/* rule 16 can match eol */\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n  char *ptr, c;\n\n  pp->lineno = lp_yylineno;\n  pv->f = DEF_INFINITE;\n  pv->Sign = 0;\n  ptr = (char *)lp_yytext;\n  while (isspace(*ptr)) ptr++;\n  if(*ptr == '-')\n    pv->Sign = 1;\n  if(lp_yyleng > 0) {\n    c = lp_yytext[lp_yyleng - 1];\n    if(!isalnum(c))\n      unput(c);\n  }\n  return(INF);\n} /* f contains the last float */\n\tYY_BREAK\ncase 17:\n/* rule 17 can match eol */\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n  int x;\n\n  pp->lineno = lp_yylineno;\n  pv->Sign = 0;\n  for(x = 0; x < lp_yyleng; x++)\n    if(lp_yytext[x] == '-' || lp_yytext[x] == '+')\n      pv->Sign = (pv->Sign == (lp_yytext[x] == '+'));\n  return (TOK_SIGN);\n  /* Sign is TRUE if the sign-string\n     represents a '-'. Otherwise Sign\n     is FALSE */\n}\n\tYY_BREAK\ncase 18:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  if((!pv->Within_int_decl) && (!pv->Within_sec_decl) && (!pv->Within_sos_decl) && (!pv->Within_free_decl)) {\n    pv->Within_int_decl = 1;\n    pv->Within_sos_decl1 = FALSE;\n  }\n  return(SEC_INT);\n}\n\tYY_BREAK\ncase 19:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  if((!pv->Within_int_decl) && (!pv->Within_sec_decl) && (!pv->Within_sos_decl) && (!pv->Within_free_decl)) {\n    pv->Within_int_decl = 2;\n    pv->Within_sos_decl1 = FALSE;\n  }\n  return(SEC_BIN);\n}\n\tYY_BREAK\ncase 20:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  if((!pv->Within_int_decl) && (!pv->Within_sec_decl) && (!pv->Within_sos_decl) && (!pv->Within_free_decl)) {\n    pv->Within_sec_decl = TRUE;\n    pv->Within_sos_decl1 = FALSE;\n  }\n  return(SEC_SEC);\n}\n\tYY_BREAK\ncase 21:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  if(!pv->Within_sos_decl)\n    pv->SOStype0 = (short)atoi(((char *)lp_yytext) + 3);\n  if((!pv->Within_int_decl) && (!pv->Within_sec_decl) && (!pv->Within_sos_decl) && (!pv->Within_free_decl))\n    pv->Within_sos_decl = TRUE;\n  return(SEC_SOS);\n}\n\tYY_BREAK\ncase 22:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  FREE(pv->Last_var);\n  pv->Last_var = strdup((char *)lp_yytext);\n  pv->Last_var[strlen(pv->Last_var) - 2] = 0;\n  return(SOSDESCR);\n}\n\tYY_BREAK\ncase 23:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  if((!pv->Within_int_decl) && (!pv->Within_sec_decl) && (!pv->Within_sos_decl) && (!pv->Within_free_decl)) {\n    pv->Within_free_decl = TRUE;\n    pv->Within_sos_decl1 = FALSE;\n  }\n  return(SEC_FREE);\n}\n\tYY_BREAK\ncase 24:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n  char *ptr;\n\n  pp->lineno = lp_yylineno;\n  FREE(pv->Last_var);\n  pv->Last_var = strdup((char *)lp_yytext);\n  ptr = pv->Last_var + strlen(pv->Last_var);\n  ptr[-1] = ' ';\n  while ((--ptr >= pv->Last_var) && (isspace(*ptr)))\n    *ptr = 0;\n  return(VARIABLECOLON);\n}\n\tYY_BREAK\ncase 25:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  FREE(pv->Last_var);\n  pv->Last_var = strdup((char *)lp_yytext);\n  return(VAR);\n}\n\tYY_BREAK\ncase 26:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n\n  pp->lineno = lp_yylineno;\n  return (COLON);\n}\n\tYY_BREAK\ncase 27:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n\n  pp->lineno = lp_yylineno;\n  return(AR_M_OP);\n}\n\tYY_BREAK\ncase 28:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  pv->OP = *lp_yytext;\n  return(RE_OPEQ);\n}\n\tYY_BREAK\ncase 29:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  pv->OP = *lp_yytext;\n  return(RE_OPLE);\n}\n\tYY_BREAK\ncase 30:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  pv->OP = *lp_yytext;\n  return(RE_OPGE);\n}\n\tYY_BREAK\ncase 31:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n  parse_vars *pv = (parse_vars *) pp->parse_vars;\n\n  pp->lineno = lp_yylineno;\n  pv->Within_int_decl = pv->Within_sec_decl = pv->Within_sos_decl = pv->Within_free_decl = FALSE;\n  check_int_sec_sos_free_decl(pp, (int) pv->Within_int_decl, (int) pv->Within_sec_decl, (int) pv->Within_sos_decl, (int) pv->Within_free_decl);\n  return(END_C);\n}\n\tYY_BREAK\ncase 32:\nYY_RULE_SETUP\n{\n  parse_parm *pp = PARM;\n\n  pp->lineno = lp_yylineno;\n  report(NULL, CRITICAL, \"LEX ERROR : %s lineno %d\\n\", lp_yytext, lp_yylineno);\n  return(UNDEFINED);\n}\n\tYY_BREAK\ncase 33:\nYY_RULE_SETUP\nECHO;\n\tYY_BREAK\ncase YY_STATE_EOF(INITIAL):\ncase YY_STATE_EOF(COMMENT):\ncase YY_STATE_EOF(LINECOMMENT):\n\tlp_yyterminate();\n\n\tcase YY_END_OF_BUFFER:\n\t\t{\n\t\t/* Amount of text matched not including the EOB char. */\n\t\tint lp_yy_amount_of_matched_text = (int) (lp_yy_cp - lp_yyg->lp_yytext_ptr) - 1;\n\n\t\t/* Undo the effects of YY_DO_BEFORE_ACTION. */\n\t\t*lp_yy_cp = lp_yyg->lp_yy_hold_char;\n\t\tYY_RESTORE_YY_MORE_OFFSET\n\n\t\tif ( YY_CURRENT_BUFFER_LVALUE->lp_yy_buffer_status == YY_BUFFER_NEW )\n\t\t\t{\n\t\t\t/* We're scanning a new file or input source.  It's\n\t\t\t * possible that this happened because the user\n\t\t\t * just pointed lp_yyin at a new source and called\n\t\t\t * lp_yylex().  If so, then we have to assure\n\t\t\t * consistency between YY_CURRENT_BUFFER and our\n\t\t\t * globals.  Here is the right place to do so, because\n\t\t\t * this is the first action (other than possibly a\n\t\t\t * back-up) that will match for the new input source.\n\t\t\t */\n\t\t\tlp_yyg->lp_yy_n_chars = YY_CURRENT_BUFFER_LVALUE->lp_yy_n_chars;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_input_file = lp_yyin;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_buffer_status = YY_BUFFER_NORMAL;\n\t\t\t}\n\n\t\t/* Note that here we test for lp_yy_c_buf_p \"<=\" to the position\n\t\t * of the first EOB in the buffer, since lp_yy_c_buf_p will\n\t\t * already have been incremented past the NUL character\n\t\t * (since all states make transitions on EOB to the\n\t\t * end-of-buffer state).  Contrast this with the test\n\t\t * in input().\n\t\t */\n\t\tif ( lp_yyg->lp_yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[lp_yyg->lp_yy_n_chars] )\n\t\t\t{ /* This was really a NUL. */\n\t\t\tlp_yy_state_type lp_yy_next_state;\n\n\t\t\tlp_yyg->lp_yy_c_buf_p = lp_yyg->lp_yytext_ptr + lp_yy_amount_of_matched_text;\n\n\t\t\tlp_yy_current_state = lp_yy_get_previous_state( lp_yyscanner );\n\n\t\t\t/* Okay, we're now positioned to make the NUL\n\t\t\t * transition.  We couldn't have\n\t\t\t * lp_yy_get_previous_state() go ahead and do it\n\t\t\t * for us because it doesn't know how to deal\n\t\t\t * with the possibility of jamming (and we don't\n\t\t\t * want to build jamming into it because then it\n\t\t\t * will run more slowly).\n\t\t\t */\n\n\t\t\tlp_yy_next_state = lp_yy_try_NUL_trans( lp_yy_current_state , lp_yyscanner);\n\n\t\t\tlp_yy_bp = lp_yyg->lp_yytext_ptr + YY_MORE_ADJ;\n\n\t\t\tif ( lp_yy_next_state )\n\t\t\t\t{\n\t\t\t\t/* Consume the NUL. */\n\t\t\t\tlp_yy_cp = ++lp_yyg->lp_yy_c_buf_p;\n\t\t\t\tlp_yy_current_state = lp_yy_next_state;\n\t\t\t\tgoto lp_yy_match;\n\t\t\t\t}\n\n\t\t\telse\n\t\t\t\t{\n\t\t\t\tlp_yy_cp = lp_yyg->lp_yy_c_buf_p;\n\t\t\t\tgoto lp_yy_find_action;\n\t\t\t\t}\n\t\t\t}\n\n\t\telse switch ( lp_yy_get_next_buffer( lp_yyscanner ) )\n\t\t\t{\n\t\t\tcase EOB_ACT_END_OF_FILE:\n\t\t\t\t{\n\t\t\t\tlp_yyg->lp_yy_did_buffer_switch_on_eof = 0;\n\n\t\t\t\tif ( lp_yywrap(lp_yyscanner ) )\n\t\t\t\t\t{\n\t\t\t\t\t/* Note: because we've taken care in\n\t\t\t\t\t * lp_yy_get_next_buffer() to have set up\n\t\t\t\t\t * lp_yytext, we can now set up\n\t\t\t\t\t * lp_yy_c_buf_p so that if some total\n\t\t\t\t\t * hoser (like flex itself) wants to\n\t\t\t\t\t * call the scanner after we return the\n\t\t\t\t\t * YY_NULL, it'll still work - another\n\t\t\t\t\t * YY_NULL will get returned.\n\t\t\t\t\t */\n\t\t\t\t\tlp_yyg->lp_yy_c_buf_p = lp_yyg->lp_yytext_ptr + YY_MORE_ADJ;\n\n\t\t\t\t\tlp_yy_act = YY_STATE_EOF(YY_START);\n\t\t\t\t\tgoto do_action;\n\t\t\t\t\t}\n\n\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\tif ( ! lp_yyg->lp_yy_did_buffer_switch_on_eof )\n\t\t\t\t\t\tYY_NEW_FILE;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\tcase EOB_ACT_CONTINUE_SCAN:\n\t\t\t\tlp_yyg->lp_yy_c_buf_p =\n\t\t\t\t\tlp_yyg->lp_yytext_ptr + lp_yy_amount_of_matched_text;\n\n\t\t\t\tlp_yy_current_state = lp_yy_get_previous_state( lp_yyscanner );\n\n\t\t\t\tlp_yy_cp = lp_yyg->lp_yy_c_buf_p;\n\t\t\t\tlp_yy_bp = lp_yyg->lp_yytext_ptr + YY_MORE_ADJ;\n\t\t\t\tgoto lp_yy_match;\n\n\t\t\tcase EOB_ACT_LAST_MATCH:\n\t\t\t\tlp_yyg->lp_yy_c_buf_p =\n\t\t\t\t&YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[lp_yyg->lp_yy_n_chars];\n\n\t\t\t\tlp_yy_current_state = lp_yy_get_previous_state( lp_yyscanner );\n\n\t\t\t\tlp_yy_cp = lp_yyg->lp_yy_c_buf_p;\n\t\t\t\tlp_yy_bp = lp_yyg->lp_yytext_ptr + YY_MORE_ADJ;\n\t\t\t\tgoto lp_yy_find_action;\n\t\t\t}\n\t\tbreak;\n\t\t}\n\n\tdefault:\n\t\tYY_FATAL_ERROR(\n\t\t\t\"fatal flex scanner internal error--no action found\" );\n\t} /* end of action switch */\n\t\t} /* end of scanning one token */\n} /* end of lp_yylex */\n\n/* lp_yy_get_next_buffer - try to read in a new buffer\n *\n * Returns a code representing an action:\n *\tEOB_ACT_LAST_MATCH -\n *\tEOB_ACT_CONTINUE_SCAN - continue scanning from current position\n *\tEOB_ACT_END_OF_FILE - end of file\n */\nstatic int lp_yy_get_next_buffer (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\tchar *dest = YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf;\n\tchar *source = lp_yyg->lp_yytext_ptr;\n\tint number_to_move, i;\n\tint ret_val;\n\n\tif ( lp_yyg->lp_yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[lp_yyg->lp_yy_n_chars + 1] )\n\t\tYY_FATAL_ERROR(\n\t\t\"fatal flex scanner internal error--end of buffer missed\" );\n\n\tif ( YY_CURRENT_BUFFER_LVALUE->lp_yy_fill_buffer == 0 )\n\t\t{ /* Don't try to fill the buffer, so this is an EOF. */\n\t\tif ( lp_yyg->lp_yy_c_buf_p - lp_yyg->lp_yytext_ptr - YY_MORE_ADJ == 1 )\n\t\t\t{\n\t\t\t/* We matched a single character, the EOB, so\n\t\t\t * treat this as a final EOF.\n\t\t\t */\n\t\t\treturn EOB_ACT_END_OF_FILE;\n\t\t\t}\n\n\t\telse\n\t\t\t{\n\t\t\t/* We matched some text prior to the EOB, first\n\t\t\t * process it.\n\t\t\t */\n\t\t\treturn EOB_ACT_LAST_MATCH;\n\t\t\t}\n\t\t}\n\n\t/* Try to read more data. */\n\n\t/* First move last chars to start of buffer. */\n\tnumber_to_move = (int) (lp_yyg->lp_yy_c_buf_p - lp_yyg->lp_yytext_ptr) - 1;\n\n\tfor ( i = 0; i < number_to_move; ++i )\n\t\t*(dest++) = *(source++);\n\n\tif ( YY_CURRENT_BUFFER_LVALUE->lp_yy_buffer_status == YY_BUFFER_EOF_PENDING )\n\t\t/* don't do the read, it's not guaranteed to return an EOF,\n\t\t * just force an EOF\n\t\t */\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_n_chars = lp_yyg->lp_yy_n_chars = 0;\n\n\telse\n\t\t{\n\t\t\tint num_to_read =\n\t\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_buf_size - number_to_move - 1;\n\n\t\twhile ( num_to_read <= 0 )\n\t\t\t{ /* Not enough room in the buffer - grow it. */\n\n\t\t\t/* just a shorter name for the current buffer */\n\t\t\tYY_BUFFER_STATE b = YY_CURRENT_BUFFER;\n\n\t\t\tint lp_yy_c_buf_p_offset =\n\t\t\t\t(int) (lp_yyg->lp_yy_c_buf_p - b->lp_yy_ch_buf);\n\n\t\t\tif ( b->lp_yy_is_our_buffer )\n\t\t\t\t{\n\t\t\t\tint new_size = b->lp_yy_buf_size * 2;\n\n\t\t\t\tif ( new_size <= 0 )\n\t\t\t\t\tb->lp_yy_buf_size += b->lp_yy_buf_size / 8;\n\t\t\t\telse\n\t\t\t\t\tb->lp_yy_buf_size *= 2;\n\n\t\t\t\tb->lp_yy_ch_buf = (char *)\n\t\t\t\t\t/* Include room in for 2 EOB chars. */\n\t\t\t\t\tlp_yyrealloc((void *) b->lp_yy_ch_buf,b->lp_yy_buf_size + 2 ,lp_yyscanner );\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t/* Can't grow it, we don't own it. */\n\t\t\t\tb->lp_yy_ch_buf = 0;\n\n\t\t\tif ( ! b->lp_yy_ch_buf )\n\t\t\t\tYY_FATAL_ERROR(\n\t\t\t\t\"fatal error - scanner input buffer overflow\" );\n\n\t\t\tlp_yyg->lp_yy_c_buf_p = &b->lp_yy_ch_buf[lp_yy_c_buf_p_offset];\n\n\t\t\tnum_to_read = YY_CURRENT_BUFFER_LVALUE->lp_yy_buf_size -\n\t\t\t\t\t\tnumber_to_move - 1;\n\n\t\t\t}\n\n\t\tif ( num_to_read > YY_READ_BUF_SIZE )\n\t\t\tnum_to_read = YY_READ_BUF_SIZE;\n\n\t\t/* Read in more data. */\n\t\tYY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[number_to_move]),\n\t\t\tlp_yyg->lp_yy_n_chars, (size_t) num_to_read );\n\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_n_chars = lp_yyg->lp_yy_n_chars;\n\t\t}\n\n\tif ( lp_yyg->lp_yy_n_chars == 0 )\n\t\t{\n\t\tif ( number_to_move == YY_MORE_ADJ )\n\t\t\t{\n\t\t\tret_val = EOB_ACT_END_OF_FILE;\n\t\t\tlp_yyrestart(lp_yyin  ,lp_yyscanner);\n\t\t\t}\n\n\t\telse\n\t\t\t{\n\t\t\tret_val = EOB_ACT_LAST_MATCH;\n\t\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_buffer_status =\n\t\t\t\tYY_BUFFER_EOF_PENDING;\n\t\t\t}\n\t\t}\n\n\telse\n\t\tret_val = EOB_ACT_CONTINUE_SCAN;\n\n\tif ((lp_yy_size_t) (lp_yyg->lp_yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->lp_yy_buf_size) {\n\t\t/* Extend the array by 50%, plus the number we really need. */\n\t\tlp_yy_size_t new_size = lp_yyg->lp_yy_n_chars + number_to_move + (lp_yyg->lp_yy_n_chars >> 1);\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf = (char *) lp_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf,new_size ,lp_yyscanner );\n\t\tif ( ! YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in lp_yy_get_next_buffer()\" );\n\t}\n\n\tlp_yyg->lp_yy_n_chars += number_to_move;\n\tYY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[lp_yyg->lp_yy_n_chars] = YY_END_OF_BUFFER_CHAR;\n\tYY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[lp_yyg->lp_yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;\n\n\tlp_yyg->lp_yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[0];\n\n\treturn ret_val;\n}\n\n/* lp_yy_get_previous_state - get the state just before the EOB char was reached */\n\n    static lp_yy_state_type lp_yy_get_previous_state (lp_yyscan_t lp_yyscanner)\n{\n\tlp_yy_state_type lp_yy_current_state;\n\tchar *lp_yy_cp;\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n\tlp_yy_current_state = lp_yyg->lp_yy_start;\n\tlp_yy_current_state += YY_AT_BOL();\n\n\tfor ( lp_yy_cp = lp_yyg->lp_yytext_ptr + YY_MORE_ADJ; lp_yy_cp < lp_yyg->lp_yy_c_buf_p; ++lp_yy_cp )\n\t\t{\n\t\tYY_CHAR lp_yy_c = (*lp_yy_cp ? lp_yy_ec[YY_SC_TO_UI(*lp_yy_cp)] : 1);\n\t\tif ( lp_yy_accept[lp_yy_current_state] )\n\t\t\t{\n\t\t\tlp_yyg->lp_yy_last_accepting_state = lp_yy_current_state;\n\t\t\tlp_yyg->lp_yy_last_accepting_cpos = lp_yy_cp;\n\t\t\t}\n\t\twhile ( lp_yy_chk[lp_yy_base[lp_yy_current_state] + lp_yy_c] != lp_yy_current_state )\n\t\t\t{\n\t\t\tlp_yy_current_state = (int) lp_yy_def[lp_yy_current_state];\n\t\t\tif ( lp_yy_current_state >= 144 )\n\t\t\t\tlp_yy_c = lp_yy_meta[(unsigned int) lp_yy_c];\n\t\t\t}\n\t\tlp_yy_current_state = lp_yy_nxt[lp_yy_base[lp_yy_current_state] + (unsigned int) lp_yy_c];\n\t\t}\n\n\treturn lp_yy_current_state;\n}\n\n/* lp_yy_try_NUL_trans - try to make a transition on the NUL character\n *\n * synopsis\n *\tnext_state = lp_yy_try_NUL_trans( current_state );\n */\n    static lp_yy_state_type lp_yy_try_NUL_trans  (lp_yy_state_type lp_yy_current_state , lp_yyscan_t lp_yyscanner)\n{\n\tint lp_yy_is_jam;\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner; /* This var may be unused depending upon options. */\n\tchar *lp_yy_cp = lp_yyg->lp_yy_c_buf_p;\n\n\tYY_CHAR lp_yy_c = 1;\n\tif ( lp_yy_accept[lp_yy_current_state] )\n\t\t{\n\t\tlp_yyg->lp_yy_last_accepting_state = lp_yy_current_state;\n\t\tlp_yyg->lp_yy_last_accepting_cpos = lp_yy_cp;\n\t\t}\n\twhile ( lp_yy_chk[lp_yy_base[lp_yy_current_state] + lp_yy_c] != lp_yy_current_state )\n\t\t{\n\t\tlp_yy_current_state = (int) lp_yy_def[lp_yy_current_state];\n\t\tif ( lp_yy_current_state >= 144 )\n\t\t\tlp_yy_c = lp_yy_meta[(unsigned int) lp_yy_c];\n\t\t}\n\tlp_yy_current_state = lp_yy_nxt[lp_yy_base[lp_yy_current_state] + (unsigned int) lp_yy_c];\n\tlp_yy_is_jam = (lp_yy_current_state == 143);\n\n\treturn lp_yy_is_jam ? 0 : lp_yy_current_state;\n}\n\n    static void lp_yyunput (int c, char * lp_yy_bp , lp_yyscan_t lp_yyscanner)\n{\n\tchar *lp_yy_cp;\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n    lp_yy_cp = lp_yyg->lp_yy_c_buf_p;\n\n\t/* undo effects of setting up lp_yytext */\n\t*lp_yy_cp = lp_yyg->lp_yy_hold_char;\n\n\tif ( lp_yy_cp < YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf + 2 )\n\t\t{ /* need to shift things up to make room */\n\t\t/* +2 for EOB chars. */\n\t\tint number_to_move = lp_yyg->lp_yy_n_chars + 2;\n\t\tchar *dest = &YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[\n\t\t\t\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_buf_size + 2];\n\t\tchar *source =\n\t\t\t\t&YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[number_to_move];\n\n\t\twhile ( source > YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf )\n\t\t\t*--dest = *--source;\n\n\t\tlp_yy_cp += (int) (dest - source);\n\t\tlp_yy_bp += (int) (dest - source);\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_n_chars =\n\t\t\tlp_yyg->lp_yy_n_chars = YY_CURRENT_BUFFER_LVALUE->lp_yy_buf_size;\n\n\t\tif ( lp_yy_cp < YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf + 2 )\n\t\t\tYY_FATAL_ERROR( \"flex scanner push-back overflow\" );\n\t\t}\n\n\t*--lp_yy_cp = (char) c;\n\n    if ( c == '\\n' ){\n        --lp_yylineno;\n    }\n\n\tlp_yyg->lp_yytext_ptr = lp_yy_bp;\n\tlp_yyg->lp_yy_hold_char = *lp_yy_cp;\n\tlp_yyg->lp_yy_c_buf_p = lp_yy_cp;\n}\n\n#ifndef YY_NO_INPUT\n#ifdef __cplusplus\n    static inline int lp_yyinput (lp_yyscan_t lp_yyscanner)\n#else\n    static inline int input  (lp_yyscan_t lp_yyscanner)\n#endif\n\n{\n\tint c;\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n\t*lp_yyg->lp_yy_c_buf_p = lp_yyg->lp_yy_hold_char;\n\n\tif ( *lp_yyg->lp_yy_c_buf_p == YY_END_OF_BUFFER_CHAR )\n\t\t{\n\t\t/* lp_yy_c_buf_p now points to the character we want to return.\n\t\t * If this occurs *before* the EOB characters, then it's a\n\t\t * valid NUL; if not, then we've hit the end of the buffer.\n\t\t */\n\t\tif ( lp_yyg->lp_yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->lp_yy_ch_buf[lp_yyg->lp_yy_n_chars] )\n\t\t\t/* This was really a NUL. */\n\t\t\t*lp_yyg->lp_yy_c_buf_p = '\\0';\n\n\t\telse\n\t\t\t{ /* need more input */\n\t\t\tint offset = lp_yyg->lp_yy_c_buf_p - lp_yyg->lp_yytext_ptr;\n\t\t\t++lp_yyg->lp_yy_c_buf_p;\n\n\t\t\tswitch ( lp_yy_get_next_buffer( lp_yyscanner ) )\n\t\t\t\t{\n\t\t\t\tcase EOB_ACT_LAST_MATCH:\n\t\t\t\t\t/* This happens because lp_yy_g_n_b()\n\t\t\t\t\t * sees that we've accumulated a\n\t\t\t\t\t * token and flags that we need to\n\t\t\t\t\t * try matching the token before\n\t\t\t\t\t * proceeding.  But for input(),\n\t\t\t\t\t * there's no matching to consider.\n\t\t\t\t\t * So convert the EOB_ACT_LAST_MATCH\n\t\t\t\t\t * to EOB_ACT_END_OF_FILE.\n\t\t\t\t\t */\n\n\t\t\t\t\t/* Reset buffer status. */\n\t\t\t\t\tlp_yyrestart(lp_yyin ,lp_yyscanner);\n\n\t\t\t\t\t/*FALLTHROUGH*/\n\n\t\t\t\tcase EOB_ACT_END_OF_FILE:\n\t\t\t\t\t{\n\t\t\t\t\tif ( lp_yywrap(lp_yyscanner ) )\n\t\t\t\t\t\treturn EOF;\n\n\t\t\t\t\tif ( ! lp_yyg->lp_yy_did_buffer_switch_on_eof )\n\t\t\t\t\t\tYY_NEW_FILE;\n#ifdef __cplusplus\n\t\t\t\t\treturn lp_yyinput(lp_yyscanner);\n#else\n\t\t\t\t\treturn input(lp_yyscanner);\n#endif\n\t\t\t\t\t}\n\n\t\t\t\tcase EOB_ACT_CONTINUE_SCAN:\n\t\t\t\t\tlp_yyg->lp_yy_c_buf_p = lp_yyg->lp_yytext_ptr + offset;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\tc = *(unsigned char *) lp_yyg->lp_yy_c_buf_p;\t/* cast for 8-bit char's */\n\t*lp_yyg->lp_yy_c_buf_p = '\\0';\t/* preserve lp_yytext */\n\tlp_yyg->lp_yy_hold_char = *++lp_yyg->lp_yy_c_buf_p;\n\n\tYY_CURRENT_BUFFER_LVALUE->lp_yy_at_bol = (c == '\\n');\n\tif ( YY_CURRENT_BUFFER_LVALUE->lp_yy_at_bol )\n\t\t\n    do{ lp_yylineno++;\n        lp_yycolumn=0;\n    }while(0)\n;\n\n\treturn c;\n}\n#endif\t/* ifndef YY_NO_INPUT */\n\n/** Immediately switch to a different input stream.\n * @param input_file A readable stream.\n * @param lp_yyscanner The scanner object.\n * @note This function does not reset the start condition to @c INITIAL .\n */\n    void lp_yyrestart  (FILE * input_file , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n\tif ( ! YY_CURRENT_BUFFER ){\n        lp_yyensure_buffer_stack (lp_yyscanner);\n\t\tYY_CURRENT_BUFFER_LVALUE =\n            lp_yy_create_buffer(lp_yyin,YY_BUF_SIZE ,lp_yyscanner);\n\t}\n\n\tlp_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,lp_yyscanner);\n\tlp_yy_load_buffer_state(lp_yyscanner );\n}\n\n/** Switch to a different input buffer.\n * @param new_buffer The new input buffer.\n * @param lp_yyscanner The scanner object.\n */\n    void lp_yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n\t/* TODO. We should be able to replace this entire function body\n\t * with\n\t *\t\tlp_yypop_buffer_state();\n\t *\t\tlp_yypush_buffer_state(new_buffer);\n     */\n\tlp_yyensure_buffer_stack (lp_yyscanner);\n\tif ( YY_CURRENT_BUFFER == new_buffer )\n\t\treturn;\n\n\tif ( YY_CURRENT_BUFFER )\n\t\t{\n\t\t/* Flush out information for old buffer. */\n\t\t*lp_yyg->lp_yy_c_buf_p = lp_yyg->lp_yy_hold_char;\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_buf_pos = lp_yyg->lp_yy_c_buf_p;\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_n_chars = lp_yyg->lp_yy_n_chars;\n\t\t}\n\n\tYY_CURRENT_BUFFER_LVALUE = new_buffer;\n\tlp_yy_load_buffer_state(lp_yyscanner );\n\n\t/* We don't actually know whether we did this switch during\n\t * EOF (lp_yywrap()) processing, but the only time this flag\n\t * is looked at is after lp_yywrap() is called, so it's safe\n\t * to go ahead and always set it.\n\t */\n\tlp_yyg->lp_yy_did_buffer_switch_on_eof = 1;\n}\n\nstatic void lp_yy_load_buffer_state  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\tlp_yyg->lp_yy_n_chars = YY_CURRENT_BUFFER_LVALUE->lp_yy_n_chars;\n\tlp_yyg->lp_yytext_ptr = lp_yyg->lp_yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->lp_yy_buf_pos;\n\tlp_yyin = YY_CURRENT_BUFFER_LVALUE->lp_yy_input_file;\n\tlp_yyg->lp_yy_hold_char = *lp_yyg->lp_yy_c_buf_p;\n}\n\n/** Allocate and initialize an input buffer state.\n * @param file A readable stream.\n * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.\n * @param lp_yyscanner The scanner object.\n * @return the allocated buffer state.\n */\n    YY_BUFFER_STATE lp_yy_create_buffer  (FILE * file, int  size , lp_yyscan_t lp_yyscanner)\n{\n\tYY_BUFFER_STATE b;\n\n\tb = (YY_BUFFER_STATE) lp_yyalloc(sizeof( struct lp_yy_buffer_state ) ,lp_yyscanner );\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in lp_yy_create_buffer()\" );\n\n\tb->lp_yy_buf_size = size;\n\n\t/* lp_yy_ch_buf has to be 2 characters longer than the size given because\n\t * we need to put in 2 end-of-buffer characters.\n\t */\n\tb->lp_yy_ch_buf = (char *) lp_yyalloc(b->lp_yy_buf_size + 2 ,lp_yyscanner );\n\tif ( ! b->lp_yy_ch_buf )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in lp_yy_create_buffer()\" );\n\n\tb->lp_yy_is_our_buffer = 1;\n\n\tlp_yy_init_buffer(b,file ,lp_yyscanner);\n\n\treturn b;\n}\n\n/** Destroy the buffer.\n * @param b a buffer created with lp_yy_create_buffer()\n * @param lp_yyscanner The scanner object.\n */\n    void lp_yy_delete_buffer (YY_BUFFER_STATE  b , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n\tif ( ! b )\n\t\treturn;\n\n\tif ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */\n\t\tYY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;\n\n\tif ( b->lp_yy_is_our_buffer )\n\t\tlp_yyfree((void *) b->lp_yy_ch_buf ,lp_yyscanner );\n\n\tlp_yyfree((void *) b ,lp_yyscanner );\n}\n\n#ifndef __cplusplus\nextern int isatty (int );\n#endif /* __cplusplus */\n\n/* Initializes or reinitializes a buffer.\n * This function is sometimes called more than once on the same buffer,\n * such as during a lp_yyrestart() or at EOF.\n */\n    static void lp_yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , lp_yyscan_t lp_yyscanner)\n\n{\n\tint oerrno = errno;\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n\tlp_yy_flush_buffer(b ,lp_yyscanner);\n\n\tb->lp_yy_input_file = file;\n\tb->lp_yy_fill_buffer = 1;\n\n    /* If b is the current buffer, then lp_yy_init_buffer was _probably_\n     * called from lp_yyrestart() or through lp_yy_get_next_buffer.\n     * In that case, we don't want to reset the lineno or column.\n     */\n    if (b != YY_CURRENT_BUFFER){\n        b->lp_yy_bs_lineno = 1;\n        b->lp_yy_bs_column = 0;\n    }\n\n        b->lp_yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;\n\n\terrno = oerrno;\n}\n\n/** Discard all buffered characters. On the next scan, YY_INPUT will be called.\n * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.\n * @param lp_yyscanner The scanner object.\n */\n    void lp_yy_flush_buffer (YY_BUFFER_STATE  b , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\tif ( ! b )\n\t\treturn;\n\n\tb->lp_yy_n_chars = 0;\n\n\t/* We always need two end-of-buffer characters.  The first causes\n\t * a transition to the end-of-buffer state.  The second causes\n\t * a jam in that state.\n\t */\n\tb->lp_yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;\n\tb->lp_yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;\n\n\tb->lp_yy_buf_pos = &b->lp_yy_ch_buf[0];\n\n\tb->lp_yy_at_bol = 1;\n\tb->lp_yy_buffer_status = YY_BUFFER_NEW;\n\n\tif ( b == YY_CURRENT_BUFFER )\n\t\tlp_yy_load_buffer_state(lp_yyscanner );\n}\n\n/** Pushes the new state onto the stack. The new state becomes\n *  the current state. This function will allocate the stack\n *  if necessary.\n *  @param new_buffer The new state.\n *  @param lp_yyscanner The scanner object.\n */\nvoid lp_yypush_buffer_state (YY_BUFFER_STATE new_buffer , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\tif (new_buffer == NULL)\n\t\treturn;\n\n\tlp_yyensure_buffer_stack(lp_yyscanner);\n\n\t/* This block is copied from lp_yy_switch_to_buffer. */\n\tif ( YY_CURRENT_BUFFER )\n\t\t{\n\t\t/* Flush out information for old buffer. */\n\t\t*lp_yyg->lp_yy_c_buf_p = lp_yyg->lp_yy_hold_char;\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_buf_pos = lp_yyg->lp_yy_c_buf_p;\n\t\tYY_CURRENT_BUFFER_LVALUE->lp_yy_n_chars = lp_yyg->lp_yy_n_chars;\n\t\t}\n\n\t/* Only push if top exists. Otherwise, replace top. */\n\tif (YY_CURRENT_BUFFER)\n\t\tlp_yyg->lp_yy_buffer_stack_top++;\n\tYY_CURRENT_BUFFER_LVALUE = new_buffer;\n\n\t/* copied from lp_yy_switch_to_buffer. */\n\tlp_yy_load_buffer_state(lp_yyscanner );\n\tlp_yyg->lp_yy_did_buffer_switch_on_eof = 1;\n}\n\n/** Removes and deletes the top of the stack, if present.\n *  The next element becomes the new top.\n *  @param lp_yyscanner The scanner object.\n */\nvoid lp_yypop_buffer_state (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\tif (!YY_CURRENT_BUFFER)\n\t\treturn;\n\n\tlp_yy_delete_buffer(YY_CURRENT_BUFFER ,lp_yyscanner);\n\tYY_CURRENT_BUFFER_LVALUE = NULL;\n\tif (lp_yyg->lp_yy_buffer_stack_top > 0)\n\t\t--lp_yyg->lp_yy_buffer_stack_top;\n\n\tif (YY_CURRENT_BUFFER) {\n\t\tlp_yy_load_buffer_state(lp_yyscanner );\n\t\tlp_yyg->lp_yy_did_buffer_switch_on_eof = 1;\n\t}\n}\n\n/* Allocates the stack if it does not exist.\n *  Guarantees space for at least one push.\n */\nstatic void lp_yyensure_buffer_stack (lp_yyscan_t lp_yyscanner)\n{\n\tint num_to_alloc;\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n\tif (!lp_yyg->lp_yy_buffer_stack) {\n\n\t\t/* First allocation is just for 2 elements, since we don't know if this\n\t\t * scanner will even need a stack. We use 2 instead of 1 to avoid an\n\t\t * immediate realloc on the next call.\n         */\n\t\tnum_to_alloc = 1;\n\t\tlp_yyg->lp_yy_buffer_stack = (struct lp_yy_buffer_state**)lp_yyalloc\n\t\t\t\t\t\t\t\t(num_to_alloc * sizeof(struct lp_yy_buffer_state*)\n\t\t\t\t\t\t\t\t, lp_yyscanner);\n\t\tif ( ! lp_yyg->lp_yy_buffer_stack )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in lp_yyensure_buffer_stack()\" );\n\t\t\t\t\t\t\t\t\n\t\tmemset(lp_yyg->lp_yy_buffer_stack, 0, num_to_alloc * sizeof(struct lp_yy_buffer_state*));\n\t\t\t\t\n\t\tlp_yyg->lp_yy_buffer_stack_max = num_to_alloc;\n\t\tlp_yyg->lp_yy_buffer_stack_top = 0;\n\t\treturn;\n\t}\n\n\tif (lp_yyg->lp_yy_buffer_stack_top >= (lp_yyg->lp_yy_buffer_stack_max) - 1){\n\n\t\t/* Increase the buffer to prepare for a possible push. */\n\t\tint grow_size = 8 /* arbitrary grow size */;\n\n\t\tnum_to_alloc = lp_yyg->lp_yy_buffer_stack_max + grow_size;\n\t\tlp_yyg->lp_yy_buffer_stack = (struct lp_yy_buffer_state**)lp_yyrealloc\n\t\t\t\t\t\t\t\t(lp_yyg->lp_yy_buffer_stack,\n\t\t\t\t\t\t\t\tnum_to_alloc * sizeof(struct lp_yy_buffer_state*)\n\t\t\t\t\t\t\t\t, lp_yyscanner);\n\t\tif ( ! lp_yyg->lp_yy_buffer_stack )\n\t\t\tYY_FATAL_ERROR( \"out of dynamic memory in lp_yyensure_buffer_stack()\" );\n\n\t\t/* zero only the new slots.*/\n\t\tmemset(lp_yyg->lp_yy_buffer_stack + lp_yyg->lp_yy_buffer_stack_max, 0, grow_size * sizeof(struct lp_yy_buffer_state*));\n\t\tlp_yyg->lp_yy_buffer_stack_max = num_to_alloc;\n\t}\n}\n\n/** Setup the input buffer state to scan directly from a user-specified character buffer.\n * @param base the character buffer\n * @param size the size in bytes of the character buffer\n * @param lp_yyscanner The scanner object.\n * @return the newly allocated buffer state object.\n */\nYY_BUFFER_STATE lp_yy_scan_buffer  (char * base, lp_yy_size_t  size , lp_yyscan_t lp_yyscanner)\n{\n\tYY_BUFFER_STATE b;\n\n\tif ( size < 2 ||\n\t     base[size-2] != YY_END_OF_BUFFER_CHAR ||\n\t     base[size-1] != YY_END_OF_BUFFER_CHAR )\n\t\t/* They forgot to leave room for the EOB's. */\n\t\treturn 0;\n\n\tb = (YY_BUFFER_STATE) lp_yyalloc(sizeof( struct lp_yy_buffer_state ) ,lp_yyscanner );\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in lp_yy_scan_buffer()\" );\n\n\tb->lp_yy_buf_size = size - 2;\t/* \"- 2\" to take care of EOB's */\n\tb->lp_yy_buf_pos = b->lp_yy_ch_buf = base;\n\tb->lp_yy_is_our_buffer = 0;\n\tb->lp_yy_input_file = 0;\n\tb->lp_yy_n_chars = b->lp_yy_buf_size;\n\tb->lp_yy_is_interactive = 0;\n\tb->lp_yy_at_bol = 1;\n\tb->lp_yy_fill_buffer = 0;\n\tb->lp_yy_buffer_status = YY_BUFFER_NEW;\n\n\tlp_yy_switch_to_buffer(b ,lp_yyscanner );\n\n\treturn b;\n}\n\n/** Setup the input buffer state to scan a string. The next call to lp_yylex() will\n * scan from a @e copy of @a str.\n * @param lp_yystr a NUL-terminated string to scan\n * @param lp_yyscanner The scanner object.\n * @return the newly allocated buffer state object.\n * @note If you want to scan bytes that may contain NUL values, then use\n *       lp_yy_scan_bytes() instead.\n */\nYY_BUFFER_STATE lp_yy_scan_string (lp_yyconst char * lp_yystr , lp_yyscan_t lp_yyscanner)\n{\n\n\treturn lp_yy_scan_bytes(lp_yystr,strlen(lp_yystr) ,lp_yyscanner);\n}\n\n/** Setup the input buffer state to scan the given bytes. The next call to lp_yylex() will\n * scan from a @e copy of @a bytes.\n * @param bytes the byte buffer to scan\n * @param len the number of bytes in the buffer pointed to by @a bytes.\n * @param lp_yyscanner The scanner object.\n * @return the newly allocated buffer state object.\n */\nYY_BUFFER_STATE lp_yy_scan_bytes  (lp_yyconst char * lp_yybytes, int  _lp_yybytes_len , lp_yyscan_t lp_yyscanner)\n{\n\tYY_BUFFER_STATE b;\n\tchar *buf;\n\tlp_yy_size_t n;\n\tint i;\n\n\t/* Get memory for full buffer, including space for trailing EOB's. */\n\tn = _lp_yybytes_len + 2;\n\tbuf = (char *) lp_yyalloc(n ,lp_yyscanner );\n\tif ( ! buf )\n\t\tYY_FATAL_ERROR( \"out of dynamic memory in lp_yy_scan_bytes()\" );\n\n\tfor ( i = 0; i < _lp_yybytes_len; ++i )\n\t\tbuf[i] = lp_yybytes[i];\n\n\tbuf[_lp_yybytes_len] = buf[_lp_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;\n\n\tb = lp_yy_scan_buffer(buf,n ,lp_yyscanner);\n\tif ( ! b )\n\t\tYY_FATAL_ERROR( \"bad buffer in lp_yy_scan_bytes()\" );\n\n\t/* It's okay to grow etc. this buffer, and we should throw it\n\t * away when we're done.\n\t */\n\tb->lp_yy_is_our_buffer = 1;\n\n\treturn b;\n}\n\n#ifndef YY_EXIT_FAILURE\n#define YY_EXIT_FAILURE 2\n#endif\n\nstatic void lp_yy_fatal_error (lp_yyconst char* msg , lp_yyscan_t lp_yyscanner)\n{\n        (void) lp_yyscanner; /* Remove unused parameter warning */\n    \t(void) fprintf( stderr, \"%s\\n\", msg );\n\texit( YY_EXIT_FAILURE );\n}\n\n/* Redefine lp_yyless() so it works in section 3 code. */\n\n#undef lp_yyless\n#define lp_yyless(n) \\\n\tdo \\\n\t\t{ \\\n\t\t/* Undo effects of setting up lp_yytext. */ \\\n        int lp_yyless_macro_arg = (n); \\\n        YY_LESS_LINENO(lp_yyless_macro_arg);\\\n\t\tlp_yytext[lp_yyleng] = lp_yyg->lp_yy_hold_char; \\\n\t\tlp_yyg->lp_yy_c_buf_p = lp_yytext + lp_yyless_macro_arg; \\\n\t\tlp_yyg->lp_yy_hold_char = *lp_yyg->lp_yy_c_buf_p; \\\n\t\t*lp_yyg->lp_yy_c_buf_p = '\\0'; \\\n\t\tlp_yyleng = lp_yyless_macro_arg; \\\n\t\t} \\\n\twhile ( 0 )\n\n/* Accessor  methods (get/set functions) to struct members. */\n\n/** Get the user-defined data for this scanner.\n * @param lp_yyscanner The scanner object.\n */\nYY_EXTRA_TYPE lp_yyget_extra  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    return lp_yyextra;\n}\n\n/** Get the current line number.\n * @param lp_yyscanner The scanner object.\n */\nint lp_yyget_lineno  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n        if (! YY_CURRENT_BUFFER)\n            return 0;\n\n    return lp_yylineno;\n}\n\n/** Get the current column number.\n * @param lp_yyscanner The scanner object.\n */\nint lp_yyget_column  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n        if (! YY_CURRENT_BUFFER)\n            return 0;\n\n    return lp_yycolumn;\n}\n\n/** Get the input stream.\n * @param lp_yyscanner The scanner object.\n */\nFILE *lp_yyget_in  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    return lp_yyin;\n}\n\n/** Get the output stream.\n * @param lp_yyscanner The scanner object.\n */\nFILE *lp_yyget_out  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    return lp_yyout;\n}\n\n/** Get the length of the current token.\n * @param lp_yyscanner The scanner object.\n */\nint lp_yyget_leng  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    return lp_yyleng;\n}\n\n/** Get the current token.\n * @param lp_yyscanner The scanner object.\n */\n\nchar *lp_yyget_text  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    return lp_yytext;\n}\n\n/** Set the user-defined data. This data is never touched by the scanner.\n * @param user_defined The data to be associated with this scanner.\n * @param lp_yyscanner The scanner object.\n */\nvoid lp_yyset_extra (YY_EXTRA_TYPE  user_defined , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    lp_yyextra = user_defined ;\n}\n\n/** Set the current line number.\n * @param line_number\n * @param lp_yyscanner The scanner object.\n */\nvoid lp_yyset_lineno (int  line_number , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n        /* lineno is only valid if an input buffer exists. */\n        if (! YY_CURRENT_BUFFER )\n           lp_yy_fatal_error( \"lp_yyset_lineno called with no buffer\" , lp_yyscanner);\n\n    lp_yylineno = line_number;\n}\n\n/** Set the current column.\n * @param line_number\n * @param lp_yyscanner The scanner object.\n */\nvoid lp_yyset_column (int  column_no , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n        /* column is only valid if an input buffer exists. */\n        if (! YY_CURRENT_BUFFER )\n           lp_yy_fatal_error( \"lp_yyset_column called with no buffer\" , lp_yyscanner);\n\n    lp_yycolumn = column_no;\n}\n\n/** Set the input stream. This does not discard the current\n * input buffer.\n * @param in_str A readable stream.\n * @param lp_yyscanner The scanner object.\n * @see lp_yy_switch_to_buffer\n */\nvoid lp_yyset_in (FILE *  in_str , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    lp_yyin = in_str ;\n}\n\nvoid lp_yyset_out (FILE *  out_str , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    lp_yyout = out_str ;\n}\n\nint lp_yyget_debug  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    return lp_yy_flex_debug;\n}\n\nvoid lp_yyset_debug (int  bdebug , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    lp_yy_flex_debug = bdebug ;\n}\n\n/* Accessor methods for lp_yylval and lp_yylloc */\n\nYYSTYPE * lp_yyget_lval  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    return lp_yylval;\n}\n\nvoid lp_yyset_lval (YYSTYPE *  lp_yylval_param , lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    lp_yylval = lp_yylval_param;\n}\n\n/* User-visible API */\n\n/* lp_yylex_init is special because it creates the scanner itself, so it is\n * the ONLY reentrant function that doesn't take the scanner as the last argument.\n * That's why we explicitly handle the declaration, instead of using our macros.\n */\n\nint lp_yylex_init(lp_yyscan_t* ptr_lp_yy_globals)\n\n{\n    if (ptr_lp_yy_globals == NULL){\n        errno = EINVAL;\n        return 1;\n    }\n\n    *ptr_lp_yy_globals = (lp_yyscan_t) lp_yyalloc ( sizeof( struct lp_yyguts_t ), NULL );\n\n    if (*ptr_lp_yy_globals == NULL){\n        errno = ENOMEM;\n        return 1;\n    }\n\n    /* By setting to 0xAA, we expose bugs in lp_yy_init_globals. Leave at 0x00 for releases. */\n    memset(*ptr_lp_yy_globals,0x00,sizeof(struct lp_yyguts_t));\n\n    return lp_yy_init_globals ( *ptr_lp_yy_globals );\n}\n\n/* lp_yylex_init_extra has the same functionality as lp_yylex_init, but follows the\n * convention of taking the scanner as the last argument. Note however, that\n * this is a *pointer* to a scanner, as it will be allocated by this call (and\n * is the reason, too, why this function also must handle its own declaration).\n * The user defined value in the first argument will be available to lp_yyalloc in\n * the lp_yyextra field.\n */\n\nint lp_yylex_init_extra(YY_EXTRA_TYPE lp_yy_user_defined,lp_yyscan_t* ptr_lp_yy_globals )\n\n{\n    struct lp_yyguts_t dummy_lp_yyguts;\n\n    lp_yyset_extra (lp_yy_user_defined, &dummy_lp_yyguts);\n\n    if (ptr_lp_yy_globals == NULL){\n        errno = EINVAL;\n        return 1;\n    }\n\t\n    *ptr_lp_yy_globals = (lp_yyscan_t) lp_yyalloc ( sizeof( struct lp_yyguts_t ), &dummy_lp_yyguts );\n\t\n    if (*ptr_lp_yy_globals == NULL){\n        errno = ENOMEM;\n        return 1;\n    }\n\n    /* By setting to 0xAA, we expose bugs in\n    lp_yy_init_globals. Leave at 0x00 for releases. */\n    memset(*ptr_lp_yy_globals,0x00,sizeof(struct lp_yyguts_t));\n\n    lp_yyset_extra (lp_yy_user_defined, *ptr_lp_yy_globals);\n\n    return lp_yy_init_globals ( *ptr_lp_yy_globals );\n}\n\nstatic int lp_yy_init_globals (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n    /* Initialization is the same as for the non-reentrant scanner.\n     * This function is called from lp_yylex_destroy(), so don't allocate here.\n     */\n\n    lp_yyg->lp_yy_buffer_stack = 0;\n    lp_yyg->lp_yy_buffer_stack_top = 0;\n    lp_yyg->lp_yy_buffer_stack_max = 0;\n    lp_yyg->lp_yy_c_buf_p = (char *) 0;\n    lp_yyg->lp_yy_init = 0;\n    lp_yyg->lp_yy_start = 0;\n\n    lp_yyg->lp_yy_start_stack_ptr = 0;\n    lp_yyg->lp_yy_start_stack_depth = 0;\n    lp_yyg->lp_yy_start_stack =  NULL;\n\n/* Defined in main.c */\n#ifdef YY_STDINIT\n    lp_yyin = stdin;\n    lp_yyout = stdout;\n#else\n    lp_yyin = (FILE *) 0;\n    lp_yyout = (FILE *) 0;\n#endif\n\n    /* For future reference: Set errno on error, since we are called by\n     * lp_yylex_init()\n     */\n    return 0;\n}\n\n/* lp_yylex_destroy is for both reentrant and non-reentrant scanners. */\nint lp_yylex_destroy  (lp_yyscan_t lp_yyscanner)\n{\n    struct lp_yyguts_t * lp_yyg = (struct lp_yyguts_t*)lp_yyscanner;\n\n    /* Pop the buffer stack, destroying each element. */\n\twhile(YY_CURRENT_BUFFER){\n\t\tlp_yy_delete_buffer(YY_CURRENT_BUFFER ,lp_yyscanner );\n\t\tYY_CURRENT_BUFFER_LVALUE = NULL;\n\t\tlp_yypop_buffer_state(lp_yyscanner);\n\t}\n\n\t/* Destroy the stack itself. */\n\tlp_yyfree(lp_yyg->lp_yy_buffer_stack ,lp_yyscanner);\n\tlp_yyg->lp_yy_buffer_stack = NULL;\n\n    /* Destroy the start condition stack. */\n        lp_yyfree(lp_yyg->lp_yy_start_stack ,lp_yyscanner );\n        lp_yyg->lp_yy_start_stack = NULL;\n\n    /* Reset the globals. This is important in a non-reentrant scanner so the next time\n     * lp_yylex() is called, initialization will occur. */\n    lp_yy_init_globals( lp_yyscanner);\n\n    /* Destroy the main struct (reentrant only). */\n    lp_yyfree ( lp_yyscanner , lp_yyscanner );\n    lp_yyscanner = NULL;\n    return 0;\n}\n\n/*\n * Internal utility routines.\n */\n\n#ifndef lp_yytext_ptr\nstatic void lp_yy_flex_strncpy (char* s1, lp_yyconst char * s2, int n , lp_yyscan_t lp_yyscanner)\n{\n\tint i;\n\tfor ( i = 0; i < n; ++i )\n\t\ts1[i] = s2[i];\n}\n#endif\n\n#ifdef YY_NEED_STRLEN\nstatic int lp_yy_flex_strlen (lp_yyconst char * s , lp_yyscan_t lp_yyscanner)\n{\n\tint n;\n\tfor ( n = 0; s[n]; ++n )\n\t\t;\n\n\treturn n;\n}\n#endif\n\nvoid *lp_yyalloc (lp_yy_size_t  size , lp_yyscan_t lp_yyscanner)\n{\n        (void) lp_yyscanner; /* Remove unused parameter warning */\n\treturn (void *) malloc( size );\n}\n\nvoid *lp_yyrealloc  (void * ptr, lp_yy_size_t  size , lp_yyscan_t lp_yyscanner)\n{\n        (void) lp_yyscanner; /* Remove unused parameter warning */\n\t/* The cast to (char *) in the following accommodates both\n\t * implementations that use char* generic pointers, and those\n\t * that use void* generic pointers.  It works with the latter\n\t * because both ANSI C and C++ allow castless assignment from\n\t * any pointer type to void*, and deal with argument conversions\n\t * as though doing an assignment.\n\t */\n\treturn (void *) realloc( (char *) ptr, size );\n}\n\nvoid lp_yyfree (void * ptr , lp_yyscan_t lp_yyscanner)\n{\n        (void) lp_yyscanner; /* Remove unused parameter warning */\n\tfree( (char *) ptr );\t/* see lp_yyrealloc() for (char *) cast */\n}\n\n#define YYTABLES_NAME \"lp_yytables\"\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_scale.c",
    "content": "\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_report.h\"\n#include \"lp_scale.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n/*\n    Scaling routines for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: LGPL.\n\n    Requires:      lp_lib.h, lp_scale.h\n\n    Release notes:\n    v5.0.0  1 January 2004      Significantly expanded and repackaged scaling\n                                routines.\n    v5.0.1  20 February 2004    Modified rounding behaviour in several areas.\n    v5.1.0  20 July 2004        Reworked with flexible matrix storage model.\n    v5.2.0  20 February 2005    Converted to matrix storage model without the OF.\n\n   ----------------------------------------------------------------------------------\n*/\n\n/* First define scaling and unscaling primitives */\n\nREAL scaled_value(lprec *lp, REAL value, int index)\n{\n  if(fabs(value) < lp->infinite) {\n    if(lp->scaling_used) {\n      if(index > lp->rows)\n        value /= lp->scalars[index];\n      else\n        value *= lp->scalars[index];\n    }\n  }\n  else\n    value = my_sign(value)*lp->infinite;\n  return(value);\n}\n\nREAL unscaled_value(lprec *lp, REAL value, int index)\n{\n  if(fabs(value) < lp->infinite) {\n    if(lp->scaling_used) {\n      if(index > lp->rows)\n        value *= lp->scalars[index];\n      else\n        value /= lp->scalars[index];\n    }\n  }\n  else\n    value = my_sign(value)*lp->infinite;\n  return(value);\n}\n\nSTATIC REAL scaled_mat(lprec *lp, REAL value, int rownr, int colnr)\n{\n  if(lp->scaling_used)\n    value *= lp->scalars[rownr] * lp->scalars[lp->rows + colnr];\n  return( value );\n}\n\nSTATIC REAL unscaled_mat(lprec *lp, REAL value, int rownr, int colnr)\n{\n  if(lp->scaling_used)\n    value /= lp->scalars[rownr] * lp->scalars[lp->rows + colnr];\n  return( value );\n}\n\n/* Compute the scale factor by the formulae:\n      FALSE: SUM (log |Aij|) ^ 2\n      TRUE:  SUM (log |Aij| - RowScale[i] - ColScale[j]) ^ 2 */\nREAL CurtisReidMeasure(lprec *lp, MYBOOL _Advanced, REAL *FRowScale, REAL *FColScale)\n{\n  int      i, nz;\n  REAL     absvalue, logvalue;\n  REAL result;\n  MATrec   *mat = lp->matA;\n  REAL     *value;\n  int      *rownr, *colnr;\n\n  /* Do OF part */\n  result = 0;\n  for(i = 1; i <= lp->columns; i++) {\n    absvalue = fabs(lp->orig_obj[i]);\n    if(absvalue > 0) {\n      logvalue = log(absvalue);\n      if(_Advanced)\n        logvalue -= FRowScale[0] + FColScale[i];\n      result += logvalue*logvalue;\n    }\n  }\n\n  /* Do constraint matrix part */\n  mat_validate(mat);\n  value = &(COL_MAT_VALUE(0));\n  rownr = &(COL_MAT_ROWNR(0));\n  colnr = &(COL_MAT_COLNR(0));\n  nz = get_nonzeros(lp);\n  for(i = 0; i < nz;\n      i++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) {\n    absvalue = fabs(*value);\n    if(absvalue > 0) {\n      logvalue = log(absvalue);\n      if(_Advanced)\n        logvalue -= FRowScale[*rownr] + FColScale[*colnr];\n      result += logvalue*logvalue;\n    }\n  }\n  return( result );\n}\n\n/* Implementation of the Curtis-Reid scaling based on the paper\n   \"On the Automatic Scaling of Matrices for Gaussian\n    Elimination,\" Journal of the Institute of Mathematics and\n    Its Applications (1972) 10, 118-124.\n\n    Solve the system | M   E | (r)   (sigma)\n                     |       | ( ) = (     )\n                     | E^T N | (c)   ( tau )\n\n    by the conjugate gradient method (clever recurrences).\n\n    E is the matrix A with all elements = 1\n\n    M is diagonal matrix of row    counts (RowCount)\n    N is diagonal matrix of column counts (ColCount)\n\n    sigma is the vector of row    logarithm sums (RowSum)\n    tau   is the vector of column logarithm sums (ColSum)\n\n    r, c are resulting row and column scalings (RowScale, ColScale) */\n\nint CurtisReidScales(lprec *lp, MYBOOL _Advanced, REAL *FRowScale, REAL *FColScale)\n{\n  int    i, row, col, ent, nz;\n  REAL   *RowScalem2, *ColScalem2,\n         *RowSum, *ColSum,\n         *residual_even, *residual_odd;\n  REAL   sk,   qk,     ek,\n         skm1, qkm1,   ekm1,\n         qkm2, qkqkm1, ekm2, ekekm1,\n         absvalue, logvalue,\n         StopTolerance;\n  int    *RowCount, *ColCount, colMax;\n  int    Result;\n  MATrec *mat = lp->matA;\n  REAL   *value;\n  int    *rownr, *colnr;\n\n  if(CurtisReidMeasure(lp, _Advanced, FRowScale, FColScale)<0.1*get_nonzeros(lp))\n  return(0);\n\n  /* Allocate temporary memory and find RowSum and ColSum measures */\n  nz = get_nonzeros(lp);\n  colMax = lp->columns;\n\n  allocREAL(lp, &RowSum, lp->rows+1, TRUE);\n  allocINT(lp,  &RowCount, lp->rows+1, TRUE);\n  allocREAL(lp, &residual_odd, lp->rows+1, TRUE);\n\n  allocREAL(lp, &ColSum, colMax+1, TRUE);\n  allocINT(lp,  &ColCount, colMax+1, TRUE);\n  allocREAL(lp, &residual_even, colMax+1, TRUE);\n\n  allocREAL(lp, &RowScalem2, lp->rows+1, FALSE);\n  allocREAL(lp, &ColScalem2, colMax+1, FALSE);\n\n  /* Set origin for row scaling */\n  for(i = 1; i <= colMax; i++) {\n    absvalue=fabs(lp->orig_obj[i]);\n    if(absvalue>0) {\n      logvalue = log(absvalue);\n      ColSum[i] += logvalue;\n      RowSum[0] += logvalue;\n      ColCount[i]++;\n      RowCount[0]++;\n    }\n  }\n\n  value = &(COL_MAT_VALUE(0));\n  rownr = &(COL_MAT_ROWNR(0));\n  colnr = &(COL_MAT_COLNR(0));\n  for(i = 0; i < nz;\n      i++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) {\n    absvalue=fabs(*value);\n    if(absvalue>0) {\n      logvalue = log(absvalue);\n      ColSum[*colnr] += logvalue;\n      RowSum[*rownr] += logvalue;\n      ColCount[*colnr]++;\n      RowCount[*rownr]++;\n    }\n  }\n\n  /* Make sure we dont't have division by zero errors */\n  for(row = 0; row <= lp->rows; row++)\n    if(RowCount[row] == 0)\n      RowCount[row] = 1;\n  for(col = 1; col <= colMax; col++)\n    if(ColCount[col] == 0)\n      ColCount[col] = 1;\n\n  /* Initialize to RowScale = RowCount-1 RowSum\n                   ColScale = 0.0\n                   residual = ColSum - ET RowCount-1 RowSum */\n\n  StopTolerance= MAX(lp->scalelimit-floor(lp->scalelimit), DEF_SCALINGEPS);\n  StopTolerance *= (REAL) nz;\n  for(row = 0; row <= lp->rows; row++) {\n    FRowScale[row] = RowSum[row] / (REAL) RowCount[row];\n    RowScalem2[row] = FRowScale[row];\n  }\n\n  /* Compute initial residual */\n  for(col = 1; col <= colMax; col++) {\n    FColScale[col] = 0;\n    ColScalem2[col] = 0;\n    residual_even[col] = ColSum[col];\n\n    if(lp->orig_obj[col] != 0)\n      residual_even[col] -= RowSum[0] / (REAL) RowCount[0];\n\n    i = mat->col_end[col-1];\n    rownr = &(COL_MAT_ROWNR(i));\n    ent = mat->col_end[col];\n    for(; i < ent;\n        i++, rownr += matRowColStep) {\n      residual_even[col] -= RowSum[*rownr] / (REAL) RowCount[*rownr];\n    }\n  }\n\n  /* Compute sk */\n  sk = 0;\n  skm1 = 0;\n  for(col = 1; col <= colMax; col++)\n    sk += (residual_even[col]*residual_even[col]) / (REAL) ColCount[col];\n\n  Result = 0;\n  qk=1; qkm1=0; qkm2=0;\n  ek=0; ekm1=0; ekm2=0;\n\n  while(sk>StopTolerance) {\n  /* Given the values of residual and sk, construct\n     ColScale (when pass is even)\n     RowScale (when pass is odd)  */\n\n    qkqkm1 = qk * qkm1;\n    ekekm1 = ek * ekm1;\n    if((Result % 2) == 0) { /* pass is even; construct RowScale[pass+1] */\n      if(Result != 0) {\n        for(row = 0; row <= lp->rows; row++)\n          RowScalem2[row] = FRowScale[row];\n        if(qkqkm1 != 0) {\n          for(row = 0; row <= lp->rows; row++)\n            FRowScale[row]*=(1 + ekekm1 / qkqkm1);\n          for(row = 0; row<=lp->rows; row++)\n            FRowScale[row]+=(residual_odd[row] / (qkqkm1 * (REAL) RowCount[row]) -\n                             RowScalem2[row] * ekekm1 / qkqkm1);\n        }\n      }\n    }\n    else { /* pass is odd; construct ColScale[pass+1] */\n      for(col = 1; col <= colMax; col++)\n        ColScalem2[col] = FColScale[col];\n      if(qkqkm1 != 0) {\n        for(col = 1; col <= colMax; col++)\n          FColScale[col] *= (1 + ekekm1 / qkqkm1);\n        for(col = 1; col <= colMax; col++)\n          FColScale[col] += (residual_even[col] / ((REAL) ColCount[col] * qkqkm1) -\n                             ColScalem2[col] * ekekm1 / qkqkm1);\n      }\n    }\n\n    /* update residual and sk (pass + 1) */\n    if((Result % 2) == 0) { /* even */\n       /* residual */\n      for(row = 0; row <= lp->rows; row++)\n        residual_odd[row] *= ek;\n\n      for(i = 1; i <= colMax; i++)\n        if(lp->orig_obj[i] != 0)\n          residual_odd[0] += (residual_even[i] / (REAL) ColCount[i]);\n\n      rownr = &(COL_MAT_ROWNR(0));\n      colnr = &(COL_MAT_COLNR(0));\n      for(i = 0; i < nz;\n          i++, rownr += matRowColStep, colnr += matRowColStep) {\n        residual_odd[*rownr] += (residual_even[*colnr] / (REAL) ColCount[*colnr]);\n      }\n      for(row = 0; row <= lp->rows; row++)\n        residual_odd[row] *= (-1 / qk);\n\n      /* sk */\n      skm1 = sk;\n      sk = 0;\n      for(row = 0; row <= lp->rows; row++)\n        sk += (residual_odd[row]*residual_odd[row]) / (REAL) RowCount[row];\n    }\n    else { /* odd */\n      /* residual */\n      for(col = 1; col <= colMax; col++)\n        residual_even[col] *= ek;\n\n      for(i = 1; i <= colMax; i++)\n        if(lp->orig_obj[i] != 0)\n          residual_even[i] += (residual_odd[0] / (REAL) RowCount[0]);\n\n      rownr = &(COL_MAT_ROWNR(0));\n      colnr = &(COL_MAT_COLNR(0));\n      for(i = 0; i < nz;\n          i++, rownr += matRowColStep, colnr += matRowColStep) {\n        residual_even[*colnr] += (residual_odd[*rownr] / (REAL) RowCount[*rownr]);\n      }\n      for(col = 1; col <= colMax; col++)\n        residual_even[col] *= (-1 / qk);\n\n      /* sk */\n      skm1 = sk;\n      sk = 0;\n      for(col = 1; col <= colMax; col++)\n        sk += (residual_even[col]*residual_even[col]) / (REAL) ColCount[col];\n    }\n\n    /* Compute ek and qk */\n    ekm2=ekm1;\n    ekm1=ek;\n    ek=qk * sk / skm1;\n\n    qkm2=qkm1;\n    qkm1=qk;\n    qk=1-ek;\n\n    Result++;\n  }\n\n  /* Synchronize the RowScale and ColScale vectors */\n  ekekm1 = ek * ekm1;\n  if(qkm1 != 0) {\n  if((Result % 2) == 0) { /* pass is even, compute RowScale */\n    for(row = 0; row<=lp->rows; row++)\n      FRowScale[row]*=(1.0 + ekekm1 / qkm1);\n    for(row = 0; row<=lp->rows; row++)\n      FRowScale[row]+=(residual_odd[row] / (qkm1 * (REAL) RowCount[row]) -\n                      RowScalem2[row] * ekekm1 / qkm1);\n  }\n  else { /* pass is odd, compute ColScale */\n    for(col=1; col<=colMax; col++)\n      FColScale[col]*=(1 + ekekm1 / qkm1);\n    for(col=1; col<=colMax; col++)\n      FColScale[col]+=(residual_even[col] / ((REAL) ColCount[col] * qkm1) -\n                       ColScalem2[col] * ekekm1 / qkm1);\n  }\n  }\n\n  /* Do validation, if indicated */\n  if(FALSE && mat_validate(mat)){\n    double check, error;\n\n    /* CHECK: M RowScale + E ColScale = RowSum */\n    error = 0;\n    for(row = 0; row <= lp->rows; row++) {\n      check = (REAL) RowCount[row] * FRowScale[row];\n      if(row == 0) {\n        for(i = 1; i <= colMax; i++) {\n          if(lp->orig_obj[i] != 0)\n            check += FColScale[i];\n        }\n      }\n      else {\n        i = mat->row_end[row-1];\n        ent = mat->row_end[row];\n        for(; i < ent; i++) {\n          col = ROW_MAT_COLNR(i);\n          check += FColScale[col];\n        }\n      }\n      check -= RowSum[row];\n      error += check*check;\n    }\n\n    /* CHECK: E^T RowScale + N ColScale = ColSum */\n    error = 0;\n    for(col = 1; col <= colMax; col++) {\n      check = (REAL) ColCount[col] * FColScale[col];\n\n      if(lp->orig_obj[col] != 0)\n        check += FRowScale[0];\n\n      i = mat->col_end[col-1];\n      ent = mat->col_end[col];\n      rownr = &(COL_MAT_ROWNR(i));\n      for(; i < ent;\n          i++, rownr += matRowColStep) {\n        check += FRowScale[*rownr];\n      }\n      check -= ColSum[col];\n      error += check*check;\n    }\n  }\n\n  /* Convert to scaling factors (rounding to nearest power\n     of 2 can optionally be done as a separate step later) */\n  for(col = 1; col <= colMax; col++) {\n    absvalue = exp(-FColScale[col]);\n    if(absvalue < MIN_SCALAR) absvalue = MIN_SCALAR;\n    if(absvalue > MAX_SCALAR) absvalue = MAX_SCALAR;\n    if(!is_int(lp,col) || is_integerscaling(lp))\n        FColScale[col] = absvalue;\n    else\n        FColScale[col] = 1;\n  }\n  for(row = 0; row <= lp->rows; row++) {\n    absvalue = exp(-FRowScale[row]);\n    if(absvalue < MIN_SCALAR) absvalue = MIN_SCALAR;\n    if(absvalue > MAX_SCALAR) absvalue = MAX_SCALAR;\n    FRowScale[row] = absvalue;\n  }\n\n /* free temporary memory */\n  FREE(RowSum);\n  FREE(ColSum);\n  FREE(RowCount);\n  FREE(ColCount);\n  FREE(residual_even);\n  FREE(residual_odd);\n  FREE(RowScalem2);\n  FREE(ColScalem2);\n\n  return(Result);\n\n}\n\nSTATIC MYBOOL scaleCR(lprec *lp, REAL *scaledelta)\n{\n  REAL *scalechange = NULL;\n  int  Result;\n\n  if(!lp->scaling_used) {\n    allocREAL(lp, &lp->scalars, lp->sum_alloc + 1, FALSE);\n    for(Result = 0; Result <= lp->sum; Result++)\n      lp->scalars[Result] = 1;\n    lp->scaling_used = TRUE;\n  }\n\n  if(scaledelta == NULL)\n    allocREAL(lp, &scalechange, lp->sum + 1, FALSE);\n  else\n    scalechange = scaledelta;\n\n  Result=CurtisReidScales(lp, FALSE, scalechange, &scalechange[lp->rows]);\n  if(Result>0) {\n\n    /* Do the scaling*/\n    if(scale_updaterows(lp, scalechange, TRUE) ||\n       scale_updatecolumns(lp, &scalechange[lp->rows], TRUE))\n      lp->scalemode |= SCALE_CURTISREID;\n\n    set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n  }\n\n  if(scaledelta == NULL)\n    FREE(scalechange);\n\n  return((MYBOOL) (Result > 0));\n}\n\nSTATIC MYBOOL transform_for_scale(lprec *lp, REAL *value)\n{\n  MYBOOL Accept = TRUE;\n  *value = fabs(*value);\n#ifdef Paranoia\n  if(*value < lp->epsmachine) {\n    Accept = FALSE;\n    report(lp, SEVERE, \"transform_for_scale: A zero-valued entry was passed\\n\");\n  }\n  else\n#endif\n  if(is_scalemode(lp, SCALE_LOGARITHMIC))\n    *value = log(*value);\n  else if(is_scalemode(lp, SCALE_QUADRATIC))\n    (*value) *= (*value);\n  return( Accept );\n}\n\nSTATIC void accumulate_for_scale(lprec *lp, REAL *min, REAL *max, REAL value)\n{\n  if(transform_for_scale(lp, &value)) {\n    if(is_scaletype(lp, SCALE_MEAN)) {\n      *max += value;\n      *min += 1;\n    }\n    else {\n      SETMAX(*max, value);\n      SETMIN(*min, value);\n    }\n  }\n}\n\nSTATIC REAL minmax_to_scale(lprec *lp, REAL min, REAL max, int itemcount)\n{\n  REAL scale;\n\n  /* Initialize according to transformation / weighting model */\n  if(is_scalemode(lp, SCALE_LOGARITHMIC))\n    scale = 0;\n  else\n    scale = 1;\n  if(itemcount <= 0)\n    return(scale);\n\n  /* Compute base scalar according to chosen scaling type */\n  if(is_scaletype(lp, SCALE_MEAN)) {\n    if(min > 0)\n      scale = max / min;\n  }\n  else if(is_scaletype(lp, SCALE_RANGE))\n    scale = (max + min) / 2;\n  else if(is_scaletype(lp, SCALE_GEOMETRIC))\n    scale = sqrt(min*max);\n  else if(is_scaletype(lp, SCALE_EXTREME))\n    scale = max;\n\n  /* Compute final scalar according to transformation / weighting model */\n  if(is_scalemode(lp, SCALE_LOGARITHMIC))\n    scale = exp(-scale);\n  else if(is_scalemode(lp, SCALE_QUADRATIC)) {\n    if(scale == 0)\n      scale = 1;\n    else\n      scale = 1 / sqrt(scale);\n  }\n  else {\n    if(scale == 0)\n      scale = 1;\n    else\n      scale = 1 / scale;\n  }\n\n  /* Make sure we are within acceptable scaling ranges */\n  SETMAX(scale, MIN_SCALAR);\n  SETMIN(scale, MAX_SCALAR);\n\n  return(scale);\n}\n\nSTATIC REAL roundPower2(REAL scale)\n/* Purpose is to round a number to it nearest power of 2; in a system\n   with binary number representation, this avoids rounding errors when\n   scale is used to normalize another value */\n{\n  long int power2;\n  MYBOOL   isSmall = FALSE;\n\n  if(scale == 1)\n    return( scale );\n\n  /* Obtain the fractional power of 2 */\n  if(scale < 2) {\n    scale = 2 / scale;\n    isSmall = TRUE;\n  }\n  else\n    scale /= 2;\n  scale = log(scale)/log(2.0);\n\n  /* Find the desired nearest power of two and compute the associated scalar */\n  power2 = (long) ceil(scale-0.5);\n  scale = 1 << power2;\n  if(isSmall)\n    scale = 1.0 / scale;\n\n  return( scale );\n\n}\n\nSTATIC MYBOOL scale_updatecolumns(lprec *lp, REAL *scalechange, MYBOOL updateonly)\n{\n  int i, j;\n\n  /* Verify that the scale change is significant (different from the unit) */\n  for(i = lp->columns; i > 0; i--)\n    if(fabs(scalechange[i]-1) > lp->epsprimal)\n      break;\n  if(i <= 0)\n    return( FALSE );\n\n /* Update the pre-existing column scalar */\n  if(updateonly)\n    for(i = 1, j = lp->rows + 1; j <= lp->sum; i++, j++)\n      lp->scalars[j] *= scalechange[i];\n  else\n    for(i = 1, j = lp->rows + 1; j <= lp->sum; i++, j++)\n      lp->scalars[j] = scalechange[i];\n\n  return( TRUE );\n}\n\nSTATIC MYBOOL scale_updaterows(lprec *lp, REAL *scalechange, MYBOOL updateonly)\n{\n  int i;\n\n  /* Verify that the scale change is significant (different from the unit) */\n  for(i = lp->rows; i >= 0; i--) {\n    if(fabs(scalechange[i]-1) > lp->epsprimal)\n      break;\n  }\n  if(i < 0)\n    return( FALSE );\n\n /* Update the pre-existing row scalar */\n  if(updateonly)\n    for(i = 0; i <= lp->rows; i++)\n      lp->scalars[i] *= scalechange[i];\n  else\n    for(i = 0; i <= lp->rows; i++)\n      lp->scalars[i] = scalechange[i];\n\n  return( TRUE );\n}\n\nSTATIC MYBOOL scale_columns(lprec *lp, REAL *scaledelta)\n{\n  int     i,j, colMax, nz;\n  REAL    *scalechange;\n  REAL    *value;\n  int     *colnr;\n  MATrec  *mat = lp->matA;\n\n  /* Check that columns are in fact targeted */\n  if((lp->scalemode & SCALE_ROWSONLY) != 0)\n    return( TRUE );\n\n  if(scaledelta == NULL)\n    scalechange = &lp->scalars[lp->rows];\n  else\n    scalechange = &scaledelta[lp->rows];\n\n  colMax = lp->columns;\n\n  /* Scale matrix entries (including any Lagrangean constraints) */\n  for(i = 1; i <= lp->columns; i++) {\n    lp->orig_obj[i] *= scalechange[i];\n  }\n\n  mat_validate(lp->matA);\n  nz = get_nonzeros(lp);\n  value = &(COL_MAT_VALUE(0));\n  colnr = &(COL_MAT_COLNR(0));\n  for(i = 0; i < nz;\n      i++, value += matValueStep, colnr += matRowColStep) {\n    (*value) *= scalechange[*colnr];\n  }\n\n  /* Scale variable bounds as well */\n  for(i = 1, j = lp->rows + 1; j <= lp->sum; i++, j++) {\n    if(lp->orig_lowbo[j] > -lp->infinite)\n      lp->orig_lowbo[j] /= scalechange[i];\n    if(lp->orig_upbo[j] < lp->infinite)\n      lp->orig_upbo[j] /= scalechange[i];\n    if(lp->sc_lobound[i] != 0)\n      lp->sc_lobound[i] /= scalechange[i];\n  }\n\n  lp->columns_scaled = TRUE;\n  set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n\n  return( TRUE );\n}\n\nSTATIC MYBOOL scale_rows(lprec *lp, REAL *scaledelta)\n{\n  int     i, j, nz, colMax;\n  REAL    *scalechange;\n  REAL    *value;\n  int     *rownr;\n  MATrec  *mat = lp->matA;\n\n\n  /* Check that rows are in fact targeted */\n  if((lp->scalemode & SCALE_COLSONLY) != 0)\n    return( TRUE );\n\n  if(scaledelta == NULL)\n    scalechange = lp->scalars;\n  else\n    scalechange = scaledelta;\n\n  colMax = lp->columns;\n\n  /* First row-scale the matrix (including the objective function) */\n  for(i = 1; i <= colMax; i++) {\n    lp->orig_obj[i] *= scalechange[0];\n  }\n\n  nz = get_nonzeros(lp);\n  value = &(COL_MAT_VALUE(0));\n  rownr = &(COL_MAT_ROWNR(0));\n  for(i = 0; i < nz;\n      i++, value += matValueStep, rownr += matRowColStep) {\n    (*value) *= scalechange[*rownr];\n  }\n\n  /* ...and scale the rhs and the row bounds (RANGES in MPS!!) */\n  for(i = 0; i <= lp->rows; i++) {\n    if(fabs(lp->orig_rhs[i]) < lp->infinite)\n      lp->orig_rhs[i] *= scalechange[i];\n\n    j = lp->presolve_undo->var_to_orig[i];\n    if(j != 0)\n      lp->presolve_undo->fixed_rhs[j] *= scalechange[i];\n\n    if(lp->orig_upbo[i] < lp->infinite)     /* This is the range */\n      lp->orig_upbo[i] *= scalechange[i];\n\n    if((lp->orig_lowbo[i] != 0) && (fabs(lp->orig_lowbo[i]) < lp->infinite))\n      lp->orig_lowbo[i] *= scalechange[i];\n  }\n\n  set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n\n  return( TRUE );\n}\n\nSTATIC REAL scale(lprec *lp, REAL *scaledelta)\n{\n  int     i, j, nz, row_count, nzOF = 0;\n  REAL    *row_max, *row_min, *scalechange = NULL, absval;\n  REAL    col_max, col_min;\n  MYBOOL  rowscaled, colscaled;\n  MATrec  *mat = lp->matA;\n  REAL    *value;\n  int     *rownr;\n\n  if(is_scaletype(lp, SCALE_NONE))\n    return(0.0);\n\n  if(!lp->scaling_used) {\n    allocREAL(lp, &lp->scalars, lp->sum_alloc + 1, FALSE);\n    for(i = 0; i <= lp->sum; i++) {\n      lp->scalars[i] = 1;\n    }\n    lp->scaling_used = TRUE;\n  }\n#ifdef Paranoia\n  else\n    for(i = 0; i <= lp->sum; i++) {\n      if(lp->scalars[i] == 0)\n        report(lp, SEVERE, \"scale: Zero-valued scalar found at index %d\\n\", i);\n    }\n#endif\n  if(scaledelta == NULL)\n    allocREAL(lp, &scalechange, lp->sum + 1, FALSE);\n  else\n    scalechange = scaledelta;\n\n /* Must initialize due to computation of scaling statistic - KE */\n  for(i = 0; i <= lp->sum; i++)\n    scalechange[i] = 1;\n\n  row_count = lp->rows;\n  allocREAL(lp, &row_max, row_count + 1, TRUE);\n  allocREAL(lp, &row_min, row_count + 1, FALSE);\n\n  /* Initialise min and max values of rows */\n  for(i = 0; i <= row_count; i++) {\n    if(is_scaletype(lp, SCALE_MEAN))\n      row_min[i] = 0;             /* Carries the count of elements */\n    else\n      row_min[i] = lp->infinite;  /* Carries the minimum element */\n  }\n\n  /* Calculate row scaling data */\n  for(j = 1; j <= lp->columns; j++) {\n\n    absval = lp->orig_obj[j];\n    if(absval != 0) {\n      absval = scaled_mat(lp, absval, 0, j);\n      accumulate_for_scale(lp, &row_min[0], &row_max[0], absval);\n      nzOF++;\n    }\n\n    i = mat->col_end[j - 1];\n    value = &(COL_MAT_VALUE(i));\n    rownr = &(COL_MAT_ROWNR(i));\n    nz = mat->col_end[j];\n    for(; i < nz;\n        i++, value += matValueStep, rownr += matRowColStep) {\n      absval = scaled_mat(lp, *value, *rownr, j);\n      accumulate_for_scale(lp, &row_min[*rownr], &row_max[*rownr], absval);\n    }\n  }\n\n  /* Calculate scale factors for rows */\n  i = 0;\n  for(; i <= lp->rows; i++) {\n    if(i == 0)\n      nz = nzOF;\n    else\n      nz = mat_rowlength(lp->matA, i);\n    absval = minmax_to_scale(lp, row_min[i], row_max[i], nz); /* nz instead of nzOF KJEI 20/05/2010 */\n    if(absval == 0)\n      absval = 1;\n    scalechange[i] = absval;\n  }\n\n  FREE(row_max);\n  FREE(row_min);\n\n  /* Row-scale the matrix (including the objective function and Lagrangean constraints) */\n  rowscaled = scale_updaterows(lp, scalechange, TRUE);\n\n  /* Calculate column scales */\n  i = 1;\n  for(j = 1; j <= lp->columns; j++) {\n    if(is_int(lp,j) && !is_integerscaling(lp)) { /* do not scale integer columns */\n      scalechange[lp->rows + j] = 1;\n    }\n    else {\n      col_max = 0;\n      if(is_scaletype(lp, SCALE_MEAN))\n        col_min = 0;\n      else\n        col_min = lp->infinite;\n\n      absval = lp->orig_obj[j];\n      if(absval != 0) {\n        absval = scaled_mat(lp, absval, 0, j);\n        accumulate_for_scale(lp, &col_min, &col_max, absval);\n      }\n\n      i = mat->col_end[j - 1];\n      value = &(COL_MAT_VALUE(i));\n      rownr = &(COL_MAT_ROWNR(i));\n      nz = mat->col_end[j];\n      for(; i < nz;\n          i++, value += matValueStep, rownr += matRowColStep) {\n        absval = scaled_mat(lp, *value, *rownr, j);\n        accumulate_for_scale(lp, &col_min, &col_max, absval);\n      }\n      nz = mat_collength(lp->matA, j);\n      if(fabs(lp->orig_obj[j]) > 0)\n        nz++;\n      scalechange[lp->rows + j] = minmax_to_scale(lp, col_min, col_max, nz);\n    }\n  }\n\n  /* ... and then column-scale the already row-scaled matrix */\n  colscaled = scale_updatecolumns(lp, &scalechange[lp->rows], TRUE);\n\n  /* Create a geometric mean-type measure of the extent of scaling performed; */\n  /* ideally, upon successive calls to scale() the value should converge to 0 */\n  if(rowscaled || colscaled) {\n    col_max = 0;\n    for(j = 1; j <= lp->columns; j++)\n      col_max += log(scalechange[lp->rows + j]);\n    col_max = exp(col_max/lp->columns);\n\n    i = 0;\n    col_min = 0;\n    for(; i <= lp->rows; i++)\n      col_min += log(scalechange[i]);\n    col_min = exp(col_min/row_count);\n  }\n  else {\n    col_max = 1;\n    col_min = 1;\n  }\n\n  if(scaledelta == NULL)\n    FREE(scalechange);\n\n  return(1 - sqrt(col_max*col_min));\n}\n\nSTATIC MYBOOL finalize_scaling(lprec *lp, REAL *scaledelta)\n{\n  int i;\n\n  /* Check if we should equilibrate */\n  if(is_scalemode(lp, SCALE_EQUILIBRATE) && !is_scaletype(lp, SCALE_CURTISREID)) {\n    int oldmode;\n\n    oldmode = lp->scalemode;\n    lp->scalemode = SCALE_LINEAR + SCALE_EXTREME;\n    scale(lp, scaledelta);\n    lp->scalemode = oldmode;\n  }\n\n  /* Check if we should prevent rounding errors */\n  if(is_scalemode(lp, SCALE_POWER2)) {\n    REAL *scalars;\n    if(scaledelta == NULL)\n      scalars = lp->scalars;\n    else\n      scalars = scaledelta;\n\n    for(i = 0; i <= lp->sum; i++)\n      scalars[i] = roundPower2(scalars[i]);\n  }\n\n  /* Then transfer the scalars to the model's data */\n  return( scale_rows(lp, scaledelta) && scale_columns(lp, scaledelta) );\n\n}\n\nSTATIC REAL auto_scale(lprec *lp)\n{\n  int    n = 1;\n  REAL   scalingmetric = 0, *scalenew = NULL;\n\n  if(lp->scaling_used &&\n     ((((lp->scalemode & SCALE_DYNUPDATE) == 0)) || (lp->bb_level > 0)))\n    return( scalingmetric);\n\n  if(lp->scalemode != SCALE_NONE) {\n\n    /* Allocate array for incremental scaling if appropriate */\n    if((lp->solvecount > 1) && (lp->bb_level < 1) &&\n       ((lp->scalemode & SCALE_DYNUPDATE) != 0))\n      allocREAL(lp, &scalenew, lp->sum + 1, FALSE);\n\n    if(is_scaletype(lp, SCALE_CURTISREID)) {\n      scalingmetric = scaleCR(lp, scalenew);\n    }\n    else {\n      REAL scalinglimit, scalingdelta;\n      int  count;\n\n      /* Integer value of scalelimit holds the maximum number of iterations; default to 1 */\n      count = (int) floor(lp->scalelimit);\n      scalinglimit = lp->scalelimit;\n      if((count == 0) || (scalinglimit == 0)) {\n        if(scalinglimit > 0)\n          count = DEF_SCALINGLIMIT;  /* A non-zero convergence has been given, default to max 5 iterations */\n        else\n          count = 1;\n      }\n      else\n        scalinglimit -= count;\n\n      /* Scale to desired relative convergence or iteration limit */\n      n = 0;\n      scalingdelta = 1.0;\n      scalingmetric = 1.0;\n      while((n < count) && (fabs(scalingdelta) > scalinglimit)) {\n        n++;\n        scalingdelta = scale(lp, scalenew);\n        scalingmetric = scalingmetric*(1+scalingdelta);\n      }\n      scalingmetric -= 1;\n    }\n  }\n\n  /* Update the inf norm of the elements of the matrix (excluding the OF) */\n  mat_computemax(lp->matA);\n\n  /* Check if we really have to do scaling */\n  if(lp->scaling_used && (fabs(scalingmetric) >= lp->epsprimal))\n    /* Ok, do it */\n    finalize_scaling(lp, scalenew);\n\n  else {\n\n    /* Otherwise reset scaling variables */\n    if(lp->scalars != NULL) {\n      FREE(lp->scalars);\n    }\n    lp->scaling_used = FALSE;\n    lp->columns_scaled = FALSE;\n  }\n  if(scalenew != NULL)\n    FREE(scalenew);\n\n  return(scalingmetric);\n}\n\nSTATIC void unscale_columns(lprec *lp)\n{\n  int     i, j, nz;\n  MATrec  *mat = lp->matA;\n  REAL    *value;\n  int     *rownr, *colnr;\n\n  if(!lp->columns_scaled)\n    return;\n\n  /* Unscale OF */\n  for(j = 1; j <= lp->columns; j++) {\n    lp->orig_obj[j] = unscaled_mat(lp, lp->orig_obj[j], 0, j);\n  }\n\n  /* Unscale mat */\n  mat_validate(mat);\n  nz = get_nonzeros(lp);\n  value = &(COL_MAT_VALUE(0));\n  rownr = &(COL_MAT_ROWNR(0));\n  colnr = &(COL_MAT_COLNR(0));\n  for(j = 0; j < nz;\n      j++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) {\n    *value = unscaled_mat(lp, *value, *rownr, *colnr);\n  }\n\n  /* Unscale bounds as well */\n  for(i = lp->rows + 1, j = 1; i <= lp->sum; i++, j++) {\n    lp->orig_lowbo[i] = unscaled_value(lp, lp->orig_lowbo[i], i);\n    lp->orig_upbo[i]  = unscaled_value(lp, lp->orig_upbo[i], i);\n    lp->sc_lobound[j]  = unscaled_value(lp, lp->sc_lobound[j], i);\n  }\n\n  for(i = lp->rows + 1; i<= lp->sum; i++)\n    lp->scalars[i] = 1;\n\n  lp->columns_scaled = FALSE;\n  set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n}\n\nvoid undoscale(lprec *lp)\n{\n  int     i, j, nz;\n  MATrec  *mat = lp->matA;\n  REAL    *value;\n  int     *rownr, *colnr;\n\n  if(lp->scaling_used) {\n\n    /* Unscale the OF */\n    for(j = 1; j <= lp->columns; j++) {\n      lp->orig_obj[j] = unscaled_mat(lp, lp->orig_obj[j], 0, j);\n    }\n\n    /* Unscale the matrix */\n    mat_validate(mat);\n    nz = get_nonzeros(lp);\n    value = &(COL_MAT_VALUE(0));\n    rownr = &(COL_MAT_ROWNR(0));\n    colnr = &(COL_MAT_COLNR(0));\n    for(j = 0; j < nz;\n        j++, value += matValueStep, rownr += matRowColStep, colnr += matRowColStep) {\n      *value = unscaled_mat(lp, *value, *rownr, *colnr);\n    }\n\n    /* Unscale variable bounds */\n    for(i = lp->rows + 1, j = 1; i <= lp->sum; i++, j++) {\n      lp->orig_lowbo[i] = unscaled_value(lp, lp->orig_lowbo[i], i);\n      lp->orig_upbo[i]  = unscaled_value(lp, lp->orig_upbo[i], i);\n      lp->sc_lobound[j]  = unscaled_value(lp, lp->sc_lobound[j], i);\n    }\n\n    /* Unscale the rhs, upper and lower bounds... */\n    for(i = 0; i <= lp->rows; i++) {\n      lp->orig_rhs[i] = unscaled_value(lp, lp->orig_rhs[i], i);\n      j = lp->presolve_undo->var_to_orig[i];\n      if(j != 0)\n        lp->presolve_undo->fixed_rhs[j] = unscaled_value(lp, lp->presolve_undo->fixed_rhs[j], i);\n      lp->orig_lowbo[i] = unscaled_value(lp, lp->orig_lowbo[i], i);\n      lp->orig_upbo[i] = unscaled_value(lp, lp->orig_upbo[i], i);\n    }\n\n    FREE(lp->scalars);\n    lp->scaling_used = FALSE;\n    lp->columns_scaled = FALSE;\n\n    set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT | ACTION_RECOMPUTE);\n  }\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_scale.h",
    "content": "#ifndef HEADER_lp_scale\n#define HEADER_lp_scale\n\n#include \"lp_types.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Put function headers here */\nSTATIC MYBOOL scale_updatecolumns(lprec *lp, REAL *scalechange, MYBOOL updateonly);\nSTATIC MYBOOL scale_updaterows(lprec *lp, REAL *scalechange, MYBOOL updateonly);\nSTATIC MYBOOL scale_rows(lprec *lp, REAL *scaledelta);\nSTATIC MYBOOL scale_columns(lprec *lp, REAL *scaledelta);\nSTATIC void unscale_columns(lprec *lp);\nSTATIC REAL scale(lprec *lp, REAL *scaledelta);\nSTATIC REAL scaled_mat(lprec *lp, REAL value, int rownr, int colnr);\nSTATIC REAL unscaled_mat(lprec *lp, REAL value, int rownr, int colnr);\nSTATIC REAL scaled_value(lprec *lp, REAL value, int index);\nSTATIC REAL unscaled_value(lprec *lp, REAL value, int index);\nSTATIC MYBOOL scaleCR(lprec *lp, REAL *scaledelta);\nSTATIC MYBOOL finalize_scaling(lprec *lp, REAL *scaledelta);\nSTATIC REAL auto_scale(lprec *lp);\nvoid undoscale(lprec *lp);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_scale */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_simplex.c",
    "content": "\n/*\n    Core optimization drivers for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Michel Berkelaar (to lp_solve v3.2),\n                   Kjell Eikland    (v4.0 and forward)\n    Contact:\n    License terms: LGPL.\n\n    Requires:      lp_lib.h, lp_simplex.h, lp_presolve.h, lp_pricerPSE.h\n\n    Release notes:\n    v5.0.0  1 January 2004      New unit applying stacked basis and bounds storage.\n    v5.0.1 31 January 2004      Moved B&B routines to separate file and implemented\n                                a new runsolver() general purpose call method.\n    v5.0.2  1 May 2004          Changed routine names to be more intuitive.\n    v5.1.0  10 January 2005     Created modular stalling/cycling functions.\n                                Rewrote dualloop() to optimize long dual and\n                                also streamlined primloop() correspondingly.\n    v5.2.0  20 March 2005       Reimplemented primal phase 1 logic.\n                                Made multiple pricing finally work (primal simplex).\n\n   ----------------------------------------------------------------------------------\n*/\n\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_BFP.h\"\n#include \"lp_simplex.h\"\n#include \"lp_crash.h\"\n#include \"lp_presolve.h\"\n#include \"lp_price.h\"\n#include \"lp_pricePSE.h\"\n#include \"lp_report.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\nSTATIC void stallMonitor_update(lprec *lp, REAL newOF)\n{\n  int newpos;\n  OBJmonrec *monitor = lp->monitor;\n\n  if(monitor->countstep < OBJ_STEPS)\n    monitor->countstep++;\n  else\n    monitor->startstep = mod(monitor->startstep + 1, OBJ_STEPS);\n  newpos = mod(monitor->startstep + monitor->countstep - 1, OBJ_STEPS);\n  monitor->objstep[newpos] = newOF;\n  monitor->idxstep[newpos] = monitor->Icount;\n  monitor->currentstep = newpos;\n}\n\nSTATIC MYBOOL stallMonitor_creepingObj(lprec *lp)\n{\n  OBJmonrec *monitor = lp->monitor;\n\n  if(monitor->countstep > 1) {\n    REAL deltaOF = (monitor->objstep[monitor->currentstep] -\n                    monitor->objstep[monitor->startstep]) / monitor->countstep;\n    deltaOF /= MAX(1, (monitor->idxstep[monitor->currentstep] -\n                       monitor->idxstep[monitor->startstep]));\n    deltaOF = my_chsign(monitor->isdual, deltaOF);\n    return( (MYBOOL) (deltaOF < monitor->epsvalue) );\n  }\n  else\n    return( FALSE );\n}\n\nSTATIC MYBOOL stallMonitor_shortSteps(lprec *lp)\n{\n  OBJmonrec *monitor = lp->monitor;\n\n  if(monitor->countstep == OBJ_STEPS) {\n    REAL deltaOF = MAX(1, (monitor->idxstep[monitor->currentstep] -\n                           monitor->idxstep[monitor->startstep])) / monitor->countstep;\n    deltaOF = pow(deltaOF*OBJ_STEPS, 0.66);\n    return( (MYBOOL) (deltaOF > monitor->limitstall[TRUE]) );\n  }\n  else\n    return( FALSE );\n}\n\nSTATIC void stallMonitor_reset(lprec *lp)\n{\n  OBJmonrec *monitor = lp->monitor;\n\n  monitor->ruleswitches = 0;\n  monitor->Ncycle = 0;\n  monitor->Mcycle = 0;\n  monitor->Icount = 0;\n  monitor->startstep = 0;\n  monitor->objstep[monitor->startstep] = lp->infinite;\n  monitor->idxstep[monitor->startstep] = monitor->Icount;\n  monitor->prevobj = 0;\n  monitor->countstep = 1;\n}\n\nSTATIC MYBOOL stallMonitor_create(lprec *lp, MYBOOL isdual, const char *funcname)\n{\n  OBJmonrec *monitor = NULL;\n  if(lp->monitor != NULL)\n    return( FALSE );\n\n  monitor = (OBJmonrec *) calloc(sizeof(*monitor), 1);\n  if(monitor == NULL)\n    return( FALSE );\n\n  monitor->lp = lp;\n  strcpy(monitor->spxfunc, funcname);\n  monitor->isdual = isdual;\n  monitor->pivdynamic = is_piv_mode(lp, PRICE_ADAPTIVE);\n  monitor->oldpivstrategy = lp->piv_strategy;\n  monitor->oldpivrule = get_piv_rule(lp);\n  if(MAX_STALLCOUNT <= 1)\n    monitor->limitstall[FALSE] = 0;\n  else\n    monitor->limitstall[FALSE] = MAX(MAX_STALLCOUNT,\n                                     (int) pow((REAL) (lp->rows+lp->columns)/2, 0.667));\n#if 1\n  monitor->limitstall[FALSE] *= 2+2;  /* Expand degeneracy/stalling tolerance range */\n#endif\n  monitor->limitstall[TRUE] = monitor->limitstall[FALSE];\n  if(monitor->oldpivrule == PRICER_DEVEX) /* Increase tolerance since primal Steepest Edge is expensive */\n    monitor->limitstall[TRUE] *= 2;\n  if(MAX_RULESWITCH <= 0)\n    monitor->limitruleswitches = MAXINT32;\n  else\n    monitor->limitruleswitches = MAX(MAX_RULESWITCH,\n                                     lp->rows/MAX_RULESWITCH);\n  monitor->epsvalue = lp->epsprimal; /* lp->epsvalue; */\n  lp->monitor = monitor;\n  stallMonitor_reset(lp);\n  lp->suminfeas = lp->infinite;\n  return( TRUE );\n}\n\nSTATIC MYBOOL stallMonitor_check(lprec *lp, int rownr, int colnr, int lastnr,\n                                 MYBOOL minit, MYBOOL approved, MYBOOL *forceoutEQ)\n{\n  OBJmonrec *monitor = lp->monitor;\n  MYBOOL    isStalled, isCreeping, acceptance = TRUE;\n  int       altrule,\n#ifdef Paranoia\n         msglevel = NORMAL;\n#else\n         msglevel = DETAILED;\n#endif\n  REAL   deltaobj = lp->suminfeas;\n\n  /* Accept unconditionally if this is the first or second call */\n  monitor->active = FALSE;\n  if(monitor->Icount <= 1) {\n    if(monitor->Icount == 1) {\n      monitor->prevobj = lp->rhs[0];\n      monitor->previnfeas = deltaobj;\n    }\n    monitor->Icount++;\n    return( acceptance );\n  }\n\n  /* Define progress as primal objective less sum of (primal/dual) infeasibilities */\n  monitor->thisobj = lp->rhs[0];\n  monitor->thisinfeas = deltaobj;\n  if(lp->spx_trace &&\n     (lastnr > 0))\n    report(lp, NORMAL, \"%s: Objective at iter %10.0f is \" RESULTVALUEMASK \" (%4d: %4d %s- %4d)\\n\",\n                       monitor->spxfunc,\n                       (double) get_total_iter(lp), monitor->thisobj, rownr, lastnr,\n                       my_if(minit == ITERATE_MAJORMAJOR, \"<\",\"|\"), colnr);\n  monitor->pivrule = get_piv_rule(lp);\n\n  /* Check if we have a stationary solution at selected tolerance level;\n     allow some difference in case we just refactorized the basis. */\n  deltaobj = my_reldiff(monitor->thisobj, monitor->prevobj);\n  deltaobj = fabs(deltaobj); /* Pre v5.2 version */\n  isStalled = (MYBOOL) (deltaobj < monitor->epsvalue);\n\n  /* Also require that we have a measure of infeasibility-stalling */\n  if(isStalled) {\n    REAL testvalue, refvalue = monitor->epsvalue;\n#if 1\n    if(monitor->isdual)\n      refvalue *= 1000*log10(9.0+lp->rows);\n    else\n      refvalue *= 1000*log10(9.0+lp->columns);\n#else\n      refvalue *= 1000*log10(9.0+lp->sum);\n#endif\n    testvalue = my_reldiff(monitor->thisinfeas, monitor->previnfeas);\n    isStalled &= (fabs(testvalue) < refvalue);\n\n    /* Check if we should force \"major\" pivoting, i.e. no bound flips;\n      this is activated when we see the feasibility deteriorate */\n/*    if(!isStalled && (testvalue > 0) && (TRUE || is_action(lp->anti_degen, ANTIDEGEN_BOUNDFLIP))) */\n#if !defined _PRICE_NOBOUNDFLIP\n    if(!isStalled && (testvalue > 0) && is_action(lp->anti_degen, ANTIDEGEN_BOUNDFLIP))\n      acceptance = AUTOMATIC;\n  }\n#else\n    if(!isStalled && (testvalue > 0) && !ISMASKSET(lp->piv_strategy, PRICE_NOBOUNDFLIP)) {\n      SETMASK(lp->piv_strategy, PRICE_NOBOUNDFLIP);\n      acceptance = AUTOMATIC;\n    }\n  }\n  else\n    CLEARMASK(lp->piv_strategy, PRICE_NOBOUNDFLIP);\n#endif\n\n#if 1\n  isCreeping = FALSE;\n#else\n  isCreeping |= stallMonitor_creepingObj(lp);\n/*  isCreeping |= stallMonitor_shortSteps(lp); */\n#endif\n  if(isStalled || isCreeping) {\n\n    /* Update counters along with specific tolerance for bound flips */\n#if 1\n    if(minit != ITERATE_MAJORMAJOR) {\n      if(++monitor->Mcycle > 2) {\n        monitor->Mcycle = 0;\n        monitor->Ncycle++;\n      }\n    }\n    else\n#endif\n      monitor->Ncycle++;\n\n    /* Start to monitor for variable cycling if this is the initial stationarity */\n    if(monitor->Ncycle <= 1) {\n      monitor->Ccycle = colnr;\n      monitor->Rcycle = rownr;\n    }\n\n    /* Check if we should change pivoting strategy */\n    else if(isCreeping ||                                                 /* We have OF creep */\n            (monitor->Ncycle > monitor->limitstall[monitor->isdual]) ||   /* KE empirical value */\n            ((monitor->Ccycle == rownr) && (monitor->Rcycle == colnr))) {   /* Obvious cycling */\n\n      monitor->active = TRUE;\n\n      /* Try to force out equality slacks to combat degeneracy */\n      if((lp->fixedvars > 0) && (*forceoutEQ != TRUE)) {\n        *forceoutEQ = TRUE;\n        goto Proceed;\n      }\n\n      /* Our options are now to select an alternative rule or to do bound perturbation;\n         check if these options are available to us or if we must signal failure and break out. */\n      approved &= monitor->pivdynamic && (monitor->ruleswitches < monitor->limitruleswitches);\n      if(!approved && !is_anti_degen(lp, ANTIDEGEN_STALLING)) {\n        lp->spx_status = DEGENERATE;\n        report(lp, msglevel, \"%s: Stalling at iter %10.0f; no alternative strategy left.\\n\",\n                             monitor->spxfunc, (double) get_total_iter(lp));\n        acceptance = FALSE;\n        return( acceptance );\n      }\n\n      /* See if we can do the appropriate alternative rule. */\n      switch (monitor->oldpivrule) {\n        case PRICER_FIRSTINDEX:    altrule = PRICER_DEVEX;\n                                   break;\n        case PRICER_DANTZIG:       altrule = PRICER_DEVEX;\n                                   break;\n        case PRICER_DEVEX:         altrule = PRICER_STEEPESTEDGE;\n                                   break;\n        case PRICER_STEEPESTEDGE:  altrule = PRICER_DEVEX;\n                                   break;\n        default:                   altrule = PRICER_FIRSTINDEX;\n      }\n      if(approved &&\n         (monitor->pivrule != altrule) && (monitor->pivrule == monitor->oldpivrule)) {\n\n        /* Switch rule to combat degeneracy. */\n        monitor->ruleswitches++;\n        lp->piv_strategy = altrule;\n        monitor->Ccycle = 0;\n        monitor->Rcycle = 0;\n        monitor->Ncycle = 0;\n        monitor->Mcycle = 0;\n        report(lp, msglevel, \"%s: Stalling at iter %10.0f; changed to '%s' rule.\\n\",\n                             monitor->spxfunc, (double) get_total_iter(lp),\n                             get_str_piv_rule(get_piv_rule(lp)));\n        if((altrule == PRICER_DEVEX) || (altrule == PRICER_STEEPESTEDGE))\n          restartPricer(lp, AUTOMATIC);\n      }\n\n      /* If not, code for bound relaxation/perturbation */\n      else {\n        report(lp, msglevel, \"%s: Stalling at iter %10.0f; proceed to bound relaxation.\\n\",\n                             monitor->spxfunc, (double) get_total_iter(lp));\n        acceptance = FALSE;\n        lp->spx_status = DEGENERATE;\n        return( acceptance );\n      }\n    }\n  }\n\n  /* Otherwise change back to original selection strategy as soon as possible */\n  else {\n    if(monitor->pivrule != monitor->oldpivrule) {\n      lp->piv_strategy = monitor->oldpivstrategy;\n      altrule = monitor->oldpivrule;\n      if((altrule == PRICER_DEVEX) || (altrule == PRICER_STEEPESTEDGE))\n        restartPricer(lp, AUTOMATIC);\n      report(lp, msglevel, \"...returned to original pivot selection rule at iter %.0f.\\n\",\n                           (double) get_total_iter(lp));\n    }\n    stallMonitor_update(lp, monitor->thisobj);\n    monitor->Ccycle = 0;\n    monitor->Rcycle = 0;\n    monitor->Ncycle = 0;\n    monitor->Mcycle = 0;\n  }\n\n  /* Update objective progress tracker */\nProceed:\n  monitor->Icount++;\n  if(deltaobj >= monitor->epsvalue)\n    monitor->prevobj = monitor->thisobj;\n  monitor->previnfeas = monitor->thisinfeas;\n\n  return( acceptance );\n}\n\nSTATIC void stallMonitor_finish(lprec *lp)\n{\n  OBJmonrec *monitor = lp->monitor;\n  if(monitor == NULL)\n    return;\n  if(lp->piv_strategy != monitor->oldpivstrategy)\n    lp->piv_strategy = monitor->oldpivstrategy;\n  FREE(monitor);\n  lp->monitor = NULL;\n}\n\n\nSTATIC MYBOOL add_artificial(lprec *lp, int forrownr, REAL *nzarray, int *idxarray)\n/* This routine is called for each constraint at the start of\n   primloop and the primal problem is infeasible. Its\n   purpose is to add artificial variables and associated\n   objective function values to populate primal phase 1. */\n{\n  MYBOOL add;\n\n  /* Make sure we don't add unnecessary artificials, i.e. avoid\n     cases where the slack variable is enough */\n  add = !isBasisVarFeasible(lp, lp->epspivot, forrownr);\n\n  if(add) {\n    int    *rownr = NULL, i, bvar, ii;\n    REAL   *avalue = NULL, rhscoef, acoef;\n    MATrec *mat = lp->matA;\n\n    /* Check the simple case where a slack is basic */\n    for(i = 1; i <= lp->rows; i++) {\n      if(lp->var_basic[i] == forrownr)\n        break;\n    }\n    acoef = 1;\n\n    /* If not, look for any basic user variable that has a\n       non-zero coefficient in the current constraint row */\n    if(i > lp->rows) {\n      for(i = 1; i <= lp->rows; i++) {\n        ii = lp->var_basic[i] - lp->rows;\n        if((ii <= 0) || (ii > (lp->columns-lp->P1extraDim)))\n          continue;\n        ii = mat_findelm(mat, forrownr, ii);\n        if(ii >= 0) {\n          acoef = COL_MAT_VALUE(ii);\n          break;\n        }\n      }\n    }\n\n    /* If no candidate was found above, gamble on using the densest column available */\n#if 0\n    if(i > lp->rows) {\n      int len = 0;\n      bvar = 0;\n      for(i = 1; i <= lp->rows; i++) {\n        ii = lp->var_basic[i] - lp->rows;\n        if((ii <= 0) || (ii > (lp->columns-lp->P1extraDim)))\n          continue;\n        if(mat_collength(mat, ii) > len) {\n          len = mat_collength(mat, ii);\n          bvar = i;\n        }\n      }\n      i = bvar;\n      acoef = 1;\n    }\n#endif\n\n    bvar = i;\n\n    add = (MYBOOL) (bvar <= lp->rows);\n    if(add) {\n      rhscoef = lp->rhs[forrownr];\n\n     /* Create temporary sparse array storage */\n      if(nzarray == NULL)\n        allocREAL(lp, &avalue, 2, FALSE);\n      else\n        avalue = nzarray;\n      if(idxarray == NULL)\n        allocINT(lp, &rownr, 2, FALSE);\n      else\n        rownr = idxarray;\n\n     /* Set the objective coefficient */\n      rownr[0]  =  0;\n      avalue[0] = my_chsign(is_chsign(lp, 0), 1);\n\n     /* Set the constraint row coefficient */\n      rownr[1]  = forrownr;\n      avalue[1] = my_chsign(is_chsign(lp, forrownr), my_sign(rhscoef/acoef));\n\n     /* Add the column of artificial variable data to the user data matrix */\n      add_columnex(lp, 2, avalue, rownr);\n\n     /* Free the temporary sparse array storage */\n      if(idxarray == NULL)\n        FREE(rownr);\n      if(nzarray == NULL)\n        FREE(avalue);\n\n     /* Now set the artificial variable to be basic */\n      set_basisvar(lp, bvar, lp->sum);\n      lp->P1extraDim++;\n    }\n    else {\n      report(lp, CRITICAL, \"add_artificial: Could not find replacement basis variable for row %d\\n\",\n                           forrownr);\n      lp->basis_valid = FALSE;\n    }\n\n  }\n\n  return(add);\n\n}\n\nSTATIC int get_artificialRow(lprec *lp, int colnr)\n{\n  MATrec *mat = lp->matA;\n\n#ifdef Paranoia\n  if((colnr <= lp->columns-abs(lp->P1extraDim)) || (colnr > lp->columns))\n    report(lp, SEVERE, \"get_artificialRow: Invalid column index %d\\n\", colnr);\n  if(mat->col_end[colnr] - mat->col_end[colnr-1] != 1)\n    report(lp, SEVERE, \"get_artificialRow: Invalid column non-zero count\\n\");\n#endif\n\n  /* Return the row index of the singleton */\n  colnr = mat->col_end[colnr-1];\n  colnr = COL_MAT_ROWNR(colnr);\n  return( colnr );\n}\n\nSTATIC int findAnti_artificial(lprec *lp, int colnr)\n/* Primal simplex: Find a basic artificial variable to swap\n   against the non-basic slack variable, if possible */\n{\n  int    i, k, rownr = 0, P1extraDim = abs(lp->P1extraDim);\n\n  if((P1extraDim == 0) || (colnr > lp->rows) || !lp->is_basic[colnr])\n    return( rownr );\n\n  for(i = 1; i <= lp->rows; i++) {\n    k = lp->var_basic[i];\n    if((k > lp->sum-P1extraDim) && (lp->rhs[i] == 0)) {\n      rownr = get_artificialRow(lp, k-lp->rows);\n\n      /* Should we find the artificial's slack direct \"antibody\"? */\n      if(rownr == colnr)\n        break;\n      rownr = 0;\n    }\n  }\n  return( rownr );\n}\n\nSTATIC int findBasicArtificial(lprec *lp, int before)\n{\n  int i = 0, P1extraDim = abs(lp->P1extraDim);\n\n  if(P1extraDim > 0) {\n    if(before > lp->rows || before <= 1)\n      i = lp->rows;\n    else\n      i = before;\n\n    while((i > 0) && (lp->var_basic[i] <= lp->sum-P1extraDim))\n      i--;\n  }\n\n  return(i);\n}\n\nSTATIC void eliminate_artificials(lprec *lp, REAL *prow)\n{\n  int   i, j, colnr, rownr, P1extraDim = abs(lp->P1extraDim);\n\n  for(i = 1; (i <= lp->rows) && (P1extraDim > 0); i++) {\n    j = lp->var_basic[i];\n    if(j <= lp->sum-P1extraDim)\n      continue;\n    j -= lp->rows;\n    rownr = get_artificialRow(lp, j);\n    colnr = find_rowReplacement(lp, rownr, prow, NULL);\n#if 0\n    performiteration(lp, rownr, colnr, 0.0, TRUE, FALSE, prow, NULL,\n                                                          NULL, NULL, NULL);\n#else\n    set_basisvar(lp, rownr, colnr);\n#endif\n    del_column(lp, j);\n    P1extraDim--;\n  }\n  lp->P1extraDim = 0;\n}\n\nSTATIC void clear_artificials(lprec *lp)\n{\n  int i, j, n, P1extraDim;\n\n  /* Substitute any basic artificial variable for its slack counterpart */\n  n = 0;\n  P1extraDim = abs(lp->P1extraDim);\n  for(i = 1; (i <= lp->rows) && (n < P1extraDim); i++) {\n    j = lp->var_basic[i];\n    if(j <= lp->sum-P1extraDim)\n      continue;\n    j = get_artificialRow(lp, j-lp->rows);\n    set_basisvar(lp, i, j);\n    n++;\n  }\n#ifdef Paranoia\n  if(n != lp->P1extraDim)\n    report(lp, SEVERE, \"clear_artificials: Unable to clear all basic artificial variables\\n\");\n#endif\n\n  /* Delete any remaining non-basic artificial variables */\n  while(P1extraDim > 0) {\n    i = lp->sum-lp->rows;\n    del_column(lp, i);\n    P1extraDim--;\n  }\n  lp->P1extraDim = 0;\n  if(n > 0) {\n    set_action(&lp->spx_action, ACTION_REINVERT);\n    lp->basis_valid = TRUE;\n  }\n}\n\n\nSTATIC int primloop(lprec *lp, MYBOOL primalfeasible, REAL primaloffset)\n{\n  (void)primaloffset;\n  MYBOOL primal = TRUE, bfpfinal = FALSE, changedphase = FALSE, forceoutEQ = AUTOMATIC,\n         primalphase1, pricerCanChange, minit, stallaccept, pendingunbounded;\n  int    i, j, k, colnr = 0, rownr = 0, lastnr = 0,\n         candidatecount = 0, minitcount = 0, ok = TRUE;\n  LREAL  theta = 0.0;\n  REAL   epsvalue, xviolated = 0.0, cviolated = 0.0,\n         *prow = NULL, *pcol = NULL,\n         *drow = lp->drow;\n  int    *workINT = NULL,\n         *nzdrow = lp->nzdrow;\n  (void)primaloffset;\n\n  if(lp->spx_trace)\n    report(lp, DETAILED, \"Entered primal simplex algorithm with feasibility %s\\n\",\n                         my_boolstr(primalfeasible));\n\n /* Add sufficent number of artificial variables to make the problem feasible\n    through the first phase; delete when primal feasibility has been achieved */\n  lp->P1extraDim = 0;\n  if(!primalfeasible) {\n    lp->simplex_mode = SIMPLEX_Phase1_PRIMAL;\n#ifdef Paranoia\n    if(!verify_basis(lp))\n      report(lp, SEVERE, \"primloop: No valid basis for artificial variables\\n\");\n#endif\n#if 0\n    /* First check if we can get away with a single artificial variable */\n    if(lp->equalities == 0) {\n      i = (int) feasibilityOffset(lp, !primal);\n      add_artificial(lp, i, prow, (int *) pcol);\n    }\n    else\n#endif\n    /* Otherwise add as many artificial variables as is necessary\n       to force primal feasibility. */\n      for(i = 1; i <= lp->rows; i++) {\n        add_artificial(lp, i, NULL, NULL);\n      }\n\n    /* Make sure we update the working objective */\n    if(lp->P1extraDim > 0) {\n#if 1 /* v5.1 code: Not really necessary since we do not price the artificial\n        variables (stored at the end of the column list, they are initially\n        basic and are never allowed to enter the basis, once they exit) */\n      ok = allocREAL(lp, &(lp->drow), lp->sum+1, AUTOMATIC) &&\n           allocINT(lp, &(lp->nzdrow), lp->sum+1, AUTOMATIC);\n      if(!ok)\n        goto Finish;\n      lp->nzdrow[0] = 0;\n      drow = lp->drow;\n      nzdrow = lp->nzdrow;\n#endif\n      mat_validate(lp->matA);\n      set_OF_p1extra(lp, 0.0);\n    }\n    if(lp->spx_trace)\n      report(lp, DETAILED, \"P1extraDim count = %d\\n\", lp->P1extraDim);\n\n    simplexPricer(lp, (MYBOOL)!primal);\n    invert(lp, INITSOL_USEZERO, TRUE);\n  }\n  else {\n    lp->simplex_mode = SIMPLEX_Phase2_PRIMAL;\n    restartPricer(lp, (MYBOOL)!primal);\n  }\n\n  /* Create work arrays and optionally the multiple pricing structure */\n  ok = allocREAL(lp, &(lp->bsolveVal), lp->rows + 1, FALSE) &&\n       allocREAL(lp, &prow, lp->sum + 1, TRUE) &&\n       allocREAL(lp, &pcol, lp->rows + 1, TRUE);\n  if(is_piv_mode(lp, PRICE_MULTIPLE) && (lp->multiblockdiv > 1)) {\n    lp->multivars = multi_create(lp, FALSE);\n    ok &= (lp->multivars != NULL) &&\n          multi_resize(lp->multivars, lp->sum / lp->multiblockdiv, 2, FALSE, TRUE);\n  }\n  if(!ok)\n    goto Finish;\n\n  /* Initialize regular primal simplex algorithm variables */\n  lp->spx_status = RUNNING;\n  minit = ITERATE_MAJORMAJOR;\n  epsvalue = lp->epspivot;\n  pendingunbounded = FALSE;\n\n  ok = stallMonitor_create(lp, FALSE, \"primloop\");\n  if(!ok)\n    goto Finish;\n\n  lp->rejectpivot[0] = 0;\n\n /* Iterate while we are successful; exit when the model is infeasible/unbounded,\n    or we must terminate due to numeric instability or user-determined reasons */\n  while((lp->spx_status == RUNNING) && !userabort(lp, -1)) {\n\n    primalphase1 = (MYBOOL) (lp->P1extraDim > 0);\n    clear_action(&lp->spx_action, ACTION_REINVERT | ACTION_ITERATE);\n\n    /* Check if we have stalling (from numerics or degenerate cycling) */\n    pricerCanChange = !primalphase1;\n    stallaccept = stallMonitor_check(lp, rownr, colnr, lastnr, minit, pricerCanChange, &forceoutEQ);\n    if(!stallaccept)\n      break;\n\n   /* Find best column to enter the basis */\nRetryCol:\n#if 0\n    if(verify_solution(lp, FALSE, \"spx_loop\") > 0)\n      i = 1; /* This is just a debug trap */\n#endif\n    if(!changedphase) {\n      i = 0;\n      do {\n        i++;\n        colnr = colprim(lp, drow, nzdrow, (MYBOOL) (minit == ITERATE_MINORRETRY), i, &candidatecount, TRUE, &xviolated);\n      } while ((colnr == 0) && (i < partial_countBlocks(lp, (MYBOOL) !primal)) &&\n                                partial_blockStep(lp, (MYBOOL) !primal));\n\n      /* Handle direct outcomes */\n      if(colnr == 0)\n        lp->spx_status = OPTIMAL;\n      if(lp->rejectpivot[0] > 0)\n        minit = ITERATE_MAJORMAJOR;\n\n      /* See if accuracy check during compute_reducedcosts flagged refactorization */\n      if(is_action(lp->spx_action, ACTION_REINVERT))\n        bfpfinal = TRUE;\n\n    }\n\n    /* Make sure that we do not erroneously conclude that an unbounded model is optimal */\n#ifdef primal_UseRejectionList\n    if((colnr == 0) && (lp->rejectpivot[0] > 0)) {\n      lp->spx_status = UNBOUNDED;\n      if((lp->spx_trace && (lp->bb_totalnodes == 0)) ||\n         (lp->bb_trace && (lp->bb_totalnodes > 0)))\n        report(lp, DETAILED, \"The model is primal unbounded.\\n\");\n      colnr = lp->rejectpivot[1];\n      rownr = 0;\n      lp->rejectpivot[0] = 0;\n      ok = FALSE;\n      break;\n    }\n#endif\n\n    /* Check if we found an entering variable (indicating that we are still dual infeasible) */\n    if(colnr > 0) {\n      changedphase = FALSE;\n      fsolve(lp, colnr, pcol, NULL, lp->epsmachine, 1.0, TRUE);  /* Solve entering column for Pi */\n\n      /* Do special anti-degeneracy column selection, if specified */\n      if(is_anti_degen(lp, ANTIDEGEN_COLUMNCHECK) && !check_degeneracy(lp, pcol, NULL)) {\n        if(lp->rejectpivot[0] < DEF_MAXPIVOTRETRY/3) {\n          i = ++lp->rejectpivot[0];\n          lp->rejectpivot[i] = colnr;\n          report(lp, DETAILED, \"Entering column %d found to be non-improving due to degeneracy.\\n\",\n                     colnr);\n          minit = ITERATE_MINORRETRY;\n          goto RetryCol;\n        }\n        else {\n          lp->rejectpivot[0] = 0;\n          report(lp, DETAILED, \"Gave up trying to find a strictly improving entering column.\\n\");\n        }\n      }\n\n      /* Find the leaving variable that gives the most stringent bound on the entering variable */\n      theta = drow[colnr];\n      rownr = rowprim(lp, colnr, &theta, pcol, workINT, forceoutEQ, &cviolated);\n\n#ifdef AcceptMarginalAccuracy\n      /* Check for marginal accuracy */\n      if((rownr > 0) && (xviolated+cviolated < lp->epspivot)) {\n        if(lp->bb_trace || (lp->bb_totalnodes == 0))\n          report(lp, DETAILED, \"primloop: Assuming convergence with reduced accuracy %g.\\n\",\n                               MAX(xviolated, cviolated));\n        rownr = 0;\n        colnr = 0;\n        goto Optimality;\n      }\n      else\n#endif\n\n      /* See if we can do a straight artificial<->slack replacement (when \"colnr\" is a slack) */\n      if((lp->P1extraDim != 0) && (rownr == 0) && (colnr <= lp->rows))\n        rownr = findAnti_artificial(lp, colnr);\n\n      if(rownr > 0) {\n        pendingunbounded = FALSE;\n        lp->rejectpivot[0] = 0;\n        set_action(&lp->spx_action, ACTION_ITERATE);\n        if(!lp->obj_in_basis)  /* We must manually copy the reduced cost for RHS update */\n          pcol[0] = my_chsign(!lp->is_lower[colnr], drow[colnr]);\n        lp->bfp_prepareupdate(lp, rownr, colnr, pcol);\n      }\n\n      /* We may be unbounded... */\n      else {\n        /* First make sure that we are not suffering from precision loss */\n#ifdef primal_UseRejectionList\n        if(lp->rejectpivot[0] < DEF_MAXPIVOTRETRY) {\n          lp->spx_status = RUNNING;\n          lp->rejectpivot[0]++;\n          lp->rejectpivot[lp->rejectpivot[0]] = colnr;\n          report(lp, DETAILED, \"...trying to recover via another pivot column.\\n\");\n          minit = ITERATE_MINORRETRY;\n          goto RetryCol;\n        }\n        else\n#endif\n        /* Check that we are not having numerical problems */\n        if(!refactRecent(lp) && !pendingunbounded) {\n          bfpfinal = TRUE;\n          pendingunbounded = TRUE;\n          set_action(&lp->spx_action, ACTION_REINVERT);\n        }\n\n        /* Conclude that the model is unbounded */\n        else {\n          lp->spx_status = UNBOUNDED;\n          report(lp, DETAILED, \"The model is primal unbounded.\\n\");\n          break;\n        }\n      }\n    }\n\n    /* We handle optimality and phase 1 infeasibility ... */\n    else {\n\nOptimality:\n      /* Handle possible transition from phase 1 to phase 2 */\n      if(!primalfeasible || isP1extra(lp)) {\n\n        if(feasiblePhase1(lp, epsvalue)) {\n          lp->spx_status = RUNNING;\n          if(lp->bb_totalnodes == 0) {\n            report(lp, NORMAL, \"Found feasibility by primal simplex after  %10.0f iter.\\n\",\n                                (double) get_total_iter(lp));\n            if((lp->usermessage != NULL) && (lp->msgmask & MSG_LPFEASIBLE))\n              lp->usermessage(lp, lp->msghandle, MSG_LPFEASIBLE);\n          }\n          changedphase = FALSE;\n          primalfeasible = TRUE;\n          lp->simplex_mode = SIMPLEX_Phase2_PRIMAL;\n          set_OF_p1extra(lp, 0.0);\n\n         /* We can do two things now;\n            1) delete the rows belonging to those variables, since they are redundant, OR\n            2) drive out the existing artificial variables via pivoting. */\n          if(lp->P1extraDim > 0) {\n\n#ifdef Phase1EliminateRedundant\n           /* If it is not a MIP model we can try to delete redundant rows */\n            if((lp->bb_totalnodes == 0) && (MIP_count(lp) == 0)) {\n              while(lp->P1extraDim > 0) {\n                i = lp->rows;\n                while((i > 0) && (lp->var_basic[i] <= lp->sum-lp->P1extraDim))\n                  i--;\n#ifdef Paranoia\n                if(i <= 0) {\n                  report(lp, SEVERE, \"primloop: Could not find redundant artificial.\\n\");\n                  break;\n                }\n#endif\n                /* Obtain column and row indeces */\n                j = lp->var_basic[i]-lp->rows;\n                k = get_artificialRow(lp, j);\n\n                /* Delete row before column due to basis \"compensation logic\" */\n                if(lp->is_basic[k]) {\n                  lp->is_basic[lp->rows+j] = FALSE;\n                  del_constraint(lp, k);\n                }\n                else\n                  set_basisvar(lp, i, k);\n                del_column(lp, j);\n                lp->P1extraDim--;\n              }\n              lp->basis_valid = TRUE;\n            }\n           /* Otherwise we drive out the artificials by elimination pivoting */\n            else\n              eliminate_artificials(lp, prow);\n\n#else\n            /* Indicate phase 2 with artificial variables by negating P1extraDim */\n            lp->P1extraDim = my_flipsign(lp->P1extraDim);\n#endif\n          }\n\n          /* We must refactorize since the OF changes from phase 1 to phase 2 */\n          set_action(&lp->spx_action, ACTION_REINVERT);\n          bfpfinal = TRUE;\n        }\n\n        /* We are infeasible in phase 1 */\n        else {\n          lp->spx_status = INFEASIBLE;\n          minit = ITERATE_MAJORMAJOR;\n          if(lp->spx_trace)\n            report(lp, NORMAL, \"Model infeasible by primal simplex at iter   %10.0f.\\n\",\n                               (double) get_total_iter(lp));\n        }\n      }\n\n      /* Handle phase 1 optimality */\n      else {\n        /* (Do nothing special) */\n      }\n\n      /* Check if we are still primal feasible; the default assumes that this check\n         is not necessary after the relaxed problem has been solved satisfactorily. */\n      if((lp->bb_level <= 1) || (lp->improve & IMPROVE_BBSIMPLEX) /* || (lp->bb_rule & NODE_RCOSTFIXING) */) { /* NODE_RCOSTFIXING fix */\n        set_action(&lp->piv_strategy, PRICE_FORCEFULL);\n          i = rowdual(lp, lp->rhs, FALSE, FALSE, NULL);\n        clear_action(&lp->piv_strategy, PRICE_FORCEFULL);\n        if(i > 0) {\n          lp->spx_status = LOSTFEAS;\n          if(lp->total_iter == 0)\n            report(lp, DETAILED, \"primloop: Lost primal feasibility at iter  %10.0f: will try to recover.\\n\",\n                                 (double) get_total_iter(lp));\n        }\n      }\n    }\n\n    /* Pivot row/col and update the inverse */\n    if(is_action(lp->spx_action, ACTION_ITERATE)) {\n      lastnr = lp->var_basic[rownr];\n\n      if(refactRecent(lp) == AUTOMATIC)\n        minitcount = 0;\n      else if(minitcount > MAX_MINITUPDATES) {\n        recompute_solution(lp, INITSOL_USEZERO);\n        minitcount = 0;\n      }\n      minit = performiteration(lp, rownr, colnr, theta, primal,\n                                                 (MYBOOL) (/*(candidatecount > 1) && */\n                                                           (stallaccept != AUTOMATIC)),\n                                                 NULL, NULL,\n                                                 pcol, NULL, NULL);\n      if(minit != ITERATE_MAJORMAJOR)\n        minitcount++;\n\n      if((lp->spx_status == USERABORT) || (lp->spx_status == TIMEOUT))\n        break;\n      else if(minit == ITERATE_MINORMAJOR)\n        continue;\n#ifdef UsePrimalReducedCostUpdate\n      /* Do a fast update of the reduced costs in preparation for the next iteration */\n      if(minit == ITERATE_MAJORMAJOR)\n        update_reducedcosts(lp, primal, lastnr, colnr, pcol, drow);\n#endif\n\n      /* Detect if an auxiliary variable has left the basis and delete it; if\n         the non-basic variable only changed bound (a \"minor iteration\"), the\n         basic artificial variable did not leave and there is nothing to do */\n      if((minit == ITERATE_MAJORMAJOR) && (lastnr > lp->sum - abs(lp->P1extraDim))) {\n#ifdef Paranoia\n        if(lp->is_basic[lastnr] || !lp->is_basic[colnr])\n          report(lp, SEVERE, \"primloop: Invalid basis indicator for variable %d at iter %10.0f.\\n\",\n                              lastnr, (double) get_total_iter(lp));\n#endif\n        del_column(lp, lastnr-lp->rows);\n        if(lp->P1extraDim > 0)\n          lp->P1extraDim--;\n        else\n          lp->P1extraDim++;\n        if(lp->P1extraDim == 0) {\n          colnr = 0;\n          changedphase = TRUE;\n          stallMonitor_reset(lp);\n        }\n      }\n    }\n\n    if(lp->spx_status == SWITCH_TO_DUAL)\n      ;\n    else if(!changedphase && lp->bfp_mustrefactorize(lp)) {\n#ifdef ResetMinitOnReinvert\n      minit = ITERATE_MAJORMAJOR;\n#endif\n      if(!invert(lp, INITSOL_USEZERO, bfpfinal))\n        lp->spx_status = SINGULAR_BASIS;\n      bfpfinal = FALSE;\n    }\n  }\n\n  /* Remove any remaining artificial variables (feasible or infeasible model) */\n  lp->P1extraDim = abs(lp->P1extraDim);\n/*  if((lp->P1extraDim > 0) && (lp->spx_status != DEGENERATE)) { */\n  if(lp->P1extraDim > 0) {\n    clear_artificials(lp);\n    if(lp->spx_status != OPTIMAL)\n      restore_basis(lp);\n    i = invert(lp, INITSOL_USEZERO, TRUE);\n  }\n#ifdef Paranoia\n  if(!verify_basis(lp))\n    report(lp, SEVERE, \"primloop: Invalid basis detected due to internal error\\n\");\n#endif\n\n  /* Switch to dual phase 1 simplex for MIP models during\n     B&B phases, since this is typically far more efficient */\n#ifdef ForceDualSimplexInBB\n  if((lp->bb_totalnodes == 0) && (MIP_count(lp) > 0) &&\n     ((lp->simplex_strategy & SIMPLEX_Phase1_DUAL) == 0)) {\n    lp->simplex_strategy &= ~SIMPLEX_Phase1_PRIMAL;\n    lp->simplex_strategy += SIMPLEX_Phase1_DUAL;\n  }\n#endif\n\nFinish:\n  stallMonitor_finish(lp);\n  multi_free(&(lp->multivars));\n  FREE(prow);\n  FREE(pcol);\n  FREE(lp->bsolveVal);\n\n  return(ok);\n} /* primloop */\n\nSTATIC int dualloop(lprec *lp, MYBOOL dualfeasible, int dualinfeasibles[], REAL dualoffset)\n{\n  MYBOOL primal = FALSE, inP1extra, dualphase1 = FALSE, changedphase = TRUE,\n         pricerCanChange, minit, stallaccept, longsteps,\n         forceoutEQ = FALSE, bfpfinal = FALSE;\n  int    i, colnr = 0, rownr = 0, lastnr = 0,\n         candidatecount = 0, minitcount = 0,\n#ifdef FixInaccurateDualMinit\n         minitcolnr = 0,\n#endif\n         ok = TRUE;\n  int    *boundswaps = NULL;\n  LREAL  theta = 0.0;\n  REAL   epsvalue, xviolated, cviolated,\n         *prow = NULL, *pcol = NULL,\n         *drow = lp->drow;\n  int    *nzprow = NULL, *workINT = NULL,\n         *nzdrow = lp->nzdrow;\n\n  if(lp->spx_trace)\n    report(lp, DETAILED, \"Entered dual simplex algorithm with feasibility %s.\\n\",\n                         my_boolstr(dualfeasible));\n\n  /* Allocate work arrays */\n  ok = allocREAL(lp, &prow,   lp->sum + 1,  TRUE) &&\n       allocINT (lp, &nzprow, lp->sum + 1,  FALSE) &&\n       allocREAL(lp, &pcol,   lp->rows + 1, TRUE);\n  if(!ok)\n    goto Finish;\n\n  /* Set non-zero P1extraVal value to force dual feasibility when the dual\n     simplex is used as a phase 1 algorithm for the primal simplex.\n     The value will be reset when primal feasibility has been achieved, or\n     a dual non-feasibility has been encountered (no candidate for a first\n     leaving variable) */\n  inP1extra = (MYBOOL) (dualoffset != 0);\n  if(inP1extra) {\n    set_OF_p1extra(lp, dualoffset);\n    simplexPricer(lp, (MYBOOL)!primal);\n    invert(lp, INITSOL_USEZERO, TRUE);\n  }\n  else\n    restartPricer(lp, (MYBOOL)!primal);\n\n  /* Prepare dual long-step structures */\n#if 0\n  longsteps = TRUE;\n#elif 0\n  longsteps = (MYBOOL) ((MIP_count(lp) > 0) && (lp->bb_level > 1));\n#elif 0\n  longsteps = (MYBOOL) ((MIP_count(lp) > 0) && (lp->solutioncount >= 1));\n#else\n  longsteps = FALSE;\n#endif\n#ifdef UseLongStepDualPhase1\n  longsteps = !dualfeasible && (MYBOOL) (dualinfeasibles != NULL);\n#endif\n\n  if(longsteps) {\n    lp->longsteps = multi_create(lp, TRUE);\n    ok = (lp->longsteps != NULL) &&\n         multi_resize(lp->longsteps, MIN(lp->boundedvars+2, 11), 1, TRUE, TRUE);\n    if(!ok)\n      goto Finish;\n#ifdef UseLongStepPruning\n    lp->longsteps->objcheck = TRUE;\n#endif\n    boundswaps = multi_indexSet(lp->longsteps, FALSE);\n  }\n\n  /* Do regular dual simplex variable initializations */\n  lp->spx_status = RUNNING;\n  minit = ITERATE_MAJORMAJOR;\n  epsvalue = lp->epspivot;\n\n  ok = stallMonitor_create(lp, TRUE, \"dualloop\");\n  if(!ok)\n    goto Finish;\n\n  lp->rejectpivot[0] = 0;\n  if(dualfeasible)\n    lp->simplex_mode = SIMPLEX_Phase2_DUAL;\n  else\n    lp->simplex_mode = SIMPLEX_Phase1_DUAL;\n\n  /* Check if we have equality slacks in the basis and we should try to\n     drive them out in order to reduce chance of degeneracy in Phase 1.\n     forceoutEQ = FALSE :    Only eliminate assured \"good\" violated\n                             equality constraint slacks\n                  AUTOMATIC: Seek more elimination of equality constraint\n                             slacks (but not as aggressive as the rule\n                             used in lp_solve v4.0 and earlier)\n                  TRUE:      Force remaining equality slacks out of the\n                             basis */\n  if(dualphase1 || inP1extra ||\n     ((lp->fixedvars > 0) && is_anti_degen(lp, ANTIDEGEN_FIXEDVARS))) {\n    forceoutEQ = AUTOMATIC;\n  }\n#if 1\n  if(is_anti_degen(lp, ANTIDEGEN_DYNAMIC) && (bin_count(lp, TRUE)*2 > lp->columns)) {\n    switch (forceoutEQ) {\n      case FALSE:     forceoutEQ = AUTOMATIC;\n                      break;\n /*     case AUTOMATIC: forceoutEQ = TRUE;\n                      break;\n      default:        forceoutEQ = TRUE; */\n    }\n  }\n#endif\n\n  while((lp->spx_status == RUNNING) && !userabort(lp, -1)) {\n\n    /* Check if we have stalling (from numerics or degenerate cycling) */\n    pricerCanChange = !dualphase1 && !inP1extra;\n    stallaccept = stallMonitor_check(lp, rownr, colnr, lastnr, minit, pricerCanChange, &forceoutEQ);\n    if(!stallaccept)\n      break;\n\n    /* Store current LP index for reference at next iteration */\n    changedphase = FALSE;\n\n    /* Compute (pure) dual phase1 offsets / reduced costs if appropriate */\n    dualphase1 &= (MYBOOL) (lp->simplex_mode == SIMPLEX_Phase1_DUAL);\n    if(longsteps && dualphase1 && !inP1extra) {\n      obtain_column(lp, dualinfeasibles[1], pcol, NULL, NULL);\n      i = 2;\n      for(i = 2; i <= dualinfeasibles[0]; i++)\n        mat_multadd(lp->matA, pcol, dualinfeasibles[i], 1.0);\n      /* Solve (note that solved pcol will be used instead of lp->rhs) */\n      ftran(lp, pcol, NULL, lp->epsmachine);\n    }\n\n    /* Do minor iterations (non-basic variable bound flips) for as\n       long as possible since this is a cheap way of iterating */\n#if (defined dual_Phase1PriceEqualities) || (defined dual_UseRejectionList)\nRetryRow:\n#endif\n    if(minit != ITERATE_MINORRETRY) {\n      i = 0;\n      do {\n        i++;\n        rownr = rowdual(lp, my_if(dualphase1, pcol, NULL), forceoutEQ, TRUE, &xviolated);\n      } while ((rownr == 0) && (i < partial_countBlocks(lp, (MYBOOL) !primal)) &&\n                                partial_blockStep(lp, (MYBOOL) !primal));\n    }\n\n    /* Make sure that we do not erroneously conclude that an infeasible model is optimal */\n#ifdef dual_UseRejectionList\n    if((rownr == 0) && (lp->rejectpivot[0] > 0)) {\n      lp->spx_status = INFEASIBLE;\n      if((lp->spx_trace && (lp->bb_totalnodes == 0)) ||\n         (lp->bb_trace && (lp->bb_totalnodes > 0)))\n        report(lp, DETAILED, \"The model is primal infeasible.\\n\");\n      rownr = lp->rejectpivot[1];\n      colnr = 0;\n      lp->rejectpivot[0] = 0;\n      ok = FALSE;\n      break;\n    }\n#endif\n\n    /* If we found a leaving variable, find a matching entering one */\n    clear_action(&lp->spx_action, ACTION_ITERATE);\n    if(rownr > 0) {\n      colnr = coldual(lp, rownr, prow, nzprow, drow, nzdrow,\n                                 (MYBOOL) (dualphase1 && !inP1extra),\n                                 (MYBOOL) (minit == ITERATE_MINORRETRY), &candidatecount, &cviolated);\n      if(colnr < 0) {\n        minit = ITERATE_MAJORMAJOR;\n        continue;\n      }\n#ifdef AcceptMarginalAccuracy\n      else if(xviolated+cviolated < lp->epspivot) {\n        if(lp->bb_trace || (lp->bb_totalnodes == 0))\n          report(lp, DETAILED, \"dualloop: Assuming convergence with reduced accuracy %g.\\n\",\n                               MAX(xviolated, cviolated));\n        rownr = 0;\n        colnr = 0;\n      }\n#endif\n      /* Check if the long-dual found reason to prune the B&B tree */\n      if(lp->spx_status == FATHOMED)\n        break;\n    }\n    else\n      colnr = 0;\n\n    /* Process primal-infeasible row */\n    if(rownr > 0) {\n\n      if(colnr > 0) {\n#ifdef Paranoia\n        if((rownr > lp->rows) || (colnr > lp->sum)) {\n          report(lp, SEVERE, \"dualloop: Invalid row %d(%d) and column %d(%d) pair selected at iteration %.0f\\n\",\n                             rownr, lp->rows, colnr-lp->columns, lp->columns, (double) get_total_iter(lp));\n          lp->spx_status = UNKNOWNERROR;\n          break;\n        }\n#endif\n        fsolve(lp, colnr, pcol, workINT, lp->epsmachine, 1.0, TRUE);\n\n#ifdef FixInaccurateDualMinit\n       /* Prevent bound flip-flops during minor iterations; used to detect\n          infeasibility after triggering of minor iteration accuracy management */\n        if(colnr != minitcolnr)\n          minitcolnr = 0;\n#endif\n\n       /* Getting division by zero here; catch it and try to recover */\n        if(pcol[rownr] == 0) {\n          if(lp->spx_trace)\n            report(lp, DETAILED, \"dualloop: Attempt to divide by zero (pcol[%d])\\n\", rownr);\n          if(!refactRecent(lp)) {\n            report(lp, DETAILED, \"...trying to recover by refactorizing basis.\\n\");\n            set_action(&lp->spx_action, ACTION_REINVERT);\n            bfpfinal = FALSE;\n          }\n          else {\n            if(lp->bb_totalnodes == 0)\n              report(lp, DETAILED, \"...cannot recover by refactorizing basis.\\n\");\n            lp->spx_status = NUMFAILURE;\n            ok = FALSE;\n          }\n        }\n        else {\n          set_action(&lp->spx_action, ACTION_ITERATE);\n          lp->rejectpivot[0] = 0;\n          if(!lp->obj_in_basis)  /* We must manually copy the reduced cost for RHS update */\n            pcol[0] = my_chsign(!lp->is_lower[colnr], drow[colnr]);\n          theta = lp->bfp_prepareupdate(lp, rownr, colnr, pcol);\n\n         /* Verify numeric accuracy of the basis factorization and change to\n            the \"theoretically\" correct version of the theta */\n          if((lp->improve & IMPROVE_THETAGAP) && !refactRecent(lp) &&\n             (my_reldiff(fabs(theta), fabs(prow[colnr])) >\n              lp->epspivot*10.0*log(2.0+50.0*lp->rows))) {  /* This is my kludge - KE */\n            set_action(&lp->spx_action, ACTION_REINVERT);\n            bfpfinal = TRUE;\n#ifdef IncreasePivotOnReducedAccuracy\n            lp->epspivot = MIN(1.0e-4, lp->epspivot*2.0);\n#endif\n            report(lp, DETAILED, \"dualloop: Refactorizing at iter %.0f due to loss of accuracy.\\n\",\n                                 (double) get_total_iter(lp));\n          }\n          theta = prow[colnr];\n          compute_theta(lp, rownr, &theta, !lp->is_lower[colnr], 0, primal);\n        }\n      }\n\n#ifdef FixInaccurateDualMinit\n      /* Force reinvertion and try another row if we did not find a bound-violated leaving column */\n      else if(!refactRecent(lp) && (minit != ITERATE_MAJORMAJOR) && (colnr != minitcolnr)) {\n        minitcolnr = colnr;\n        i = invert(lp, INITSOL_USEZERO, TRUE);\n        if((lp->spx_status == USERABORT) || (lp->spx_status == TIMEOUT))\n          break;\n        else if(!i) {\n          lp->spx_status = SINGULAR_BASIS;\n          break;\n        }\n        minit = ITERATE_MAJORMAJOR;\n        continue;\n      }\n#endif\n\n      /* We may be infeasible, have lost dual feasibility, or simply have no valid entering\n         variable for the selected row.  The strategy is to refactorize if we suspect numerical\n         problems and loss of dual feasibility; this is done if it has been a while since\n         refactorization.  If not, first try to select a different row/leaving variable to\n         see if a valid entering variable can be found.  Otherwise, determine this model\n         as infeasible. */\n      else {\n\n        /* As a first option, try to recover from any numerical trouble by refactorizing */\n        if(!refactRecent(lp)) {\n          set_action(&lp->spx_action, ACTION_REINVERT);\n          bfpfinal = TRUE;\n        }\n\n#ifdef dual_UseRejectionList\n        /* Check for pivot size issues */\n        else if(lp->rejectpivot[0] < DEF_MAXPIVOTRETRY) {\n          lp->spx_status = RUNNING;\n          lp->rejectpivot[0]++;\n          lp->rejectpivot[lp->rejectpivot[0]] = rownr;\n          if(lp->bb_totalnodes == 0)\n            report(lp, DETAILED, \"...trying to find another pivot row!\\n\");\n          goto RetryRow;\n        }\n#endif\n        /* Check if we may have lost dual feasibility if we also did phase 1 here */\n        else if(dualphase1 && (dualoffset != 0)) {\n          lp->spx_status = LOSTFEAS;\n          if((lp->spx_trace && (lp->bb_totalnodes == 0)) ||\n             (lp->bb_trace && (lp->bb_totalnodes > 0)))\n            report(lp, DETAILED, \"dualloop: Model lost dual feasibility.\\n\");\n          ok = FALSE;\n          break;\n        }\n\n        /* Otherwise just determine that we are infeasible */\n        else {\n          if(lp->spx_status == RUNNING) {\n#if 1\n            if(xviolated < lp->epspivot) {\n              if(lp->bb_trace || (lp->bb_totalnodes == 0))\n                report(lp, NORMAL, \"The model is primal optimal, but marginally infeasible.\\n\");\n              lp->spx_status = OPTIMAL;\n              break;\n            }\n#endif\n            lp->spx_status = INFEASIBLE;\n            if((lp->spx_trace && (lp->bb_totalnodes == 0)) ||\n               (lp->bb_trace && (lp->bb_totalnodes > 0)))\n            report(lp, DETAILED, \"The model is primal infeasible.\\n\");\n          }\n          ok = FALSE;\n          break;\n        }\n      }\n    }\n\n    /* Make sure that we enter the primal simplex with a high quality solution */\n    else if(inP1extra && !refactRecent(lp) && is_action(lp->improve, IMPROVE_INVERSE)) {\n       set_action(&lp->spx_action, ACTION_REINVERT);\n       bfpfinal = TRUE;\n    }\n\n    /* High quality solution with no leaving candidates available ... */\n    else {\n\n      bfpfinal = TRUE;\n\n#ifdef dual_RemoveBasicFixedVars\n      /* See if we should try to eliminate basic fixed variables;\n        can be time-consuming for some models */\n      if(inP1extra && (colnr == 0) && (lp->fixedvars > 0) && is_anti_degen(lp, ANTIDEGEN_FIXEDVARS)) {\n        report(lp, DETAILED, \"dualloop: Trying to pivot out %d fixed basic variables at iter %.0f\\n\",\n                             lp->fixedvars, (double) get_total_iter(lp));\n        rownr = 0;\n        while(lp->fixedvars > 0) {\n          rownr = findBasicFixedvar(lp, rownr, TRUE);\n          if(rownr == 0) {\n            colnr = 0;\n            break;\n          }\n          colnr = find_rowReplacement(lp, rownr, prow, nzprow);\n          if(colnr > 0) {\n            theta = 0;\n            performiteration(lp, rownr, colnr, theta, TRUE, FALSE, prow, NULL,\n                                                            NULL, NULL, NULL);\n            lp->fixedvars--;\n          }\n        }\n      }\n#endif\n\n      /* Check if we are INFEASIBLE for the case that the dual is used\n         as phase 1 before the primal simplex phase 2 */\n      if(inP1extra && (colnr < 0) && !isPrimalFeasible(lp, lp->epsprimal, NULL, NULL)) {\n        if(lp->bb_totalnodes == 0) {\n          if(dualfeasible)\n            report(lp, DETAILED, \"The model is primal infeasible and dual feasible.\\n\");\n          else\n            report(lp, DETAILED, \"The model is primal infeasible and dual unbounded.\\n\");\n        }\n        set_OF_p1extra(lp, 0);\n        inP1extra = FALSE;\n        set_action(&lp->spx_action, ACTION_REINVERT);\n        lp->spx_status = INFEASIBLE;\n        lp->simplex_mode = SIMPLEX_UNDEFINED;\n        ok = FALSE;\n      }\n\n      /* Check if we are FEASIBLE (and possibly also optimal) for the case that the\n         dual is used as phase 1 before the primal simplex phase 2 */\n      else if(inP1extra) {\n\n        /* Set default action; force an update of the rhs vector, adjusted for\n           the new P1extraVal=0 (set here so that usermessage() behaves properly) */\n        if(lp->bb_totalnodes == 0) {\n          report(lp, NORMAL, \"Found feasibility by dual simplex after    %10.0f iter.\\n\",\n                             (double) get_total_iter(lp));\n          if((lp->usermessage != NULL) && (lp->msgmask & MSG_LPFEASIBLE))\n            lp->usermessage(lp, lp->msghandle, MSG_LPFEASIBLE);\n        }\n        set_OF_p1extra(lp, 0);\n        inP1extra = FALSE;\n        set_action(&lp->spx_action, ACTION_REINVERT);\n\n#if 1\n        /* Optionally try another dual loop, if so selected by the user */\n        if((lp->simplex_strategy & SIMPLEX_DUAL_PRIMAL) && (lp->fixedvars == 0))\n          lp->spx_status = SWITCH_TO_PRIMAL;\n#endif\n        changedphase = TRUE;\n\n      }\n\n      /* We are primal feasible and also optimal if we were in phase 2 */\n      else  {\n\n        lp->simplex_mode = SIMPLEX_Phase2_DUAL;\n\n        /* Check if we still have equality slacks stuck in the basis; drive them out? */\n        if((lp->fixedvars > 0) && (lp->bb_totalnodes == 0)) {\n#ifdef dual_Phase1PriceEqualities\n          if(forceoutEQ != TRUE) {\n            forceoutEQ = TRUE;\n            goto RetryRow;\n          }\n#endif\n#ifdef Paranoia\n          report(lp, NORMAL,\n#else\n          report(lp, DETAILED,\n#endif\n                    \"Found dual solution with %d fixed slack variables left basic.\\n\",\n                    lp->fixedvars);\n        }\n        /* Check if we are still dual feasible; the default assumes that this check\n          is not necessary after the relaxed problem has been solved satisfactorily. */\n        colnr = 0;\n        if((dualoffset != 0) || (lp->bb_level <= 1) || (lp->improve & IMPROVE_BBSIMPLEX) || (lp->bb_rule & NODE_RCOSTFIXING)) { /* NODE_RCOSTFIXING fix */\n          set_action(&lp->piv_strategy, PRICE_FORCEFULL);\n            colnr = colprim(lp, drow, nzdrow, FALSE, 1, &candidatecount, FALSE, NULL);\n          clear_action(&lp->piv_strategy, PRICE_FORCEFULL);\n          if((dualoffset == 0) && (colnr > 0)) {\n            lp->spx_status = LOSTFEAS;\n            if(lp->total_iter == 0)\n              report(lp, DETAILED, \"Recovering lost dual feasibility at iter %10.0f.\\n\",\n                                   (double) get_total_iter(lp));\n            break;\n          }\n        }\n\n        if(colnr == 0)\n          lp->spx_status = OPTIMAL;\n        else {\n          lp->spx_status = SWITCH_TO_PRIMAL;\n          if(lp->total_iter == 0)\n            report(lp, DETAILED, \"Use primal simplex for finalization at iter  %10.0f.\\n\",\n                                 (double) get_total_iter(lp));\n        }\n        if((lp->total_iter == 0) && (lp->spx_status == OPTIMAL))\n          report(lp, DETAILED, \"Optimal solution with dual simplex at iter   %10.0f.\\n\",\n                               (double) get_total_iter(lp));\n      }\n\n      /* Determine if we are ready to break out of the loop */\n      if(!changedphase)\n        break;\n    }\n\n    /* Check if we are allowed to iterate on the chosen column and row */\n    if(is_action(lp->spx_action, ACTION_ITERATE)) {\n\n      lastnr = lp->var_basic[rownr];\n      if(refactRecent(lp) == AUTOMATIC)\n        minitcount = 0;\n      else if(minitcount > MAX_MINITUPDATES) {\n        recompute_solution(lp, INITSOL_USEZERO);\n        minitcount = 0;\n      }\n      minit = performiteration(lp, rownr, colnr, theta, primal,\n                                                 (MYBOOL) (/*(candidatecount > 1) && */\n                                                           (stallaccept != AUTOMATIC)),\n                                                 prow, nzprow,\n                                                 pcol, NULL, boundswaps);\n\n      /* Check if we should abandon iterations on finding that there is no\n        hope that this branch can improve on the incumbent B&B solution */\n      if(!lp->is_strongbranch && (lp->solutioncount >= 1) && !lp->spx_perturbed && !inP1extra &&\n          bb_better(lp, OF_WORKING, OF_TEST_WE)) {\n        lp->spx_status = FATHOMED;\n        ok = FALSE;\n        break;\n      }\n\n      if(minit != ITERATE_MAJORMAJOR)\n        minitcount++;\n\n      /* Update reduced costs for (pure) dual long-step phase 1 */\n      if(longsteps && dualphase1 && !inP1extra) {\n        dualfeasible = isDualFeasible(lp, lp->epsprimal, NULL, dualinfeasibles, NULL);\n        if(dualfeasible) {\n          dualphase1 = FALSE;\n          changedphase = TRUE;\n          lp->simplex_mode = SIMPLEX_Phase2_DUAL;\n        }\n      }\n#ifdef UseDualReducedCostUpdate\n      /* Do a fast update of reduced costs in preparation for the next iteration */\n      else if(minit == ITERATE_MAJORMAJOR)\n        update_reducedcosts(lp, primal, lastnr, colnr, prow, drow);\n#endif\n      if((minit == ITERATE_MAJORMAJOR) && (lastnr <= lp->rows) && is_fixedvar(lp, lastnr))\n        lp->fixedvars--;\n    }\n\n    /* Refactorize if required to */\n    if(lp->bfp_mustrefactorize(lp)) {\n      if(invert(lp, INITSOL_USEZERO, bfpfinal)) {\n\n#if 0\n        /* Verify dual feasibility in case we are attempting the extra dual loop */\n        if(changedphase && (dualoffset != 0) && !inP1extra && (lp->spx_status != SWITCH_TO_PRIMAL)) {\n#if 1\n          if(!isDualFeasible(lp, lp->epsdual, &colnr, NULL, NULL)) {\n#else\n          set_action(&lp->piv_strategy, PRICE_FORCEFULL);\n            colnr = colprim(lp, drow, nzdrow, FALSE, 1, &candidatecount, FALSE, NULL);\n          clear_action(&lp->piv_strategy, PRICE_FORCEFULL);\n          if(colnr > 0) {\n#endif\n            lp->spx_status = SWITCH_TO_PRIMAL;\n            colnr = 0;\n          }\n        }\n#endif\n\n        bfpfinal = FALSE;\n#ifdef ResetMinitOnReinvert\n        minit = ITERATE_MAJORMAJOR;\n#endif\n      }\n      else\n        lp->spx_status = SINGULAR_BASIS;\n    }\n  }\n\nFinish:\n  stallMonitor_finish(lp);\n  multi_free(&(lp->longsteps));\n  FREE(prow);\n  FREE(nzprow);\n  FREE(pcol);\n\n  return(ok);\n}\n\nSTATIC int spx_run(lprec *lp, MYBOOL validInvB)\n{\n  (void)validInvB;\n  int    i, j, singular_count, lost_feas_count, *infeasibles = NULL, *boundflip_count;\n  MYBOOL primalfeasible, dualfeasible, lost_feas_state, isbb;\n  REAL   primaloffset = 0, dualoffset = 0;\n  (void)validInvB;\n\n  lp->current_iter  = 0;\n  lp->current_bswap = 0;\n  lp->spx_status    = RUNNING;\n  lp->bb_status = lp->spx_status;\n  lp->P1extraDim = 0;\n  set_OF_p1extra(lp, 0);\n  singular_count  = 0;\n  lost_feas_count = 0;\n  lost_feas_state = FALSE;\n  lp->simplex_mode = SIMPLEX_DYNAMIC;\n\n  /* Compute the number of fixed basic and bounded variables (used in long duals) */\n  lp->fixedvars = 0;\n  lp->boundedvars = 0;\n  for(i = 1; i <= lp->rows; i++) {\n    j = lp->var_basic[i];\n    if((j <= lp->rows) && is_fixedvar(lp, j))\n      lp->fixedvars++;\n    if((lp->upbo[i] < lp->infinite) && (lp->upbo[i] > lp->epsprimal))\n      lp->boundedvars++;\n  }\n  for(; i <= lp->sum; i++){\n    if((lp->upbo[i] < lp->infinite) && (lp->upbo[i] > lp->epsprimal))\n      lp->boundedvars++;\n  }\n#ifdef UseLongStepDualPhase1\n  allocINT(lp, &infeasibles, lp->columns + 1, FALSE);\n  infeasibles[0] = 0;\n#endif\n\n  /* Reinvert for initialization, if necessary */\n  isbb = (MYBOOL) ((MIP_count(lp) > 0) && (lp->bb_level > 1));\n  if(is_action(lp->spx_action, ACTION_REINVERT)) {\n    if(isbb && (lp->bb_bounds->nodessolved == 0))\n/*    if(isbb && (lp->bb_basis->pivots == 0)) */\n      recompute_solution(lp, INITSOL_SHIFTZERO);\n    else {\n      i = my_if(is_action(lp->spx_action, ACTION_REBASE), INITSOL_SHIFTZERO, INITSOL_USEZERO);\n      invert(lp, (MYBOOL) i, TRUE);\n    }\n  }\n  else if(is_action(lp->spx_action, ACTION_REBASE))\n    recompute_solution(lp, INITSOL_SHIFTZERO);\n\n  /* Optionally try to do bound flips to obtain dual feasibility */\n  if(is_action(lp->improve, IMPROVE_DUALFEAS) || (lp->rows == 0))\n    boundflip_count = &i;\n  else\n    boundflip_count = NULL;\n\n  /* Loop for as long as is needed */\n  while(lp->spx_status == RUNNING) {\n\n    /* Check for dual and primal feasibility */\n    dualfeasible   = isbb ||\n                     isDualFeasible(lp, lp->epsprimal, boundflip_count, infeasibles, &dualoffset);\n\n    /* Recompute if the dual feasibility check included bound flips */\n    if(is_action(lp->spx_action, ACTION_RECOMPUTE))\n      recompute_solution(lp, INITSOL_USEZERO);\n    primalfeasible = isPrimalFeasible(lp, lp->epsprimal, NULL, &primaloffset);\n\n    if(userabort(lp, -1))\n      break;\n\n    if(lp->spx_trace) {\n      if(primalfeasible)\n        report(lp, NORMAL, \"Start at primal feasible basis\\n\");\n      else if(dualfeasible)\n        report(lp, NORMAL, \"Start at dual feasible basis\\n\");\n      else if(lost_feas_count > 0)\n        report(lp, NORMAL, \"Continuing at infeasible basis\\n\");\n      else\n        report(lp, NORMAL, \"Start at infeasible basis\\n\");\n    }\n\n   /* Now do the simplex magic */\n    if(((lp->simplex_strategy & SIMPLEX_Phase1_DUAL) == 0) ||\n       ((MIP_count(lp) > 0) && (lp->total_iter == 0) &&\n        is_presolve(lp, PRESOLVE_REDUCEMIP))) {\n      if(!lost_feas_state && primalfeasible && ((lp->simplex_strategy & SIMPLEX_Phase2_DUAL) > 0))\n        lp->spx_status = SWITCH_TO_DUAL;\n      else\n        primloop(lp, primalfeasible, 0.0);\n      if(lp->spx_status == SWITCH_TO_DUAL)\n        dualloop(lp, TRUE, NULL, 0.0);\n    }\n    else {\n      if(!lost_feas_state && primalfeasible && ((lp->simplex_strategy & SIMPLEX_Phase2_PRIMAL) > 0))\n        lp->spx_status = SWITCH_TO_PRIMAL;\n      else\n        dualloop(lp, dualfeasible, infeasibles, dualoffset);\n      if(lp->spx_status == SWITCH_TO_PRIMAL)\n        primloop(lp, TRUE, 0.0);\n    }\n\n    /* Check for simplex outcomes that always involve breaking out of the loop;\n       this includes optimality, unboundedness, pure infeasibility (i.e. not\n       loss of feasibility), numerical failure and perturbation-based degeneracy\n       handling */\n    i = lp->spx_status;\n    primalfeasible = (MYBOOL) (i == OPTIMAL);\n    if(primalfeasible || (i == UNBOUNDED))\n      break;\n    else if(((i == INFEASIBLE) && is_anti_degen(lp, ANTIDEGEN_INFEASIBLE)) ||\n             ((i == LOSTFEAS)   && is_anti_degen(lp, ANTIDEGEN_LOSTFEAS)) ||\n             ((i == NUMFAILURE) && is_anti_degen(lp, ANTIDEGEN_NUMFAILURE)) ||\n             ((i == DEGENERATE) && is_anti_degen(lp, ANTIDEGEN_STALLING))) {\n      /* Check if we should not loop here, but do perturbations */\n      if((lp->bb_level <= 1)   || is_anti_degen(lp, ANTIDEGEN_DURINGBB))\n        break;\n\n      /* Assume that accuracy during B&B is high and that infeasibility is \"real\" */\n#ifdef AssumeHighAccuracyInBB\n      if((lp->bb_level > 1) && (i == INFEASIBLE))\n        break;\n#endif\n    }\n\n    /* Check for outcomes that may involve trying another simplex loop */\n    if(lp->spx_status == SINGULAR_BASIS) {\n      lost_feas_state = FALSE;\n      singular_count++;\n      if(singular_count >= DEF_MAXSINGULARITIES) {\n        report(lp, IMPORTANT, \"spx_run: Failure due to too many singular bases.\\n\");\n        lp->spx_status = NUMFAILURE;\n        break;\n      }\n      if(lp->spx_trace || (lp->verbose > DETAILED))\n        report(lp, NORMAL, \"spx_run: Singular basis; attempting to recover.\\n\");\n      lp->spx_status = RUNNING;\n      /* Singular pivots are simply skipped by the inversion, leaving a row's\n         slack variable in the basis instead of the singular user variable. */\n    }\n    else {\n      lost_feas_state = (MYBOOL) (lp->spx_status == LOSTFEAS);\n#if 0\n      /* Optionally handle loss of numerical accuracy as loss of feasibility,\n         but only attempt a single loop to try to recover from this. */\n      lost_feas_state |= (MYBOOL) ((lp->spx_status == NUMFAILURE) && (lost_feas_count < 1));\n#endif\n      if(lost_feas_state) {\n        lost_feas_count++;\n        if(lost_feas_count < DEF_MAXSINGULARITIES) {\n          report(lp, DETAILED, \"spx_run: Recover lost feasibility at iter  %10.0f.\\n\",\n                                (double) get_total_iter(lp));\n          lp->spx_status = RUNNING;\n        }\n        else {\n          report(lp, IMPORTANT, \"spx_run: Lost feasibility %d times - iter %10.0f and %9.0f nodes.\\n\",\n                                lost_feas_count, (double) get_total_iter(lp), (double) lp->bb_totalnodes);\n          lp->spx_status = NUMFAILURE;\n        }\n      }\n    }\n  }\n\n  /* Update iteration tallies before returning */\n  lp->total_iter   += lp->current_iter;\n  lp->current_iter  = 0;\n  lp->total_bswap  += lp->current_bswap;\n  lp->current_bswap = 0;\n  FREE(infeasibles);\n\n  return(lp->spx_status);\n} /* spx_run */\n\nlprec *make_lag(lprec *lpserver)\n{\n  int    i;\n  lprec  *hlp;\n  MYBOOL ret;\n  REAL   *duals;\n\n  /* Create a Lagrangean solver instance */\n  hlp = make_lp(0, lpserver->columns);\n\n  if(hlp != NULL) {\n\n    /* First create and core variable data */\n    set_sense(hlp, is_maxim(lpserver));\n    /*hlp->lag_bound = lpserver->bb_limitOF;*/\n    for(i = 1; i <= lpserver->columns; i++) {\n      set_mat(hlp, 0, i, get_mat(lpserver, 0, i));\n      if(is_binary(lpserver, i))\n        set_binary(hlp, i, TRUE);\n      else {\n        set_int(hlp, i, is_int(lpserver, i));\n        set_bounds(hlp, i, get_lowbo(lpserver, i), get_upbo(lpserver, i));\n      }\n    }\n    /* Then fill data for the Lagrangean constraints */\n    hlp->matL = lpserver->matA;\n    inc_lag_space(hlp, lpserver->rows, TRUE);\n    ret = get_ptr_sensitivity_rhs(hlp, &duals, NULL, NULL);\n    for(i = 1; i <= lpserver->rows; i++) {\n      hlp->lag_con_type[i] = get_constr_type(lpserver, i);\n      hlp->lag_rhs[i] = lpserver->orig_rhs[i];\n      hlp->lambda[i] = (ret) ? duals[i - 1] : 0.0;\n    }\n  }\n\n  return(hlp);\n}\n\nSTATIC int heuristics(lprec *lp, int mode)\n/* Initialize / bound a MIP problem */\n{\n  (void)mode;\n  lprec *hlp;\n  int   status = PROCFAIL;\n  (void)mode;\n\n  if(lp->bb_level > 1)\n    return( status );\n\n  status = RUNNING;\n  lp->bb_limitOF = my_chsign(is_maxim(lp), -lp->infinite);\n  if(FALSE && (lp->int_vars > 0)) {\n\n    /* 1. Copy the problem into a new relaxed instance, extracting Lagrangean constraints */\n    hlp = make_lag(lp);\n\n    /* 2. Run the Lagrangean relaxation */\n    status = solve(hlp);\n\n    /* 3. Copy the key results (bound) into the original problem */\n    lp->bb_heuristicOF = hlp->best_solution[0];\n\n    /* 4. Delete the helper heuristic */\n    hlp->matL = NULL;\n    delete_lp(hlp);\n  }\n\n  lp->timeheuristic = timeNow();\n  return( status );\n}\n\nSTATIC int lag_solve(lprec *lp, REAL start_bound, int num_iter)\n{\n  int    i, j, citer, nochange, oldpresolve;\n  MYBOOL LagFeas, AnyFeas, Converged, same_basis;\n  REAL   *OrigObj, *ModObj, *SubGrad, *BestFeasSol;\n  REAL   Zub, Zlb, Znow, Zprev, Zbest, rhsmod, hold;\n  REAL   Phi, StepSize = 0.0, SqrsumSubGrad;\n\n  /* Make sure we have something to work with */\n  if(lp->spx_status != OPTIMAL) {\n    lp->lag_status = NOTRUN;\n    return( lp->lag_status );\n  }\n\n  /* Allocate iteration arrays */\n  if(!allocREAL(lp, &OrigObj, lp->columns + 1, FALSE) ||\n     !allocREAL(lp, &ModObj,  lp->columns + 1, TRUE) ||\n     !allocREAL(lp, &SubGrad, get_Lrows(lp) + 1, TRUE) ||\n     !allocREAL(lp, &BestFeasSol, lp->sum + 1, TRUE)) {\n    lp->lag_status = NOMEMORY;\n     return( lp->lag_status );\n  }\n  lp->lag_status = RUNNING;\n\n  /* Prepare for Lagrangean iterations using results from relaxed problem */\n  oldpresolve = lp->do_presolve;\n  lp->do_presolve = PRESOLVE_NONE;\n  push_basis(lp, NULL, NULL, NULL);\n\n  /* Initialize variables (assume minimization problem in overall structure) */\n  Zlb      = lp->best_solution[0];\n  Zub      = start_bound;\n  Zbest    = Zub;\n  Znow     = Zlb;\n  Zprev    = lp->infinite;\n  rhsmod   = 0;\n\n  Phi      = DEF_LAGCONTRACT; /* In the range 0-2.0 to guarantee convergence */\n/*  Phi      = 0.15; */\n  LagFeas  = FALSE;\n  Converged= FALSE;\n  AnyFeas  = FALSE;\n  citer    = 0;\n  nochange = 0;\n\n  /* Initialize reference and solution vectors; don't bother about the\n     original OF offset since we are maintaining an offset locally. */\n\n/* #define DirectOverrideOF */\n\n  get_row(lp, 0, OrigObj);\n#ifdef DirectOverrideOF\n  set_OF_override(lp, ModObj);\n#endif\n  OrigObj[0] = get_rh(lp, 0);\n  for(i = 1 ; i <= get_Lrows(lp); i++)\n    lp->lambda[i] = 0;\n\n  /* Iterate to convergence, failure or user-specified termination */\n  while((lp->lag_status == RUNNING) && (citer < num_iter)) {\n\n    citer++;\n\n    /* Compute constraint feasibility gaps and associated sum of squares,\n       and determine feasibility over the Lagrangean constraints;\n       SubGrad is the subgradient, which here is identical to the slack. */\n    LagFeas = TRUE;\n    Converged = TRUE;\n    SqrsumSubGrad = 0;\n    for(i = 1; i <= get_Lrows(lp); i++) {\n      hold = lp->lag_rhs[i];\n      for(j = 1; j <= lp->columns; j++)\n        hold -= mat_getitem(lp->matL, i, j) * lp->best_solution[lp->rows + j];\n      if(LagFeas) {\n        if(lp->lag_con_type[i] == EQ) {\n          if(fabs(hold) > lp->epsprimal)\n            LagFeas = FALSE;\n        }\n        else if(hold < -lp->epsprimal)\n          LagFeas = FALSE;\n      }\n      /* Test for convergence and update */\n      if(Converged && (fabs(my_reldiff(hold , SubGrad[i])) > /* lp->lag_accept */ DEF_LAGACCEPT))\n        Converged = FALSE;\n      SubGrad[i] = hold;\n      SqrsumSubGrad += hold * hold;\n    }\n    SqrsumSubGrad = sqrt(SqrsumSubGrad);\n#if 1\n    Converged &= LagFeas;\n#endif\n    if(Converged)\n      break;\n\n    /* Modify step parameters and initialize ahead of next iteration */\n    Znow = lp->best_solution[0] - rhsmod;\n    if(Znow > Zub) {\n      /* Handle exceptional case where we overshoot */\n      Phi *= DEF_LAGCONTRACT;\n      StepSize *= (Zub-Zlb) / (Znow-Zlb);\n    }\n    else\n#define LagBasisContract\n#ifdef LagBasisContract\n/*      StepSize = Phi * (Zub - Znow) / SqrsumSubGrad; */\n      StepSize = Phi * (2-DEF_LAGCONTRACT) * (Zub - Znow) / SqrsumSubGrad;\n#else\n      StepSize = Phi * (Zub - Znow) / SqrsumSubGrad;\n#endif\n\n    /* Compute the new dual price vector (Lagrangean multipliers, lambda) */\n    for(i = 1; i <= get_Lrows(lp); i++) {\n      lp->lambda[i] += StepSize * SubGrad[i];\n      if((lp->lag_con_type[i] != EQ) && (lp->lambda[i] > 0)) {\n        /* Handle case where we overshoot and need to correct (see above) */\n        if(Znow < Zub)\n          lp->lambda[i] = 0;\n      }\n    }\n/*    normalizeVector(lp->lambda, get_Lrows(lp)); */\n\n    /* Save the current vector if it is better */\n    if(LagFeas && (Znow < Zbest)) {\n\n      /* Recompute the objective function value in terms of the original values */\n      MEMCOPY(BestFeasSol, lp->best_solution, lp->sum+1);\n      hold = OrigObj[0];\n      for(i = 1; i <= lp->columns; i++)\n        hold += lp->best_solution[lp->rows + i] * OrigObj[i];\n      BestFeasSol[0] = hold;\n      if(lp->lag_trace)\n        report(lp, NORMAL, \"lag_solve: Improved feasible solution at iteration %d of %g\\n\",\n                           citer, hold);\n\n      /* Reset variables */\n      Zbest = Znow;\n      AnyFeas  = TRUE;\n      nochange = 0;\n    }\n    else if(Znow == Zprev) {\n      nochange++;\n      if(nochange > LAG_SINGULARLIMIT) {\n        Phi *= 0.5;\n        nochange = 0;\n      }\n    }\n    Zprev = Znow;\n\n    /* Recompute the objective function values for the next iteration */\n    for(j = 1; j <= lp->columns; j++) {\n      hold = 0;\n      for(i = 1; i <= get_Lrows(lp); i++)\n        hold += lp->lambda[i] * mat_getitem(lp->matL, i, j);\n      ModObj[j] = OrigObj[j] - my_chsign(is_maxim(lp), hold);\n#ifndef DirectOverrideOF\n      set_mat(lp, 0, j, ModObj[j]);\n#endif\n    }\n\n    /* Recompute the fixed part of the new objective function */\n    rhsmod = my_chsign(is_maxim(lp), get_rh(lp, 0));\n    for(i = 1; i <= get_Lrows(lp); i++)\n      rhsmod += lp->lambda[i] * lp->lag_rhs[i];\n\n    /* Print trace/debugging information, if specified */\n    if(lp->lag_trace) {\n      report(lp, IMPORTANT, \"Zub: %10g Zlb: %10g Stepsize: %10g Phi: %10g Feas %d\\n\",\n                 (double) Zub, (double) Zlb, (double) StepSize, (double) Phi, LagFeas);\n      for(i = 1; i <= get_Lrows(lp); i++)\n        report(lp, IMPORTANT, \"%3d SubGrad %10g lambda %10g\\n\",\n                   i, (double) SubGrad[i], (double) lp->lambda[i]);\n      if(lp->sum < 20)\n        print_lp(lp);\n    }\n\n    /* Solve the Lagrangean relaxation, handle failures and compute\n       the Lagrangean objective value, if successful */\n    i = spx_solve(lp);\n    if(lp->spx_status == UNBOUNDED) {\n      if(lp->lag_trace) {\n        report(lp, NORMAL, \"lag_solve: Unbounded solution encountered with this OF:\\n\");\n        for(i = 1; i <= lp->columns; i++)\n          report(lp, NORMAL, RESULTVALUEMASK \" \", (double) ModObj[i]);\n      }\n      goto Leave;\n    }\n    else if((lp->spx_status == NUMFAILURE)   || (lp->spx_status == PROCFAIL) ||\n            (lp->spx_status == USERABORT) || (lp->spx_status == TIMEOUT) ||\n            (lp->spx_status == INFEASIBLE)) {\n      lp->lag_status = lp->spx_status;\n    }\n\n    /* Compare optimal bases and contract if we have basis stationarity */\n#ifdef LagBasisContract\n    same_basis = compare_basis(lp);\n    if(LagFeas &&\n       !same_basis) {\n      pop_basis(lp, FALSE);\n      push_basis(lp, NULL, NULL, NULL);\n      Phi *= DEF_LAGCONTRACT;\n    }\n    if(lp->lag_trace) {\n      report(lp, DETAILED, \"lag_solve: Simplex status code %d, same basis %s\\n\",\n                 lp->spx_status, my_boolstr(same_basis));\n      print_solution(lp, 1);\n    }\n#endif\n  }\n\n  /* Transfer solution values */\n  if(AnyFeas) {\n    /*lp->lag_bound = my_chsign(is_maxim(lp), Zbest);*/\n    for(i = 0; i <= lp->sum; i++)\n      lp->solution[i] = BestFeasSol[i];\n    transfer_solution(lp, TRUE);\n    if(!is_maxim(lp))\n      for(i = 1; i <= get_Lrows(lp); i++)\n        lp->lambda[i] = my_flipsign(lp->lambda[i]);\n  }\n\n  /* Do standard postprocessing */\nLeave:\n\n  /* Set status variables and report */\n  if(citer >= num_iter) {\n    if(AnyFeas)\n      lp->lag_status = FEASFOUND;\n    else\n      lp->lag_status = NOFEASFOUND;\n  }\n  else\n    lp->lag_status = lp->spx_status;\n  if(lp->lag_status == OPTIMAL) {\n    report(lp, NORMAL, \"\\nLagrangean convergence achieved in %d iterations\\n\",  citer);\n    i = check_solution(lp, lp->columns,\n                       lp->best_solution, lp->orig_upbo, lp->orig_lowbo, lp->epssolution);\n  }\n  else {\n    report(lp, NORMAL, \"\\nUnsatisfactory convergence achieved over %d Lagrangean iterations.\\n\",\n                       citer);\n    if(AnyFeas)\n      report(lp, NORMAL, \"The best feasible Lagrangean objective function value was %g\\n\",\n                         lp->best_solution[0]);\n  }\n\n  /* Restore the original objective function */\n#ifdef DirectOverrideOF\n  set_OF_override(lp, NULL);\n#else\n  for(i = 1; i <= lp->columns; i++)\n    set_mat(lp, 0, i, OrigObj[i]);\n#endif\n\n  /* ... and then free memory */\n  FREE(BestFeasSol);\n  FREE(SubGrad);\n  FREE(OrigObj);\n  FREE(ModObj);\n  pop_basis(lp, FALSE);\n\n  lp->do_presolve = oldpresolve;\n\n  return( lp->lag_status );\n}\n\nSTATIC int spx_solve(lprec *lp)\n{\n  int       status;\n  MYBOOL    iprocessed;\n\n  lp->total_iter       = 0;\n  lp->total_bswap      = 0;\n  lp->perturb_count    = 0;\n  lp->bb_maxlevel      = 1;\n  lp->bb_totalnodes    = 0;\n  lp->bb_improvements  = 0;\n  lp->bb_strongbranches= 0;\n  lp->is_strongbranch  = FALSE;\n  lp->bb_level         = 0;\n  lp->bb_solutionlevel = 0;\n  lp->best_solution[0] = my_chsign(is_maxim(lp), lp->infinite);\n  if(lp->invB != NULL)\n    lp->bfp_restart(lp);\n\n  lp->spx_status = presolve(lp);\n  if(lp->spx_status == PRESOLVED) {\n    status = lp->spx_status;\n    goto Reconstruct;\n  }\n  else if(lp->spx_status != RUNNING)\n    goto Leave;\n\n  iprocessed = !lp->wasPreprocessed;\n  if(!preprocess(lp) || userabort(lp, -1))\n    goto Leave;\n\n  if(mat_validate(lp->matA)) {\n\n    /* Do standard initializations */\n    lp->solutioncount = 0;\n    lp->real_solution = lp->infinite;\n    set_action(&lp->spx_action, ACTION_REBASE | ACTION_REINVERT);\n    lp->bb_break = FALSE;\n\n    /* Do the call to the real underlying solver (note that\n       run_BB is replaceable with any compatible MIP solver) */\n    status = run_BB(lp);\n\n    /* Restore modified problem */\n    if(iprocessed)\n      postprocess(lp);\n\n    /* Restore data related to presolve (mainly a placeholder as of v5.1) */\nReconstruct:\n    if(!postsolve(lp, status))\n      report(lp, SEVERE, \"spx_solve: Failure during postsolve.\\n\");\n\n    goto Leave;\n  }\n\n  /* If we get here, mat_validate(lp) failed. */\n  if(lp->bb_trace || lp->spx_trace)\n    report(lp, CRITICAL, \"spx_solve: The current LP seems to be invalid\\n\");\n  lp->spx_status = NUMFAILURE;\n\nLeave:\n  lp->timeend = timeNow();\n\n  if((lp->lag_status != RUNNING) && (lp->invB != NULL)) {\n    int       itemp;\n    REAL      test;\n\n    itemp = lp->bfp_nonzeros(lp, TRUE);\n    test = 100;\n    if(lp->total_iter > 0)\n      test *= (REAL) lp->total_bswap/lp->total_iter;\n    report(lp, NORMAL, \"\\n \");\n    report(lp, NORMAL, \"MEMO: lp_solve version %d.%d.%d.%d for %d bit OS, with %d bit REAL variables.\\n\",\n                        MAJORVERSION, MINORVERSION, RELEASE, BUILD, 8*sizeof(void *), 8*sizeof(REAL));\n    report(lp, NORMAL, \"      In the total iteration count %.0f, %.0f (%.1f%%) were bound flips.\\n\",\n                        (double) lp->total_iter, (double) lp->total_bswap, test);\n    report(lp, NORMAL, \"      There were %d refactorizations, %d triggered by time and %d by density.\\n\",\n                        lp->bfp_refactcount(lp, BFP_STAT_REFACT_TOTAL),\n                        lp->bfp_refactcount(lp, BFP_STAT_REFACT_TIMED),\n                        lp->bfp_refactcount(lp, BFP_STAT_REFACT_DENSE));\n    report(lp, NORMAL, \"       ... on average %.1f major pivots per refactorization.\\n\",\n                        get_refactfrequency(lp, TRUE));\n    report(lp, NORMAL, \"      The largest [%s] fact(B) had %d NZ entries, %.1fx largest basis.\\n\",\n                        lp->bfp_name(), itemp, lp->bfp_efficiency(lp));\n    if(lp->perturb_count > 0)\n      report(lp, NORMAL, \"      The bounds were relaxed via perturbations %d times.\\n\",\n                          lp->perturb_count);\n    if(MIP_count(lp) > 0) {\n      if(lp->bb_solutionlevel > 0)\n        report(lp, NORMAL, \"      The maximum B&B level was %d, %.1fx MIP order, %d at the optimal solution.\\n\",\n                        lp->bb_maxlevel, (double) lp->bb_maxlevel / (MIP_count(lp)+lp->int_vars), lp->bb_solutionlevel);\n      else\n        report(lp, NORMAL, \"      The maximum B&B level was %d, %.1fx MIP order, with %.0f nodes explored.\\n\",\n                        lp->bb_maxlevel, (double) lp->bb_maxlevel / (MIP_count(lp)+lp->int_vars), (double) get_total_nodes(lp));\n      if(GUB_count(lp) > 0)\n        report(lp, NORMAL, \"      %d general upper-bounded (GUB) structures were employed during B&B.\\n\",\n                         GUB_count(lp));\n    }\n    report(lp, NORMAL, \"      The constraint matrix inf-norm is %g, with a dynamic range of %g.\\n\",\n                        lp->matA->infnorm, lp->matA->dynrange);\n    report(lp, NORMAL, \"      Time to load data was %.3f seconds, presolve used %.3f seconds,\\n\",\n                        lp->timestart-lp->timecreate, lp->timepresolved-lp->timestart);\n    report(lp, NORMAL, \"       ... %.3f seconds in simplex solver, in total %.3f seconds.\\n\",\n                        lp->timeend-lp->timepresolved, lp->timeend-lp->timecreate);\n  }\n  return( lp->spx_status );\n\n} /* spx_solve */\n\nint lin_solve(lprec *lp)\n{\n  int status = NOTRUN;\n\n  /* Don't do anything in case of an empty model */\n  lp->lag_status = NOTRUN;\n  /* if(get_nonzeros(lp) == 0) { */\n  if(lp->columns == 0) {\n    default_basis(lp);\n    lp->spx_status = NOTRUN;\n    return( /* OPTIMAL */ lp->spx_status);\n  }\n\n  /* Otherwise reset selected arrays before solving */\n  unset_OF_p1extra(lp);\n  free_duals(lp);\n  FREE(lp->drow);\n  FREE(lp->nzdrow);\n  if(lp->bb_cuttype != NULL)\n    freecuts_BB(lp);\n\n  /* Reset/initialize timers */\n  lp->timestart        = timeNow();\n  lp->timeheuristic    = 0;\n  lp->timepresolved    = 0;\n  lp->timeend          = 0;\n\n  /* Do heuristics ahead of solving the model */\n  if(heuristics(lp, AUTOMATIC) != RUNNING)\n    return( INFEASIBLE );\n\n  /* Solve the full, prepared model */\n  status = spx_solve(lp);\n  if((get_Lrows(lp) > 0) && (lp->lag_status == NOTRUN)) {\n    if(status == OPTIMAL)\n      status = lag_solve(lp, lp->bb_heuristicOF, DEF_LAGMAXITERATIONS);\n    else\n      report(lp, IMPORTANT, \"\\nCannot do Lagrangean optimization since root model was not solved.\\n\");\n  }\n\n  /* Reset heuristic in preparation for next run (if any) */\n  lp->bb_heuristicOF = my_chsign(is_maxim(lp), lp->infinite);\n\n  /* Check that correct status code is returned */\n/*\n   peno 26.12.07\n   status was not set to SUBOPTIMAL, only lp->spx_status\n   Bug occured by a change in 5.5.0.10 when  && (lp->bb_totalnodes > 0) was added\n   added status =\n   See UnitTest3\n*/\n/*\n   peno 12.01.08\n   If an integer solution is found with the same objective value as the relaxed solution then\n   searching is stopped. This by setting lp->bb_break. However this resulted in a report of SUBOPTIMAL\n   solution. For this,  && !bb_better(lp, OF_DUALLIMIT, OF_TEST_BE) is added in the test.\n   See UnitTest20\n*/\n  if((lp->spx_status == OPTIMAL) && (lp->bb_totalnodes > 0)) {\n    if((lp->bb_break && !bb_better(lp, OF_DUALLIMIT, OF_TEST_BE)) /* ||\n       ISMASKSET(lp->trace, TRACE_NOBBLIMIT) */)\n    status = lp->spx_status = SUBOPTIMAL;\n  }\n\n  return( status );\n}\n"
  },
  {
    "path": "utilities/lp_solve/lp_simplex.h",
    "content": "#ifndef HEADER_lp_simplex\n#define HEADER_lp_simplex\n\n#include \"lp_types.h\"\n\n#define ForceDualSimplexInBB               /* Force use/switch of dual simplex in B&B */\n#define AssumeHighAccuracyInBB    /* No iteration of simplex solves at infeasibility */\n/*#define UseLongStepPruning*/\n/*#define UseLongStepDualPhase1*/\n#define primal_UseRejectionList\n#define dual_UseRejectionList\n#define dual_RemoveBasicFixedVars\n/*#define dual_Phase1PriceEqualities */   /* Force elimination of equality slacks */\n#define AcceptMarginalAccuracy\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Put function headers here */\nSTATIC int primloop(lprec *lp, MYBOOL primalfeasible, REAL primaloffset);\nSTATIC int dualloop(lprec *lp, MYBOOL dualfeasible, int dualinfeasibles[], REAL dualoffset);\nSTATIC int spx_run(lprec *lp, MYBOOL validInvB);\nSTATIC int spx_solve(lprec *lp);\nSTATIC int lag_solve(lprec *lp, REAL start_bound, int num_iter);\nSTATIC int heuristics(lprec *lp, int mode);\nSTATIC int lin_solve(lprec *lp);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_simplex */\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_solveDLL.h",
    "content": "// stdafx.h : include file for standard system include files,\n//  or project specific include files that are used frequently, but\n//      are changed infrequently\n//\n\n#if !defined(AFX_STDAFX_H__22BF6D92_917F_4BDF_B806_0954721EBA95__INCLUDED_)\n#define AFX_STDAFX_H__22BF6D92_917F_4BDF_B806_0954721EBA95__INCLUDED_\n\n#if _MSC_VER > 1000\n#pragma once\n#endif // _MSC_VER > 1000\n\n\n// Insert your headers here\n#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers\n\n#include <windows.h>\n\n// TODO: reference additional headers your program requires here\n\n//{{AFX_INSERT_LOCATION}}\n// Microsoft Visual C++ will insert additional declarations immediately before the previous line.\n\n#endif // !defined(AFX_STDAFX_H__22BF6D92_917F_4BDF_B806_0954721EBA95__INCLUDED_)\n"
  },
  {
    "path": "utilities/lp_solve/lp_types.h",
    "content": "#ifndef HEADER_lp_types\n#define HEADER_lp_types\n\n#ifdef WIN32\n  #include <windows.h>\n#endif\n\n/* Define data types                                                         */\n/* ------------------------------------------------------------------------- */\n#ifndef LLONG\n  #if defined __BORLANDC__\n    #define LLONG __int64\n  #elif !defined _MSC_VER || _MSC_VER >= 1310\n    #define LLONG long long\n  #else\n    #define LLONG __int64\n  #endif\n#endif\n\n#ifndef COUNTER\n  #define COUNTER LLONG\n#endif\n\n#ifndef REAL\n  #define REAL    double\n#endif\n\n#ifndef REALXP\n  #if 1\n    #define REALXP long double  /* Set local accumulation variable as long double */\n  #else\n    #define REALXP REAL          /* Set local accumulation as default precision */\n  #endif\n#endif\n\n#ifndef LREAL\n  #if 0\n    #define LREAL long double   /* Set global solution update variable as long double */\n  #else\n    #define LREAL REAL           /* Set global solution update variable as default precision */\n  #endif\n#endif\n\n#define RESULTVALUEMASK \"%18.12g\" /* Set fixed-format real-valued output precision;\n                                  suggested width: ABS(exponent of DEF_EPSVALUE)+6. */\n#define INDEXVALUEMASK  \"%8d\"     /* Set fixed-format integer-valued output width */\n\n#ifndef DEF_STRBUFSIZE\n  #define DEF_STRBUFSIZE   512\n#endif\n#ifndef MAXINT32\n  #define MAXINT32  2147483647\n#endif\n#ifndef MAXUINT32\n  #define MAXUINT32 4294967295\n#endif\n\n#ifndef MAXINT64\n  #if defined _LONGLONG || defined __LONG_LONG_MAX__ || defined LLONG_MAX\n    #define MAXINT64   9223372036854775807ll\n  #else\n    #define MAXINT64   9223372036854775807l\n  #endif\n#endif\n#ifndef MAXUINT64\n  #if defined _LONGLONG || defined __LONG_LONG_MAX__ || defined LLONG_MAX\n    #define MAXUINT64 18446744073709551615ll\n  #else\n    #define MAXUINT64 18446744073709551615l\n  #endif\n#endif\n\n#ifndef CHAR_BIT\n  #define CHAR_BIT  8\n#endif\n#ifndef MYBOOL\n  #define MYBOOL  unsigned char    /* Conserve memory, could be unsigned int */\n#endif\n\n\n/* Constants                                                                 */\n/* ------------------------------------------------------------------------- */\n#ifndef NULL\n  #define NULL                   0\n#endif\n\n/* Byte-sized Booleans and extended options */\n#define FALSE                    0\n#define TRUE                     1\n#define AUTOMATIC                2\n#define DYNAMIC                  4\n\n/* Sorting and comparison constants */\n#define COMP_PREFERCANDIDATE     1\n#define COMP_PREFERNONE          0\n#define COMP_PREFERINCUMBENT    -1\n\n/* Library load status values */\n#define LIB_LOADED               0\n#define LIB_NOTFOUND             1\n#define LIB_NOINFO               2\n#define LIB_NOFUNCTION           3\n#define LIB_VERINVALID           4\n#define LIB_STR_LOADED           \"Successfully loaded\"\n#define LIB_STR_NOTFOUND         \"File not found\"\n#define LIB_STR_NOINFO           \"No version data\"\n#define LIB_STR_NOFUNCTION       \"Missing function header\"\n#define LIB_STR_VERINVALID       \"Incompatible version\"\n#define LIB_STR_MAXLEN           23\n\n\n/* Compiler/target settings                                                  */\n/* ------------------------------------------------------------------------- */\n#if (defined _WIN32) || (defined WIN32) || (defined _WIN64) || (defined WIN64)\n# define __WINAPI WINAPI\n#else\n# define __WINAPI\n#endif\n\n#if (defined _WIN32) || (defined WIN32) || (defined _WIN64) || (defined WIN64)\n# define __VACALL __cdecl\n#else\n# define __VACALL\n#endif\n\n#ifndef __BORLANDC__\n\n  #ifdef _USRDLL\n\n    #if 1\n      #define __EXPORT_TYPE __declspec(dllexport)\n    #else\n     /* Set up for the Microsoft compiler */\n      #ifdef LP_SOLVE_EXPORTS\n        #define __EXPORT_TYPE __declspec(dllexport)\n      #else\n        #define __EXPORT_TYPE __declspec(dllimport)\n      #endif\n    #endif\n\n  #else\n\n    #define __EXPORT_TYPE\n\n  #endif\n\n  #ifdef __cplusplus\n    #define __EXTERN_C extern \"C\"\n  #else\n    #define __EXTERN_C\n  #endif\n\n#else  /* Otherwise set up for the Borland compiler */\n\n  #ifdef __DLL__\n\n    #define _USRDLL\n    #define __EXTERN_C extern \"C\"\n\n    #ifdef __READING_THE_DLL\n      #define __EXPORT_TYPE __import\n    #else\n      #define __EXPORT_TYPE __export\n    #endif\n\n  #else\n\n    #define __EXPORT_TYPE\n    #define __EXTERN_C extern \"C\"\n\n  #endif\n\n#endif\n\n\n#if 0\n  #define STATIC static\n#else\n  #define STATIC\n#endif\n\n#if !defined INLINE\n  #if defined __cplusplus\n    #define INLINE inline\n  #elif (defined _WIN32) || (defined WIN32) || (defined _WIN64) || (defined WIN64)\n    #define INLINE __inline\n  #else\n    #define INLINE static\n  #endif\n#endif\n\n/* Function macros                                                           */\n/* ------------------------------------------------------------------------- */\n#define my_limitrange(x, lo, hi) ((x) < (lo) ? (lo) : ((x) > (hi) ? (hi) : (x)))\n#ifndef my_mod\n  #define my_mod(n, m)          ((n) % (m))\n#endif\n#define my_if(t, x, y)          ((t) ? (x) : (y))\n#define my_sign(x)              ((x) < 0 ? -1 : 1)\n#if 1\n  #define my_chsign(t, x)       ( ((t) && ((x) != 0)) ? -(x) : (x))\n#else\n  #define my_chsign(t, x)       ( (2*((t) == 0) - 1) * (x) )  /* \"Pipelined\", but problem with \"negative zero\" and possible problems on AIX  */\n#endif\n#define my_flipsign(x)          ( fabs((REAL) (x)) == 0 ? 0 : -(x) )\n#define my_roundzero(val, eps)  if (fabs((REAL) (val)) < eps) val = 0\n#define my_avoidtiny(val, eps)  (fabs((REAL) (val)) < eps ? 0 : val)\n\n#if 1\n  #define my_infinite(lp, val)  ( (MYBOOL) (fabs(val) >= lp->infinite) )\n#else\n  #define my_infinite(lp, val)  is_infinite(lp, val)\n#endif\n#define my_inflimit(lp, val)    ( my_infinite(lp, val) ? lp->infinite * my_sign(val) : (val) )\n#if 0\n  #define my_precision(val, eps) ((fabs((REAL) (val))) < (eps) ? 0 : (val))\n#else\n  #define my_precision(val, eps) restoreINT(val, eps)\n#endif\n#define my_reldiff(x, y)       (((x) - (y)) / (1.0 + fabs((REAL) (y))))\n#define my_boundstr(x)         (fabs(x) < lp->infinite ? sprintf(\"%g\",x) : ((x) < 0 ? \"-Inf\" : \"Inf\") )\n#ifndef my_boolstr\n  #define my_boolstr(x)          (!(x) ? \"FALSE\" : \"TRUE\")\n#endif\n#define my_basisstr(isbasic)     ((isbasic) ? \"BASIC\" : \"NON-BASIC\")\n#define my_simplexstr(isdual)    ((isdual) ? \"DUAL\" : \"PRIMAL\")\n#define my_plural_std(count)     (count == 1 ? \"\" : \"s\")\n#define my_plural_y(count)       (count == 1 ? \"y\" : \"ies\")\n#define my_lowbound(x)           ((FULLYBOUNDEDSIMPLEX) ? (x) : 0)\n\n\n/* Bound macros usable for both the standard and fully bounded simplex       */\n/* ------------------------------------------------------------------------- */\n/*\n#define my_lowbo(lp, varnr)      ( lp->isfullybounded ? lp->lowbo[varnr] : 0.0 )\n#define my_upbo(lp, varnr)       ( lp->isfullybounded ? lp->upbo[varnr]  : lp->lowbo[varnr] + lp->upbo[varnr] )\n#define my_rangebo(lp, varnr)    ( lp->isfullybounded ? lp->upbo[varnr] - lp->lowbo[varnr] : lp->upbo[varnr] )\n*/\n#define my_lowbo(lp, varnr)      ( 0.0 )\n#define my_upbo(lp, varnr)       ( lp->lowbo[varnr] + lp->upbo[varnr] )\n#define my_rangebo(lp, varnr)    ( lp->upbo[varnr] )\n\n#define my_unbounded(lp, varnr)  ((lp->upbo[varnr] >= lp->infinite) && (lp->lowbo[varnr] <= -lp->infinite))\n#define my_bounded(lp, varnr)    ((lp->upbo[varnr] < lp->infinite) && (lp->lowbo[varnr] > -lp->infinite))\n\n/* Forward declarations                                                      */\n/* ------------------------------------------------------------------------- */\ntypedef struct _lprec     lprec;\ntypedef struct _INVrec    INVrec;\nunion  QSORTrec;\n\n#ifndef UNIONTYPE\n  #ifdef __cplusplus\n    #define UNIONTYPE\n  #else\n    #define UNIONTYPE union\n  #endif\n#endif\n\n/* B4 factorization optimization data */\ntypedef struct _B4rec\n{\n  int  *B4_var;  /* Position of basic columns in the B4 basis */\n  int  *var_B4;  /* Variable in the B4 basis */\n  int  *B4_row;  /* B4 position of the i'th row */\n  int  *row_B4;  /* Original position of the i'th row */\n  REAL *wcol;\n  int  *nzwcol;\n} B4rec;\n\n#define OBJ_STEPS   5\ntypedef struct _OBJmonrec {\n  lprec  *lp;\n  int    oldpivstrategy,\n         oldpivrule, pivrule, ruleswitches,\n         limitstall[2], limitruleswitches,\n         idxstep[OBJ_STEPS], countstep, startstep, currentstep,\n         Rcycle, Ccycle, Ncycle, Mcycle, Icount;\n  REAL   thisobj, prevobj,\n         objstep[OBJ_STEPS],\n         thisinfeas, previnfeas,\n         epsvalue;\n  char   spxfunc[10];\n  MYBOOL pivdynamic;\n  MYBOOL isdual;\n  MYBOOL active;\n} OBJmonrec;\n\ntypedef struct _edgerec\n{\n  REAL      *edgeVector;\n} edgerec;\n\ntypedef struct _pricerec\n{\n  REAL   theta;\n  REAL   pivot;\n  REAL   epspivot;\n  int    varno;\n  lprec  *lp;\n  MYBOOL isdual;\n} pricerec;\ntypedef struct _multirec\n{\n  lprec    *lp;\n  int      size;                  /* The maximum number of multiply priced rows/columns */\n  int      used;                  /* The current / active number of multiply priced rows/columns */\n  int      limit;                 /* The active/used count at which a full update is triggered */\n  pricerec *items;                /* Array of best multiply priced rows/columns */\n  int      *freeList;             /* The indeces of available positions in \"items\" */\n  UNIONTYPE QSORTrec *sortedList; /* List of pointers to \"pricerec\" items in sorted order */\n  REAL     *stepList;             /* Working array (values in sortedList order) */\n  REAL     *valueList;            /* Working array (values in sortedList order) */\n  int      *indexSet;             /* The final exported index list of pivot variables */\n  int      active;                /* Index of currently active multiply priced row/column */\n  int      retries;\n  REAL     step_base;\n  REAL     step_last;\n  REAL     obj_base;\n  REAL     obj_last;\n  REAL     epszero;\n  REAL     maxpivot;\n  REAL     maxbound;\n  MYBOOL   sorted;\n  MYBOOL   truncinf;\n  MYBOOL   objcheck;\n  MYBOOL   dirty;\n} multirec;\n\n#endif /* HEADER_lp_types */\n"
  },
  {
    "path": "utilities/lp_solve/lp_utils.c",
    "content": "#define CODE_lp_utils\n\n#include <string.h>\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_utils.h\"\n#include <time.h>\n#include <sys/timeb.h>\n#include \"lp_bit.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n\n/*\n    Miscellaneous utilities as implemented for lp_solve v5.0+\n   ----------------------------------------------------------------------------------\n    Author:        Kjell Eikland\n    Contact:       kjell.eikland@broadpark.no\n    License terms: GLPL.\n\n    Requires:      lp_utils.h, lp_lib.h\n\n    Release notes:\n    v1.0.0  1 January 2003      Memory allocation, sorting, searching, time and\n                                doubly linked list functions.\n    v1.1.0  15 May 2004         Added vector packing functionality\n    v1.2.0  10 January 2005     Added vector pushing/popping functionality\n                                Modified return values and fixed problem in\n                                linked list functions.\n\n   ----------------------------------------------------------------------------------\n*/\n\nSTATIC MYBOOL allocCHAR(lprec *lp, char **ptr, int size, MYBOOL clear)\n{\n  if(clear == TRUE)\n    *ptr = (char *) calloc(size, sizeof(**ptr));\n  else if(clear & AUTOMATIC) {\n    *ptr = (char *) realloc(*ptr, size * sizeof(**ptr));\n    if(clear & TRUE)\n      MEMCLEAR(*ptr, size);\n  }\n  else\n    *ptr = (char *) malloc(size * sizeof(**ptr));\n  if(((*ptr) == NULL) && (size > 0)) {\n    lp->report(lp, CRITICAL, \"alloc of %d 'char' failed\\n\", size);\n    lp->spx_status = NOMEMORY;\n    return( FALSE );\n  }\n  else\n    return( TRUE );\n}\nSTATIC MYBOOL allocMYBOOL(lprec *lp, MYBOOL **ptr, int size, MYBOOL clear)\n{\n  if(clear == TRUE)\n    *ptr = (MYBOOL *) calloc(size, sizeof(**ptr));\n  else if(clear & AUTOMATIC) {\n    *ptr = (MYBOOL *) realloc(*ptr, size * sizeof(**ptr));\n    if(clear & TRUE)\n      MEMCLEAR(*ptr, size);\n  }\n  else\n    *ptr = (MYBOOL *) malloc(size * sizeof(**ptr));\n  if(((*ptr) == NULL) && (size > 0)) {\n    lp->report(lp, CRITICAL, \"alloc of %d 'MYBOOL' failed\\n\", size);\n    lp->spx_status = NOMEMORY;\n    return( FALSE );\n  }\n  else\n    return( TRUE );\n}\nSTATIC MYBOOL allocINT(lprec *lp, int **ptr, int size, MYBOOL clear)\n{\n  if(clear == TRUE)\n    *ptr = (int *) calloc(size, sizeof(**ptr));\n  else if(clear & AUTOMATIC) {\n    *ptr = (int *) realloc(*ptr, size * sizeof(**ptr));\n    if(clear & TRUE)\n      MEMCLEAR(*ptr, size);\n  }\n  else\n    *ptr = (int *) malloc(size * sizeof(**ptr));\n  if(((*ptr) == NULL) && (size > 0)) {\n    lp->report(lp, CRITICAL, \"alloc of %d 'INT' failed\\n\", size);\n    lp->spx_status = NOMEMORY;\n    return( FALSE );\n  }\n  else\n    return( TRUE );\n}\nSTATIC MYBOOL allocREAL(lprec *lp, REAL **ptr, int size, MYBOOL clear)\n{\n  if(clear == TRUE)\n    *ptr = (REAL *) calloc(size, sizeof(**ptr));\n  else if(clear & AUTOMATIC) {\n    *ptr = (REAL *) realloc(*ptr, size * sizeof(**ptr));\n    if(clear & TRUE)\n      MEMCLEAR(*ptr, size);\n  }\n  else\n    *ptr = (REAL *) malloc(size * sizeof(**ptr));\n  if(((*ptr) == NULL) && (size > 0)) {\n    lp->report(lp, CRITICAL, \"alloc of %d 'REAL' failed\\n\", size);\n    lp->spx_status = NOMEMORY;\n    return( FALSE );\n  }\n  else\n    return( TRUE );\n}\nSTATIC MYBOOL allocLREAL(lprec *lp, LREAL **ptr, int size, MYBOOL clear)\n{\n  if(clear == TRUE)\n    *ptr = (LREAL *) calloc(size, sizeof(**ptr));\n  else if(clear & AUTOMATIC) {\n    *ptr = (LREAL *) realloc(*ptr, size * sizeof(**ptr));\n    if(clear & TRUE)\n      MEMCLEAR(*ptr, size);\n  }\n  else\n    *ptr = (LREAL *) malloc(size * sizeof(**ptr));\n  if(((*ptr) == NULL) && (size > 0)) {\n    lp->report(lp, CRITICAL, \"alloc of %d 'LREAL' failed\\n\", size);\n    lp->spx_status = NOMEMORY;\n    return( FALSE );\n  }\n  else\n    return( TRUE );\n}\n\nSTATIC MYBOOL allocFREE(lprec *lp, void **ptr)\n{\n  MYBOOL status = TRUE;\n\n  if(*ptr != NULL) {\n    free(*ptr);\n    *ptr = NULL;\n  }\n  else {\n    status = FALSE;\n    lp->report(lp, CRITICAL, \"free() failed on line %d of file %s\\n\",\n                             __LINE__, __FILE__);\n  }\n  return(status);\n}\n\n/* Do hoops to provide debugging info with FORTIFY */\n#undef CODE_lp_utils\n#include \"lp_utils.h\"\n/* alloc-routines should always be before this line! */\n\nint comp_bits(MYBOOL *bitarray1, MYBOOL *bitarray2, int items)\n{\n  int            i, items4, left = 0, right = 0;\n  MYBOOL         comp1;\n  unsigned long comp4;\n\n  /* Convert items count to 8-bit representation, if necessary */\n  if(items > 0) {\n    i = items % 8;\n    items /= 8;\n    if(i)\n      items++;\n  }\n  else\n    items = -items;\n\n  /* Do the wide unsigned integer part for speed */\n  items4 = items / sizeof(unsigned long);\n  i = 0;\n#if defined(__clang__)\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wcast-align\"\n#endif\n  while(i < items4) {\n    comp4 = ((unsigned long *) bitarray1)[i] &  ~((unsigned long *) bitarray2)[i];\n    if(comp4)\n      left++;\n    comp4 = ((unsigned long *) bitarray2)[i] &  ~((unsigned long *) bitarray1)[i];\n    if(comp4)\n      right++;\n    i++;\n  }\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#endif\n\n  /* Do the trailing slow narrow unsigned integer part */\n  i *= sizeof(unsigned long);\n  i++;\n  while(i < items) {\n    comp1 = bitarray1[i] & ~bitarray2[i];\n    if(comp1)\n      left++;\n    comp1 = bitarray2[i] & ~bitarray1[i];\n    if(comp1)\n      right++;\n    i++;\n  }\n\n  /* Determine set comparison outcomes */\n  if((left > 0) && (right == 0))         /* array1 is a superset of array2 */\n    i = 1;\n  else if((left == 0) && (right > 0))   /* array2 is a superset of array1 */\n    i = -1;\n  else if((left == 0) && (right == 0))  /* array1 and array2 are identical */\n    i = 0;\n  else\n    i = -2;                              /* indicate all other outcomes */\n  return( i );\n}\n\n\nSTATIC workarraysrec *mempool_create(lprec *lp)\n{\n  workarraysrec *temp;\n  temp = (workarraysrec *) calloc(1, sizeof(workarraysrec));\n  temp->lp = lp;\n  return( temp );\n}\nSTATIC char *mempool_obtainVector(workarraysrec *mempool, int count, int unitsize)\n{\n  char   *newmem = NULL;\n  MYBOOL *bnewmem = NULL;\n  int    *inewmem = NULL, size, i, ib, ie, memMargin = 0;\n  REAL   *rnewmem = NULL;\n\n  /* First find the iso-sized window (binary search) */\n  size = count*unitsize;\n  memMargin += size;\n  ib = 0;\n  ie = mempool->count-1;\n  while(ie >= ib) {\n    i = (ib+ie) / 2;\n    if(abs(mempool->vectorsize[i]) > memMargin)\n      ie = i-1;\n    else if(abs(mempool->vectorsize[i]) < size)\n      ib = i+1;\n    else {\n      /* Find the beginning of the exact-sized array group */\n      do {\n        ib = i;\n        i--;\n      } while((i >= 0) && (abs(mempool->vectorsize[i]) >= size));\n      break;\n    }\n  }\n\n  /* Check if we have a preallocated unused array of sufficient size */\n  ie = mempool->count-1;\n  for(i = ib; i <= ie; i++)\n    if(mempool->vectorsize[i] < 0)\n      break;\n\n  /* Obtain and activate existing, unused vector if we are permitted */\n  if(i <= ie) {\n#ifdef Paranoia\n    if((mempool->vectorsize[i] > 0) || (abs(mempool->vectorsize[i]) < size)) {\n      lprec *lp = mempool->lp;\n      lp->report(lp, SEVERE, \"mempool_obtainVector: Invalid %s existing vector selected\\n\",\n                             (ie < 0 ? \"too small\" : \"occupied\"));\n      lp->spx_status = NOMEMORY;\n      lp->bb_break = TRUE;\n      return( newmem );\n    }\n#endif\n    newmem = mempool->vectorarray[i];\n    mempool->vectorsize[i] *= -1;\n  }\n\n  /* Otherwise allocate a new vector */\n  else if(unitsize == sizeof(MYBOOL)) {\n    allocMYBOOL(mempool->lp, &bnewmem, count, TRUE);\n    newmem = (char *) bnewmem;\n  }\n  else if(unitsize == sizeof(int)) {\n    allocINT(mempool->lp, &inewmem, count, TRUE);\n    newmem = (char *) inewmem;\n  }\n  else if(unitsize == sizeof(REAL)) {\n    allocREAL(mempool->lp, &rnewmem, count, TRUE);\n    newmem = (char *) rnewmem;\n  }\n\n  /* Insert into master array if necessary (maintain sort by ascending size) */\n  if((i > ie) && (newmem != NULL)) {\n    mempool->count++;\n    if(mempool->count >= mempool->size) {\n      mempool->size += 10;\n      mempool->vectorarray = (char **) realloc(mempool->vectorarray,\n                                     sizeof(*(mempool->vectorarray))*mempool->size);\n      mempool->vectorsize  = (int *) realloc(mempool->vectorsize,\n                                     sizeof(*(mempool->vectorsize))*mempool->size);\n    }\n    ie++;\n    i = ie + 1;\n    if(i < mempool->count) {\n      MEMMOVE(mempool->vectorarray+i, mempool->vectorarray+ie, 1);\n      MEMMOVE(mempool->vectorsize+i,  mempool->vectorsize+ie,  1);\n    }\n    mempool->vectorarray[ie] = newmem;\n    mempool->vectorsize[ie]  = size;\n  }\n\n  return( newmem );\n}\nSTATIC MYBOOL mempool_releaseVector(workarraysrec *mempool, const char *memvector, MYBOOL forcefree)\n{\n  int i;\n\n#if 0\n  forcefree = TRUE;\n#endif\n\n  for(i = mempool->count-1; i >= 0; i--)\n    if(mempool->vectorarray[i] == memvector)\n      break;\n\n  if((i < 0) || (mempool->vectorsize[i] < 0))\n    return( FALSE );\n\n  if(forcefree) {\n    FREE(mempool->vectorarray[i]);\n    mempool->count--;\n    for(; i < mempool->count; i++)\n      mempool->vectorarray[i] = mempool->vectorarray[i+1];\n  }\n  else\n    mempool->vectorsize[i] *= -1;\n\n  return( TRUE );\n}\nSTATIC MYBOOL mempool_free(workarraysrec **mempool)\n{\n  int i = (*mempool)->count;\n\n  while(i > 0) {\n    i--;\n    if((*mempool)->vectorsize[i] < 0)  /* Handle unused vectors */\n      (*mempool)->vectorsize[i] *= -1;\n    mempool_releaseVector(*mempool, (*mempool)->vectorarray[i], TRUE);\n  }\n  FREE((*mempool)->vectorarray);\n  FREE((*mempool)->vectorsize);\n  FREE(*mempool);\n  return( TRUE );\n}\n\nREAL *cloneREAL(lprec *lp, REAL *origlist, int size)\n{\n  REAL *newlist;\n\n  size += 1;\n  if(allocREAL(lp, &newlist, size, FALSE))\n    MEMCOPY(newlist, origlist, size);\n  return(newlist);\n}\nMYBOOL *cloneMYBOOL(lprec *lp, MYBOOL *origlist, int size)\n{\n  MYBOOL *newlist;\n\n  size += 1;\n  if(allocMYBOOL(lp, &newlist, size, FALSE))\n    MEMCOPY(newlist, origlist, size);\n  return(newlist);\n}\nint *cloneINT(lprec *lp, int *origlist, int size)\n{\n  int *newlist;\n\n  size += 1;\n  if(allocINT(lp, &newlist, size, FALSE))\n    MEMCOPY(newlist, origlist, size);\n  return(newlist);\n}\n\nSTATIC void roundVector(LREAL *myvector, int endpos, LREAL roundzero)\n{\n  if(roundzero > 0)\n    for(; endpos >= 0; myvector++, endpos--)\n      if(fabs(*myvector) < roundzero)\n        *myvector = 0;\n}\n\nSTATIC REAL normalizeVector(REAL *myvector, int endpos)\n/* Scale the ingoing vector so that its norm is unit, and return the original length */\n{\n  int  i;\n  REAL SSQ;\n\n  /* Cumulate squares */\n  SSQ = 0;\n  for(i = 0; i <= endpos; myvector++, i++)\n    SSQ += (*myvector) * (*myvector);\n\n  /* Normalize */\n  SSQ = sqrt(SSQ);\n  if(SSQ > 0)\n    for(myvector--; i > 0; myvector--, i--)\n      (*myvector) /= SSQ;\n\n  return( SSQ );\n}\n\n/* ---------------------------------------------------------------------------------- */\n/* Other general utilities                                                            */\n/* ---------------------------------------------------------------------------------- */\n\nSTATIC void swapINT(int *item1, int *item2)\n{\n  int hold = *item1;\n  *item1 = *item2;\n  *item2 = hold;\n}\n\nSTATIC void swapREAL(REAL *item1, REAL *item2)\n{\n  REAL hold = *item1;\n  *item1 = *item2;\n  *item2 = hold;\n}\n\nSTATIC void swapPTR(void **item1, void **item2)\n{\n  void *hold;\n  hold = *item1;\n  *item1 = *item2;\n  *item2 = hold;\n}\n\n\nSTATIC REAL restoreINT(REAL valREAL, REAL epsilon)\n{\n  REAL valINT, fracREAL, fracABS;\n\n  fracREAL = modf(valREAL, &valINT);\n  fracABS = fabs(fracREAL);\n  if(fracABS < epsilon)\n    return(valINT);\n  else if(fracABS > 1-epsilon) {\n    if(fracREAL < 0)\n      return(valINT-1);\n    else\n      return(valINT+1);\n  }\n  return(valREAL);\n}\n\nSTATIC REAL roundToPrecision(REAL value, REAL precision)\n{\n#if 1\n  REAL  vmod;\n  int   vexp2, vexp10;\n  LLONG sign;\n\n  if(precision == 0)\n    return(value);\n\n  sign  = my_sign(value);\n  value = fabs(value);\n\n  /* Round to integer if possible */\n  if(value < precision)\n    return( 0 );\n  else if(value == floor(value))\n    return( value*sign );\n  else if((value < (REAL) MAXINT64) &&\n     (modf((REAL) (value+precision), &vmod) < precision)) {\n    /* sign *= (LLONG) (value+precision); */\n    sign *= (LLONG) (value+0.5);\n    return( (REAL) sign );\n  }\n\n  /* Optionally round with base 2 representation for additional precision */\n#define roundPrecisionBase2\n#ifdef roundPrecisionBase2\n  value = frexp(value, &vexp2);\n#else\n  vexp2 = 0;\n#endif\n\n  /* Convert to desired precision */\n  vexp10 = (int) log10(value);\n  precision *= pow(10.0, vexp10);\n  modf(value/precision+0.5, &value);\n  value *= sign*precision;\n\n  /* Restore base 10 representation if base 2 was active */\n  if(vexp2 != 0)\n    value = ldexp(value, vexp2);\n#endif\n\n  return( value );\n}\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Searching function specialized for lp_solve                                        */\n/* ---------------------------------------------------------------------------------- */\nSTATIC int searchFor(int target, int *attributes, int size, int offset, MYBOOL absolute)\n{\n  int beginPos, endPos;\n  int newPos, match;\n\n /* Set starting and ending index offsets */\n  beginPos = offset;\n  endPos = beginPos + size - 1;\n\n /* Do binary search logic based on a sorted attribute vector */\n  newPos = (beginPos + endPos) / 2;\n  match = attributes[newPos];\n  if(absolute)\n    match = abs(match);\n  while(endPos - beginPos > LINEARSEARCH) {\n    if(match < target) {\n      beginPos = newPos + 1;\n      newPos = (beginPos + endPos) / 2;\n      match = attributes[newPos];\n      if(absolute)\n        match = abs(match);\n    }\n    else if(match > target) {\n      endPos = newPos - 1;\n      newPos = (beginPos + endPos) / 2;\n      match = attributes[newPos];\n      if(absolute)\n        match = abs(match);\n    }\n    else {\n      beginPos = newPos;\n      endPos = newPos;\n    }\n  }\n\n /* Do linear (unsorted) search logic */\n  if(endPos - beginPos <= LINEARSEARCH) {\n    match = attributes[beginPos];\n    if(absolute)\n      match = abs(match);\n      while((beginPos < endPos) && (match != target)) {\n        beginPos++;\n        match = attributes[beginPos];\n        if(absolute)\n          match = abs(match);\n      }\n      if(match == target)\n        endPos = beginPos;\n  }\n\n /* Return the index if a match was found, or signal failure with a -1 */\n  if((beginPos == endPos) && (match == target))\n    return(beginPos);\n  else\n    return(-1);\n\n}\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Other supporting math routines                                                     */\n/* ---------------------------------------------------------------------------------- */\n\nSTATIC MYBOOL isINT(lprec *lp, REAL value)\n{\n#if 0\n  return( (MYBOOL) (modf(fabs(value)+lp->epsint, &value) < 2*lp->epsint) );\n#elif 1\n  value = fabs(value)+lp->epsint;\n  return( (MYBOOL) (my_reldiff(value, floor(value)) < 2*lp->epsint) );\n#elif 0\n  REAL hold;\n  value = fabs(value);\n  hold = pow(10, MIN(-2, log10(value+1)+log10(lp->epsint)));\n  return( (MYBOOL) (modf(value+lp->epsint, &value) < 2*hold) );\n#elif 0\n  value -= (REAL)floor(value);\n  return( (MYBOOL) ((value < lp->epsint) || (value > (1 - lp->epsint)) );\n#else\n  value += lp->epsint;\n  return( (MYBOOL) (fabs(value-floor(value)) < 2*lp->epsint) );\n#endif\n}\n\nSTATIC MYBOOL isOrigFixed(lprec *lp, int varno)\n{\n  return( (MYBOOL) (lp->orig_upbo[varno] - lp->orig_lowbo[varno] <= lp->epsmachine) );\n}\n\nSTATIC void chsign_bounds(REAL *lobound, REAL *upbound)\n{\n  REAL temp;\n  temp = *upbound;\n  if(fabs(*lobound) > 0)\n    *upbound = -(*lobound);\n  else\n    *upbound = 0;\n  if(fabs(temp) > 0)\n    *lobound = -temp;\n  else\n    *lobound = 0;\n}\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Define randomization routine                                                       */\n/* ---------------------------------------------------------------------------------- */\nSTATIC REAL rand_uniform(lprec *lp, REAL range)\n{\n  (void)lp;\n  static MYBOOL randomized = FALSE; /* static ok here for reentrancy/multithreading */\n  (void)lp;\n\n  if(!randomized) {\n    randomized = TRUE;\n    srand((unsigned) time( NULL ));\n  }\n  range *= (REAL) rand() / (REAL) RAND_MAX;\n  return( range );\n}\n\n\n/* ---------------------------------------------------------------------------------- */\n/* Define routines for doubly linked lists of integers                                */\n/* ---------------------------------------------------------------------------------- */\n\nSTATIC int createLink(int size, LLrec **linkmap, MYBOOL *usedpos)\n{\n  int i, j;\n  MYBOOL reverse;\n\n  *linkmap = (LLrec *) calloc(1, sizeof(**linkmap));\n  if(*linkmap == NULL)\n    return( -1 );\n\n  reverse = (MYBOOL) (size < 0);\n  if(reverse)\n    size = -size;\n  (*linkmap)->map = (int *) calloc(2*(size + 1), sizeof(int));\n  if((*linkmap)->map == NULL)\n    return( -1 );\n\n  (*linkmap)->size = size;\n  j = 0;\n  if(usedpos == NULL)\n    (*linkmap)->map[0] = 0;\n  else {\n    for(i = 1; i <= size; i++)\n      if(!usedpos[i] ^ reverse) {\n        /* Set the forward link */\n        (*linkmap)->map[j] = i;\n        /* Set the backward link */\n        (*linkmap)->map[size+i] = j;\n        j = i;\n        if((*linkmap)->count == 0)\n          (*linkmap)->firstitem = i;\n        (*linkmap)->lastitem = i;\n        (*linkmap)->count++;\n      }\n  }\n  (*linkmap)->map[2*size+1] = j;\n\n  return( (*linkmap)->count );\n}\n\nSTATIC MYBOOL freeLink(LLrec **linkmap)\n{\n  MYBOOL status = TRUE;\n\n  if((linkmap == NULL) || (*linkmap == NULL))\n    status = FALSE;\n  else {\n    if((*linkmap)->map != NULL)\n      free((*linkmap)->map);\n    free(*linkmap);\n    *linkmap = NULL;\n  }\n  return( status );\n}\n\nSTATIC int sizeLink(LLrec *linkmap)\n{\n  return(linkmap->size);\n}\n\nSTATIC MYBOOL isActiveLink(LLrec *linkmap, int itemnr)\n{\n  if((linkmap->map[itemnr] != 0) ||\n     (linkmap->map[linkmap->size+itemnr] != 0) ||\n     (linkmap->map[0] == itemnr))\n    return( TRUE );\n  else\n    return( FALSE );\n}\n\nSTATIC int countActiveLink(LLrec *linkmap)\n{\n  return(linkmap->count);\n}\n\nSTATIC int countInactiveLink(LLrec *linkmap)\n{\n  return(linkmap->size-linkmap->count);\n}\n\nSTATIC int firstActiveLink(LLrec *linkmap)\n{\n  return(linkmap->map[0]);\n}\n\nSTATIC int lastActiveLink(LLrec *linkmap)\n{\n  return(linkmap->map[2*linkmap->size+1]);\n}\n\nSTATIC MYBOOL appendLink(LLrec *linkmap, int newitem)\n{\n  int k, size;\n  size = linkmap->size;\n\n  if(linkmap->map[newitem] != 0)\n    return( FALSE );\n\n  /* Link forward */\n  k = linkmap->map[2*size+1];\n  linkmap->map[k] = newitem;\n\n  /* Link backward */\n  linkmap->map[size+newitem] = k;\n  linkmap->map[2*size+1] = newitem;\n\n  /* Update count and return */\n  if(linkmap->count == 0)\n    linkmap->firstitem = newitem;\n  linkmap->lastitem = newitem;\n  linkmap->count++;\n\n  return( TRUE );\n}\n\nSTATIC MYBOOL insertLink(LLrec *linkmap, int afteritem, int newitem)\n{\n  int k, size;\n\n  size = linkmap->size;\n\n  if(linkmap->map[newitem] != 0)\n    return( FALSE );\n\n  if(afteritem == linkmap->map[2*size+1])\n    appendLink(linkmap, newitem);\n  else {\n    /* Link forward */\n    k = linkmap->map[afteritem];\n    linkmap->map[afteritem] = newitem;\n    linkmap->map[newitem] = k;\n\n    /* Link backward */\n    linkmap->map[size+k] = newitem;\n    linkmap->map[size+newitem] = afteritem;\n\n    /* Update count */\n    SETMIN(linkmap->firstitem, newitem);\n    SETMAX(linkmap->lastitem, newitem);\n    linkmap->count++;\n  }\n\n  return( TRUE );\n}\n\nSTATIC MYBOOL setLink(LLrec *linkmap, int newitem)\n{\n  if(isActiveLink(linkmap, newitem))\n    return( FALSE );\n  else\n    return( insertLink(linkmap, prevActiveLink(linkmap, newitem), newitem) );\n}\n\nSTATIC MYBOOL fillLink(LLrec *linkmap)\n{\n  int k, size;\n  size = linkmap->size;\n\n  k = firstActiveLink(linkmap);\n  if(k != 0)\n    return( FALSE );\n  for(k = 1; k <= size; k++)\n    appendLink(linkmap, k);\n  return( TRUE );\n}\n\nSTATIC int nextActiveLink(LLrec *linkmap, int backitemnr)\n{\n  if((backitemnr < 0) || (backitemnr > linkmap->size))\n    return( -1 );\n  else {\n    if(backitemnr < linkmap->lastitem)\n    while((backitemnr > linkmap->firstitem) && (linkmap->map[backitemnr] == 0))\n      backitemnr--;\n    return(linkmap->map[backitemnr]);\n  }\n}\n\nSTATIC int prevActiveLink(LLrec *linkmap, int forwitemnr)\n{\n  if((forwitemnr <= 0) || (forwitemnr > linkmap->size+1))\n    return( -1 );\n  else {\n    if(forwitemnr > linkmap->lastitem)\n      return( linkmap->lastitem);\n    if(forwitemnr > linkmap->firstitem) {\n      forwitemnr += linkmap->size;\n      while((forwitemnr < linkmap->size + linkmap->lastitem) && (linkmap->map[forwitemnr] == 0))\n        forwitemnr++;\n    }\n    else\n      forwitemnr += linkmap->size;\n    return(linkmap->map[forwitemnr]);\n  }\n}\n\nSTATIC int firstInactiveLink(LLrec *linkmap)\n{\n  int i, n;\n\n  if(countInactiveLink(linkmap) == 0)\n    return( 0 );\n  n = 1;\n  i = firstActiveLink(linkmap);\n  while(i == n) {\n    n++;\n    i = nextActiveLink(linkmap, i);\n  }\n  return( n );\n}\n\nSTATIC int lastInactiveLink(LLrec *linkmap)\n{\n  int i, n;\n\n  if(countInactiveLink(linkmap) == 0)\n    return( 0 );\n  n = linkmap->size;\n  i = lastActiveLink(linkmap);\n  while(i == n) {\n    n--;\n    i = prevActiveLink(linkmap, i);\n  }\n  return( n );\n}\n\nSTATIC int nextInactiveLink(LLrec *linkmap, int backitemnr)\n{\n  do {\n    backitemnr++;\n  } while((backitemnr <= linkmap->size) && isActiveLink(linkmap, backitemnr));\n  if(backitemnr <= linkmap->size)\n    return( backitemnr );\n  else\n    return( 0 );\n}\n\nSTATIC int prevInactiveLink(LLrec *linkmap, int forwitemnr)\n{\n  (void)linkmap;\n  (void)forwitemnr;\n  return( 0 );\n}\n\nSTATIC int removeLink(LLrec *linkmap, int itemnr)\n{\n  int size, prevnr, nextnr = -1;\n\n  size = linkmap->size;\n  if((itemnr <= 0) || (itemnr > size))\n    return( nextnr );\n#ifdef Paranoia\n  if(!isActiveLink(linkmap, itemnr))\n    return( nextnr );\n#endif\n\n  /* Get link data at the specified position */\n  nextnr = linkmap->map[itemnr];\n  prevnr = linkmap->map[size+itemnr];\n  if(itemnr == linkmap->firstitem)\n    linkmap->firstitem = nextnr;\n  if(itemnr == linkmap->lastitem)\n    linkmap->lastitem = prevnr;\n\n  /* Update forward link */\n  linkmap->map[prevnr] = linkmap->map[itemnr];\n  linkmap->map[itemnr] = 0;\n\n  /* Update backward link */\n  if(nextnr == 0)\n    linkmap->map[2*size+1] = prevnr;\n  else\n    linkmap->map[size+nextnr] = linkmap->map[size+itemnr];\n  linkmap->map[size+itemnr] = 0;\n\n  /* Decrement the count */\n  linkmap->count--;\n\n  /* Return the next active item */\n  return( nextnr );\n}\n\nSTATIC LLrec *cloneLink(LLrec *sourcemap, int newsize, MYBOOL freesource)\n{\n  LLrec *testmap = NULL;\n\n  if((newsize == sourcemap->size) || (newsize <= 0)) {\n    createLink(sourcemap->size, &testmap, NULL);\n    MEMCOPY(testmap->map, sourcemap->map, 2*(sourcemap->size+1));\n    testmap->firstitem = sourcemap->firstitem;\n    testmap->lastitem = sourcemap->lastitem;\n    testmap->size = sourcemap->size;\n    testmap->count = sourcemap->count;\n  }\n  else {\n    int j;\n\n    createLink(newsize, &testmap, NULL);\n    for(j = firstActiveLink(sourcemap); (j != 0) && (j <= newsize); j = nextActiveLink(sourcemap, j))\n      appendLink(testmap, j);\n  }\n  if(freesource)\n    freeLink(&sourcemap);\n\n  return(testmap);\n}\n\nSTATIC int compareLink(LLrec *linkmap1, LLrec *linkmap2)\n{\n  int test;\n\n  test = memcmp(&linkmap1->size, &linkmap2->size, sizeof(int));\n  if(test == 0)\n    test = memcmp(&linkmap1->count, &linkmap2->count, sizeof(int));\n    if(test == 0)\n      test = memcmp(linkmap1->map, linkmap2->map, sizeof(int)*(2*linkmap1->size+1));\n\n  return( test );\n}\n\nSTATIC MYBOOL verifyLink(LLrec *linkmap, int itemnr, MYBOOL doappend)\n{\n  LLrec *testmap;\n\n  testmap = cloneLink(linkmap, -1, FALSE);\n  if(doappend) {\n    appendLink(testmap, itemnr);\n    removeLink(testmap, itemnr);\n  }\n  else {\n    int previtem = prevActiveLink(testmap, itemnr);\n    removeLink(testmap, itemnr);\n    insertLink(testmap, previtem, itemnr);\n  }\n  itemnr = compareLink(linkmap, testmap);\n  freeLink(&testmap);\n  return((MYBOOL) (itemnr == 0));\n}\n\n/* Packed vector routines */\nSTATIC PVrec *createPackedVector(int size, REAL *values, int *workvector)\n{\n  int      i, k;\n  REGISTER REAL  ref;\n  PVrec    *newPV = NULL;\n  MYBOOL   localWV = (MYBOOL) (workvector == NULL);\n\n  if(localWV)\n    workvector = (int *) malloc((size+1)*sizeof(*workvector));\n\n  /* Tally equal-valued vector entries - also check if it is worth compressing */\n  k = 0;\n  workvector[k] = 1;\n  ref = values[1];\n  for(i = 2; i <= size; i++) {\n    if(fabs(ref - values[i]) > DEF_EPSMACHINE) {\n      k++;\n      workvector[k] = i;\n      ref = values[i];\n    }\n  }\n  if(k > size / 2) {\n    if(localWV)\n      FREE(workvector);\n    return( newPV );\n  }\n\n  /* Create the packing object, adjust the position vector and allocate value vector */\n  newPV = (PVrec *) malloc(sizeof(*newPV));\n  k++;                            /* Adjust from index to to count */\n  newPV->count = k;\n  if(localWV)\n    newPV->startpos = (int *) realloc(workvector, (k + 1)*sizeof(*(newPV->startpos)));\n  else {\n    newPV->startpos = (int *) malloc((k + 1)*sizeof(*(newPV->startpos)));\n    MEMCOPY(newPV->startpos, workvector, k);\n  }\n  newPV->startpos[k] = size + 1;  /* Store terminal index + 1 for searching purposes */\n  newPV->value = (REAL *) malloc(k*sizeof(*(newPV->value)));\n\n  /* Fill the values vector before returning */\n  for(i = 0; i < k; i++)\n    newPV->value[i] = values[newPV->startpos[i]];\n\n  return( newPV );\n}\n\nSTATIC MYBOOL unpackPackedVector(PVrec *PV, REAL **target)\n{\n  int      i, ii, k;\n  REGISTER REAL ref;\n\n  /* Test for validity of the target and create it if necessary */\n  if(target == NULL)\n    return( FALSE );\n  if(*target == NULL)\n    allocREAL(NULL, target, PV->startpos[PV->count], FALSE);\n\n  /* Expand the packed vector into the target */\n  i = PV->startpos[0];\n  for(k = 0; k < PV->count; k++) {\n    ii = PV->startpos[k+1];\n    ref = PV->value[k];\n    while (i < ii) {\n      (*target)[i] = ref;\n      i++;\n    }\n  }\n  return( TRUE );\n}\n\nSTATIC REAL getvaluePackedVector(PVrec *PV, int index)\n{\n  index = searchFor(index, PV->startpos, PV->count, 0, FALSE);\n  index = abs(index)-1;\n  if(index >= 0)\n    return( PV->value[index] );\n  else\n    return( 0 );\n}\n\nSTATIC MYBOOL freePackedVector(PVrec **PV)\n{\n  if((PV == NULL) || (*PV == NULL))\n    return( FALSE );\n\n  FREE((*PV)->value);\n  FREE((*PV)->startpos);\n  FREE(*PV);\n  return( TRUE );\n}\n\nSTATIC void pushPackedVector(PVrec *PV, PVrec *parent)\n{\n  PV->parent = parent;\n}\n\nSTATIC PVrec *popPackedVector(PVrec *PV)\n{\n  PVrec *parent = PV->parent;\n  freePackedVector(&PV);\n  return( parent );\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_utils.h",
    "content": "#ifndef HEADER_lp_utils\n#define HEADER_lp_utils\n\n#ifdef FORTIFY\n\n#include \"lp_fortify.h\"\n\n#define allocCHAR allocCHAR_FORTIFY\n#define allocMYBOOL allocMYBOOL_FORTIFY\n#define allocINT allocINT_FORTIFY\n#define allocREAL allocREAL_FORTIFY\n#define allocLREAL allocLREAL_FORTIFY\n\n#endif\n\n#include \"lp_types.h\"\n\n/* Temporary data storage arrays */\ntypedef struct _workarraysrec\n{\n  lprec     *lp;\n  int       size;\n  int       count;\n  char      **vectorarray;\n  int       *vectorsize;\n} workarraysrec;\n\ntypedef struct _LLrec\n{\n  int       size;               /* The allocated list size */\n  int       count;              /* The current entry count */\n  int       firstitem;\n  int       lastitem;\n  int       *map;               /* The list of forward and backward-mapped entries */\n} LLrec;\n\ntypedef struct _PVrec\n{\n  int       count;              /* The allocated list item count */\n  int       *startpos;          /* Starting index of the current value */\n  REAL      *value;             /* The list of forward and backward-mapped entries */\n  struct   _PVrec *parent;     /* The parent record in a pushed chain */\n} PVrec;\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Put function headers here */\nSTATIC MYBOOL allocCHAR(lprec *lp, char **ptr, int size, MYBOOL clear);\nSTATIC MYBOOL allocMYBOOL(lprec *lp, MYBOOL **ptr, int size, MYBOOL clear);\nSTATIC MYBOOL allocINT(lprec *lp, int **ptr, int size, MYBOOL clear);\nSTATIC MYBOOL allocREAL(lprec *lp, REAL **ptr, int size, MYBOOL clear);\nSTATIC MYBOOL allocLREAL(lprec *lp, LREAL **ptr, int size, MYBOOL clear);\nSTATIC MYBOOL allocFREE(lprec *lp, void **ptr);\nREAL *cloneREAL(lprec *lp, REAL *origlist, int size);\nMYBOOL *cloneMYBOOL(lprec *lp, MYBOOL *origlist, int size);\nint *cloneINT(lprec *lp, int *origlist, int size);\n\nint comp_bits(MYBOOL *bitarray1, MYBOOL *bitarray2, int items);\n\nSTATIC workarraysrec *mempool_create(lprec *lp);\nSTATIC char *mempool_obtainVector(workarraysrec *mempool, int count, int unitsize);\nSTATIC MYBOOL mempool_releaseVector(workarraysrec *mempool, const char *memvector, MYBOOL forcefree);\nSTATIC MYBOOL mempool_free(workarraysrec **mempool);\n\nSTATIC void roundVector(LREAL *myvector, int endpos, LREAL roundzero);\nSTATIC REAL normalizeVector(REAL *myvector, int endpos);\n\nSTATIC void swapINT(int *item1, int *item2);\nSTATIC void swapREAL(REAL *item1, REAL *item2);\nSTATIC void swapPTR(void **item1, void **item2);\nSTATIC REAL restoreINT(REAL valREAL, REAL epsilon);\nSTATIC REAL roundToPrecision(REAL value, REAL precision);\n\nSTATIC int searchFor(int target, int *attributes, int size, int offset, MYBOOL absolute);\n\nSTATIC MYBOOL isINT(lprec *lp, REAL value);\nSTATIC MYBOOL isOrigFixed(lprec *lp, int varno);\nSTATIC void chsign_bounds(REAL *lobound, REAL *upbound);\nSTATIC REAL rand_uniform(lprec *lp, REAL range);\n\n/* Doubly linked list routines */\nSTATIC int createLink(int size, LLrec **linkmap, MYBOOL *usedpos);\nSTATIC MYBOOL freeLink(LLrec **linkmap);\nSTATIC int sizeLink(LLrec *linkmap);\nSTATIC MYBOOL isActiveLink(LLrec *linkmap, int itemnr);\nSTATIC int countActiveLink(LLrec *linkmap);\nSTATIC int countInactiveLink(LLrec *linkmap);\nSTATIC int firstActiveLink(LLrec *linkmap);\nSTATIC int lastActiveLink(LLrec *linkmap);\nSTATIC MYBOOL appendLink(LLrec *linkmap, int newitem);\nSTATIC MYBOOL insertLink(LLrec *linkmap, int afteritem, int newitem);\nSTATIC MYBOOL setLink(LLrec *linkmap, int newitem);\nSTATIC MYBOOL fillLink(LLrec *linkmap);\nSTATIC int nextActiveLink(LLrec *linkmap, int backitemnr);\nSTATIC int prevActiveLink(LLrec *linkmap, int forwitemnr);\nSTATIC int firstInactiveLink(LLrec *linkmap);\nSTATIC int lastInactiveLink(LLrec *linkmap);\nSTATIC int nextInactiveLink(LLrec *linkmap, int backitemnr);\nSTATIC int prevInactiveLink(LLrec *linkmap, int forwitemnr);\nSTATIC int removeLink(LLrec *linkmap, int itemnr);\nSTATIC LLrec *cloneLink(LLrec *sourcemap, int newsize, MYBOOL freesource);\nSTATIC int compareLink(LLrec *linkmap1, LLrec *linkmap2);\nSTATIC MYBOOL verifyLink(LLrec *linkmap, int itemnr, MYBOOL doappend);\n\n/* Packed vector routines */\nSTATIC PVrec  *createPackedVector(int size, REAL *values, int *workvector);\nSTATIC void   pushPackedVector(PVrec *PV, PVrec *parent);\nSTATIC MYBOOL unpackPackedVector(PVrec *PV, REAL **target);\nSTATIC REAL   getvaluePackedVector(PVrec *PV, int index);\nSTATIC PVrec  *popPackedVector(PVrec *PV);\nSTATIC MYBOOL freePackedVector(PVrec **PV);\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_utils */\n\n#ifdef FORTIFY\n\n#if defined CODE_lp_utils && !defined CODE_lp_utils_\nint _Fortify_ret;\n#else\nextern int _Fortify_ret;\n#endif\n\n#ifdef CODE_lp_utils\n#define CODE_lp_utils_\n#else\n# undef allocCHAR\n# undef allocMYBOOL\n# undef allocINT\n# undef allocREAL\n# undef allocLREAL\n# define allocCHAR(lp, ptr, size, clear) (Fortify_LINE(__LINE__), Fortify_FILE(__FILE__), _Fortify_ret = allocCHAR_FORTIFY(lp, ptr, size, clear), Fortify_LINE(0), Fortify_FILE(NULL), _Fortify_ret)\n# define allocMYBOOL(lp, ptr, size, clear) (Fortify_LINE(__LINE__), Fortify_FILE(__FILE__), _Fortify_ret = allocMYBOOL_FORTIFY(lp, ptr, size, clear), Fortify_LINE(0), Fortify_FILE(NULL), _Fortify_ret)\n# define allocINT(lp, ptr, size, clear) (Fortify_LINE(__LINE__), Fortify_FILE(__FILE__), _Fortify_ret = allocINT_FORTIFY(lp, ptr, size, clear), Fortify_LINE(0), Fortify_FILE(NULL), _Fortify_ret)\n# define allocREAL(lp, ptr, size, clear) (Fortify_LINE(__LINE__), Fortify_FILE(__FILE__), _Fortify_ret = allocREAL_FORTIFY(lp, ptr, size, clear), Fortify_LINE(0), Fortify_FILE(NULL), _Fortify_ret)\n# define allocLREAL(lp, ptr, size, clear) (Fortify_LINE(__LINE__), Fortify_FILE(__FILE__), _Fortify_ret = allocLREAL_FORTIFY(lp, ptr, size, clear), Fortify_LINE(0), Fortify_FILE(NULL), _Fortify_ret)\n#endif\n\n#endif\n\n"
  },
  {
    "path": "utilities/lp_solve/lp_wlp.c",
    "content": "\n#include <stdio.h>\n#include <stdarg.h>\n#include <string.h>\n\n#include \"commonlib.h\"\n#include \"lp_lib.h\"\n#include \"lp_scale.h\"\n#include \"lp_utils.h\"\n#include \"lp_report.h\"\n#include \"lp_wlp.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n/* Define buffer-size controled function mapping */\n# if defined _MSC_VER\n#  define vsnprintf _vsnprintf\n# endif\n\n/* ------------------------------------------------------------------------- */\n/* Input and output of lp format model files for lp_solve                    */\n/* ------------------------------------------------------------------------- */\n\nstatic int write_data(void *userhandle, write_modeldata_func write_modeldata, const char *format, ...)\n{\n  char buff[DEF_STRBUFSIZE+1];\n  va_list ap;\n  int n;\n\n  va_start(ap, format);\n  vsnprintf(buff, DEF_STRBUFSIZE, format, ap);\n  va_end(ap);\n  n = write_modeldata(userhandle, buff);\n  return(n);\n}\n\nSTATIC void write_lpcomment(void *userhandle, write_modeldata_func write_modeldata, const char *string, MYBOOL newlinebefore)\n{\n  write_data(userhandle, write_modeldata, \"%s/* %s */\\n\", (newlinebefore) ? \"\\n\" : \"\", string);\n}\n\nSTATIC int write_lprow(lprec *lp, int rowno, void *userhandle, write_modeldata_func write_modeldata, int maxlen, int *idx, REAL *val)\n{\n  int     i, j, nchars, elements;\n  REAL    a;\n  MYBOOL  first = TRUE;\n  char    buf[50];\n\n  elements = get_rowex(lp, rowno, val, idx);\n  if(write_modeldata != NULL) {\n    nchars = 0;\n    for(i = 0; i < elements; i++) {\n      j = idx[i];\n      if(is_splitvar(lp, j))\n        continue;\n      a = val[i];\n      if(!first)\n        nchars += write_data(userhandle, write_modeldata, \" \");\n      else\n        first = FALSE;\n      sprintf(buf, \"%+.12g\", (double)a);\n      if(strcmp(buf, \"-1\") == 0)\n        nchars += write_data(userhandle, write_modeldata, \"-\");\n      else if(strcmp(buf, \"+1\") == 0)\n        nchars += write_data(userhandle, write_modeldata, \"+\");\n      else\n        nchars += write_data(userhandle, write_modeldata, \"%s \", buf);\n      nchars += write_data(userhandle, write_modeldata, \"%s\", get_col_name(lp, j));\n      /* Check if we should add a linefeed */\n      if((maxlen > 0) && (nchars >= maxlen) && (i < elements-1)) {\n        write_data(userhandle, write_modeldata, \"%s\", \"\\n\");\n        nchars = 0;\n      }\n    }\n  }\n  return(elements);\n}\n\n#if !defined LP_MAXLINELEN\n# define LP_MAXLINELEN 100\n#endif\n\nMYBOOL __WINAPI write_lpex(lprec *lp, void *userhandle, write_modeldata_func write_modeldata)\n{\n  int    i, j, b,\n         nrows = lp->rows,\n         ncols = lp->columns,\n         nchars, maxlen = LP_MAXLINELEN,\n         *idx;\n  MYBOOL ok;\n  REAL   a, *val;\n  const char   *ptr;\n\n  if(!mat_validate(lp->matA)) {\n    report(lp, IMPORTANT, \"LP_writefile: Could not validate the data matrix.\\n\");\n    return(FALSE);\n  }\n\n  /* Write name of model */\n  ptr = get_lp_name(lp);\n  if(ptr != NULL) {\n    if(*ptr)\n      write_lpcomment(userhandle, write_modeldata, ptr, FALSE);\n    else\n      ptr = NULL;\n  }\n\n  /* Write the objective function */\n  write_lpcomment(userhandle, write_modeldata, \"Objective function\", (MYBOOL) (ptr != NULL));\n  if(is_maxim(lp))\n    write_data(userhandle, write_modeldata, \"max: \");\n  else\n    write_data(userhandle, write_modeldata, \"min: \");\n\n  allocREAL(lp, &val, 1 + lp->columns, TRUE);\n  allocINT(lp, &idx, 1 + lp->columns, TRUE);\n\n  write_lprow(lp, 0, userhandle, write_modeldata, maxlen, idx, val);\n  a = get_rh(lp, 0);\n  if(a != 0)\n    write_data(userhandle, write_modeldata, \" %+.12g\", a);\n  write_data(userhandle, write_modeldata, \";\\n\");\n\n  /* Write constraints */\n  if(nrows > 0)\n    write_lpcomment(userhandle, write_modeldata, \"Constraints\", TRUE);\n  for(j = 1; j <= nrows; j++) {\n    if(((lp->names_used) && (lp->row_name[j] != NULL)) || (write_lprow(lp, j, userhandle, NULL, maxlen, idx, val) == 1))\n      ptr = get_row_name(lp, j);\n    else\n      ptr = NULL;\n    if((ptr != NULL) && (*ptr))\n      write_data(userhandle, write_modeldata, \"%s: \", ptr);\n\n#ifndef SingleBoundedRowInLP\n    /* Write the ranged part of the constraint, if specified */\n    if ((lp->orig_upbo[j]) && (lp->orig_upbo[j] < lp->infinite)) {\n      if(my_chsign(is_chsign(lp, j), lp->orig_rhs[j]) == -lp->infinite)\n        write_data(userhandle, write_modeldata, \"-Inf %s \", (is_chsign(lp, j)) ? \">=\" : \"<=\");\n      else if(my_chsign(is_chsign(lp, j), lp->orig_rhs[j]) == lp->infinite)\n        write_data(userhandle, write_modeldata, \"+Inf %s \", (is_chsign(lp, j)) ? \">=\" : \"<=\");\n      else\n        write_data(userhandle, write_modeldata, \"%+.12g %s \",\n                (lp->orig_upbo[j]-lp->orig_rhs[j]) * (is_chsign(lp, j) ? 1.0 : -1.0) / (lp->scaling_used ? lp->scalars[j] : 1.0),\n                (is_chsign(lp, j)) ? \">=\" : \"<=\");\n    }\n#endif\n\n    if((!write_lprow(lp, j, userhandle, write_modeldata, maxlen, idx, val)) && (ncols >= 1))\n      write_data(userhandle, write_modeldata, \"0 %s\", get_col_name(lp, 1));\n\n    if(lp->orig_upbo[j] == 0)\n      write_data(userhandle, write_modeldata, \" =\");\n    else if(is_chsign(lp, j))\n      write_data(userhandle, write_modeldata, \" >=\");\n    else\n      write_data(userhandle, write_modeldata, \" <=\");\n    if(fabs(get_rh(lp, j) + lp->infinite) < 1)\n      write_data(userhandle, write_modeldata, \" -Inf;\\n\");\n    else if(fabs(get_rh(lp, j) - lp->infinite) < 1)\n      write_data(userhandle, write_modeldata, \" +Inf;\\n\");\n    else\n      write_data(userhandle, write_modeldata, \" %.12g;\\n\", get_rh(lp, j));\n\n#ifdef SingleBoundedRowInLP\n    /* Write the ranged part of the constraint, if specified */\n    if ((lp->orig_upbo[j]) && (lp->orig_upbo[j] < lp->infinite)) {\n      if(((lp->names_used) && (lp->row_name[j] != NULL)) || (write_lprow(lp, j, userhandle, NULL, maxlen, idx, val) == 1))\n        ptr = get_row_name(lp, j);\n      else\n        ptr = NULL;\n      if((ptr != NULL) && (*ptr))\n        write_data(userhandle, write_modeldata, \"%s: \", ptr);\n      if((!write_lprow(lp, j, userhandle, write_modeldata, maxlen, idx, val)) && (get_Ncolumns(lp) >= 1))\n        write_data(userhandle, write_modeldata, \"0 %s\", get_col_name(lp, 1));\n      write_data(userhandle, write_modeldata, \" %s %g;\\n\",\n                     (is_chsign(lp, j)) ? \"<=\" : \">=\",\n                     (lp->orig_upbo[j]-lp->orig_rhs[j]) * (is_chsign(lp, j) ? 1.0 : -1.0) / (lp->scaling_used ? lp->scalars[j] : 1.0));\n    }\n#endif\n  }\n\n  /* Write bounds on variables */\n  ok = FALSE;\n  for(i = nrows + 1; i <= lp->sum; i++)\n    if(!is_splitvar(lp, i - nrows)) {\n      if(lp->orig_lowbo[i] == lp->orig_upbo[i]) {\n        if(!ok) {\n          write_lpcomment(userhandle, write_modeldata, \"Variable bounds\", TRUE);\n          ok = TRUE;\n        }\n        write_data(userhandle, write_modeldata, \"%s = %.12g;\\n\", get_col_name(lp, i - nrows), get_upbo(lp, i - nrows));\n      }\n      else {\n#ifndef SingleBoundedRowInLP\n        if((lp->orig_lowbo[i] != 0) && (lp->orig_upbo[i] < lp->infinite)) {\n          if(!ok) {\n            write_lpcomment(userhandle, write_modeldata, \"Variable bounds\", TRUE);\n            ok = TRUE;\n          }\n          if(lp->orig_lowbo[i] == -lp->infinite)\n            write_data(userhandle, write_modeldata, \"-Inf\");\n          else\n            write_data(userhandle, write_modeldata, \"%.12g\", get_lowbo(lp, i - nrows));\n          write_data(userhandle, write_modeldata, \" <= %s <= \", get_col_name(lp, i - nrows));\n          if(lp->orig_lowbo[i] == lp->infinite)\n            write_data(userhandle, write_modeldata, \"+Inf\");\n          else\n            write_data(userhandle, write_modeldata, \"%.12g\", get_upbo(lp, i - nrows));\n          write_data(userhandle, write_modeldata, \";\\n\");\n        }\n        else\n#endif\n        {\n          if(lp->orig_lowbo[i] != 0) {\n            if(!ok) {\n              write_lpcomment(userhandle, write_modeldata, \"Variable bounds\", TRUE);\n              ok = TRUE;\n            }\n            if(lp->orig_lowbo[i] == -lp->infinite)\n              write_data(userhandle, write_modeldata, \"%s >= -Inf;\\n\", get_col_name(lp, i - nrows));\n            else if(lp->orig_lowbo[i] == lp->infinite)\n              write_data(userhandle, write_modeldata, \"%s >= +Inf;\\n\", get_col_name(lp, i - nrows));\n            else\n              write_data(userhandle, write_modeldata, \"%s >= %.12g;\\n\",\n                         get_col_name(lp, i - nrows), get_lowbo(lp, i - nrows));\n          }\n          if(lp->orig_upbo[i] != lp->infinite) {\n            if(!ok) {\n              write_lpcomment(userhandle, write_modeldata, \"Variable bounds\", TRUE);\n              ok = TRUE;\n            }\n            write_data(userhandle, write_modeldata, \"%s <= %.12g;\\n\",\n                       get_col_name(lp, i - nrows), get_upbo(lp, i - nrows));\n          }\n        }\n      }\n    }\n\n  /* Write optional integer section */\n  if(lp->int_vars > 0) {\n    write_lpcomment(userhandle, write_modeldata, \"Integer definitions\", TRUE);\n    i = 1;\n    while((i <= ncols) && !is_int(lp, i))\n      i++;\n    if(i <= ncols) {\n      nchars = write_data(userhandle, write_modeldata, \"int %s\", get_col_name(lp, i));\n      i++;\n      for(; i <= ncols; i++)\n        if((!is_splitvar(lp, i)) && (is_int(lp, i))) {\n          if((maxlen!= 0) && (nchars > maxlen)) {\n            write_data(userhandle, write_modeldata, \"%s\", \"\\n\");\n            nchars = 0;\n          }\n          write_data(userhandle, write_modeldata, \",%s\", get_col_name(lp, i));\n        }\n      write_data(userhandle, write_modeldata, \";\\n\");\n    }\n  }\n\n  /* Write optional SEC section */\n  if(lp->sc_vars > 0) {\n    write_lpcomment(userhandle, write_modeldata, \"Semi-continuous variables\", TRUE);\n    i = 1;\n    while((i <= ncols) && !is_semicont(lp, i))\n      i++;\n    if(i <= ncols) {\n      nchars = write_data(userhandle, write_modeldata, \"sec %s\", get_col_name(lp, i));\n      i++;\n      for(; i <= ncols; i++)\n        if((!is_splitvar(lp, i)) && (is_semicont(lp, i))) {\n          if((maxlen != 0) && (nchars > maxlen)) {\n            write_data(userhandle, write_modeldata, \"%s\", \"\\n\");\n            nchars = 0;\n          }\n          nchars += write_data(userhandle, write_modeldata, \",%s\", get_col_name(lp, i));\n        }\n      write_data(userhandle, write_modeldata, \";\\n\");\n    }\n  }\n\n  /* Write optional SOS section */\n  if(SOS_count(lp) > 0) {\n    SOSgroup *SOS = lp->SOS;\n    write_lpcomment(userhandle, write_modeldata, \"SOS definitions\", TRUE);\n    write_data(userhandle, write_modeldata, \"SOS\\n\");\n    for(b = 0, i = 0; i < SOS->sos_count; b = SOS->sos_list[i]->priority, i++) {\n      nchars = write_data(userhandle, write_modeldata, \"%s: \",\n              (SOS->sos_list[i]->name == NULL) ||\n              (*SOS->sos_list[i]->name==0) ? \"SOS\" : SOS->sos_list[i]->name); /* formatnumber12((double) lp->sos_list[i]->priority) */\n\n      for(a = 0.0, j = 1; j <= SOS->sos_list[i]->size; a = SOS->sos_list[i]->weights[j], j++) {\n        if((maxlen != 0) && (nchars > maxlen)) {\n          write_data(userhandle, write_modeldata, \"%s\", \"\\n\");\n          nchars = 0;\n        }\n        if(SOS->sos_list[i]->weights[j] == ++a)\n          nchars += write_data(userhandle, write_modeldata, \"%s%s\",\n                  (j > 1) ? \",\" : \"\",\n                  get_col_name(lp, SOS->sos_list[i]->members[j]));\n        else\n          nchars += write_data(userhandle, write_modeldata, \"%s%s:%.12g\",\n                  (j > 1) ? \",\" : \"\",\n                  get_col_name(lp, SOS->sos_list[i]->members[j]),\n        SOS->sos_list[i]->weights[j]);\n      }\n      if(SOS->sos_list[i]->priority == ++b)\n        nchars += write_data(userhandle, write_modeldata, \" <= %d;\\n\", SOS->sos_list[i]->type);\n      else\n        nchars += write_data(userhandle, write_modeldata, \" <= %d:%d;\\n\", SOS->sos_list[i]->type, SOS->sos_list[i]->priority);\n    }\n  }\n\n  FREE(val);\n  FREE(idx);\n\n  ok = TRUE;\n\n  return(ok);\n}\n\nstatic int __WINAPI write_lpdata(void *userhandle, char *buf)\n{\n  return(fprintf((FILE *) userhandle, \"%s\", buf));\n}\n\nMYBOOL LP_writefile(lprec *lp, const char *filename)\n{\n  FILE *output = stdout;\n  MYBOOL ok;\n\n  if (filename != NULL) {\n    ok = (MYBOOL) ((output = fopen(filename, \"w\")) != NULL);\n    if(!ok)\n      return(ok);\n  }\n  else\n    output = lp->outstream;\n\n  ok = write_lpex(lp, (void *) output, write_lpdata);\n\n  if (filename != NULL)\n    fclose(output);\n\n  return(ok);\n}\n\nMYBOOL LP_writehandle(lprec *lp, FILE *output)\n{\n  MYBOOL ok;\n\n  if (output != NULL)\n    set_outputstream(lp, output);\n\n  output = lp->outstream;\n\n  ok = write_lpex(lp, (void *) output, write_lpdata);\n\n  return(ok);\n}\n"
  },
  {
    "path": "utilities/lp_solve/lp_wlp.h",
    "content": "#ifndef HEADER_lp_lp\n#define HEADER_lp_lp\n\n#include \"lp_types.h\"\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Put function headers here */\nMYBOOL LP_writefile(lprec *lp, const char *filename);\nMYBOOL LP_writehandle(lprec *lp, FILE *output);\n\n\n#ifdef __cplusplus\n }\n#endif\n\n#endif /* HEADER_lp_lp */\n\n"
  },
  {
    "path": "utilities/lp_solve/lpkit.h",
    "content": "#include \"lp_lib.h\"\n#include \"lp_report.h\"\n\n#define MALLOC(ptr, nr, type)\\\n  ((((nr) == 0) || ((ptr = (type *) malloc((size_t)((nr) * sizeof(*ptr)))) == NULL)) ? \\\n   report(NULL, CRITICAL, \"malloc of %d bytes failed on line %d of file %s\\n\",\\\n           (nr) * sizeof(*ptr), __LINE__, __FILE__), (ptr = NULL /* (void *) 0 */) : \\\n   ptr\\\n  )\n\n#define CALLOC(ptr, nr, type)\\\n  ((((nr) == 0) || ((ptr = (type *) calloc((size_t)(nr), sizeof(*ptr))) == NULL)) ? \\\n   report(NULL, CRITICAL, \"calloc of %d bytes failed on line %d of file %s\\n\",\\\n           (nr) * sizeof(*ptr), __LINE__, __FILE__), (ptr = NULL /* (void *) 0 */) : \\\n   ptr\\\n  )\n\n#define REALLOC(ptr, nr, type)\\\n  ((((nr) == 0) || ((ptr = (type *) realloc(ptr, (size_t)((nr) * sizeof(*ptr)))) == NULL)) ? \\\n   report(NULL, CRITICAL, \"realloc of %d bytes failed on line %d of file %s\\n\",\\\n           (nr) * sizeof(*ptr), __LINE__, __FILE__), (ptr = NULL /* (void *) 0 */) : \\\n   ptr\\\n  )\n\n#if defined FREE\n# undef FREE\n#endif\n\n#define FREE(ptr) if (ptr != NULL) {free(ptr), ptr = NULL;} else\n\n#define MALLOCCPY(nptr, optr, nr, type)\\\n  (MALLOC(nptr, nr, type), (nptr != NULL) ? memcpy(nptr, optr, (size_t)((nr) * sizeof(*optr))) : 0, nptr)\n"
  },
  {
    "path": "utilities/lp_solve/shared/commonlib.c",
    "content": "\n#include <sys/types.h>\n\n#if defined INTEGERTIME || defined CLOCKTIME || defined PosixTime\n# include <time.h>\n#elif defined EnhTime\n# include <windows.h>\n#else\n# include <sys/timeb.h>\n#endif\n\n#include <stdlib.h>\n#include <stdio.h>\n#ifdef WIN32\n# include <io.h>       /* Used in file search functions */\n#endif\n#include <ctype.h>\n#include <string.h>\n#include <float.h>\n#include <math.h>\n#include \"commonlib.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n#if defined FPUexception\n/* FPU exception masks */\nunsigned int clearFPU()\n{\n  return( _clearfp() );\n}\nunsigned int resetFPU(unsigned int mask)\n{\n  _clearfp();\n  mask = _controlfp( mask, 0xfffff);\n  return( mask );\n}\nunsigned int catchFPU(unsigned int mask)\n{\n  /* Always call _clearfp before enabling/unmasking a FPU exception */\n  unsigned int u = _clearfp();\n\n  /* Set the new mask by not-and'ing it with the previous settings */\n  u = _controlfp(0, 0);\n  mask = u & ~mask;\n  mask = _controlfp(mask, _MCW_EM);\n\n  /* Return the previous mask */\n  return( u );\n}\n#endif\n\n/* Math operator equivalence function */\nint intpow(int base, int exponent)\n{\n  int result = 1;\n  while(exponent > 0) {\n    result *= base;\n    exponent--;\n  }\n  while(exponent < 0) {\n    result /= base;\n    exponent++;\n  }\n  return( result );\n}\nint mod(int n, int d)\n{\n  return(n % d);\n}\n\n/* Some string functions */\nvoid strtoup(char *s)\n{\n  if(s != NULL)\n  while (*s) {\n    *s = toupper(*s);\n    s++;\n  }\n}\nvoid strtolo(char *s)\n{\n  if(s != NULL)\n  while (*s) {\n    *s = tolower(*s);\n    s++;\n  }\n}\nvoid strcpyup(char *t, const char *s)\n{\n  if((s != NULL) && (t != NULL)) {\n    while (*s) {\n      *t = toupper(*s);\n      t++;\n      s++;\n    }\n    *t = '\\0';\n  }\n}\nvoid strcpylo(char *t, const char *s)\n{\n  if((s != NULL) && (t != NULL)) {\n    while (*s) {\n      *t = tolower(*s);\n      t++;\n      s++;\n    }\n    *t = '\\0';\n  }\n}\n\n/* Unix library naming utility function */\nMYBOOL so_stdname(char *stdname, const char *descname, int buflen)\n{\n  const char *ptr;\n\n  if((descname == NULL) || (stdname == NULL) || (((int) strlen(descname)) >= buflen - 6))\n    return( FALSE );\n\n  strcpy(stdname, descname);\n  if((ptr = strrchr(descname, '/')) == NULL)\n    ptr = descname;\n  else\n    ptr++;\n  stdname[(int) (ptr - descname)] = 0;\n  if(strncmp(ptr, \"lib\", 3))\n    strcat(stdname, \"lib\");\n  strcat(stdname, ptr);\n  if(strcmp(stdname + strlen(stdname) - 3, \".so\"))\n    strcat(stdname, \".so\");\n  return( TRUE );\n}\n\n/* Return the greatest common divisor of a and b, or -1 if it is\n   not defined. Return through the pointer arguments the integers\n   such that gcd(a,b) = c*a + b*d. */\nint gcd(LLONG a, LLONG b, int *c, int *d)\n{\n  LLONG q,r,t;\n  int   cret,dret,C,D,rval, sgn_a = 1,sgn_b = 1, swap = 0;\n\n  if((a == 0) || (b == 0))\n    return( -1 );\n\n  /* Use local multiplier instances, if necessary */\n  if(c == NULL)\n    c = &cret;\n  if(d == NULL)\n    d = &dret;\n\n  /* Normalize so that 0 < a <= b */\n  if(a < 0){\n    a = -a;\n    sgn_a = -1;\n  }\n  if(b < 0){\n    b = -b;\n    sgn_b = -1;\n  }\n  if(b < a){\n    t = b;\n    b = a;\n    a = t;\n    swap = 1;\n  }\n\n  /* Now a <= b and both >= 1. */\n  q = b/a;\n  r = b - a*q;\n  if(r == 0) {\n    if(swap){\n      *d = 1;\n      *c = 0;\n    }\n    else {\n      *c = 1;\n      *d = 0;\n    }\n    *c = sgn_a*(*c);\n    *d = sgn_b*(*d);\n    return( (int) a );\n  }\n\n  rval = gcd(a,r,&C,&D);\n  if(swap){\n    *d = (int) (C-D*q);\n    *c = D;\n  }\n  else {\n    *d = D;\n    *c = (int) (C-D*q);\n  }\n  *c = sgn_a*(*c);\n  *d = sgn_b*(*d);\n  return( rval );\n}\n\n/* Array search functions */\nint findIndex(int target, int *attributes, int count, int offset)\n{\n  int focusPos, beginPos, endPos;\n  int focusAttrib, beginAttrib, endAttrib;\n\n /* Set starting and ending index offsets */\n  beginPos = offset;\n  endPos = beginPos + count - 1;\n  if(endPos < beginPos)\n    return(-1);\n\n /* Do binary search logic based on a sorted (decending) attribute vector */\n  focusPos = (beginPos + endPos) / 2;\n  beginAttrib = attributes[beginPos];\n  focusAttrib = attributes[focusPos];\n  endAttrib   = attributes[endPos];\n\n  while(endPos - beginPos > LINEARSEARCH) {\n    if(beginAttrib == target) {\n      focusAttrib = beginAttrib;\n      endPos = beginPos;\n    }\n    else if(endAttrib == target) {\n      focusAttrib = endAttrib;\n      beginPos = endPos;\n    }\n    else if(focusAttrib < target) {\n      beginPos = focusPos + 1;\n      beginAttrib = attributes[beginPos];\n      focusPos = (beginPos + endPos) / 2;\n      focusAttrib = attributes[focusPos];\n    }\n    else if(focusAttrib > target) {\n      endPos = focusPos - 1;\n      endAttrib = attributes[endPos];\n      focusPos = (beginPos + endPos) / 2;\n      focusAttrib = attributes[focusPos];\n    }\n    else {\n      beginPos = focusPos;\n      endPos = focusPos;\n    }\n  }\n\n /* Do linear (unsorted) search logic */\n  if(endPos - beginPos <= LINEARSEARCH) {\n\n    /* CPU intensive loop; provide alternative evaluation models */\n#if defined DOFASTMATH\n    /* Do fast pointer arithmetic */\n    int *attptr = attributes + beginPos;\n    while((beginPos < endPos) && ((*attptr) < target)) {\n      beginPos++;\n      attptr++;\n    }\n    focusAttrib = (*attptr);\n#else\n    /* Do traditional indexed access */\n    focusAttrib = attributes[beginPos];\n    while((beginPos < endPos) && (focusAttrib < target)) {\n      beginPos++;\n      focusAttrib = attributes[beginPos];\n    }\n#endif\n  }\n\n /* Return the index if a match was found, or signal failure with a -1        */\n  if(focusAttrib == target)             /* Found; return retrieval index      */\n    return(beginPos);\n  else if(focusAttrib > target)         /* Not found; last item               */\n    return(-beginPos);\n  else if(beginPos > offset+count-1)\n    return(-(endPos+1));                /* Not found; end of list             */\n  else\n    return(-(beginPos+1));              /* Not found; intermediate point      */\n\n}\nint findIndexEx(void *target, void *attributes, int count, int offset, int recsize, findCompare_func findCompare, MYBOOL ascending)\n{\n  int  focusPos, beginPos, endPos, compare, order;\n  void *focusAttrib, *beginAttrib, *endAttrib;\n\n /* Set starting and ending index offsets */\n  beginPos = offset;\n  endPos = beginPos + count - 1;\n  if(endPos < beginPos)\n    return(-1);\n  order = (ascending ? -1 : 1);\n\n /* Do binary search logic based on a sorted attribute vector */\n  focusPos = (beginPos + endPos) / 2;\n  beginAttrib = CMP_ATTRIBUTES(beginPos);\n  focusAttrib = CMP_ATTRIBUTES(focusPos);\n  endAttrib   = CMP_ATTRIBUTES(endPos);\n\n  compare = 0;\n  while(endPos - beginPos > LINEARSEARCH) {\n    if(findCompare(target, beginAttrib) == 0) {\n      focusAttrib = beginAttrib;\n      endPos = beginPos;\n    }\n    else if(findCompare(target, endAttrib) == 0) {\n      focusAttrib = endAttrib;\n      beginPos = endPos;\n    }\n    else {\n      compare = findCompare(target, focusAttrib)*order;\n      if(compare < 0) {\n        beginPos = focusPos + 1;\n        beginAttrib = CMP_ATTRIBUTES(beginPos);\n        focusPos = (beginPos + endPos) / 2;\n        focusAttrib = CMP_ATTRIBUTES(focusPos);\n      }\n      else if(compare > 0) {\n        endPos = focusPos - 1;\n        endAttrib = CMP_ATTRIBUTES(endPos);\n        focusPos = (beginPos + endPos) / 2;\n        focusAttrib = CMP_ATTRIBUTES(focusPos);\n      }\n      else {\n        beginPos = focusPos;\n        endPos = focusPos;\n      }\n    }\n  }\n\n /* Do linear (unsorted) search logic */\n  if(endPos - beginPos <= LINEARSEARCH) {\n\n    /* Do traditional indexed access */\n    focusAttrib = CMP_ATTRIBUTES(beginPos);\n    if(beginPos == endPos)\n      compare = findCompare(target, focusAttrib)*order;\n    else\n    while((beginPos < endPos) &&\n          ((compare = findCompare(target, focusAttrib)*order) < 0)) {\n      beginPos++;\n      focusAttrib = CMP_ATTRIBUTES(beginPos);\n    }\n  }\n\n /* Return the index if a match was found, or signal failure with a -1        */\n  if(compare == 0)                      /* Found; return retrieval index      */\n    return(beginPos);\n  else if(compare > 0)                  /* Not found; last item               */\n    return(-beginPos);\n  else if(beginPos > offset+count-1)\n    return(-(endPos+1));                /* Not found; end of list             */\n  else\n    return(-(beginPos+1));              /* Not found; intermediate point      */\n\n}\n\n/* Simple sorting and searching comparison \"operators\" */\nint CMP_CALLMODEL compareCHAR(const void *current, const void *candidate)\n{\n  return( CMP_COMPARE( *(char *) current, *(char *) candidate ) );\n}\nint CMP_CALLMODEL compareINT(const void *current, const void *candidate)\n{\n  return( CMP_COMPARE( *(int *) current, *(int *) candidate ) );\n}\nint CMP_CALLMODEL compareREAL(const void *current, const void *candidate)\n{\n  return( CMP_COMPARE( *(REAL *) current, *(REAL *) candidate ) );\n}\n\n/* Heap sort function (procedurally based on the Numerical Recipes version,\n   but expanded and generalized to hande any object with the use of\n   qsort-style comparison operator).  An expanded version is also implemented,\n   where interchanges are reflected in a caller-initialized integer \"tags\" list. */\nvoid hpsort(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare)\n{\n  int  i, j, k, ir, order;\n  char *hold, *base;\n  char          *save;\n\n  if(count < 2)\n    return;\n  offset -= 1;\n  attributes = CMP_ATTRIBUTES(offset);\n  base = CMP_ATTRIBUTES(1);\n  save = (char *) malloc(recsize);\n  if(descending)\n    order = -1;\n  else\n    order = 1;\n\n  k = (count >> 1) + 1;\n  ir = count;\n\n  for(;;) {\n    if(k > 1) {\n      MEMCOPY(save, CMP_ATTRIBUTES(--k), recsize);\n    }\n    else {\n      hold = CMP_ATTRIBUTES(ir);\n      MEMCOPY(save, hold, recsize);\n      MEMCOPY(hold, base, recsize);\n      if(--ir == 1) {\n        MEMCOPY(base, save, recsize);\n        break;\n      }\n    }\n\n    i = k;\n    j = k << 1;\n    while(j <= ir) {\n      hold = CMP_ATTRIBUTES(j);\n      if( (j < ir) && (findCompare(hold, CMP_ATTRIBUTES(j+1))*order < 0) ) {\n        hold += recsize;\n        j++;\n      }\n      if(findCompare(save, hold)*order < 0) {\n        MEMCOPY(CMP_ATTRIBUTES(i), hold, recsize);\n        i = j;\n        j <<= 1;\n\t    }\n      else\n        break;\n    }\n    MEMCOPY(CMP_ATTRIBUTES(i), save, recsize);\n  }\n\n  FREE(save);\n}\nvoid hpsortex(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare, int *tags)\n{\n  if(count < 2)\n    return;\n  if(tags == NULL) {\n    hpsort(attributes, count, offset, recsize, descending, findCompare);\n    return;\n  }\n  else {\n    int  i, j, k, ir, order;\n    char *hold, *base;\n    char          *save;\n    int           savetag;\n\n    offset -= 1;\n    attributes = CMP_ATTRIBUTES(offset);\n    tags += offset;\n    base = CMP_ATTRIBUTES(1);\n    save = (char *) malloc(recsize);\n    if(descending)\n      order = -1;\n    else\n      order = 1;\n\n    k = (count >> 1) + 1;\n    ir = count;\n\n    for(;;) {\n      if(k > 1) {\n        MEMCOPY(save, CMP_ATTRIBUTES(--k), recsize);\n        savetag = tags[k];\n      }\n      else {\n        hold = CMP_ATTRIBUTES(ir);\n        MEMCOPY(save, hold, recsize);\n        MEMCOPY(hold, base, recsize);\n        savetag = tags[ir];\n        tags[ir] = tags[1];\n        if(--ir == 1) {\n          MEMCOPY(base, save, recsize);\n          tags[1] = savetag;\n          break;\n        }\n      }\n\n      i = k;\n      j = k << 1;\n      while(j <= ir) {\n        hold = CMP_ATTRIBUTES(j);\n        if( (j < ir) && (findCompare(hold, CMP_ATTRIBUTES(j+1))*order < 0) ) {\n          hold += recsize;\n          j++;\n        }\n        if(findCompare(save, hold)*order < 0) {\n          MEMCOPY(CMP_ATTRIBUTES(i), hold, recsize);\n          tags[i] = tags[j];\n          i = j;\n          j <<= 1;\n  \t    }\n        else\n          break;\n      }\n      MEMCOPY(CMP_ATTRIBUTES(i), save, recsize);\n      tags[i] = savetag;\n    }\n\n    FREE(save);\n  }\n}\n\n/* This is a \"specialized generic\" version of C.A.R Hoare's Quick Sort algorithm.\n   It will handle arrays that are already sorted, and arrays with duplicate keys.\n   There are two versions here; one extended conventional with optional tag data\n   for each sortable value, and a version for the QSORTrec format.  The QSORTrec\n   format i.a. includes the ability for to do linked list sorting. If the passed\n   comparison operator is NULL, the comparison is assumed to be for integers. */\n#define QS_IS_switch LINEARSEARCH    /* Threshold for switching to insertion sort */\n\nvoid qsortex_swap(void *attributes, int l, int r, int recsize,\n                         void *tags, int tagsize, char *save, char *savetag)\n{\n   MEMCOPY(save, CMP_ATTRIBUTES(l), recsize);\n   MEMCOPY(CMP_ATTRIBUTES(l), CMP_ATTRIBUTES(r), recsize);\n   MEMCOPY(CMP_ATTRIBUTES(r), save, recsize);\n   if(tags != NULL) {\n     MEMCOPY(savetag, CMP_TAGS(l), tagsize);\n     MEMCOPY(CMP_TAGS(l), CMP_TAGS(r), tagsize);\n     MEMCOPY(CMP_TAGS(r), savetag, tagsize);\n   }\n}\n\nint qsortex_sort(void *attributes, int l, int r, int recsize, int sortorder, findCompare_func findCompare,\n                        void *tags, int tagsize, char *save, char *savetag)\n{\n  int i, j, nmove = 0;\n  char     *v;\n\n  /* Perform the a fast QuickSort */\n  if((r-l) > QS_IS_switch) {\n    i = (r+l)/2;\n\n    /* Tri-Median Method */\n    if(sortorder*findCompare(CMP_ATTRIBUTES(l), CMP_ATTRIBUTES(i)) > 0)\n      { nmove++; qsortex_swap(attributes, l,i, recsize, tags, tagsize, save, savetag); }\n    if(sortorder*findCompare(CMP_ATTRIBUTES(l), CMP_ATTRIBUTES(r)) > 0)\n      { nmove++; qsortex_swap(attributes, l,r, recsize, tags, tagsize, save, savetag); }\n    if(sortorder*findCompare(CMP_ATTRIBUTES(i), CMP_ATTRIBUTES(r)) > 0)\n      { nmove++; qsortex_swap(attributes, i,r, recsize, tags, tagsize, save, savetag); }\n\n    j = r-1;\n    qsortex_swap(attributes, i,j, recsize, tags, tagsize, save, savetag);\n    i = l;\n    v = CMP_ATTRIBUTES(j);\n    for(;;) {\n      while(sortorder*findCompare(CMP_ATTRIBUTES(++i), v) < 0);\n      while(sortorder*findCompare(CMP_ATTRIBUTES(--j), v) > 0);\n      if(j < i) break;\n      nmove++; qsortex_swap(attributes, i,j, recsize, tags, tagsize, save, savetag);\n    }\n    nmove++; qsortex_swap(attributes, i,r-1, recsize, tags, tagsize, save, savetag);\n    nmove += qsortex_sort(attributes, l,j,   recsize, sortorder, findCompare, tags, tagsize, save, savetag);\n    nmove += qsortex_sort(attributes, i+1,r, recsize, sortorder, findCompare, tags, tagsize, save, savetag);\n  }\n  return( nmove );\n}\n\nint qsortex_finish(void *attributes, int lo0, int hi0, int recsize, int sortorder, findCompare_func findCompare,\n                          void *tags, int tagsize, char *save, char *savetag)\n{\n  int i, j, nmove = 0;\n\n  /* This is actually InsertionSort, which is faster for local sorts */\n  for(i = lo0+1; i <= hi0; i++) {\n\n    /* Save bottom-most item */\n    MEMCOPY(save, CMP_ATTRIBUTES(i), recsize);\n    if(tags != NULL)\n      MEMCOPY(savetag, CMP_TAGS(i), tagsize);\n\n    /* Shift down! */\n    j = i;\n    while ((j > lo0) && (sortorder*findCompare(CMP_ATTRIBUTES(j-1), save) > 0)) {\n      MEMCOPY(CMP_ATTRIBUTES(j), CMP_ATTRIBUTES(j-1), recsize);\n      if(tags != NULL)\n        MEMCOPY(CMP_TAGS(j), CMP_TAGS(j-1), tagsize);\n      j--;\n      nmove++;\n    }\n\n    /* Store bottom-most item at the top */\n    MEMCOPY(CMP_ATTRIBUTES(j), save, recsize);\n    if(tags != NULL)\n      MEMCOPY(CMP_TAGS(j), savetag, tagsize);\n  }\n  return( nmove );\n}\n\nint qsortex(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare, void *tags, int tagsize)\n{\n  int  iswaps = 0, sortorder = (descending ? -1 : 1);\n  char *save = NULL, *savetag = NULL;\n\n  /* Check and initialize to zero-based arrays */\n  if(count <= 1)\n    goto Finish;\n  attributes = (void *) CMP_ATTRIBUTES(offset);\n  save = (char *) malloc(recsize);\n  if((tagsize <= 0) && (tags != NULL))\n    tags = NULL;\n  else if(tags != NULL) {\n    tags = (void *) CMP_TAGS(offset);\n    savetag = (char *) malloc(tagsize);\n  }\n  count--;\n\n  /* Perform sort */\n  iswaps = qsortex_sort(attributes, 0, count, recsize, sortorder, findCompare, tags, tagsize, save, savetag);\n#if QS_IS_switch > 0\n  iswaps += qsortex_finish(attributes, 0, count, recsize, sortorder, findCompare, tags, tagsize, save, savetag);\n#endif\n\nFinish:\n  FREE(save);\n  FREE(savetag);\n  return( iswaps );\n}\n\n#undef QS_IS_switch\n\n/* This is a \"specialized generic\" version of C.A.R Hoare's Quick Sort algorithm.\n   It will handle arrays that are already sorted, and arrays with duplicate keys.\n   The implementation here requires the user to pass a comparison operator and\n   assumes that the array passed has the QSORTrec format, which i.a. includes\n   the ability for to do linked list sorting. If the passed comparison operator\n   is NULL, the comparison is assumed to be for integers. */\n#define QS_IS_switch 4    /* Threshold for switching to insertion sort */\n\nvoid QS_swap(UNIONTYPE QSORTrec a[], int i, int j)\n{\n  UNIONTYPE QSORTrec T = a[i];\n  a[i] = a[j];\n  a[j] = T;\n}\nint QS_addfirst(UNIONTYPE QSORTrec a[], void *mydata)\n{\n  a[0].pvoid2.ptr = mydata;\n  return( 0 );\n}\nint QS_append(UNIONTYPE QSORTrec a[], int ipos, void *mydata)\n{\n  if(ipos <= 0)\n    ipos = QS_addfirst(a, mydata);\n  else\n    a[ipos].pvoid2.ptr = mydata;\n  return( ipos );\n}\nvoid QS_replace(UNIONTYPE QSORTrec a[], int ipos, void *mydata)\n{\n  a[ipos].pvoid2.ptr = mydata;\n}\nvoid QS_insert(UNIONTYPE QSORTrec a[], int ipos, void *mydata, int epos)\n{\n  for(; epos > ipos; epos--)\n    a[epos] = a[epos-1];\n  a[ipos].pvoid2.ptr = mydata;\n}\nvoid QS_delete(UNIONTYPE QSORTrec a[], int ipos, int epos)\n{\n  for(; epos > ipos; epos--)\n    a[epos] = a[epos-1];\n}\nint QS_sort(UNIONTYPE QSORTrec a[], int l, int r, findCompare_func findCompare)\n{\n  int i, j, nmove = 0;\n  UNIONTYPE QSORTrec v;\n\n  /* Perform the a fast QuickSort */\n  if((r-l) > QS_IS_switch) {\n    i = (r+l)/2;\n\n    /* Tri-Median Method */\n    if(findCompare((char *) &a[l], (char *) &a[i]) > 0)\n      { nmove++; QS_swap(a,l,i); }\n    if(findCompare((char *) &a[l], (char *) &a[r]) > 0)\n      { nmove++; QS_swap(a,l,r); }\n    if(findCompare((char *) &a[i], (char *) &a[r]) > 0)\n      { nmove++; QS_swap(a,i,r); }\n\n    j = r-1;\n    QS_swap(a,i,j);\n    i = l;\n    v = a[j];\n    for(;;) {\n      while(findCompare((char *) &a[++i], (char *) &v) < 0);\n      while(findCompare((char *) &a[--j], (char *) &v) > 0);\n      if(j < i) break;\n      nmove++; QS_swap (a,i,j);\n    }\n    nmove++; QS_swap(a,i,r-1);\n    nmove += QS_sort(a,l,j,findCompare);\n    nmove += QS_sort(a,i+1,r,findCompare);\n  }\n  return( nmove );\n}\nint QS_finish(UNIONTYPE QSORTrec a[], int lo0, int hi0, findCompare_func findCompare)\n{\n  int      i, j, nmove = 0;\n  UNIONTYPE QSORTrec v;\n\n  /* This is actually InsertionSort, which is faster for local sorts */\n  for(i = lo0+1; i <= hi0; i++) {\n\n    /* Save bottom-most item */\n    v = a[i];\n\n    /* Shift down! */\n    j = i;\n    while ((j > lo0) && (findCompare((char *) &a[j-1], (char *) &v) > 0)) {\n      a[j] = a[j-1];\n      j--;\n      nmove++;\n    }\n\n    /* Store bottom-most item at the top */\n    a[j] = v;\n  }\n  return( nmove );\n}\nMYBOOL QS_execute(UNIONTYPE QSORTrec a[], int count, findCompare_func findCompare, int *nswaps)\n{\n  int iswaps = 0;\n\n  /* Check and initialize */\n  if(count <= 1)\n    goto Finish;\n  count--;\n\n  /* Perform sort */\n  iswaps = QS_sort(a, 0, count, findCompare);\n#if QS_IS_switch > 0\n  iswaps += QS_finish(a, 0, count, findCompare);\n#endif\n\nFinish:\n  if(nswaps != NULL)\n    *nswaps = iswaps;\n  return( TRUE );\n}\n\n\n\n/* Simple specialized bubble/insertion sort functions */\nint sortByREAL(int *item, REAL *weight, int size, int offset, MYBOOL unique)\n{\n  int i, ii, saveI;\n  REAL saveW;\n\n  for(i = 1; i < size; i++) {\n    ii = i+offset-1;\n    while ((ii >= offset) && (weight[ii] >= weight[ii+1])) {\n      if(weight[ii] == weight[ii+1]) {\n        if(unique)\n          return(item[ii]);\n      }\n      else {\n        saveI = item[ii];\n        saveW = weight[ii];\n        item[ii] = item[ii+1];\n        weight[ii] = weight[ii+1];\n        item[ii+1] = saveI;\n        weight[ii+1] = saveW;\n      }\n      ii--;\n    }\n  }\n  return(0);\n}\nint sortByINT(int *item, int *weight, int size, int offset, MYBOOL unique)\n{\n  int i, ii, saveI;\n  int saveW;\n\n  for(i = 1; i < size; i++) {\n    ii = i+offset-1;\n    while ((ii >= offset) && (weight[ii] >= weight[ii+1])) {\n      if(weight[ii] == weight[ii+1]) {\n        if(unique)\n          return(item[ii]);\n      }\n      else {\n        saveI = item[ii];\n        saveW = weight[ii];\n        item[ii] = item[ii+1];\n        weight[ii] = weight[ii+1];\n        item[ii+1] = saveI;\n        weight[ii+1] = saveW;\n      }\n      ii--;\n    }\n  }\n  return(0);\n}\nREAL sortREALByINT(REAL *item, int *weight, int size, int offset, MYBOOL unique)\n{\n  int  i, ii, saveW;\n  REAL saveI;\n\n  for(i = 1; i < size; i++) {\n    ii = i+offset-1;\n    while ((ii >= offset) && (weight[ii] >= weight[ii+1])) {\n      if(weight[ii] == weight[ii+1]) {\n        if(unique)\n          return(item[ii]);\n      }\n      else {\n        saveI = item[ii];\n        saveW = weight[ii];\n        item[ii] = item[ii+1];\n        weight[ii] = weight[ii+1];\n        item[ii+1] = saveI;\n        weight[ii+1] = saveW;\n      }\n      ii--;\n    }\n  }\n  return(0);\n}\n\n\n/* Time and message functions */\ndouble timeNow(void)\n{\n#ifdef INTEGERTIME\n  return((double)time(NULL));\n#elif defined CLOCKTIME\n  return((double)clock()/CLOCKS_PER_SEC /* CLK_TCK */);\n#elif defined PosixTime\n  struct timespec t;\n# if 0\n  clock_gettime(CLOCK_REALTIME, &t);\n  return( (double) t.tv_sec + (double) t.tv_nsec/1.0e9 );\n# else\n  static double   timeBase;\n\n  clock_gettime(CLOCK_MONOTONIC, &t);\n  if(timeBase == 0)\n    timeBase = clockNow() - ((double) t.tv_sec + (double) t.tv_nsec/1.0e9);\n  return( timeBase + (double) t.tv_sec + (double) t.tv_nsec/1.0e9 );\n# endif\n#elif defined EnhTime\n  static LARGE_INTEGER freq;\n  static double        timeBase;\n  LARGE_INTEGER        now;\n\n  QueryPerformanceCounter(&now);\n  if(timeBase == 0) {\n    QueryPerformanceFrequency(&freq);\n    timeBase = clockNow() - (double) now.QuadPart/(double) freq.QuadPart;\n  }\n  return( timeBase + (double) now.QuadPart/(double) freq.QuadPart );\n#else\n  struct timeb buf;\n\n  ftime(&buf);\n  return((double)buf.time+((double) buf.millitm)/1000.0);\n#endif\n}\n\n\n/* Miscellaneous reporting functions */\n\n/* List a vector of INT values for the given index range */\nvoid blockWriteINT(FILE *output, const char *label, int *myvector, int first, int last)\n{\n  int i, k = 0;\n\n  fprintf(output, \"%s\", label);\n  fprintf(output, \"\\n\");\n  for(i = first; i <= last; i++) {\n    fprintf(output, \" %5d\", myvector[i]);\n    k++;\n    if(k % 12 == 0) {\n      fprintf(output, \"\\n\");\n      k = 0;\n    }\n  }\n  if(k % 12 != 0)\n    fprintf(output, \"\\n\");\n}\n\n/* List a vector of MYBOOL values for the given index range */\nvoid blockWriteBOOL(FILE *output, const char *label, MYBOOL *myvector, int first, int last, MYBOOL asRaw)\n{\n  int i, k = 0;\n\n  fprintf(output, \"%s\", label);\n  fprintf(output, \"\\n\");\n  for(i = first; i <= last; i++) {\n    if(asRaw)\n      fprintf(output, \" %1d\", myvector[i]);\n    else\n      fprintf(output, \" %5s\", my_boolstr(myvector[i]));\n    k++;\n    if(k % 36 == 0) {\n      fprintf(output, \"\\n\");\n      k = 0;\n    }\n  }\n  if(k % 36 != 0)\n    fprintf(output, \"\\n\");\n}\n\n/* List a vector of REAL values for the given index range */\nvoid blockWriteREAL(FILE *output, const char *label, REAL *myvector, int first, int last)\n{\n  int i, k = 0;\n\n  fprintf(output, \"%s\", label);\n  fprintf(output, \"\\n\");\n  for(i = first; i <= last; i++) {\n    fprintf(output, \" %18g\", myvector[i]);\n    k++;\n    if(k % 4 == 0) {\n      fprintf(output, \"\\n\");\n      k = 0;\n    }\n  }\n  if(k % 4 != 0)\n    fprintf(output, \"\\n\");\n}\n\n\n/* CONSOLE vector and matrix printing routines */\nvoid printvec( int n, REAL *x, int modulo )\n{\n  int i;\n\n  if (modulo <= 0) modulo = 5;\n  for (i = 1; i<=n; i++) {\n    if(mod(i, modulo) == 1)\n      printf(\"\\n%2d:%12g\", i, x[i]);\n    else\n      printf(\" %2d:%12g\", i, x[i]);\n  }\n  if(i % modulo != 0) printf(\"\\n\");\n}\n\n\nvoid printmatUT( int size, int n, REAL *U, int modulo)\n{\n   int i, ll;\n   ll = 0;\n   for(i = 1; i<=n; i++) {\n     printvec(n-i+1, &U[ll], modulo);\n     ll += size-i+1;\n   }\n}\n\n\nvoid printmatSQ( int size, int n, REAL *X, int modulo)\n{\n   int i, ll;\n   ll = 0;\n   for(i = 1; i<=n; i++) {\n     printvec(n, &X[ll], modulo);\n     ll += size;\n   }\n}\n\n/* Miscellaneous file functions */\n#if defined _MSC_VER\n/* Check MS versions before 7 */\n#if _MSC_VER < 1300\n# define intptr_t long\n#endif\n\nint fileCount( const char *filemask )\n{\n  struct   _finddata_t c_file;\n  intptr_t hFile;\n  int      count = 0;\n\n  /* Find first .c file in current directory */\n  if( (hFile = _findfirst( filemask, &c_file )) == -1L )\n    ;\n  /* Iterate over all matching names */\n  else {\n     while( _findnext( hFile, &c_file ) == 0 )\n       count++;\n    _findclose( hFile );\n  }\n  return( count );\n}\nMYBOOL fileSearchPath( const char *envvar, const char *searchfile, const char *foundpath )\n{\n   char pathbuffer[_MAX_PATH];\n\n   _searchenv( searchfile, envvar, pathbuffer );\n   if(pathbuffer[0] == '\\0')\n     return( FALSE );\n   else {\n     if(foundpath != NULL)\n       strcpy(foundpath, pathbuffer);\n     return( TRUE );\n   }\n}\n#endif\n"
  },
  {
    "path": "utilities/lp_solve/shared/commonlib.h",
    "content": "#ifndef HEADER_commonlib\n#define HEADER_commonlib\n\n#include <stdlib.h>\n#include <stdio.h>\n#ifdef WIN32\n  #include <windows.h>\n#endif\n\n/* static char SpaceChars[3] = {\" \" \"\\7\"}; */\n/* static char NumChars[14]  = {\"0123456789-+.\"}; */\n\n#define BIGNUMBER      1.0e+30\n#define TINYNUMBER     1.0e-04\n#define MACHINEPREC   2.22e-16\n#define MATHPREC       1.0e-16\n#define ERRLIMIT       1.0e-06\n\n#ifndef LINEARSEARCH\n  #define LINEARSEARCH 5\n#endif\n\n#if 0\n  #define INTEGERTIME\n#endif\n\n/* ************************************************************************ */\n/* Define loadable library function headers                                 */\n/* ************************************************************************ */\n#if (defined WIN32) || (defined WIN64)\n  #define my_LoadLibrary(name)              LoadLibrary(name)\n  #define my_GetProcAddress(handle, name)   GetProcAddress(handle, name)\n  #define my_FreeLibrary(handle)            FreeLibrary(handle); \\\n                                            handle = NULL\n#else\n  #define my_LoadLibrary(name)              dlopen(name, RTLD_LAZY)\n  #define my_GetProcAddress(handle, name)   dlsym(handle, name)\n  #define my_FreeLibrary(handle)            dlclose(handle); \\\n                                            handle = NULL\n#endif\n\n\n/* ************************************************************************ */\n/* Define sizes of standard number types                                    */\n/* ************************************************************************ */\n#ifndef LLONG\n  #if defined __BORLANDC__\n    #define LLONG __int64\n  #elif !defined _MSC_VER || _MSC_VER >= 1310\n    #define LLONG long long\n  #else\n    #define LLONG __int64\n  #endif\n#endif\n\n#ifndef MYBOOL\n  #if 0\n    #define MYBOOL unsigned int\n  #else\n    #define MYBOOL unsigned char\n  #endif\n#endif\n\n#ifndef REAL\n  #define REAL     double\n#endif\n#ifndef BLAS_prec\n  #define BLAS_prec \"d\" /* The BLAS precision prefix must correspond to the REAL type */\n#endif\n\n#ifndef REALXP\n  #if 1\n    #define REALXP long double  /* Set local accumulation variable as long double */\n  #else\n    #define REALXP REAL          /* Set local accumulation as default precision */\n  #endif\n#endif\n\n#ifndef my_boolstr\n  #define my_boolstr(x)          (!(x) ? \"FALSE\" : \"TRUE\")\n#endif\n\n#ifndef NULL\n  #define NULL \t       0\n#endif\n\n#ifndef FALSE\n  #define FALSE        0\n  #define TRUE         1\n#endif\n\n#ifndef DEF_STRBUFSIZE\n  #define DEF_STRBUFSIZE   512\n#endif\n#ifndef MAXINT32\n  #define MAXINT32  2147483647\n#endif\n#ifndef MAXUINT32\n  #define MAXUINT32 4294967295\n#endif\n\n#ifndef MAXINT64\n  #if defined _LONGLONG || defined __LONG_LONG_MAX__ || defined LLONG_MAX\n    #define MAXINT64   9223372036854775807ll\n  #else\n    #define MAXINT64   9223372036854775807l\n  #endif\n#endif\n#ifndef MAXUINT64\n  #if defined _LONGLONG || defined __LONG_LONG_MAX__ || defined LLONG_MAX\n    #define MAXUINT64 18446744073709551615ll\n  #else\n    #define MAXUINT64 18446744073709551615l\n  #endif\n#endif\n\n#ifndef DOFASTMATH\n  #define DOFASTMATH\n#endif\n\n\n#ifndef CALLOC\n#define CALLOC(ptr, nr)\\\n  if(!((void *) ptr = calloc((size_t)(nr), sizeof(*ptr))) && nr) {\\\n    printf(\"calloc of %d bytes failed on line %d of file %s\\n\",\\\n           (size_t) nr * sizeof(*ptr), __LINE__, __FILE__);\\\n  }\n#endif\n\n#ifndef MALLOC\n#define MALLOC(ptr, nr)\\\n  if(!((void *) ptr = malloc((size_t)((size_t) (nr) * sizeof(*ptr)))) && nr) {\\\n    printf(\"malloc of %d bytes failed on line %d of file %s\\n\",\\\n           (size_t) nr * sizeof(*ptr), __LINE__, __FILE__);\\\n  }\n#endif\n\n#ifndef REALLOC\n#define REALLOC(ptr, nr)\\\n  if(!((void *) ptr = realloc(ptr, (size_t)((size_t) (nr) * sizeof(*ptr)))) && nr) {\\\n    printf(\"realloc of %d bytes failed on line %d of file %s\\n\",\\\n           (size_t) nr * sizeof(*ptr), __LINE__, __FILE__);\\\n  }\n#endif\n\n#ifndef FREE\n#define FREE(ptr)\\\n  if((void *) ptr != NULL) {\\\n    free(ptr);\\\n    ptr = NULL; \\\n  }\n#endif\n\n#ifndef MEMCOPY\n#define MEMCOPY(nptr, optr, nr)\\\n  memcpy((nptr), (optr), (size_t)((size_t)(nr) * sizeof(*(optr))))\n#endif\n\n#ifndef MEMMOVE\n#define MEMMOVE(nptr, optr, nr)\\\n  memmove((nptr), (optr), (size_t)((size_t)(nr) * sizeof(*(optr))))\n#endif\n\n#ifndef MEMALLOCCOPY\n#define MEMALLOCCOPY(nptr, optr, nr)\\\n  {MALLOC(nptr, (size_t)(nr));\\\n   MEMCOPY(nptr, optr, (size_t)(nr));}\n#endif\n\n#ifndef STRALLOCCOPY\n#define STRALLOCCOPY(nstr, ostr)\\\n  {nstr = (char *) malloc((size_t) (strlen(ostr) + 1));\\\n   strcpy(nstr, ostr);}\n#endif\n\n#ifndef MEMCLEAR\n/*#define useMMX*/\n#ifdef useMMX\n  #define MEMCLEAR(ptr, nr)\\\n    mem_set((ptr), '\\0', (size_t)((size_t)(nr) * sizeof(*(ptr))))\n#else\n  #define MEMCLEAR(ptr, nr)\\\n    memset((ptr), '\\0', (size_t)((size_t)(nr) * sizeof(*(ptr))))\n#endif\n#endif\n\n\n#define MIN(x, y)         ((x) < (y) ? (x) : (y))\n#define MAX(x, y)         ((x) > (y) ? (x) : (y))\n#define SETMIN(x, y)      if((x) > (y)) x = y\n#define SETMAX(x, y)      if((x) < (y)) x = y\n#define LIMIT(lo, x, hi)  ((x < (lo) ? lo : ((x) > hi ? hi : x)))\n#define BETWEEN(x, a, b)  (MYBOOL) (((x)-(a)) * ((x)-(b)) <= 0)\n#define IF(t, x, y)       ((t) ? (x) : (y))\n#define SIGN(x)           ((x) < 0 ? -1 : 1)\n\n#define DELTA_SIZE(newSize, oldSize) ((int) ((newSize) * MIN(1.33, pow(1.5, fabs((double)newSize)/((oldSize+newSize)+1)))))\n\n#ifndef CMP_CALLMODEL\n#if (defined WIN32) || (defined WIN64)\n  #define CMP_CALLMODEL _cdecl\n#else\n  #define CMP_CALLMODEL\n#endif\n#endif\n\ntypedef int (CMP_CALLMODEL findCompare_func)(const void *current, const void *candidate);\n#define CMP_COMPARE(current, candidate) ( current < candidate ? -1 : (current > candidate ? 1 : 0) )\n#define CMP_ATTRIBUTES(item)            (((char *) attributes)+(item)*recsize)\n#define CMP_TAGS(item)                  (((char *) tags)+(item)*tagsize)\n\n#ifndef UNIONTYPE\n  #ifdef __cplusplus\n    #define UNIONTYPE\n  #else\n    #define UNIONTYPE union\n  #endif\n#endif\n\n/* This defines a 16 byte sort record (in both 32 and 64 bit OS-es) */\ntypedef struct _QSORTrec1\n{\n  void     *ptr;\n  void     *ptr2;\n} QSORTrec1;\ntypedef struct _QSORTrec2\n{\n  void     *ptr;\n  double   realval;\n} QSORTrec2;\ntypedef struct _QSORTrec3\n{\n  void     *ptr;\n  int      intval;\n  int      intpar1;\n} QSORTrec3;\ntypedef struct _QSORTrec4\n{\n  REAL     realval;\n  int      intval;\n  int      intpar1;\n} QSORTrec4;\ntypedef struct _QSORTrec5\n{\n  double   realval;\n  long int longval;\n} QSORTrec5;\ntypedef struct _QSORTrec6\n{\n  double   realval;\n  double   realpar1;\n} QSORTrec6;\ntypedef struct _QSORTrec7\n{\n  int      intval;\n  int      intpar1;\n  int      intpar2;\n  int      intpar3;\n} QSORTrec7;\nunion QSORTrec\n{\n  QSORTrec1 pvoid2;\n  QSORTrec2 pvoidreal;\n  QSORTrec3 pvoidint2;\n  QSORTrec4 realint2;\n  QSORTrec5 reallong;\n  QSORTrec6 real2;\n  QSORTrec7 int4;\n};\n\n\n#ifdef __cplusplus\n  extern \"C\" {\n#endif\n\nint intpow(int base, int exponent);\nint mod(int n, int d);\n\nvoid strtoup(char *s);\nvoid strtolo(char *s);\nvoid strcpyup(char *t, const char *s);\nvoid strcpylo(char *t, const char *s);\n\nMYBOOL so_stdname(char *stdname, const char *descname, int buflen);\nint gcd(LLONG a, LLONG b, int *c, int *d);\n\nint findIndex(int target, int *attributes, int count, int offset);\nint findIndexEx(void *target, void *attributes, int count, int offset, int recsize, findCompare_func findCompare, MYBOOL ascending);\n\nvoid qsortex_swap(void *attributes, int l, int r, int recsize,\n                         void *tags, int tagsize, char *save, char *savetag);\n\nint qsortex(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare, void *tags, int tagsize);\n\nint CMP_CALLMODEL compareCHAR(const void *current, const void *candidate);\nint CMP_CALLMODEL compareINT(const void *current, const void *candidate);\nint CMP_CALLMODEL compareREAL(const void *current, const void *candidate);\nvoid hpsort(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare);\nvoid hpsortex(void *attributes, int count, int offset, int recsize, MYBOOL descending, findCompare_func findCompare, int *tags);\n\nvoid QS_swap(UNIONTYPE QSORTrec a[], int i, int j);\nint QS_addfirst(UNIONTYPE QSORTrec a[], void *mydata);\nint QS_append(UNIONTYPE QSORTrec a[], int ipos, void *mydata);\nvoid QS_replace(UNIONTYPE QSORTrec a[], int ipos, void *mydata);\nvoid QS_insert(UNIONTYPE QSORTrec a[], int ipos, void *mydata, int epos);\nvoid QS_delete(UNIONTYPE QSORTrec a[], int ipos, int epos);\nMYBOOL QS_execute(UNIONTYPE QSORTrec a[], int count, findCompare_func findCompare, int *nswaps);\n\nint sortByREAL(int *item, REAL *weight, int size, int offset, MYBOOL unique);\nint sortByINT(int *item, int *weight, int size, int offset, MYBOOL unique);\nREAL sortREALByINT(REAL *item, int *weight, int size, int offset, MYBOOL unique);\n\ndouble timeNow(void);\n\nvoid blockWriteBOOL(FILE *output, const char *label, MYBOOL *myvector, int first, int last, MYBOOL asRaw);\nvoid blockWriteINT(FILE *output, const char *label, int *myvector, int first, int last);\nvoid blockWriteREAL(FILE *output, const char *label, REAL *myvector, int first, int last);\n\nvoid printvec( int n, REAL *x, int modulo );\nvoid printmatSQ( int size, int n, REAL *X, int modulo );\nvoid printmatUT( int size, int n, REAL *U, int modulo );\n\nunsigned int catchFPU(unsigned int mask);\n\n#if defined _MSC_VER\nint fileCount( const char *filemask );\nMYBOOL fileSearchPath( const char *envvar, const char *searchfile, const char *foundpath );\n#endif\n\n#ifdef __cplusplus\n  }\n#endif\n\n#endif /* HEADER_commonlib */\n"
  },
  {
    "path": "utilities/lp_solve/shared/mmio.c",
    "content": "/*\n*   Matrix Market I/O library for ANSI C\n*\n*   See https://math.nist.gov/MatrixMarket for details.\n*\n*   (Version 1.01, 5/2003)\n*/\n\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <ctype.h>\n\n#include \"mmio.h\"\n\nint mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,\n                double **val_, int **I_, int **J_)\n{\n    FILE *f;\n    MM_typecode matcode;\n    int M, N, nz;\n    int i;\n    double *val;\n    int *I, *J;\n    int x;\n\n    if ((f = fopen(fname, \"r\")) == NULL)\n            return -1;\n\n\n    if (mm_read_banner(f, &matcode) != 0)\n    {\n        printf(\"mm_read_unsymetric: Could not process Matrix Market banner \");\n        printf(\" in file [%s]\\n\", fname);\n        return -1;\n    }\n\n\n\n    if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) &&\n            mm_is_sparse(matcode)))\n    {\n        fprintf(stderr, \"Sorry, this application does not support \");\n        fprintf(stderr, \"Market Market type: [%s]\\n\",\n                mm_typecode_to_str(matcode));\n        return -1;\n    }\n\n    /* find out size of sparse matrix: M, N, nz .... */\n\n    if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0)\n    {\n        fprintf(stderr, \"read_unsymmetric_sparse(): could not parse matrix size.\\n\");\n        return -1;\n    }\n\n    *M_ = M;\n    *N_ = N;\n    *nz_ = nz;\n\n    /* reseve memory for matrices */\n\n    I = (int *) malloc(nz * sizeof(int));\n    J = (int *) malloc(nz * sizeof(int));\n    val = (double *) malloc(nz * sizeof(double));\n\n    *val_ = val;\n    *I_ = I;\n    *J_ = J;\n\n    /* NOTE: when reading in doubles, ANSI C requires the use of the \"l\"  */\n    /*   specifier as in \"%lg\", \"%lf\", \"%le\", otherwise errors will occur */\n    /*  (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15)            */\n\n    for (i=0; i<nz; i++)\n    {\n        x = fscanf(f, \"%d %d %lg\\n\", &I[i], &J[i], &val[i]);\n        I[i]--;  /* adjust from 1-based to 0-based */\n        J[i]--;\n    }\n    fclose(f);\n\n    return 0;\n}\n\nint mm_is_valid(MM_typecode matcode)\n{\n    if (!mm_is_matrix(matcode)) return 0;\n    if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0;\n    if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0;\n    if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) ||\n                mm_is_skew(matcode))) return 0;\n    return 1;\n}\n\nint mm_read_banner(FILE *f, MM_typecode *matcode)\n{\n    char line[MM_MAX_LINE_LENGTH];\n    char banner[MM_MAX_TOKEN_LENGTH];\n    char mtx[MM_MAX_TOKEN_LENGTH];\n    char crd[MM_MAX_TOKEN_LENGTH];\n    char data_type[MM_MAX_TOKEN_LENGTH];\n    char storage_scheme[MM_MAX_TOKEN_LENGTH];\n    char *p;\n\n\n    mm_clear_typecode(matcode);\n\n    if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)\n        return MM_PREMATURE_EOF;\n\n    if (sscanf(line, \"%s %s %s %s %s\", banner, mtx, crd, data_type,\n        storage_scheme) != 5)\n        return MM_PREMATURE_EOF;\n\n\t/* convert to lower case */\n    for (p=mtx; *p!='\\0'; *p= (char) tolower(*p),p++);\n    for (p=crd; *p!='\\0'; *p= (char) tolower(*p),p++);\n    for (p=data_type; *p!='\\0'; *p= (char) tolower(*p),p++);\n    for (p=storage_scheme; *p!='\\0'; *p= (char) tolower(*p),p++);\n\n    /* check for banner */\n    if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0)\n        return MM_NO_HEADER;\n\n    /* first field should be \"mtx\" */\n    if (strcmp(mtx, MM_MTX_STR) != 0)\n        return  MM_UNSUPPORTED_TYPE;\n    mm_set_matrix(matcode);\n\n\n    /* second field describes whether this is a sparse matrix (in coordinate\n            storgae) or a dense array */\n\n\n    if (strcmp(crd, MM_SPARSE_STR) == 0)\n        mm_set_sparse(matcode);\n    else\n    if (strcmp(crd, MM_DENSE_STR) == 0)\n            mm_set_dense(matcode);\n    else\n        return MM_UNSUPPORTED_TYPE;\n\n\n    /* third field */\n\n    if (strcmp(data_type, MM_REAL_STR) == 0)\n        mm_set_real(matcode);\n    else\n    if (strcmp(data_type, MM_COMPLEX_STR) == 0)\n        mm_set_complex(matcode);\n    else\n    if (strcmp(data_type, MM_PATTERN_STR) == 0)\n        mm_set_pattern(matcode);\n    else\n    if (strcmp(data_type, MM_INT_STR) == 0)\n        mm_set_integer(matcode);\n    else\n        return MM_UNSUPPORTED_TYPE;\n\n\n    /* fourth field */\n\n    if (strcmp(storage_scheme, MM_GENERAL_STR) == 0)\n        mm_set_general(matcode);\n    else\n    if (strcmp(storage_scheme, MM_SYMM_STR) == 0)\n        mm_set_symmetric(matcode);\n    else\n    if (strcmp(storage_scheme, MM_HERM_STR) == 0)\n        mm_set_hermitian(matcode);\n    else\n    if (strcmp(storage_scheme, MM_SKEW_STR) == 0)\n        mm_set_skew(matcode);\n    else\n        return MM_UNSUPPORTED_TYPE;\n\n\n    return 0;\n}\n\nint mm_write_mtx_crd_size(FILE *f, int M, int N, int nz)\n{\n    if (fprintf(f, \"%d %d %d\\n\", M, N, nz) < 0)\n        return MM_COULD_NOT_WRITE_FILE;\n    else\n        return 0;\n}\n\nint mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz )\n{\n    char line[MM_MAX_LINE_LENGTH];\n    int num_items_read;\n\n    /* set return null parameter values, in case we exit with errors */\n    *M = *N = *nz = 0;\n\n    /* now continue scanning until you reach the end-of-comments */\n    do {\n      if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)\n          return MM_PREMATURE_EOF;\n    } while (line[0] == '%');\n\n    /* line[] is either blank, har M,N or M,N,nz */\n    if (sscanf(line, \"%d %d %d\", M, N, nz) >= 2)\n      return 0;\n\n    else\n    do {\n        num_items_read = fscanf(f, \"%d %d %d\", M, N, nz);\n        if (num_items_read == EOF) return MM_PREMATURE_EOF;\n    } while (num_items_read < 2);\n\n    return 0;\n}\n\n\nint mm_read_mtx_array_size(FILE *f, int *M, int *N)\n{\n    char line[MM_MAX_LINE_LENGTH];\n    int num_items_read;\n    /* set return null parameter values, in case we exit with errors */\n    *M = *N = 0;\n\n    /* now continue scanning until you reach the end-of-comments */\n    do\n    {\n        if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)\n            return MM_PREMATURE_EOF;\n    }while (line[0] == '%');\n\n    /* line[] is either blank or has M,N, nz */\n    if (sscanf(line, \"%d %d\", M, N) == 2)\n        return 0;\n\n    else /* we have a blank line */\n    do\n    {\n        num_items_read = fscanf(f, \"%d %d\", M, N);\n        if (num_items_read == EOF) return MM_PREMATURE_EOF;\n    }\n    while (num_items_read != 2);\n\n    return 0;\n}\n\nint mm_write_mtx_array_size(FILE *f, int M, int N)\n{\n    if (fprintf(f, \"%d %d\\n\", M, N) < 0)\n        return MM_COULD_NOT_WRITE_FILE;\n    else\n        return 0;\n}\n\n\n\n/*-------------------------------------------------------------------------*/\n\n/******************************************************************/\n/* use when I[], J[], and val[]J, and val[] are already allocated */\n/******************************************************************/\n\nint mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],\n        double val[], MM_typecode matcode)\n{\n    (void)M; // Remove unused variable warning\n    (void)N; // Remove unused variable warning\n    int i;\n    (void)M; // Remove unused variable warning\n    (void)N; // Remove unused variable warning\n    if (mm_is_complex(matcode))\n    {\n        for (i=0; i<nz; i++)\n            if (fscanf(f, \"%d %d %lg %lg\", &I[i], &J[i], &val[2*i], &val[2*i+1])\n                != 4) return MM_PREMATURE_EOF;\n    }\n    else if (mm_is_real(matcode))\n    {\n        for (i=0; i<nz; i++)\n        {\n            if (fscanf(f, \"%d %d %lg\\n\", &I[i], &J[i], &val[i])\n                != 3) return MM_PREMATURE_EOF;\n\n        }\n    }\n\n    else if (mm_is_pattern(matcode))\n    {\n        for (i=0; i<nz; i++)\n            if (fscanf(f, \"%d %d\", &I[i], &J[i])\n                != 2) return MM_PREMATURE_EOF;\n    }\n    else\n        return MM_UNSUPPORTED_TYPE;\n\n    return 0;\n\n}\n\nint mm_read_mtx_crd_entry(FILE *f, int *I, int *J,\n        double *real, double *imag, MM_typecode matcode)\n{\n    if (mm_is_complex(matcode))\n    {\n            if (fscanf(f, \"%d %d %lg %lg\", I, J, real, imag)\n                != 4) return MM_PREMATURE_EOF;\n    }\n    else if (mm_is_real(matcode))\n    {\n            if (fscanf(f, \"%d %d %lg\\n\", I, J, real)\n                != 3) return MM_PREMATURE_EOF;\n\n    }\n\n    else if (mm_is_pattern(matcode))\n    {\n            if (fscanf(f, \"%d %d\", I, J) != 2) return MM_PREMATURE_EOF;\n    }\n    else\n        return MM_UNSUPPORTED_TYPE;\n\n    return 0;\n\n}\n\n\n/************************************************************************\n    mm_read_mtx_crd()  fills M, N, nz, array of values, and return\n                        type code, e.g. 'MCRS'\n\n                        if matrix is complex, values[] is of size 2*nz,\n                            (nz pairs of real/imaginary values)\n************************************************************************/\n\nint mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,\n        double **val, MM_typecode *matcode)\n{\n    int ret_code;\n    FILE *f;\n\n    if (strcmp(fname, \"stdin\") == 0) f=stdin;\n    else\n    if ((f = fopen(fname, \"r\")) == NULL)\n        return MM_COULD_NOT_READ_FILE;\n\n\n    if ((ret_code = mm_read_banner(f, matcode)) != 0)\n        return ret_code;\n\n    if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&\n            mm_is_matrix(*matcode)))\n        return MM_UNSUPPORTED_TYPE;\n\n    if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0)\n        return ret_code;\n\n\n    *I = (int *)  malloc(*nz * sizeof(int));\n    *J = (int *)  malloc(*nz * sizeof(int));\n    *val = NULL;\n\n    if (mm_is_complex(*matcode))\n    {\n        *val = (double *) malloc(*nz * 2 * sizeof(double));\n        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,\n                *matcode);\n        if (ret_code != 0) return ret_code;\n    }\n    else if (mm_is_real(*matcode))\n    {\n        *val = (double *) malloc(*nz * sizeof(double));\n        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,\n                *matcode);\n        if (ret_code != 0) return ret_code;\n    }\n\n    else if (mm_is_pattern(*matcode))\n    {\n        ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,\n                *matcode);\n        if (ret_code != 0) return ret_code;\n    }\n\n    if (f != stdin) fclose(f);\n    return 0;\n}\n\nint mm_write_banner(FILE *f, MM_typecode matcode)\n{\n    char *str = mm_typecode_to_str(matcode);\n    int ret_code;\n\n    ret_code = fprintf(f, \"%s %s\\n\", MatrixMarketBanner, str);\n/*    free(str);  This is a bug from the official distribution - KE fixed */\n    if (ret_code < 0 )\n        return MM_COULD_NOT_WRITE_FILE;\n    else\n        return 0;\n}\n\nint mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],\n        double val[], MM_typecode matcode)\n{\n    FILE *f;\n    int i;\n\n    if (strcmp(fname, \"stdout\") == 0)\n        f = stdout;\n    else\n    if ((f = fopen(fname, \"w\")) == NULL)\n        return MM_COULD_NOT_WRITE_FILE;\n\n    /* print banner followed by typecode */\n    fprintf(f, \"%s \", MatrixMarketBanner);\n    fprintf(f, \"%s\\n\", mm_typecode_to_str(matcode));\n\n    /* print matrix sizes and nonzeros */\n    fprintf(f, \"%d %d %d\\n\", M, N, nz);\n\n    /* print values */\n    if (mm_is_pattern(matcode))\n        for (i=0; i<nz; i++)\n            fprintf(f, \"%d %d\\n\", I[i], J[i]);\n    else\n    if (mm_is_real(matcode))\n        for (i=0; i<nz; i++)\n            fprintf(f, \"%d %d %20.16g\\n\", I[i], J[i], val[i]);\n    else\n    if (mm_is_complex(matcode))\n        for (i=0; i<nz; i++)\n            fprintf(f, \"%d %d %20.16g %20.16g\\n\", I[i], J[i], val[2*i],\n                        val[2*i+1]);\n    else\n    {\n        if (f != stdout) fclose(f);\n        return MM_UNSUPPORTED_TYPE;\n    }\n\n    if (f !=stdout) fclose(f);\n\n    return 0;\n}\n\n\nchar  *mm_typecode_to_str(MM_typecode matcode)\n{\n    static char buffer[MM_MAX_LINE_LENGTH];\n    const char * types[4];\n\n    /* check for MTX type */\n    if (mm_is_matrix(matcode))\n        types[0] = MM_MTX_STR;\n    else\n        return NULL;\n\n    /* check for CRD or ARR matrix */\n    if (mm_is_sparse(matcode))\n        types[1] = MM_SPARSE_STR;\n    else\n    if (mm_is_dense(matcode))\n        types[1] = MM_DENSE_STR;\n    else\n        return NULL;\n\n    /* check for element data type */\n    if (mm_is_real(matcode))\n        types[2] = MM_REAL_STR;\n    else\n    if (mm_is_complex(matcode))\n        types[2] = MM_COMPLEX_STR;\n    else\n    if (mm_is_pattern(matcode))\n        types[2] = MM_PATTERN_STR;\n    else\n    if (mm_is_integer(matcode))\n        types[2] = MM_INT_STR;\n    else\n        return NULL;\n\n\n    /* check for symmetry type */\n    if (mm_is_general(matcode))\n        types[3] = MM_GENERAL_STR;\n    else\n    if (mm_is_symmetric(matcode))\n        types[3] = MM_SYMM_STR;\n    else\n    if (mm_is_hermitian(matcode))\n        types[3] = MM_HERM_STR;\n    else\n    if (mm_is_skew(matcode))\n        types[3] = MM_SKEW_STR;\n    else\n        return NULL;\n\n    sprintf(buffer,\"%s %s %s %s\", types[0], types[1], types[2], types[3]);\n    return & buffer[0];\n\n}\n"
  },
  {
    "path": "utilities/lp_solve/shared/mmio.h",
    "content": "/*\n*   Matrix Market I/O library for ANSI C\n*\n*   See https://math.nist.gov/MatrixMarket for details.\n*\n*\n*/\n\n#ifndef MM_IO_H\n#define MM_IO_H\n\n#define MM_MAX_LINE_LENGTH 1025\n#define MatrixMarketBanner \"%%MatrixMarket\"\n#define MM_MAX_TOKEN_LENGTH 64\n\ntypedef char MM_typecode[4];\n\nchar *mm_typecode_to_str(MM_typecode matcode);\n\nint mm_read_banner(FILE *f, MM_typecode *matcode);\nint mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz);\nint mm_read_mtx_array_size(FILE *f, int *M, int *N);\n\nint mm_write_banner(FILE *f, MM_typecode matcode);\nint mm_write_mtx_crd_size(FILE *f, int M, int N, int nz);\nint mm_write_mtx_array_size(FILE *f, int M, int N);\n\n\n/********************* MM_typecode query fucntions ***************************/\n\n#define mm_is_matrix(typecode)  ((typecode)[0]=='M')\n\n#define mm_is_sparse(typecode)  ((typecode)[1]=='C')\n#define mm_is_coordinate(typecode)((typecode)[1]=='C')\n#define mm_is_dense(typecode) ((typecode)[1]=='A')\n#define mm_is_array(typecode) ((typecode)[1]=='A')\n\n#define mm_is_complex(typecode) ((typecode)[2]=='C')\n#define mm_is_real(typecode)    ((typecode)[2]=='R')\n#define mm_is_pattern(typecode) ((typecode)[2]=='P')\n#define mm_is_integer(typecode) ((typecode)[2]=='I')\n\n#define mm_is_symmetric(typecode)((typecode)[3]=='S')\n#define mm_is_general(typecode) ((typecode)[3]=='G')\n#define mm_is_skew(typecode)  ((typecode)[3]=='K')\n#define mm_is_hermitian(typecode)((typecode)[3]=='H')\n\nint mm_is_valid(MM_typecode matcode);   /* too complex for a macro */\n\n\n/********************* MM_typecode modify fucntions ***************************/\n\n#define mm_set_matrix(typecode) ((*typecode)[0]='M')\n#define mm_set_coordinate(typecode) ((*typecode)[1]='C')\n#define mm_set_array(typecode)  ((*typecode)[1]='A')\n#define mm_set_dense(typecode)  mm_set_array(typecode)\n#define mm_set_sparse(typecode) mm_set_coordinate(typecode)\n\n#define mm_set_complex(typecode)((*typecode)[2]='C')\n#define mm_set_real(typecode) ((*typecode)[2]='R')\n#define mm_set_pattern(typecode)((*typecode)[2]='P')\n#define mm_set_integer(typecode)((*typecode)[2]='I')\n\n\n#define mm_set_symmetric(typecode)((*typecode)[3]='S')\n#define mm_set_general(typecode)((*typecode)[3]='G')\n#define mm_set_skew(typecode) ((*typecode)[3]='K')\n#define mm_set_hermitian(typecode)((*typecode)[3]='H')\n\n#define mm_clear_typecode(typecode) ((*typecode)[0]=(*typecode)[1]= \\\n                  (*typecode)[2]=' ',(*typecode)[3]='G')\n\n#define mm_initialize_typecode(typecode) mm_clear_typecode(typecode)\n\n\n/********************* Matrix Market error codes ***************************/\n\n\n#define MM_COULD_NOT_READ_FILE  11\n#define MM_PREMATURE_EOF        12\n#define MM_NOT_MTX              13\n#define MM_NO_HEADER            14\n#define MM_UNSUPPORTED_TYPE     15\n#define MM_LINE_TOO_LONG        16\n#define MM_COULD_NOT_WRITE_FILE 17\n\n\n/******************** Matrix Market internal definitions ********************\n\n   MM_matrix_typecode: 4-character sequence\n\n            ojbect    sparse/     data        storage\n                  dense       type        scheme\n\n   string position:  [0]        [1]     [2]         [3]\n\n   Matrix typecode:  M(atrix)  C(oord)    R(eal)    G(eneral)\n                    A(array)  C(omplex)   H(ermitian)\n                      P(attern)   S(ymmetric)\n                        I(nteger) K(kew)\n\n ***********************************************************************/\n\n#define MM_MTX_STR    \"matrix\"\n#define MM_ARRAY_STR  \"array\"\n#define MM_DENSE_STR  \"array\"\n#define MM_COORDINATE_STR \"coordinate\"\n#define MM_SPARSE_STR \"coordinate\"\n#define MM_COMPLEX_STR  \"complex\"\n#define MM_REAL_STR   \"real\"\n#define MM_INT_STR    \"integer\"\n#define MM_GENERAL_STR  \"general\"\n#define MM_SYMM_STR   \"symmetric\"\n#define MM_HERM_STR   \"hermitian\"\n#define MM_SKEW_STR   \"skew-symmetric\"\n#define MM_PATTERN_STR  \"pattern\"\n\n\n/*  high level routines */\n\nint mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],\n     double val[], MM_typecode matcode);\nint mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],\n    double val[], MM_typecode matcode);\nint mm_read_mtx_crd_entry(FILE *f, int *I, int *J, double *real, double *img,\n      MM_typecode matcode);\n\nint mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,\n                double **val_, int **I_, int **J_);\n\n\n\n#endif\n"
  },
  {
    "path": "utilities/lp_solve/shared/myblas.c",
    "content": "\n#include <stdlib.h>\n#include <stdio.h>\n/*#include <memory.h>*/\n#include <string.h>\n#include <math.h>\n#include \"myblas.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n/* ************************************************************************ */\n/* Initialize BLAS interfacing routines                                     */\n/* ************************************************************************ */\nMYBOOL mustinitBLAS = TRUE;\n#ifdef WIN32\n  HINSTANCE hBLAS = NULL;\n#else\n  void      *hBLAS = NULL;\n#endif\n\n\n/* ************************************************************************ */\n/* Function pointers for external BLAS library (C base 0)                   */\n/* ************************************************************************ */\nBLAS_dscal_func  *BLAS_dscal;\nBLAS_dcopy_func  *BLAS_dcopy;\nBLAS_daxpy_func  *BLAS_daxpy;\nBLAS_dswap_func  *BLAS_dswap;\nBLAS_ddot_func   *BLAS_ddot;\nBLAS_idamax_func *BLAS_idamax;\nBLAS_dload_func  *BLAS_dload;\nBLAS_dnormi_func *BLAS_dnormi;\n\n\n/* ************************************************************************ */\n/* Define the BLAS interfacing routines                                     */\n/* ************************************************************************ */\n\nvoid init_BLAS(void)\n{\n  if(mustinitBLAS) {\n    load_BLAS(NULL);\n    mustinitBLAS = FALSE;\n  }\n}\n\nMYBOOL is_nativeBLAS(void)\n{\n#ifdef LoadableBlasLib\n  return( (MYBOOL) (hBLAS == NULL) );\n#else\n  return( TRUE );\n#endif\n}\n\nMYBOOL load_BLAS(const char *libname)\n{\n  MYBOOL result = TRUE;\n\n#ifdef LoadableBlasLib\n  if(hBLAS != NULL) {\n  #ifdef WIN32\n    FreeLibrary(hBLAS);\n  #else\n    dlclose(hBLAS);\n  #endif\n    hBLAS = NULL;\n  }\n#endif\n\n  if(libname == NULL) {\n    if(!mustinitBLAS && is_nativeBLAS())\n      return( FALSE );\n    BLAS_dscal = my_dscal;\n    BLAS_dcopy = my_dcopy;\n    BLAS_daxpy = my_daxpy;\n    BLAS_dswap = my_dswap;\n    BLAS_ddot  = my_ddot;\n    BLAS_idamax = my_idamax;\n    BLAS_dload = my_dload;\n    BLAS_dnormi = my_dnormi;\n    if(mustinitBLAS)\n      mustinitBLAS = FALSE;\n  }\n  else {\n#ifdef LoadableBlasLib\n  #ifdef WIN32\n   /* Get a handle to the Windows DLL module. */\n    hBLAS = LoadLibrary(libname);\n\n   /* If the handle is valid, try to get the function addresses. */\n    result = (MYBOOL) (hBLAS != NULL);\n    if(result) {\n      BLAS_dscal  = (BLAS_dscal_func *)  GetProcAddress(hBLAS, BLAS_prec \"scal\");\n      BLAS_dcopy  = (BLAS_dcopy_func *)  GetProcAddress(hBLAS, BLAS_prec \"copy\");\n      BLAS_daxpy  = (BLAS_daxpy_func *)  GetProcAddress(hBLAS, BLAS_prec \"axpy\");\n      BLAS_dswap  = (BLAS_dswap_func *)  GetProcAddress(hBLAS, BLAS_prec \"swap\");\n      BLAS_ddot   = (BLAS_ddot_func *)   GetProcAddress(hBLAS, BLAS_prec \"dot\");\n      BLAS_idamax = (BLAS_idamax_func *) GetProcAddress(hBLAS, \"i\" BLAS_prec \"amax\");\n#if 0\n      BLAS_dload  = (BLAS_dload_func *)  GetProcAddress(hBLAS, BLAS_prec \"load\");\n      BLAS_dnormi = (BLAS_dnormi_func *) GetProcAddress(hBLAS, BLAS_prec \"normi\");\n#endif\n    }\n  #else\n   /* First standardize UNIX .SO library name format. */\n    char blasname[260];\n    const char *ptr;\n\n    strcpy(blasname, libname);\n    if((ptr = strrchr(libname, '/')) == NULL)\n      ptr = libname;\n    else\n      ptr++;\n    blasname[(int) (ptr - libname)] = 0;\n    if(strncmp(ptr, \"lib\", 3))\n      strcat(blasname, \"lib\");\n    strcat(blasname, ptr);\n    if(strcmp(blasname + strlen(blasname) - 3, \".so\"))\n      strcat(blasname, \".so\");\n\n   /* Get a handle to the module. */\n    hBLAS = dlopen(blasname, RTLD_LAZY);\n\n   /* If the handle is valid, try to get the function addresses. */\n    result = (MYBOOL) (hBLAS != NULL);\n    if(result) {\n      BLAS_dscal  = (BLAS_dscal_func *)  dlsym(hBLAS, BLAS_prec \"scal\");\n      BLAS_dcopy  = (BLAS_dcopy_func *)  dlsym(hBLAS, BLAS_prec \"copy\");\n      BLAS_daxpy  = (BLAS_daxpy_func *)  dlsym(hBLAS, BLAS_prec \"axpy\");\n      BLAS_dswap  = (BLAS_dswap_func *)  dlsym(hBLAS, BLAS_prec \"swap\");\n      BLAS_ddot   = (BLAS_ddot_func *)   dlsym(hBLAS, BLAS_prec \"dot\");\n      BLAS_idamax = (BLAS_idamax_func *) dlsym(hBLAS, \"i\" BLAS_prec \"amax\");\n#if 0\n      BLAS_dload  = (BLAS_dload_func *)  dlsym(hBLAS, BLAS_prec \"load\");\n      BLAS_dnormi = (BLAS_dnormi_func *) dlsym(hBLAS, BLAS_prec \"normi\");\n#endif\n    }\n  #endif\n#endif\n    /* Do validation */\n    if(!result ||\n       ((BLAS_dscal  == NULL) ||\n        (BLAS_dcopy  == NULL) ||\n        (BLAS_daxpy  == NULL) ||\n        (BLAS_dswap  == NULL) ||\n        (BLAS_ddot   == NULL) ||\n        (BLAS_idamax == NULL) ||\n        (BLAS_dload  == NULL) ||\n        (BLAS_dnormi == NULL))\n      ) {\n      load_BLAS(NULL);\n      result = FALSE;\n    }\n  }\n  return( result );\n}\nMYBOOL unload_BLAS(void)\n{\n  return( load_BLAS(NULL) );\n}\n\n\n/* ************************************************************************ */\n/* Now define the unoptimized local BLAS functions                          */\n/* ************************************************************************ */\nvoid daxpy( int n, REAL da, REAL *dx, int incx, REAL *dy, int incy)\n{\n  dx++;\n  dy++;\n  BLAS_daxpy( &n, &da, dx, &incx, dy, &incy);\n}\nvoid BLAS_CALLMODEL my_daxpy( int *_n, REAL *_da, REAL *dx, int *_incx, REAL *dy, int *_incy)\n{\n\n/* constant times a vector plus a vector.\n   uses unrolled loops for increments equal to one.\n   jack dongarra, linpack, 3/11/78.\n   modified 12/3/93, array[1] declarations changed to array[*] */\n\n  int      i, ix, iy;\n#if !defined DOFASTMATH\n  int      m, mp1;\n#endif\n  REAL rda;\n  REAL     da = *_da;\n  int      n = *_n, incx = *_incx, incy = *_incy;\n\n  if (n <= 0) return;\n  if (da == 0.0) return;\n\n  dx--;\n  dy--;\n  ix = 1;\n  iy = 1;\n  if (incx < 0)\n     ix = (-n+1)*incx + 1;\n  if (incy < 0)\n     iy = (-n+1)*incy + 1;\n  rda = da;\n\n/* CPU intensive loop; option to do pointer arithmetic */\n#if defined DOFASTMATH\n  {\n    REAL *xptr, *yptr;\n    for (i = 1, xptr = dx + ix, yptr = dy + iy;\n         i <= n; i++, xptr += incx, yptr += incy)\n      (*yptr) += rda*(*xptr);\n    return;\n  }\n#else\n\n  if (incx==1 && incy==1) goto x20;\n\n/* code for unequal increments or equal increments not equal to 1 */\n  for (i = 1; i<=n; i++) {\n     dy[iy]+= rda*dx[ix];\n     ix+= incx;\n     iy+= incy;\n  }\n  return;\n\n/*  code for both increments equal to 1 */\n\n/*  clean-up loop */\nx20:\n  m = n % 4;\n  if (m == 0) goto x40;\n  for (i = 1; i<=m; i++)\n     dy[i]+= rda*dx[i];\n  if(n < 4) return;\nx40:\n  mp1 = m + 1;\n  for (i = mp1; i<=n; i=i+4) {\n    dy[i]+= rda*dx[i];\n    dy[i + 1]+= rda*dx[i + 1];\n    dy[i + 2]+= rda*dx[i + 2];\n    dy[i + 3]+= rda*dx[i + 3];\n  }\n#endif\n}\n\n\n/* ************************************************************************ */\nvoid dcopy( int n, REAL *dx, int incx, REAL *dy, int incy)\n{\n  dx++;\n  dy++;\n  BLAS_dcopy( &n, dx, &incx, dy, &incy);\n}\n\nvoid BLAS_CALLMODEL my_dcopy (int *_n, REAL *dx, int *_incx, REAL *dy, int *_incy)\n{\n\n/* copies a vector, x, to a vector, y.\n   uses unrolled loops for increments equal to one.\n   jack dongarra, linpack, 3/11/78.\n   modified 12/3/93, array[1] declarations changed to array[*] */\n\n  int      i, ix, iy;\n#if !defined DOFASTMATH\n  int      m, mp1;\n#endif\n  int      n = *_n, incx = *_incx, incy = *_incy;\n\n  if (n<=0) return;\n\n  dx--;\n  dy--;\n  ix = 1;\n  iy = 1;\n  if (incx<0)\n    ix = (-n+1)*incx + 1;\n  if (incy<0)\n    iy = (-n+1)*incy + 1;\n\n\n/* CPU intensive loop; option to do pointer arithmetic */\n#if defined DOFASTMATH\n  {\n    REAL *xptr, *yptr;\n    for (i = 1, xptr = dx + ix, yptr = dy + iy;\n         i <= n; i++, xptr += incx, yptr += incy)\n      (*yptr) = (*xptr);\n    return;\n  }\n#else\n\n  if (incx==1 && incy==1) goto x20;\n\n/* code for unequal increments or equal increments not equal to 1 */\n\n  for (i = 1; i<=n; i++) {\n    dy[iy] = dx[ix];\n    ix+= incx;\n    iy+= incy;\n  }\n  return;\n\n/* code for both increments equal to 1 */\n\n/* version with fast machine copy logic (requires memory.h or string.h) */\nx20:\n#if defined DOFASTMATH\n  MEMCOPY(&dy[1], &dx[1], n);\n  return;\n#else\n\n  m = n % 7;\n  if (m == 0) goto x40;\n  for (i = 1; i<=m; i++)\n     dy[i] = dx[i];\n  if (n < 7) return;\n\nx40:\n  mp1 = m + 1;\n  for (i = mp1; i<=n; i=i+7) {\n     dy[i] = dx[i];\n     dy[i + 1] = dx[i + 1];\n     dy[i + 2] = dx[i + 2];\n     dy[i + 3] = dx[i + 3];\n     dy[i + 4] = dx[i + 4];\n     dy[i + 5] = dx[i + 5];\n     dy[i + 6] = dx[i + 6];\n  }\n#endif\n#endif\n}\n\n\n/* ************************************************************************ */\n\nvoid dscal (int n, REAL da, REAL *dx, int incx)\n{\n  dx++;\n  BLAS_dscal (&n, &da, dx, &incx);\n}\n\nvoid BLAS_CALLMODEL my_dscal (int *_n, REAL *_da, REAL *dx, int *_incx)\n{\n\n/* Multiply a vector by a constant.\n\n     --Input--\n        N  number of elements in input vector(s)\n       DA  double precision scale factor\n       DX  double precision vector with N elements\n     INCX  storage spacing between elements of DX\n\n     --Output--\n       DX  double precision result (unchanged if N.LE.0)\n\n     Replace double precision DX by double precision DA*DX.\n     For I = 0 to N-1, replace DX(IX+I*INCX) with  DA * DX(IX+I*INCX),\n     where IX = 1 if INCX .GE. 0, else IX = 1+(1-N)*INCX. */\n\n  int      i;\n#if !defined DOFASTMATH\n  int      ix, m, mp1;\n#endif\n  REAL rda;\n  REAL      da = *_da;\n  int      n = *_n, incx = *_incx;\n\n  if (n <= 0)\n    return;\n  rda = da;\n\n  dx--;\n\n/* Optionally do fast pointer arithmetic */\n#if defined DOFASTMATH\n  {\n    REAL *xptr;\n    for (i = 1, xptr = dx + 1; i <= n; i++, xptr += incx)\n      (*xptr) *= rda;\n    return;\n  }\n#else\n\n  if (incx == 1)\n    goto x20;\n\n/* Code for increment not equal to 1 */\n  ix = 1;\n  if (incx < 0)\n    ix = (-n+1)*incx + 1;\n  for(i = 1; i <= n; i++, ix += incx)\n    dx[ix] *= rda;\n  return;\n\n/* Code for increment equal to 1. */\n/* Clean-up loop so remaining vector length is a multiple of 5. */\nx20:\n  m = n % 5;\n  if (m == 0) goto x40;\n  for( i = 1; i <= m; i++)\n    dx[i] *= rda;\n  if (n < 5)\n    return;\nx40:\n  mp1 = m + 1;\n  for(i = mp1; i <= n; i += 5) {\n    dx[i]   *= rda;\n    dx[i+1] *= rda;\n    dx[i+2] *= rda;\n    dx[i+3] *= rda;\n    dx[i+4] *= rda;\n  }\n#endif\n}\n\n\n/* ************************************************************************ */\n\nREAL ddot(int n, REAL *dx, int incx, REAL *dy, int incy)\n{\n  dx++;\n  dy++;\n  return( BLAS_ddot (&n, dx, &incx, dy, &incy) );\n}\n\nREAL BLAS_CALLMODEL my_ddot(int *_n, REAL *dx, int *_incx, REAL *dy, int *_incy)\n{\n\n/* forms the dot product of two vectors.\n   uses unrolled loops for increments equal to one.\n   jack dongarra, linpack, 3/11/78.\n   modified 12/3/93, array[1] declarations changed to array[*] */\n\n  REAL dtemp;\n  int      i, ix, iy;\n#if !defined DOFASTMATH\n  int      m, mp1;\n#endif\n  int      n = *_n, incx = *_incx, incy = *_incy;\n\n  dtemp = 0.0;\n  if (n<=0)\n    return( (REAL) dtemp);\n\n  dx--;\n  dy--;\n  ix = 1;\n  iy = 1;\n  if (incx<0)\n     ix = (-n+1)*incx + 1;\n  if (incy<0)\n     iy = (-n+1)*incy + 1;\n\n/* CPU intensive loop; option to do pointer arithmetic */\n\n#if defined DOFASTMATH\n  {\n    REAL *xptr, *yptr;\n    for (i = 1, xptr = dx + ix, yptr = dy + iy;\n         i <= n; i++, xptr += incx, yptr += incy)\n      dtemp+= (*yptr)*(*xptr);\n    return(dtemp);\n  }\n#else\n\n  if (incx==1 && incy==1) goto x20;\n\n/* code for unequal increments or equal increments not equal to 1 */\n\n  for (i = 1; i<=n; i++) {\n     dtemp+= dx[ix]*dy[iy];\n     ix+= incx;\n     iy+= incy;\n  }\n  return(dtemp);\n\n/* code for both increments equal to 1 */\n\n/* clean-up loop */\n\nx20:\n  m = n % 5;\n  if (m == 0) goto x40;\n  for (i = 1; i<=m; i++)\n     dtemp+= dx[i]*dy[i];\n  if (n < 5) goto x60;\n\nx40:\n  mp1 = m + 1;\n  for (i = mp1; i<=n; i=i+5)\n     dtemp+= dx[i]*dy[i] + dx[i + 1]*dy[i + 1] +\n             dx[i + 2]*dy[i + 2] + dx[i + 3]*dy[i + 3] + dx[i + 4]*dy[i + 4];\n\nx60:\n  return(dtemp);\n#endif\n}\n\n\n/* ************************************************************************ */\n\nvoid dswap( int n, REAL *dx, int incx, REAL *dy, int incy )\n{\n  dx++;\n  dy++;\n  BLAS_dswap( &n, dx, &incx, dy, &incy );\n}\n\nvoid BLAS_CALLMODEL my_dswap( int *_n, REAL *dx, int *_incx, REAL *dy, int *_incy )\n{\n  int   i, ix, iy;\n#if !defined DOFASTMATH\n  int   m, mp1, ns;\n  REAL  dtemp2, dtemp3;\n#endif\n  REAL  dtemp1;\n  int   n = *_n, incx = *_incx, incy = *_incy;\n\n  if (n <= 0) return;\n\n  dx--;\n  dy--;\n  ix = 1;\n  iy = 1;\n  if (incx < 0)\n    ix = (-n+1)*incx + 1;\n  if (incy < 0)\n    iy = (-n+1)*incy + 1;\n\n/* CPU intensive loop; option to do pointer arithmetic */\n#if defined DOFASTMATH\n  {\n    REAL *xptr, *yptr;\n    for (i = 1, xptr = dx + ix, yptr = dy + iy;\n         i <= n; i++, xptr += incx, yptr += incy) {\n      dtemp1 = (*xptr);\n     (*xptr) = (*yptr);\n     (*yptr) = dtemp1;\n    }\n    return;\n  }\n#else\n\n  if (incx == incy) {\n    if (incx <= 0) goto x5;\n    if (incx == 1) goto x20;\n    goto x60;\n  }\n\n/* code for unequal or nonpositive increments. */\nx5:\n  for (i = 1; i<=n; i++) {\n     dtemp1 = dx[ix];\n     dx[ix] = dy[iy];\n     dy[iy] = dtemp1;\n     ix+= incx;\n     iy+= incy;\n  }\n  return;\n\n/* code for both increments equal to 1.\n   clean-up loop so remaining vector length is a multiple of 3. */\nx20:\n  m = n % 3;\n  if (m == 0) goto x40;\n  for (i = 1; i<=m; i++) {\n     dtemp1 = dx[i];\n     dx[i] = dy[i];\n     dy[i] = dtemp1;\n  }\n  if (n < 3) return;\n\nx40:\n  mp1 = m + 1;\n  for (i = mp1; i<=n; i=i+3) {\n     dtemp1 = dx[i];\n     dtemp2 = dx[i+1];\n     dtemp3 = dx[i+2];\n     dx[i] = dy[i];\n     dx[i+1] = dy[i+1];\n     dx[i+2] = dy[i+2];\n     dy[i] = dtemp1;\n     dy[i+1] = dtemp2;\n     dy[i+2] = dtemp3;\n  }\n  return;\n\n/* code for equal, positive, non-unit increments. */\nx60:\n  ns = n*incx;\n  for (i = 1; i<=ns; i=i+incx) {\n     dtemp1 = dx[i];\n     dx[i] = dy[i];\n     dy[i] = dtemp1;\n  }\n#endif\n}\n\n\n/* ************************************************************************ */\n\nvoid dload(int n, REAL da, REAL *dx, int incx)\n{\n  dx++;\n  BLAS_dload (&n, &da, dx, &incx);\n}\n\nvoid BLAS_CALLMODEL my_dload (int *_n, REAL *_da, REAL *dx, int *_incx)\n{\n/* copies a scalar, a, to a vector, x.\n   uses unrolled loops when incx equals one.\n\n   To change the precision of this program, run the change\n   program on dload.f\n   Alternatively, to make a single precision version append a\n   comment character to the start of all lines between sequential\n      precision > double\n   and\n      end precision > double\n   comments and delete the comment character at the start of all\n   lines between sequential\n      precision > single\n   and\n      end precision > single\n   comments.  To make a double precision version interchange\n    the append and delete operations in these instructions. */\n\n  int    i, ix, m, mp1;\n  REAL   da = *_da;\n  int    n = *_n, incx = *_incx;\n\n  if (n<=0) return;\n  dx--;\n  if (incx==1) goto x20;\n\n/* code for incx not equal to 1 */\n\n  ix = 1;\n  if (incx<0)\n     ix = (-n+1)*incx + 1;\n  for (i = 1; i<=n; i++) {\n     dx[ix] = da;\n     ix+= incx;\n  }\n  return;\n\n/* code for incx equal to 1 and clean-up loop */\n\nx20:\n  m = n % 7;\n  if (m == 0) goto x40;\n  for (i = 1; i<=m; i++)\n     dx[i] = da;\n  if (n < 7) return;\n\nx40:\n  mp1 = m + 1;\n  for (i = mp1; i<=n; i=i+7) {\n     dx[i] = da;\n     dx[i + 1] = da;\n     dx[i + 2] = da;\n     dx[i + 3] = da;\n     dx[i + 4] = da;\n     dx[i + 5] = da;\n     dx[i + 6] = da;\n  }\n}\n\n/* ************************************************************************ */\nint idamax( int n, REAL *x, int is )\n{\n  x++;\n  return ( BLAS_idamax( &n, x, &is ) );\n}\n\nint BLAS_CALLMODEL my_idamax( int *_n, REAL *x, int *_is )\n{\n  REAL xmax, xtest;\n  int    i, imax = 0;\n#if !defined DOFASTMATH\n  int    ii;\n#endif\n  int    n = *_n, is = *_is;\n\n  if((n < 1) || (is <= 0))\n    return(imax);\n  imax = 1;\n  if(n == 1)\n    return(imax);\n\n#if defined DOFASTMATH\n  xmax = fabs(*x);\n  for (i = 2, x += is; i <= n; i++, x += is) {\n    xtest = fabs(*x);\n    if(xtest > xmax) {\n      xmax = xtest;\n      imax = i;\n    }\n  }\n#else\n  x--;\n  ii = 1;\n  xmax = fabs(x[ii]);\n  for(i = 2, ii+ = is; i <= n; i++, ii+ = is) {\n    xtest = fabs(x[ii]);\n\t  if(xtest > xmax) {\n      xmax = xtest;\n\t\t  imax = i;\n    }\n  }\n#endif\n  return(imax);\n}\n\n\n/* ************************************************************************ */\nREAL dnormi( int n, REAL *x )\n{\n  x++;\n  return( BLAS_dnormi( &n, x ) );\n}\n\nREAL BLAS_CALLMODEL my_dnormi( int *_n, REAL *x )\n{\n/* ===============================================================\n   dnormi  returns the infinity-norm of the vector x.\n   =============================================================== */\n   int      j;\n   REAL hold, absval;\n   int      n = *_n;\n\n   x--;\n   hold = 0.0;\n/*   for(j = 1; j <= n; j++) */\n   for(j = n; j > 0; j--) {\n     absval = fabs(x[j]);\n     hold = MAX( hold, absval );\n   }\n\n   return( hold );\n}\n\n\n/* ************************************************************************ */\n/* Subvector and submatrix access routines (Fortran compatibility)          */\n/* ************************************************************************ */\n\n#ifndef UseMacroVector\nint  subvec( int item)\n{\n  return( item-1 );\n}\n#endif\n\nint submat( int nrowb, int row, int col)\n{\n  return( nrowb*(col-1) + subvec(row) );\n}\n\nint posmat( int nrowb, int row, int col)\n{\n  return( submat(nrowb, row, col)+BLAS_BASE );\n}\n\n/* ************************************************************************ */\n/* Randomization functions                                                  */\n/* ************************************************************************ */\n\nvoid randomseed(int seeds[])\n/* Simply create some default seed values */\n{\n  seeds[1] = 123456;\n  seeds[2] = 234567;\n  seeds[3] = 345678;\n}\n\nvoid randomdens( int n, REAL *x, REAL r1, REAL r2, REAL densty, int *seeds )\n{\n/* ------------------------------------------------------------------\n   random  generates a vector x[*] of random numbers\n   in the range (r1, r2) with (approximate) specified density.\n   seeds[*] must be initialized before the first call.\n   ------------------------------------------------------------------ */\n\n  int   i;\n  REAL  *y;\n\n  y = (REAL *) malloc(sizeof(*y) * (n+1));\n  ddrand( n, x, 1, seeds );\n  ddrand( n, y, 1, seeds );\n\n  for (i = 1; i<=n; i++) {\n     if (y[i] < densty)\n        x[i] = r1  +  (r2 - r1) * x[i];\n     else\n        x[i] = 0.0;\n  }\n  free(y);\n}\n\n\n/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */\n\nvoid ddrand( int n, REAL *x, int incx, int *seeds )\n{\n\n/* ------------------------------------------------------------------\n   ddrand fills a vector x with uniformly distributed random numbers\n   in the interval (0, 1) using a method due to  Wichman and Hill.\n\n   seeds[1..3] should be set to integer values\n   between 1 and 30000 before the first entry.\n\n   Integer arithmetic up to 30323 is required.\n\n   Blatantly copied from Wichman and Hill 19-January-1987.\n   14-Feb-94. Original version.\n   30 Jun 1999. seeds stored in an array.\n   30 Jun 1999. This version of ddrand.\n   ------------------------------------------------------------------ */\n\n  int    ix, xix;\n\n  if (n < 1) return;\n\n  for (ix = 1; ix<=1+(n-1)*incx; ix=ix+incx) {\n     seeds[1]     = 171*(seeds[1] % 177) -  2*(seeds[1]/177);\n     seeds[2]     = 172*(seeds[2] % 176) - 35*(seeds[2]/176);\n     seeds[3]     = 170*(seeds[3] % 178) - 63*(seeds[3]/178);\n\n     if (seeds[1] < 0) seeds[1] = seeds[1] + 30269;\n     if (seeds[2] < 0) seeds[2] = seeds[2] + 30307;\n     if (seeds[3] < 0) seeds[3] = seeds[3] + 30323;\n\n\t x[ix]  = ((REAL) seeds[1])/30269.0 +\n             ((REAL) seeds[2])/30307.0 +\n             ((REAL) seeds[3])/30323.0;\n     xix    = (int) x[ix];\n\t x[ix]  = fabs(x[ix] - xix);\n   }\n\n}\n\n"
  },
  {
    "path": "utilities/lp_solve/shared/myblas.h",
    "content": "#ifndef HEADER_myblas\n#define HEADER_myblas\n\n/* ************************************************************************ */\n/* BLAS function interface with local and external loadable versions        */\n/* Author:  Kjell Eikland                                                   */\n/* Version: Initial version spring 2004                                     */\n/* Licence: LGPL                                                            */\n/* ************************************************************************ */\n/* Changes: 19 September 2004   Moved function pointer variable             */\n/*                              declarations from myblas.h to myblas.c      */\n/*                              to avoid linker problems with the Mac.      */\n/*          20 April 2005       Modified all double types to REAL to self-  */\n/*                              adjust to global settings.  Note that BLAS  */\n/*                              as of now does not have double double.      */\n/* ************************************************************************ */\n\n#define BLAS_BASE         1\n#define UseMacroVector\n#if defined LoadableBlasLib\n#  if LoadableBlasLib == 0\n#    undef LoadableBlasLib\n#  endif\n#else\n#  define LoadableBlasLib\n#endif\n\n\n/* ************************************************************************ */\n/* Include necessary libraries                                              */\n/* ************************************************************************ */\n#include \"commonlib.h\"\n#ifdef LoadableBlasLib\n  #ifdef WIN32\n    #include <windows.h>\n  #else\n    #include <dlfcn.h>\n  #endif\n#endif\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n/* ************************************************************************ */\n/* BLAS functions                                                           */\n/* ************************************************************************ */\n\n#ifndef BLAS_CALLMODEL\n#ifdef WIN32\n# define BLAS_CALLMODEL _cdecl\n#else\n# define BLAS_CALLMODEL\n#endif\n#endif\n\ntypedef void   (BLAS_CALLMODEL BLAS_dscal_func) (int *n, REAL *da, REAL *dx, int *incx);\ntypedef void   (BLAS_CALLMODEL BLAS_dcopy_func) (int *n, REAL *dx, int *incx,  REAL *dy, int *incy);\ntypedef void   (BLAS_CALLMODEL BLAS_daxpy_func) (int *n, REAL *da, REAL *dx, int *incx,  REAL *dy, int *incy);\ntypedef void   (BLAS_CALLMODEL BLAS_dswap_func) (int *n, REAL *dx, int *incx,  REAL *dy, int *incy);\ntypedef double (BLAS_CALLMODEL BLAS_ddot_func)  (int *n, REAL *dx, int *incx,  REAL *dy, int *incy);\ntypedef int    (BLAS_CALLMODEL BLAS_idamax_func)(int *n, REAL *x,  int *is);\ntypedef void   (BLAS_CALLMODEL BLAS_dload_func) (int *n, REAL *da, REAL *dx, int *incx);\ntypedef double (BLAS_CALLMODEL BLAS_dnormi_func)(int *n, REAL *x);\n\n#ifndef __WINAPI\n# ifdef WIN32\n#  define __WINAPI WINAPI\n# else\n#  define __WINAPI\n# endif\n#endif\n\nvoid init_BLAS(void);\nMYBOOL is_nativeBLAS(void);\nMYBOOL load_BLAS(const char *libname);\nMYBOOL unload_BLAS(void);\n\n/* ************************************************************************ */\n/* User-callable BLAS definitions (C base 1)                                */\n/* ************************************************************************ */\nvoid dscal ( int n, REAL da,  REAL *dx, int incx );\nvoid dcopy ( int n, REAL *dx, int incx, REAL *dy, int incy );\nvoid daxpy ( int n, REAL da,  REAL *dx, int incx,   REAL *dy, int incy );\nvoid dswap ( int n, REAL *dx, int incx, REAL *dy, int incy );\nREAL ddot  ( int n, REAL *dx, int incx, REAL *dy, int incy );\nint  idamax( int n, REAL *x,  int is );\nvoid dload ( int n, REAL da,  REAL *dx, int incx );\nREAL dnormi( int n, REAL *x );\n\n\n/* ************************************************************************ */\n/* Locally implemented BLAS functions (C base 0)                            */\n/* ************************************************************************ */\nvoid BLAS_CALLMODEL my_dscal ( int *n, REAL *da, REAL *dx,  int *incx );\nvoid BLAS_CALLMODEL my_dcopy ( int *n, REAL *dx, int *incx, REAL *dy, int *incy );\nvoid BLAS_CALLMODEL my_daxpy ( int *n, REAL *da, REAL *dx,  int *incx,  REAL *dy, int *incy );\nvoid BLAS_CALLMODEL my_dswap ( int *n, REAL *dx, int *incx, REAL *dy, int *incy );\nREAL BLAS_CALLMODEL my_ddot  ( int *n, REAL *dx, int *incx,  REAL *dy, int *incy );\nint  BLAS_CALLMODEL my_idamax( int *n, REAL *x,  int *is );\nvoid BLAS_CALLMODEL my_dload ( int *n, REAL *da, REAL *dx, int *incx );\nREAL BLAS_CALLMODEL my_dnormi( int *n, REAL *x );\n\n\n/* ************************************************************************ */\n/* Subvector and submatrix access routines (Fortran compatibility)          */\n/* ************************************************************************ */\n#ifdef UseMacroVector\n  #define subvec(item) (item - 1)\n#else\n  int subvec( int item );\n#endif\n\nint submat( int nrowb, int row, int col );\nint posmat( int nrowb, int row, int col );\n\n\n/* ************************************************************************ */\n/* Randomization functions                                                  */\n/* ************************************************************************ */\nvoid randomseed(int *seeds);\nvoid randomdens( int n, REAL *x, REAL r1, REAL r2, REAL densty, int *seeds);\nvoid ddrand( int n, REAL *x, int incx, int *seeds );\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "utilities/lp_solve/yacc_read.c",
    "content": "/*\n   ============================================================================\n   NAME : yacc_read.c\n\n   PURPOSE : translation of lp-problem and storage in sparse matrix\n\n   SHORT : Subroutines for yacc program to store the input in an intermediate\n   data-structure. The yacc and lex programs translate the input.  First the\n   problemsize is determined and the date is read into an intermediate\n   structure, then readinput fills the sparse matrix.\n\n   USAGE : call yyparse(); to start reading the input.  call readinput(); to\n   fill the sparse matrix.\n   ============================================================================\n   Rows : contains the amount of rows + 1. Rows-1 is the amount of constraints\n   (no bounds) Rows also contains the rownr 0 which is the objective function\n\n   Columns : contains the amount of columns (different variable names found in\n   the constraints)\n\n   Nonnuls : contains the amount of nonnuls = sum of different entries of all\n   columns in the constraints and in the objectfunction\n\n   Hash_tab : contains all columnnames on the first level of the structure the\n   row information is kept under each column structure in a linked list (also\n   the objective funtion is in this structure) Bound information is also\n   stored under under the column name\n\n   First_rside : points to a linked list containing all relational operators\n   and the righthandside values of the constraints the linked list is in\n   reversed order with respect to the rownumbers\n   ============================================================================ */\n#include <string.h>\n#include <limits.h>\n#include <setjmp.h>\n#include \"lpkit.h\"\n#include \"yacc_read.h\"\n\n#ifdef FORTIFY\n# include \"lp_fortify.h\"\n#endif\n\n#define tol 1.0e-10\n#define coldatastep 100\n\n#define HASHSIZE       10007  /* A prime number! */\n\nstruct structSOSvars {\n  char                 *name;\n  int                  col;\n  REAL                 weight;\n  struct structSOSvars *next;\n};\n\nstruct structSOS {\n  char                 *name;\n  short                type;\n  int                  Nvars;\n  int                  weight;\n  struct structSOSvars *SOSvars, *LastSOSvars;\n  struct structSOS     *next;\n};\n\nstruct SOSrow {\n  int  col;\n  REAL value;\n  struct SOSrow *next;\n};\n\nstruct SOSrowdata {\n  short type;\n  char *name;\n  struct SOSrow *SOSrow;\n};\n\nstruct rside /* contains relational operator and rhs value */\n{\n  int           row;\n  REAL          value;\n  REAL          range_value;\n  struct rside  *next;\n  short         relat;\n  short         range_relat;\n  char          negate;\n  short         SOStype;\n};\n\nstruct column\n{\n  int            row;\n  REAL           value;\n  struct  column *next;\n  struct  column *prev;\n};\n\nstruct structcoldata {\n  int               must_be_int;\n  int               must_be_sec;\n  int               must_be_free;\n  REAL              upbo;\n  REAL              lowbo;\n  struct  column   *firstcol;\n  struct  column   *col;\n};\n\nstatic void error(parse_parm *pp, int verbose, const char *string)\n{\n  if(pp == NULL)\n    report(NULL, CRITICAL, string);\n  else if(pp->Verbose >= verbose)\n    report(NULL, verbose, \"%s on line %d\\n\", string, pp->lineno);\n}\n\n/*\n * error handling routine for yyparse()\n */\nvoid read_error(parse_parm *pp, void *scanner, const char * string)\n{\n  (void)scanner;\n  error(pp, CRITICAL, string);\n}\n\n/* called when lex gets a fatal error */\nvoid lex_fatal_error(parse_parm *pp, void *scanner, const char * msg)\n{\n  read_error(pp, scanner, msg);\n  longjmp(pp->jump_buf, 1);\n}\n\nvoid add_row(parse_parm *pp)\n{\n  pp->Rows++;\n  pp->rs = NULL;\n  pp->Lin_term_count = 0;\n}\n\nvoid add_sos_row(parse_parm *pp, short SOStype)\n{\n  if (pp->rs != NULL)\n    pp->rs->SOStype = SOStype;\n  pp->Rows++;\n  pp->rs = NULL;\n  pp->Lin_term_count = 0;\n}\n\nvoid check_int_sec_sos_free_decl(parse_parm *pp, int within_int_decl, int within_sec_decl, int sos_decl0, int within_free_decl)\n{\n  pp->Ignore_int_decl = TRUE;\n  pp->Ignore_sec_decl = TRUE;\n  pp->Ignore_free_decl = TRUE;\n  pp->sos_decl = 0;\n  if(within_int_decl) {\n    pp->Ignore_int_decl = FALSE;\n    pp->int_decl = (char) within_int_decl;\n    if(within_sec_decl)\n      pp->Ignore_sec_decl = FALSE;\n  }\n  else if(within_sec_decl) {\n    pp->Ignore_sec_decl = FALSE;\n  }\n  else if(sos_decl0) {\n    pp->sos_decl = (char) sos_decl0;\n  }\n  else if(within_free_decl) {\n    pp->Ignore_free_decl = FALSE;\n  }\n}\n\nstatic void add_int_var(parse_parm *pp, const char *name, short int_decl)\n{\n  hashelem *hp;\n\n  if((hp = findhash(name, pp->Hash_tab)) == NULL) {\n    char buf[256];\n\n    sprintf(buf, \"Unknown variable %s declared integer, ignored\", name);\n    error(pp, IMPORTANT, buf);\n  }\n  else if(pp->coldata[hp->index].must_be_int) {\n    char buf[256];\n\n    sprintf(buf, \"Variable %s declared integer more than once, ignored\", name);\n    error(pp, IMPORTANT, buf);\n  }\n  else {\n    pp->coldata[hp->index].must_be_int = TRUE;\n    if(int_decl == 2) {\n      if(pp->coldata[hp->index].lowbo != -DEF_INFINITE * (REAL) 10.0) {\n        char buf[256];\n\n        sprintf(buf, \"Variable %s: lower bound on variable redefined\", name);\n        error(pp, IMPORTANT, buf);\n      }\n      pp->coldata[hp->index].lowbo = 0;\n      if(pp->coldata[hp->index].upbo < DEF_INFINITE) {\n        char buf[256];\n\n        sprintf(buf, \"Variable %s: upper bound on variable redefined\", name);\n        error(pp, IMPORTANT, buf);\n      }\n      pp->coldata[hp->index].upbo = 1;\n    }\n    else if(int_decl == 3) {\n      if(pp->coldata[hp->index].upbo == DEF_INFINITE * (REAL) 10.0)\n        pp->coldata[hp->index].upbo = 1.0;\n    }\n  }\n}\n\nstatic void add_sec_var(parse_parm *pp, const char *name)\n{\n  hashelem *hp;\n\n  if((hp = findhash(name, pp->Hash_tab)) == NULL) {\n    char buf[256];\n\n    sprintf(buf, \"Unknown variable %s declared semi-continuous, ignored\", name);\n    error(pp, IMPORTANT, buf);\n  }\n  else if(pp->coldata[hp->index].must_be_sec) {\n    char buf[256];\n\n    sprintf(buf, \"Variable %s declared semi-continuous more than once, ignored\", name);\n    error(pp, IMPORTANT, buf);\n  }\n  else\n    pp->coldata[hp->index].must_be_sec = TRUE;\n}\n\nint set_sec_threshold(parse_parm *pp, const char *name, REAL threshold)\n{\n  hashelem *hp;\n\n  if((hp = findhash(name, pp->Hash_tab)) == NULL) {\n    char buf[256];\n\n    sprintf(buf, \"Unknown variable %s declared semi-continuous, ignored\", name);\n    error(pp, IMPORTANT, buf);\n    return(FALSE);\n  }\n\n  if ((pp->coldata[hp->index].lowbo > 0.0) && (threshold > 0.0)) {\n    char buf[256];\n\n    pp->coldata[hp->index].must_be_sec = FALSE;\n    sprintf(buf, \"Variable %s declared semi-continuous, but it has a non-negative lower bound (%f), ignored\", name, pp->coldata[hp->index].lowbo);\n    error(pp, IMPORTANT, buf);\n  }\n  if (threshold > pp->coldata[hp->index].lowbo)\n    pp->coldata[hp->index].lowbo = threshold;\n\n  return(pp->coldata[hp->index].must_be_sec);\n}\n\nstatic void add_free_var(parse_parm *pp, const char *name)\n{\n  hashelem *hp;\n\n  if((hp = findhash(name, pp->Hash_tab)) == NULL) {\n    char buf[256];\n\n    sprintf(buf, \"Unknown variable %s declared free, ignored\", name);\n    error(pp, IMPORTANT, buf);\n  }\n  else if(pp->coldata[hp->index].must_be_free) {\n    char buf[256];\n\n    sprintf(buf, \"Variable %s declared free more than once, ignored\", name);\n    error(pp, IMPORTANT, buf);\n  }\n  else\n  {\n    if(pp->coldata[hp->index].lowbo != -DEF_INFINITE * (REAL) 10.0) {\n      char buf[256];\n\n      sprintf(buf, \"Variable %s: lower bound on variable redefined\", name);\n      error(pp, IMPORTANT, buf);\n    }\n\n    if(pp->coldata[hp->index].upbo < DEF_INFINITE) {\n      char buf[256];\n\n      sprintf(buf, \"Variable %s: upper bound on variable redefined\", name);\n      error(pp, IMPORTANT, buf);\n    }\n\n    pp->coldata[hp->index].must_be_free = TRUE;\n  }\n}\n\nstatic int add_sos_name(parse_parm *pp, const char *name)\n{\n  struct structSOS *SOS;\n\n  if(CALLOC(SOS, 1, struct structSOS) == NULL)\n    return(FALSE);\n\n  if(MALLOC(SOS->name, strlen(name) + 1, char) == NULL)\n  {\n    FREE(SOS);\n    return(FALSE);\n  }\n  strcpy(SOS->name, name);\n  SOS->type = 0;\n\n  if(pp->FirstSOS == NULL)\n    pp->FirstSOS = SOS;\n  else\n    pp->LastSOS->next = SOS;\n  pp->LastSOS = SOS;\n\n  return(TRUE);\n}\n\nstatic int add_sos_var(parse_parm *pp, const char *name)\n{\n  struct structSOSvars *SOSvar;\n\n  if(name != NULL) {\n    if(CALLOC(SOSvar, 1, struct structSOSvars) == NULL)\n      return(FALSE);\n\n    if(MALLOC(SOSvar->name, strlen(name) + 1, char) == NULL)\n    {\n      FREE(SOSvar);\n      return(FALSE);\n    }\n    strcpy(SOSvar->name, name);\n\n    if(pp->LastSOS->SOSvars == NULL)\n      pp->LastSOS->SOSvars = SOSvar;\n    else\n      pp->LastSOS->LastSOSvars->next = SOSvar;\n    pp->LastSOS->LastSOSvars = SOSvar;\n    pp->LastSOS->Nvars = pp->LastSOS->Nvars + 1;\n  }\n  pp->LastSOS->LastSOSvars->weight = 0;\n\n  return(TRUE);\n}\n\nvoid storevarandweight(parse_parm *pp, const char *name)\n{\n  if(!pp->Ignore_int_decl) {\n    add_int_var(pp, name, pp->int_decl);\n    if(!pp->Ignore_sec_decl)\n      add_sec_var(pp, name);\n  }\n  else if(!pp->Ignore_sec_decl)\n    add_sec_var(pp, name);\n  else if(pp->sos_decl==1)\n    add_sos_name(pp, name);\n  else if(pp->sos_decl==2)\n    add_sos_var(pp, name);\n  else if(!pp->Ignore_free_decl)\n    add_free_var(pp, name);\n}\n\nint set_sos_type(parse_parm *pp, int SOStype)\n{\n  if(pp->LastSOS != NULL)\n    pp->LastSOS->type = (short) SOStype;\n  return(TRUE);\n}\n\nint set_sos_weight(parse_parm *pp, double weight, int sos_decl)\n{\n  if(pp->LastSOS != NULL) {\n    if(sos_decl==1)\n      pp->LastSOS->weight = (int) (weight+.1);\n    else\n      pp->LastSOS->LastSOSvars->weight = weight;\n  }\n  return(TRUE);\n}\n\nstatic int inccoldata(parse_parm *pp)\n{\n  long Columns = pp->Columns;\n\n  if(Columns == 0)\n    CALLOC(pp->coldata, coldatastep, struct structcoldata);\n  else if((Columns%coldatastep) == 0)\n    REALLOC(pp->coldata, Columns + coldatastep, struct structcoldata);\n\n  if(pp->coldata != NULL) {\n    pp->coldata[Columns].upbo = (REAL) DEF_INFINITE * (REAL) 10.0;\n    pp->coldata[Columns].lowbo = (REAL) -DEF_INFINITE * (REAL) 10.0; /* temporary. If still this value then 0 will be taken */\n    pp->coldata[Columns].col = NULL;\n    pp->coldata[Columns].firstcol = NULL;\n    pp->coldata[Columns].must_be_int = FALSE;\n    pp->coldata[Columns].must_be_sec = FALSE;\n    pp->coldata[Columns].must_be_free = FALSE;\n  }\n\n  return(pp->coldata != NULL);\n}\n\n/*\n * initialisation of hashstruct and globals.\n */\nstatic int init_read(parse_parm *pp, int verbose)\n{\n  int ok = FALSE;\n\n  pp->Verbose = verbose;\n  set_obj_dir(pp, TRUE);\n  pp->Rows = 0;\n  pp->Non_zeros = 0;\n  pp->Columns = 0;\n  pp->FirstSOS = pp->LastSOS = NULL;\n  pp->Lin_term_count = 0;\n  if (CALLOC(pp->First_rside, 1, struct rside) != NULL) {\n    pp->rs = pp->First_rside;\n    pp->rs->value = pp->rs->range_value = 0;\n    /* first row (nr 0) is always the objective function */\n    pp->rs->relat = OF;\n    pp->rs->range_relat = -1;\n    pp->rs->SOStype = 0;\n    pp->Hash_tab = NULL;\n    pp->Hash_constraints = NULL;\n    if (((pp->Hash_tab = create_hash_table(HASHSIZE, 0)) == NULL) ||\n        ((pp->Hash_constraints = create_hash_table(HASHSIZE, 0)) == NULL)){\n      FREE(pp->First_rside);\n      FREE(pp->Hash_tab);\n      FREE(pp->Hash_constraints);\n    }\n    else\n      ok = TRUE;\n  }\n  return(ok);\n} /* init */\n\n/*\n * clears the tmp_store variable after all information has been copied\n */\nvoid null_tmp_store(parse_parm *pp, int init_Lin_term_count)\n{\n  pp->tmp_store.value = 0;\n  pp->tmp_store.rhs_value = 0;\n  FREE(pp->tmp_store.name);\n  if(init_Lin_term_count)\n    pp->Lin_term_count = 0;\n}\n\n/*\n * variable : pointer to text array with name of variable\n * row      : the rownumber of the constraint\n * value    : value of matrixelement\n *            A(row, variable).\n * Sign     : (global)  determines the sign of value.\n * store()  : stores value in matrix\n *            A(row, variable). If A(row, variable) already contains data,\n *            value is added to the existing value.\n */\nstatic int store(parse_parm *pp, const char *variable,\n                 int row,\n                 REAL value)\n{\n  hashelem *h_tab_p;\n  struct column *col_p;\n\n  if(value == 0) {\n    char buf[256];\n\n    sprintf(buf, \"(store) Warning, variable %s has an effective coefficient of 0, Ignored\", variable);\n    error(pp, NORMAL, buf);\n    /* return(TRUE); */\n  }\n\n  if((h_tab_p = findhash(variable, pp->Hash_tab)) == NULL) {\n    if (((h_tab_p = puthash(variable, pp->Columns, NULL, pp->Hash_tab)) == NULL)\n       ) return(FALSE);\n    inccoldata(pp);\n    pp->Columns++; /* counter for calloc of final array */\n    if(value) {\n      if (CALLOC(col_p, 1, struct column) == NULL)\n        return(FALSE);\n      pp->Non_zeros++; /* for calloc of final arrays */\n      col_p->row = row;\n      col_p->value = value;\n      pp->coldata[h_tab_p->index].firstcol = pp->coldata[h_tab_p->index].col = col_p;\n    }\n  }\n  else if((pp->coldata[h_tab_p->index].col == NULL) || (pp->coldata[h_tab_p->index].col->row != row)) {\n    if(value) {\n      if (CALLOC(col_p, 1, struct column) == NULL)\n        return(FALSE);\n      pp->Non_zeros++; /* for calloc of final arrays */\n      if(pp->coldata[h_tab_p->index].col != NULL)\n        pp->coldata[h_tab_p->index].col->prev = col_p;\n      else\n        pp->coldata[h_tab_p->index].firstcol = col_p;\n      col_p->value = value;\n      col_p->row = row;\n      col_p->next = pp->coldata[h_tab_p->index].col;\n      pp->coldata[h_tab_p->index].col = col_p;\n    }\n  }\n  else if(value) {\n    pp->coldata[h_tab_p->index].col->value += value;\n    if(fabs(pp->coldata[h_tab_p->index].col->value) < tol) /* eliminitate rounding errors */\n      pp->coldata[h_tab_p->index].col->value = 0;\n  }\n  return(TRUE);\n} /* store */\n\nstatic int storefirst(parse_parm *pp)\n{\n    struct rside *rp;\n\n    if ((pp->rs != NULL) && (pp->rs->row == pp->tmp_store.row))\n      return(TRUE);\n\n    /* make space for the rhs information */\n    if (CALLOC(rp, 1, struct rside) == NULL)\n      return(FALSE);\n    rp->next = pp->First_rside;\n    pp->First_rside = pp->rs = rp;\n    pp->rs->row = /* row */ pp->tmp_store.row;\n    pp->rs->value = pp->tmp_store.rhs_value;\n    pp->rs->relat = pp->tmp_store.relat;\n    pp->rs->range_relat = -1;\n    pp->rs->SOStype = 0;\n\n    if(pp->tmp_store.name != NULL) {\n      if(pp->tmp_store.value != 0) {\n        if (!store(pp, pp->tmp_store.name, pp->tmp_store.row, pp->tmp_store.value))\n          return(FALSE);\n      }\n      else {\n        char buf[256];\n\n        sprintf(buf, \"Warning, variable %s has an effective coefficient of 0, ignored\", pp->tmp_store.name);\n        error(pp, NORMAL, buf);\n      }\n    }\n    null_tmp_store(pp, FALSE);\n    return(TRUE);\n}\n\n/*\n * store relational operator given in yylex[0] in the rightside list.\n * Also checks if it constraint was a bound and if so stores it in the\n * boundslist\n */\nint store_re_op(parse_parm *pp, char OP, int HadConstraint, int HadVar, int Had_lineair_sum)\n{\n  short tmp_relat;\n\n  switch(OP) {\n\n  case '=':\n    tmp_relat = EQ;\n    break;\n\n  case '>':\n    tmp_relat = GE;\n    break;\n\n  case '<':\n    tmp_relat = LE;\n    break;\n\n  case 0:\n    if(pp->rs != NULL)\n      tmp_relat = pp->rs->relat;\n    else\n      tmp_relat = pp->tmp_store.relat;\n    break;\n\n  default:\n    {\n      char buf[256];\n\n      sprintf(buf, \"Error: unknown relational operator %c\", OP);\n      error(pp, CRITICAL, buf);\n    }\n    return(FALSE);\n    break;\n  }\n\n  if(/* pp->Lin_term_count > 1 */ HadConstraint && HadVar) {/* it is not a bound */\n    if(pp->Lin_term_count <= 1)\n      if(!storefirst(pp))\n        return(FALSE);\n    pp->rs->relat = tmp_relat;\n  }\n  else if(/* pp->Lin_term_count == 0 */ HadConstraint && !Had_lineair_sum /* HadVar */ /* && (pp->rs != NULL) */) { /* it is a range */\n    if(pp->Lin_term_count == 1)\n      if(!storefirst(pp))\n        return(FALSE);\n    if(pp->rs == NULL) { /* range before row, already reported */\n      error(pp, CRITICAL, \"Error: range for undefined row\");\n      return(FALSE);\n    }\n\n    if(pp->rs->negate)\n      switch (tmp_relat) {\n      case LE:\n        tmp_relat = GE;\n        break;\n      case GE:\n        tmp_relat = LE;\n        break;\n      }\n\n    if(pp->rs->range_relat != -1) {\n      error(pp, CRITICAL, \"Error: There was already a range for this row\");\n      return(FALSE);\n    }\n    else if(tmp_relat == pp->rs->relat) {\n      error(pp, CRITICAL, \"Error: relational operator for range is the same as relation operator for equation\");\n      return(FALSE);\n    }\n    else\n      pp->rs->range_relat = tmp_relat;\n  }\n  else /* could be a bound */\n    pp->tmp_store.relat = tmp_relat;\n\n  return(TRUE);\n} /* store_re_op */\n\nint negate_constraint(parse_parm *pp)\n{\n    if(pp->rs != NULL)\n      pp->rs->negate = TRUE;\n\n    return(TRUE);\n}\n\n/*\n * store RHS value in the rightside structure\n * if type = true then\n */\nint rhs_store(parse_parm *pp, REAL value, int HadConstraint, int HadVar, int Had_lineair_sum)\n{\n  (void)Had_lineair_sum;\n  if(/* pp->Lin_term_count > 1 */ (HadConstraint && HadVar) || (pp->Rows == 0)){ /* not a bound */\n    if (pp->Rows == 0)\n      value = -value;\n    /* if(pp->Lin_term_count < 2) */\n    if(pp->rs == NULL)\n      pp->tmp_store.rhs_value += value;\n    else\n\n    if(pp->rs == NULL) {\n      error(pp, CRITICAL, \"Error: No variable specified\");\n      return(FALSE);\n    }\n    else\n      pp->rs->value += value;\n  }\n  else if(/* pp->Lin_term_count == 0 */ HadConstraint && !HadVar) { /* a range */\n    if(pp->rs == NULL) /* if range before row, already reported */\n      pp->tmp_store.rhs_value += value;\n    else if(pp->rs->range_relat < 0) /* was a bad range; ignore */;\n    else {\n      if(pp->rs->negate)\n        value = -value;\n      if(((pp->rs->relat == LE) && (pp->rs->range_relat == GE) &&\n         (pp->rs->value < value)) ||\n        ((pp->rs->relat == GE) && (pp->rs->range_relat == LE) &&\n         (pp->rs->value > value)) ||\n        ((pp->rs->relat == EQ) || (pp->rs->range_relat == EQ))) {\n        pp->rs->range_relat = -2;\n        error(pp, CRITICAL, \"Error: range restriction conflicts\");\n        return(FALSE);\n      }\n      else\n        pp->rs->range_value += value;\n    }\n  }\n  else /* a bound */\n    pp->tmp_store.rhs_value += value;\n  return(TRUE);\n} /* RHS_store */\n\n/*\n * store all data in the right place\n * count the amount of lineair terms in a constraint\n * only store in data-structure if the constraint is not a bound\n */\nint var_store(parse_parm *pp, const char *var, REAL value, int HadConstraint, int HadVar, int Had_lineair_sum)\n{\n  (void)HadConstraint;\n  (void)HadVar;\n  (void)Had_lineair_sum;\n  int row;\n  (void)HadConstraint;\n  (void)HadVar;\n  (void)Had_lineair_sum;\n\n  row = pp->Rows;\n\n  /* also in a bound the same var name can occur more than once. Check for\n     this. Don't increment Lin_term_count */\n\n  if(pp->Lin_term_count != 1 || pp->tmp_store.name == NULL || strcmp(pp->tmp_store.name, var) != 0)\n    pp->Lin_term_count++;\n\n  /* always store objective function with rownr == 0. */\n  if(row == 0)\n    return(store(pp, var,  row,  value));\n\n  if(pp->Lin_term_count == 1) { /* don't store yet. could be a bound */\n    if(MALLOC(pp->tmp_store.name, strlen(var) + 1, char) != NULL)\n      strcpy(pp->tmp_store.name, var);\n    pp->tmp_store.row = row;\n    pp->tmp_store.value += value;\n    return(TRUE);\n  }\n\n  if(pp->Lin_term_count == 2) { /* now you can also store the first variable */\n    if(!storefirst(pp))\n      return(FALSE);\n    /* null_tmp_store(pp, FALSE); */\n  }\n\n  return(store(pp, var, row, value));\n} /* var_store */\n\n\n\n/*\n * store the information in tmp_store because it is a bound\n */\nint store_bounds(parse_parm *pp, int warn)\n{\n  if(pp->tmp_store.value != 0) {\n    hashelem *h_tab_p;\n    REAL boundvalue;\n\n    if((h_tab_p = findhash(pp->tmp_store.name, pp->Hash_tab)) == NULL) {\n      /* a new columnname is found, create an entry in the hashlist */\n      if ((h_tab_p = puthash(pp->tmp_store.name, pp->Columns, NULL, pp->Hash_tab)) == NULL) {\n        error(pp, CRITICAL, \"Not enough memory\");\n        return(FALSE);\n      }\n      inccoldata(pp);\n      pp->Columns++; /* counter for calloc of final array */\n    }\n\n    if(pp->tmp_store.value < 0) { /* divide by negative number, */\n      /* relational operator may change */\n      if(pp->tmp_store.relat == GE)\n        pp->tmp_store.relat = LE;\n      else if(pp->tmp_store.relat == LE)\n        pp->tmp_store.relat = GE;\n    }\n\n    boundvalue = pp->tmp_store.rhs_value / pp->tmp_store.value;\n\n#if FALSE\n    /* Check sanity of bound; all variables should be positive */\n    if(   ((pp->tmp_store.relat == EQ) && (boundvalue < 0))\n       || ((pp->tmp_store.relat == LE) && (boundvalue < 0))) { /* Error */\n      error(pp, CRITICAL, \"Error: variables must always be non-negative\");\n      return(FALSE);\n    }\n#endif\n\n#if FALSE\n    if((pp->tmp_store.relat == GE) && (boundvalue <= 0)) /* Warning */\n      error(pp, NORMAL, \"Warning: useless bound; variables are always >= 0\");\n#endif\n\n    /* bound seems to be sane, add it */\n    if((pp->tmp_store.relat == GE) || (pp->tmp_store.relat == EQ)) {\n      if(boundvalue > pp->coldata[h_tab_p->index].lowbo - tol)\n        pp->coldata[h_tab_p->index].lowbo = boundvalue;\n      else if(warn)\n        error(pp, NORMAL, \"Ineffective lower bound, ignored\");\n    }\n    if((pp->tmp_store.relat == LE) || (pp->tmp_store.relat == EQ)) {\n      if(boundvalue < pp->coldata[h_tab_p->index].upbo + tol)\n        pp->coldata[h_tab_p->index].upbo  = boundvalue;\n      else if (warn)\n        error(pp, NORMAL, \"Ineffective upper bound, ignored\");\n    }\n\n    /* check for empty range */\n    if((warn) && (pp->coldata[h_tab_p->index].upbo + tol < pp->coldata[h_tab_p->index].lowbo)) {\n      error(pp, CRITICAL, \"Error: bound contradicts earlier bounds\");\n      return(FALSE);\n    }\n  }\n  else /* pp->tmp_store.value = 0 ! */ {\n    char buf[256];\n\n    if((pp->tmp_store.rhs_value == 0) ||\n       ((pp->tmp_store.rhs_value > 0) && (pp->tmp_store.relat == LE)) ||\n       ((pp->tmp_store.rhs_value < 0) && (pp->tmp_store.relat == GE))) {\n      sprintf(buf, \"Variable %s has an effective coefficient of 0 in bound, ignored\",\n              pp->tmp_store.name);\n      if(warn)\n        error(pp, NORMAL, buf);\n    }\n    else {\n      sprintf(buf, \"Error, variable %s has an effective coefficient of 0 in bound\",\n              pp->tmp_store.name);\n      error(pp, CRITICAL, buf);\n      return(FALSE);\n    }\n  }\n\n  /* null_tmp_store(pp, FALSE); */\n  pp->tmp_store.rhs_value = 0;\n\n  return(TRUE);\n} /* store_bounds */\n\nint set_title(parse_parm *pp, const char *name)\n{\n  pp->title = strdup(name);\n  return(TRUE);\n}\n\nint add_constraint_name(parse_parm *pp, const char *name)\n{\n  int row;\n  hashelem *hp;\n\n  if((hp = findhash(name, pp->Hash_constraints)) != NULL) {\n    row = hp->index;\n    pp->rs = pp->First_rside;\n    while ((pp->rs != NULL) && (pp->rs->row != row))\n      pp->rs = pp->rs->next;\n  }\n  else {\n    row = pp->Rows;\n    if (((hp = puthash(name, row, NULL, pp->Hash_constraints)) == NULL)\n       ) return(FALSE);\n    if(row)\n      pp->rs = NULL;\n  }\n\n  return(TRUE);\n}\n\n/*\n * transport the data from the intermediate structure to the sparse matrix\n * and free the intermediate structure\n */\nstatic int readinput(parse_parm *pp, lprec *lp)\n{\n  int    i, i1, count, index, col;\n  struct column *cp, *tcp;\n  hashelem *hp;\n  struct rside *rp;\n  signed char *negateAndSOS = NULL;\n  REAL *row = NULL, a;\n  int *rowno = NULL;\n  MYBOOL SOSinMatrix = FALSE;\n  struct SOSrowdata *SOSrowdata = NULL;\n  struct SOSrow *SOSrow, *SOSrow1;\n\n  if(lp != NULL) {\n    if (CALLOC(negateAndSOS, 1 + pp->Rows, signed char) == NULL)\n      return(FALSE);\n\n    rp = pp->First_rside;\n    for(i = pp->Rows; (i >= 0) && (rp != NULL); i--) {\n      if(rp->SOStype == 0)\n        negateAndSOS[i] = (rp->negate ? -1 : 0);\n      else\n        negateAndSOS[i] = (signed char) rp->SOStype;\n\n      rp = rp->next;\n    }\n\n    /* fill names with the rownames */\n    hp = pp->Hash_constraints->first;\n    while(hp != NULL) {\n      if (/* (negateAndSOS[hp->index] <= 0) && */ (!set_row_name(lp, hp->index, hp->name)))\n        return(FALSE);\n      hp = hp->nextelem;\n    }\n  }\n\n  for(i = pp->Rows; i >= 0; i--) {\n    rp = pp->First_rside;\n    if((lp != NULL) && (rp != NULL)) {\n      if(rp->SOStype == 0) {\n        if (rp->negate) {\n          switch (rp->relat) {\n          case LE:\n            rp->relat = GE;\n            break;\n          case GE:\n            rp->relat = LE;\n            break;\n          }\n          switch (rp->range_relat) {\n          case LE:\n            rp->range_relat = GE;\n            break;\n          case GE:\n            rp->range_relat = LE;\n            break;\n          }\n          rp->range_value = -rp->range_value;\n          rp->value = -rp->value;\n        }\n\n        if((rp->range_relat >= 0) && (rp->value == lp->infinite)) {\n          rp->value = rp->range_value;\n          rp->relat = rp->range_relat;\n          rp->range_relat = -1;\n        }\n        else if((rp->range_relat >= 0) && (rp->value == -lp->infinite)) {\n          rp->value = rp->range_value;\n          rp->relat = rp->range_relat;\n          rp->range_relat = -1;\n        }\n        if ((rp->range_relat >= 0) && (rp->range_value == rp->value)) {\n          rp->relat = EQ;\n          rp->range_relat = EQ;\n        }\n        if(i) {\n          set_constr_type(lp, i, rp->relat);\n          pp->relat[i] = rp->relat;\n        }\n        set_rh(lp, i, rp->value);\n        if (rp->range_relat >= 0)\n          set_rh_range(lp, i, rp->range_value - rp->value);\n      }\n      else {\n        SOSinMatrix = TRUE;\n        if(i)\n          pp->relat[i] = rp->relat;\n      }\n    }\n    if(rp != NULL) {\n      pp->First_rside = rp->next;\n      free(rp); /* free memory when data has been read */\n    }\n    else\n      pp->First_rside = NULL;\n  }\n\n  while(pp->First_rside != NULL) {\n    rp = pp->First_rside;\n    pp->First_rside = rp->next;\n    free(rp); /* free memory when data has been read */\n  }\n\n  /* start reading the Hash_list structure */\n  index = 0;\n\n  if((SOSinMatrix) && (CALLOC(SOSrowdata, 1 + pp->Rows, struct SOSrowdata) == NULL)) {\n    FREE(negateAndSOS);\n    FREE(row);\n    FREE(rowno);\n    return(FALSE);\n  }\n\n  if((lp != NULL) &&\n     ((MALLOC(row, 1 + pp->Rows, REAL) == NULL) || (MALLOC(rowno, 1 + pp->Rows, int) == NULL))) {\n    FREE(SOSrowdata);\n    FREE(negateAndSOS);\n    FREE(row);\n    FREE(rowno);\n    return(FALSE);\n  }\n\n  /* for(i = 0; i < pp->Hash_tab->size; i++) {\n    hp = pp->Hash_tab->table[i]; */\n    hp = pp->Hash_tab->first;\n    while(hp != NULL) {\n      count = 0;\n      index++;\n      cp = pp->coldata[hp->index].firstcol;\n      col = hp->index + 1;\n      while(cp != NULL) {\n        if(lp != NULL) {\n          if (negateAndSOS[cp->row] <= 0) {\n            rowno[count] = cp->row;\n              a = cp->value;\n              if (negateAndSOS[cp->row])\n                a = -a;\n            row[count++] = a;\n          }\n          else {\n            if (MALLOC(SOSrow, 1, struct SOSrow) == NULL) {\n              FREE(SOSrowdata);\n              FREE(negateAndSOS);\n              FREE(row);\n              FREE(rowno);\n              return(FALSE);\n            }\n            if(SOSrowdata[cp->row].SOSrow == NULL)\n              SOSrowdata[cp->row].name = strdup(get_row_name(lp, cp->row));\n            SOSrow->next = SOSrowdata[cp->row].SOSrow;\n            SOSrowdata[cp->row].SOSrow = SOSrow;\n            SOSrowdata[cp->row].type = negateAndSOS[cp->row];\n            SOSrow->col = col;\n            SOSrow->value = cp->value;\n          }\n        }\n        tcp = cp;\n        /* cp = cp->next; */\n        cp = cp->prev;\n        free(tcp); /* free memory when data has been read */\n      }\n\n      if(lp != NULL) {\n        add_columnex(lp, count, row, rowno);\n        /* check for bound */\n        if(pp->coldata[hp->index].lowbo == -DEF_INFINITE * 10.0)\n          /* lp->orig_lowbo[pp->Rows+index] = 0.0; */\n          set_lowbo(lp, index, 0);\n        else\n          /* lp->orig_lowbo[pp->Rows+index] = pp->coldata[hp->index].lowbo; */\n          set_lowbo(lp, index, pp->coldata[hp->index].lowbo);\n        /* lp->orig_upbo[pp->Rows+index] = pp->coldata[hp->index].upbo; */\n        if(pp->coldata[hp->index].upbo >= DEF_INFINITE)\n          set_upbo(lp, index, DEF_INFINITE);\n        else\n          set_upbo(lp, index, pp->coldata[hp->index].upbo);\n\n        /* check if it must be an integer variable */\n        if(pp->coldata[hp->index].must_be_int) {\n          /* lp->must_be_int[pp->Rows + index]=TRUE; */\n          set_int(lp, index, TRUE);\n        }\n        if(pp->coldata[hp->index].must_be_sec) {\n          set_semicont(lp, index, TRUE);\n        }\n        if(pp->coldata[hp->index].must_be_free) {\n          set_unbounded(lp, index);\n        }\n\n        /* copy name of column variable */\n        if (!set_col_name(lp, index, hp->name)) {\n          FREE(SOSrowdata);\n          FREE(negateAndSOS);\n          FREE(row);\n          FREE(rowno);\n          return(FALSE);\n        }\n\n        /* put matrix values in intermediate row */\n        /* cp = hp->col; */\n        /* cp = hp->firstcol; */\n      }\n\n      /* thp = hp; */\n      /* hp = hp->next; */\n      /* free(thp->name); */\n      /* free(thp); */ /* free memory when data has been read */\n\n      hp = hp->nextelem;\n\n    }\n    /* pp->Hash_tab->table[i] = NULL; */\n\n  FREE(pp->coldata);\n\n  if(SOSrowdata != NULL) {\n    struct structSOS *structSOS;\n    struct structSOSvars *SOSvars, *SOSvars1;\n    int SOSweight = 0;\n\n    for(i = 1; i <= pp->Rows; i++) {\n      SOSrow = SOSrowdata[i].SOSrow;\n      if(SOSrow != NULL) {\n        if(MALLOC(structSOS, 1, struct structSOS) == NULL) {\n          FREE(SOSrowdata);\n          FREE(negateAndSOS);\n          FREE(row);\n          FREE(rowno);\n          return(FALSE);\n        }\n        structSOS->Nvars = 0;\n        structSOS->type = SOSrowdata[i].type;\n        structSOS->weight = ++SOSweight;\n        structSOS->name = strdup(SOSrowdata[i].name);\n        structSOS->LastSOSvars = NULL;\n        structSOS->next = pp->FirstSOS;\n        pp->FirstSOS = structSOS;\n        SOSvars = NULL;\n        while(SOSrow != NULL) {\n          SOSvars1 = SOSvars;\n          MALLOC(SOSvars, 1, struct structSOSvars);\n          SOSvars->next = SOSvars1;\n          SOSvars->col = SOSrow->col;\n          SOSvars->weight = SOSrow->value;\n          SOSvars->name = NULL;\n          structSOS->Nvars++;\n          SOSrow1 = SOSrow->next;\n          FREE(SOSrow);\n          SOSrow = SOSrow1;\n        }\n        structSOS->SOSvars = SOSvars;\n      }\n    }\n    FREE(SOSrowdata);\n  }\n\n  while(pp->FirstSOS != NULL)\n  {\n    struct structSOSvars *SOSvars, *SOSvars1;\n    int *sosvars, n, col2;\n    REAL *weights;\n    hashelem *hp2;\n\n    pp->LastSOS = pp->FirstSOS;\n    pp->FirstSOS = pp->FirstSOS->next;\n    SOSvars = pp->LastSOS->SOSvars;\n    if(lp != NULL) {\n      MALLOC(sosvars, pp->LastSOS->Nvars, int);\n      MALLOC(weights, pp->LastSOS->Nvars, double);\n    }\n    else {\n      sosvars = NULL;\n      weights = NULL;\n    }\n    n = 0;\n    while(SOSvars != NULL)\n    {\n      SOSvars1 = SOSvars;\n      SOSvars = SOSvars->next;\n      if(lp != NULL) {\n        col2 = SOSvars1->col;\n        if(col2 == 0)\n          if((hp2 = findhash(SOSvars1->name, lp->colname_hashtab)) != NULL)\n            col2 = hp2->index;\n        if (col2) {\n          sosvars[n] = col2;\n          weights[n++] = SOSvars1->weight;\n        }\n      }\n      FREE(SOSvars1->name);\n      FREE(SOSvars1);\n    }\n    if(lp != NULL) {\n      add_SOS(lp, pp->LastSOS->name, pp->LastSOS->type, pp->LastSOS->weight, n, sosvars, weights);\n      FREE(weights);\n      FREE(sosvars);\n    }\n    FREE(pp->LastSOS->name);\n    FREE(pp->LastSOS);\n  }\n\n  if(negateAndSOS != NULL) {\n    for(i1 = 0, i = 1; i <= pp->Rows; i++)\n      if(negateAndSOS[i] <= 0)\n        pp->relat[++i1] = pp->relat[i];\n\n#if 01\n    for(i = pp->Rows; i > 0; i--)\n      if(negateAndSOS[i] > 0) {\n        del_constraint(lp, i);\n        pp->Rows--;\n      }\n#endif\n  }\n\n  /* the following should be replaced by a call to the MPS print routine MB */\n\n#if 0\n  if(pp->Verbose) {\n    int j;\n\n    printf(\"\\n\");\n    printf(\"**********Data read**********\\n\");\n    printf(\"Rows    : %d\\n\", pp->Rows);\n    printf(\"Columns : %d\\n\", pp->Columns);\n    printf(\"Nonnuls : %d\\n\", pp->Non_zeros);\n    printf(\"NAME          LPPROB\\n\");\n    printf(\"ROWS\\n\");\n    for(i = 0; i <= pp->Rows; i++) {\n      if(pp->relat[i] == LE)\n        printf(\" L  \");\n      else if(pp->relat[i] == EQ)\n        printf(\" E  \");\n      else if(pp->relat[i] == GE)\n        printf(\" G  \");\n      else if(pp->relat[i] == OF)\n        printf(\" N  \");\n      printf(\"%s\\n\", get_row_name(lp, i));\n    }\n\n    printf(\"COLUMNS\\n\");\n    j = 0;\n    for(i = 0; i < pp->Non_zeros; i++) {\n      if(i == lp->col_end[j])\n        j++;\n      printf(\"    %-8s  %-8s  %g\\n\", get_col_name(lp, j),\n             get_row_name(lp, lp->mat[i].row_nr), (double)lp->mat[i].value);\n    }\n\n    printf(\"RHS\\n\");\n    for(i = 0; i <= pp->Rows; i++) {\n      printf(\"    RHS       %-8s  %g\\n\", get_row_name(lp, i),\n             (double)lp->orig_rhs[i]);\n    }\n\n    printf(\"RANGES\\n\");\n    for(i = 1; i <= pp->Rows; i++)\n      if((lp->orig_upbo[i] != lp->infinite) && (lp->orig_upbo[i] != 0)) {\n        printf(\"    RGS       %-8s  %g\\n\", get_row_name(lp, i),\n               (double)lp->orig_upbo[i]);\n      }\n      else if((lp->orig_lowbo[i] != 0)) {\n        printf(\"    RGS       %-8s  %g\\n\", get_row_name(lp, i),\n               (double)-lp->orig_lowbo[i]);\n      }\n\n    printf(\"BOUNDS\\n\");\n    for(i = pp->Rows + 1; i <= pp->Rows + pp->Columns; i++) {\n      if((lp->orig_lowbo[i] != 0) && (lp->orig_upbo[i] < lp->infinite) &&\n         (lp->orig_lowbo[i] == lp->orig_upbo[i])) {\n        printf(\" FX BND       %-8s  %g\\n\", get_col_name(lp, i - pp->Rows),\n               (double)lp->orig_upbo[i]);\n      }\n      else {\n        if(lp->orig_upbo[i] < lp->infinite)\n            printf(\" UP BND       %-8s  %g\\n\", get_col_name(lp, i - pp->Rows),\n                   (double)lp->orig_upbo[i]);\n        if(lp->orig_lowbo[i] > 0)\n            printf(\" LO BND       %-8s  %g\\n\", get_col_name(lp, i - pp->Rows),\n                   (double)lp->orig_lowbo[i]);\n      }\n    }\n\n    printf(\"ENDATA\\n\");\n  }\n#endif\n\n  FREE(row);\n  FREE(rowno);\n  FREE(negateAndSOS);\n  return(TRUE);\n} /* readinput */\n\nlprec *yacc_read(lprec *lp, int verbose, char *lp_name, int (*parse) (parse_parm *pp), parse_parm *pp, void (*delete_allocated_memory) (parse_parm *pp))\n{\n  REAL *orig_upbo;\n  int stat = -1;\n  lprec *lp0 = lp;\n\n  pp->title = lp_name;\n\n  if(!init_read(pp, verbose))\n    error(pp, CRITICAL, \"init_read failed\");\n  else if (setjmp(pp->jump_buf) == 0)\n    stat = parse(pp);\n\n  delete_allocated_memory(pp);\n\n  pp->Rows--;\n\n  pp->relat = NULL;\n  if((stat != 0) || (CALLOC(pp->relat, pp->Rows + 1, short) != NULL)) {\n    if(stat == 0) {\n      if(lp == NULL) {\n        lp = make_lp(pp->Rows, 0);\n      }\n      else {\n        int NRows;\n\n        for(NRows = get_Nrows(lp); NRows < pp->Rows; NRows++)\n          add_constraintex(lp, 0, NULL, NULL, LE, 0);\n      }\n    }\n    else\n      lp = NULL;\n    if ((stat != 0) || (lp != NULL)) {\n      if(lp != NULL) {\n        set_verbose(lp, pp->Verbose);\n      }\n\n      if (!readinput(pp, lp)) {\n        if((lp != NULL) && (lp0 == NULL))\n          delete_lp(lp);\n        lp = NULL;\n      }\n\n      if(lp != NULL) {\n        set_lp_name(lp, pp->title);\n        if(pp->Maximise)\n          set_maxim(lp);\n\n        if(pp->Rows) {\n          int row;\n\n          MALLOCCPY(orig_upbo, lp->orig_upbo, 1 + pp->Rows, REAL);\n          for(row = 1; row <= pp->Rows; row++)\n            set_constr_type(lp, row, pp->relat[row]);\n\n          memcpy(lp->orig_upbo, orig_upbo, (1 + pp->Rows) * sizeof(*orig_upbo)); /* restore upper bounds (range) */\n          FREE(orig_upbo);\n        }\n      }\n      if((pp->title != NULL) && (pp->title != lp_name))\n        free(pp->title);\n\n      free_hash_table(pp->Hash_tab);\n      free_hash_table(pp->Hash_constraints);\n    }\n    FREE(pp->relat);\n  }\n  null_tmp_store(pp, FALSE);\n  return(lp);\n}\n"
  },
  {
    "path": "utilities/lp_solve/yacc_read.h",
    "content": "/* prototypes of functions used in the parser */\n\n#include <setjmp.h>\n\n#ifndef __READ_H__\n#define __READ_H__\n\nstruct _tmp_store_struct\n{\n  char    *name;\n  int     row;\n  REAL    value;\n  REAL    rhs_value;\n  short   relat;\n};\n\ntypedef struct parse_parm_s\n{\n  void *scanner;\n  long lineno;\n  int Verbose;\n  jmp_buf jump_buf;\n  long Rows, Columns, Non_zeros, Lin_term_count;\n  struct rside *First_rside, *rs;\n  short SOStype;         /* SOS type */\n  char Ignore_int_decl, int_decl, Ignore_sec_decl, Ignore_free_decl, sos_decl, Maximise;\n  hashtable *Hash_tab, *Hash_constraints;\n  struct structcoldata *coldata;\n  struct structSOS *FirstSOS, *LastSOS;\n  struct _tmp_store_struct tmp_store;\n  char *title;\n  short *relat;\n  void *parse_vars;\n} parse_parm;\n\nvoid lex_fatal_error(parse_parm *, void *, const char * );\nint set_title(parse_parm *pp, const char *name);\nint add_constraint_name(parse_parm *pp, const char *name);\nint store_re_op(parse_parm *pp, char OP, int HadConstraint, int HadVar, int Had_lineair_sum);\nvoid null_tmp_store(parse_parm *pp, int init_Lin_term_count);\nint store_bounds(parse_parm *pp, int warn);\nvoid storevarandweight(parse_parm *pp, const char *name);\nint set_sos_type(parse_parm *pp, int SOStype);\nint set_sos_weight(parse_parm *pp, double weight, int sos_decl);\nint set_sec_threshold(parse_parm *pp, const char *name, REAL threshold);\nint rhs_store(parse_parm *pp, REAL value, int HadConstraint, int HadVar, int Had_lineair_sum);\nint var_store(parse_parm *pp, const char *var, REAL value, int HadConstraint, int HadVar, int Had_lineair_sum);\nint negate_constraint(parse_parm *pp);\nvoid add_row(parse_parm *pp);\nvoid add_sos_row(parse_parm *pp, short SOStype);\n\nvoid read_error(parse_parm *, void *, const char * );\nvoid check_int_sec_sos_free_decl(parse_parm *, int, int, int, int);\nlprec *yacc_read(lprec *lp, int verbose, char *lp_name, int (*parse) (parse_parm *pp), parse_parm *pp, void (*delete_allocated_memory) (parse_parm *pp));\n\n#define set_obj_dir(pp, maximise) pp->Maximise = maximise\n#endif\n"
  },
  {
    "path": "wrapping/CMakeLists.txt",
    "content": "itk_wrap_module(RTK)\n\nset(WRAPPER_SUBMODULE_ORDER\n  itkFixedArrayRTK\n  itkVectorRTK\n  itkCovariantVectorRTK\n  itkPointRTK\n  itkContinuousIndexRTK\n  itkMatrixRTK\n  itkVariableLengthVectorRTK\n  itkImageBaseRTK\n  itkImageRTK\n  itkCudaImageRTK\n  itkVectorImageRTK\n  rtkFFTRampImageFilter\n  rtkParkerShortScanImageFilter\n  rtkScatterGlareCorrectionImageFilter\n  itkImageSourceRTK\n  itkImageToImageFilterRTK\n  itkCudaImageToImageFilterRTK\n  itkInPlaceImageFilterRTK\n  itkCudaInPlaceImageFilterRTK\n  rtkForwardProjectionImageFilter\n  itkPyBufferRTK\n)\n\nitk_auto_load_submodules()\nitk_end_wrap_module()\n\nset(RTK_VERSION_SCRIPT \"${RTK_BINARY_DIR}/applications/rtkversion.py\")\nconfigure_file (${RTK_SOURCE_DIR}/applications/rtkversion.py.in ${RTK_VERSION_SCRIPT})\n\nfile(GLOB RTK_GROUP_SCRIPTS CONFIGURE_DEPENDS\n  \"${RTK_SOURCE_DIR}/applications/rtk*_group.py\")\nfile(GLOB RTK_APP_SCRIPTS CONFIGURE_DEPENDS\n  \"${RTK_SOURCE_DIR}/applications/rtk*/rtk*.py\")\n\nwrap_itk_python_bindings_install(/itk \"RTK\"\n  __init_rtk__.py\n  ${RTK_GROUP_SCRIPTS}\n  ${RTK_APP_SCRIPTS}\n  ${RTK_VERSION_SCRIPT}\n  ${RTK_SOURCE_DIR}/wrapping/rtkExtras.py\n  ${RTK_SOURCE_DIR}/applications/rtkargumentparser.py\n)\n"
  },
  {
    "path": "wrapping/ConvexShape.i",
    "content": "%include \"typemaps.i\"\n\n// rtkConvexShape::IsIntersectedByRay\n%apply double &OUTPUT {double & nearDist, double & farDist};"
  },
  {
    "path": "wrapping/FieldOfViewImageFilter.i",
    "content": "%include \"typemaps.i\"\n\n// rtk::FieldOfViewImageFilter::ComputeFOVRadius\n%apply double &OUTPUT {double & x, double & z, double & r};"
  },
  {
    "path": "wrapping/__init_rtk__.py",
    "content": "import sys\nimport importlib\nimport os\n\nitk_module = sys.modules[\"itk\"]\nrtk_module = getattr(itk_module, \"RTK\")\n\n# Import RTK submodules\nrtk_submodules = [\n    \"itk.rtkversion\",\n    \"itk.rtkargumentparser\",\n    \"itk.rtkinputprojections_group\",\n    \"itk.rtk3Doutputimage_group\",\n    \"itk.rtkprojectors_group\",\n    \"itk.rtkiterations_group\",\n    \"itk.rtkExtras\",\n]\nfor mod_name in rtk_submodules:\n    mod = importlib.import_module(mod_name)\n    for a in dir(mod):\n        if a[0] != \"_\":\n            setattr(rtk_module, a, getattr(mod, a))\n\n# Application modules\n_app_modules = [\n    \"rtkadmmtotalvariation\",\n    \"rtkamsterdamshroud\",\n    \"rtkbackprojections\",\n    \"rtkbioscangeometry\",\n    \"rtkcheckimagequality\",\n    \"rtkconjugategradient\",\n    \"rtkdigisensgeometry\",\n    \"rtkdrawgeometricphantom\",\n    \"rtkdrawshepploganphantom\",\n    \"rtkdualenergyforwardmodel\",\n    \"rtkdualenergysimplexdecomposition\",\n    \"rtkelektasynergygeometry\",\n    \"rtkextractphasesignal\",\n    \"rtkfdk\",\n    \"rtkfieldofview\",\n    \"rtkforwardprojections\",\n    \"rtkorageometry\",\n    \"rtkprojectgeometricphantom\",\n    \"rtkprojections\",\n    \"rtkprojectshepploganphantom\",\n    \"rtkshowgeometry\",\n    \"rtksimulatedgeometry\",\n    \"rtkvarianobigeometry\",\n]\n\n# Dynamically access make_application_func from rtkExtras\nrtk_extras = importlib.import_module(\"itk.rtkExtras\")\nmake_application_func = getattr(rtk_extras, \"make_application_func\")\n\n# Dynamically register applications\nfor app_name in _app_modules:\n    setattr(rtk_module, app_name, make_application_func(app_name))\n"
  },
  {
    "path": "wrapping/itkContinuousIndexRTK.wrap",
    "content": "list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\nif (${_index} EQUAL -1)\n  itk_wrap_class(\"itk::ContinuousIndex\")\n    itk_wrap_template(\"${ITKM_D}1\" \"double, 1\")\n  itk_end_wrap_class()\nendif()\n"
  },
  {
    "path": "wrapping/itkCovariantVectorRTK.wrap",
    "content": "list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\nif (${_index} EQUAL -1)\n  itk_wrap_class(\"itk::CovariantVector\")\n    itk_wrap_template(\"${ITKM_D}1\" \"${ITKT_D}, 1\")\n  itk_end_wrap_class()\nendif()\n\n"
  },
  {
    "path": "wrapping/itkCudaImageDataManagerRTK.wrap",
    "content": "if(RTK_USE_CUDA)\n\n  itk_wrap_include(itkCudaImage.h)\n\n  itk_wrap_class(\"itk::CudaImageDataManager\" POINTER)\n\n    # Add all missing image with dim == 4\n    list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\n    if(${_index} EQUAL -1)\n      itk_wrap_template(\"CI${ITKM_F}4\" \"itk::CudaImage<${ITKT_F}, 4>\")\n      foreach(c 2 3 4)\n        itk_wrap_template(\"CI${ITKM_VF${c}}4\" \"itk::CudaImage<${ITKT_VF${c}}, 4>\")\n        itk_wrap_template(\"CI${ITKM_CVF${c}}4\" \"itk::CudaImage<${ITKT_CVF${c}}, 4>\")\n      endforeach()\n    endif()\n\n    # Add all missing image with comp == 5\n    list(FIND ITK_WRAP_VECTOR_COMPONENTS \"5\" _index)\n    if(${_index} EQUAL -1)\n      UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n      foreach(d ${imageDimensions})\n        itk_wrap_template(\"CI${ITKM_VF5}${d}\" \"itk::CudaImage<${ITKT_VF5}, ${d}>\")\n        itk_wrap_template(\"CI${ITKM_CVF5}${d}\" \"itk::CudaImage<${ITKT_CVF5}, ${d}>\")\n      endforeach()\n    endif()\n\n  itk_end_wrap_class()\n\nendif()\n"
  },
  {
    "path": "wrapping/itkCudaImageRTK.wrap",
    "content": "if(RTK_USE_CUDA)\n\n  if(CudaCommon_VERSION_MAJOR)\n    configure_file(\"${CudaCommon_SOURCE_DIR}/wrapping/CudaImage.i.init\" \"${CMAKE_CURRENT_BINARY_DIR}/CudaImageRTK.i\" @ONLY)\n  endif()\n\n  function(wrap_CudaImage_swig_ext type px_type)\n    if(CudaCommon_VERSION_MAJOR)\n      set(CudaImageTypes ${type})\n      set(PixelType ${px_type})\n      configure_file(${CudaCommon_SOURCE_DIR}/wrapping/CudaImage.i.in ${CMAKE_CURRENT_BINARY_DIR}/CudaImageRTK.i.temp @ONLY)\n      file(READ ${CMAKE_CURRENT_BINARY_DIR}/CudaImageRTK.i.temp CudaImageInterfaceTemp)\n      file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/CudaImageRTK.i ${CudaImageInterfaceTemp})\n    endif()\n  endfunction()\n\n  itk_wrap_class(\"itk::CudaImage\" POINTER_WITH_CONST_POINTER)\n\n    # Add all missing image with dim == 4\n    list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\n    if (${_index} EQUAL -1)\n      itk_wrap_template(\"F4\" \"${ITKT_F}, 4\")\n      wrap_CudaImage_swig_ext(F4 F)\n      foreach(vector_type VF CVF)\n        foreach(c 2 3 4)\n          itk_wrap_template(\"${ITKM_${vector_type}${c}}4\" \"${ITKT_${vector_type}${c}}, 4\")\n          wrap_CudaImage_swig_ext(${ITKM_${vector_type}${c}}4 F)\n        endforeach()\n      endforeach()\n    endif()\n\n    # Add all missing image with comp == 5\n    list(FIND ITK_WRAP_VECTOR_COMPONENTS \"5\" _index)\n    if(${_index} EQUAL -1)\n      UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n      foreach(d ${imageDimensions})\n        foreach(vector_type VF CVF)\n          itk_wrap_template(\"${ITKM_${vector_type}5}${d}\" \"${ITKT_${vector_type}5}, ${d}\")\n          wrap_CudaImage_swig_ext(${ITKM_${vector_type}5}${d} F)\n        endforeach()\n      endforeach()\n    endif()\n\n  itk_end_wrap_class()\n\n  if(CudaCommon_VERSION_MAJOR)\n    # Add library files to be included at a submodule level and copy them into\n    # ITK's wrapping typedef directory.\n    # Another approach is to add CudaImage.i to the WRAPPER_SWIG_LIBRARY_FILES list\n    # but then the %pythoncode from CudaImage.i.init gets only included in\n    # itkCudaDataManagerPython.py even if the WRAPPER_SUBMODULE_ORDER is set.\n    # Prefer using ITK_WRAP_PYTHON_SWIG_EXT to make sure the block is included in\n    # the right file exclusively.\n    set(ITK_WRAP_PYTHON_SWIG_EXT\n      \"%include CudaImageRTK.i\\n${ITK_WRAP_PYTHON_SWIG_EXT}\")\n\n    file(COPY \"${CMAKE_CURRENT_BINARY_DIR}/CudaImageRTK.i\"\n      DESTINATION \"${WRAPPER_MASTER_INDEX_OUTPUT_DIR}\")\n\n    # Make sure to rebuild the python file when CudaImage.i is modified.\n    # Touching CudaImage.i directly does not force a rebuild because it is just\n    # appended to the ITK_WRAP_PYTHON_SWIG_EXT variable\n    file(TOUCH ${WRAPPER_MASTER_INDEX_OUTPUT_DIR}/itkCudaImageRTK.i)\n  endif()\n\nendif()\n"
  },
  {
    "path": "wrapping/itkCudaImageToImageFilterRTK.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(rtkFFTRampImageFilter.h)\n  itk_wrap_include(rtkScatterGlareCorrectionImageFilter.h)\n\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n\n    foreach(d ${ITK_WRAP_IMAGE_DIMS})\n      itk_wrap_template(\"CI${ITKM_F}${d}CI${ITKM_F}${d}\"\n        \"itk::CudaImage<${ITKT_F}, ${d}>, itk::CudaImage<${ITKT_F}, ${d}>\")\n    endforeach()\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n    UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n    foreach(component ${vectorComponents})\n      foreach(d ${imageDimensions})\n        itk_wrap_template(\"CI${ITKM_VF${component}}${d}CI${ITKM_VF${component}}${d}\"\n          \"itk::CudaImage<${ITKT_VF${component}}, ${d}>, itk::CudaImage<${ITKT_VF${component}}, ${d}>\")\n      endforeach()\n    endforeach()\n\n    itk_wrap_template(\"CIF3CIF3RFCIF3CIF3F\"\n      \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, rtk::FFTRampImageFilter< itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float >\")\n    itk_wrap_template(\"CIF3CIF3SGCIF3CIF3F\"\n      \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, rtk::ScatterGlareCorrectionImageFilter< itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float >\")\n  itk_end_wrap_class()\n\nendif()\n"
  },
  {
    "path": "wrapping/itkCudaInPlaceImageFilterRTK.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(rtkParkerShortScanImageFilter.h)\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n\n    #itk_wrap_image_filter_combinations(\"${WRAP_ITK_REAL}\" \"${WRAP_ITK_REAL}\")\n    foreach(d ${ITK_WRAP_IMAGE_DIMS})\n      itk_wrap_template(\"CI${ITKM_F}${d}CI${ITKM_F}${d}\"\n        \"itk::CudaImage<${ITKT_F}, ${d}>, itk::CudaImage<${ITKT_F}, ${d}>\")\n    endforeach()\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n    foreach(component ${vectorComponents})\n      foreach(d ${ITK_WRAP_IMAGE_DIMS})\n        itk_wrap_template(\"CI${ITKM_V${ITKM_F}${component}}${d}CI${ITKM_V${ITKM_F}${component}}${d}\"\n          \"itk::CudaImage<itk::Vector<${ITKT_F},${component}>, ${d}>, itk::CudaImage<itk::Vector<${ITKT_F},${component}>, ${d}>\")\n      endforeach()\n    endforeach()\n\n    itk_wrap_template(\"CIF3CIF3PSCIF3\"\n      \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, rtk::ParkerShortScanImageFilter< itk::CudaImage<float, 3>>\")\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n    foreach(d ${ITK_WRAP_IMAGE_DIMS})\n      itk_wrap_template(\"CI${ITKM_F}${d}CI${ITKM_F}${d}IPIFCI${ITKM_F}${d}\" \"itk::CudaImage<${ITKT_F}, ${d}>, itk::CudaImage<${ITKT_F}, ${d}>, itk::InPlaceImageFilter< itk::CudaImage<${ITKT_F}, ${d}> >\")\n    endforeach()\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    # Force ITK_WRAP_IMAGE_DIMS to \"2;3;4\"\n    UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n    UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n    foreach(component ${vectorComponents})\n      foreach(d ${imageDimensions})\n        itk_wrap_template(\"CI${ITKM_VF${component}}${d}CI${ITKM_VF${component}}${d}IPIFCI${ITKM_VF${component}}${d}\"\n          \"itk::CudaImage<${ITKT_VF${component}}, ${d}>, itk::CudaImage<${ITKT_VF${component}}, ${d}>, itk::InPlaceImageFilter< itk::CudaImage<${ITKT_VF${component}}, ${d}> >\")\n      endforeach()\n    endforeach()\n\n    itk_wrap_template(\"CIF3CIF3PSCIF3\"\n      \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, rtk::ParkerShortScanImageFilter< itk::CudaImage<float, 3>>\")\n  itk_end_wrap_class()\n\nendif()\n"
  },
  {
    "path": "wrapping/itkFixedArrayRTK.wrap",
    "content": "itk_wrap_class(\"itk::FixedArray\")\n  itk_wrap_template(\"i2\" \"int, 2\")\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/itkImageBaseRTK.wrap",
    "content": "list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\nif (${_index} EQUAL -1)\n  itk_wrap_class(\"itk::ImageBase\" POINTER)\n    # See ITK_DIR/Wrapping/Generators/Python/CMakeLists.txt to understand the next 3 lines\n    set(ITK_WRAP_PYTHON_SWIG_EXT \"${ITK_WRAP_PYTHON_SWIG_EXT}%inline %{\\n\")\n    set(ITK_WRAP_PYTHON_SWIG_EXT \"${ITK_WRAP_PYTHON_SWIG_EXT}#include \\\"itkContinuousIndexRTKSwigInterface.h\\\"\\n\")\n    set(ITK_WRAP_PYTHON_SWIG_EXT \"${ITK_WRAP_PYTHON_SWIG_EXT}%}\\n\")\n\n    list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n    if (${_index} EQUAL -1)\n      itk_wrap_template(\"1\" \"1\")\n    endif()\n  itk_end_wrap_class()\nendif()\n\n"
  },
  {
    "path": "wrapping/itkImageDuplicatorRTK.wrap",
    "content": "list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\nif (${_index} EQUAL -1)\n  itk_wrap_class(\"itk::ImageDuplicator\" POINTER)\n    # Making sure that all types wrapped in PyBuffer are also wrapped for ImageDuplicator\n    # as this filter is used in the Python NumPy  bridge.\n    UNIQUE(types \"D;UC;US;${WRAP_ITK_REAL}\")\n    foreach(t ${types})\n      itk_wrap_template(\"I${ITKM_${t}}1\" \"itk::Image<${ITKT_${t}}, 1>\")\n    endforeach()\n\n  itk_end_wrap_class()\nendif()\n\n"
  },
  {
    "path": "wrapping/itkImageFileReaderRTK.wrap",
    "content": "itk_wrap_class(\"itk::ImageFileReader\" POINTER)\n\n  # Force ITK_WRAP_VECTOR_COMPONENTS to \"2;3;4;5\"\n  set(vectorComponents 2 3 4 5)\n  foreach(component ${vectorComponents})\n    list(FIND ITK_WRAP_VECTOR_COMPONENTS \"${component}\" _index)\n    if (${_index} EQUAL -1)\n      foreach(vt ${WRAP_ITK_VECTOR_REAL})\n        foreach(d ${ITK_WRAP_IMAGE_DIMS})\n          itk_wrap_template(\"I${ITKM_${vt}${component}}${d}\" \"itk::Image<${ITKT_${vt}${component}}, ${d}>\")\n        endforeach()\n      endforeach()\n    endif()\n  endforeach()\n\n  # Wrap ITK dimension 1 missing types\n  UNIQUE(image_types \"D;UC;US;${WRAP_ITK_REAL}\")\n  list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n  if (${_index} EQUAL -1)\n    foreach(t ${image_types})\n      itk_wrap_template(\"I${ITKM_${t}}1\" \"itk::Image<${ITKT_${t}}, 1>\")\n    endforeach()\n  endif()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/itkImageFileWriterRTK.wrap",
    "content": "itk_wrap_class(\"itk::ImageFileWriter\" POINTER)\n\n  # Force ITK_WRAP_VECTOR_COMPONENTS to \"2;3;4;5\"\n  set(vectorComponents 2 3 4 5)\n  foreach(component ${vectorComponents})\n    list(FIND ITK_WRAP_VECTOR_COMPONENTS \"${component}\" _index)\n    if (${_index} EQUAL -1)\n      foreach(vt ${WRAP_ITK_VECTOR_REAL})\n        foreach(d ${ITK_WRAP_IMAGE_DIMS})\n          itk_wrap_template(\"I${ITKM_${vt}${component}}${d}\" \"itk::Image<${ITKT_${vt}${component}}, ${d}>\")\n        endforeach()\n      endforeach()\n    endif()\n  endforeach()\n\n  # Wrap ITK dimension 1 missing types\n  UNIQUE(image_types \"D;UC;US;${WRAP_ITK_REAL}\")\n  list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n  if (${_index} EQUAL -1)\n    foreach(t ${image_types})\n      itk_wrap_template(\"I${ITKM_${t}}1\" \"itk::Image<${ITKT_${t}}, 1>\")\n    endforeach()\n  endif()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/itkImageRTK.wrap",
    "content": "itk_wrap_class(\"itk::Image\" POINTER)\n\n  # Wrap ITK unsigned short missing types\n  foreach(d 1 2 3 4)\n    list(FIND ITK_WRAP_IMAGE_DIMS ${d} _index)\n    if (${_index} EQUAL -1 OR NOT ITK_WRAP_unsigned_short)\n      itk_wrap_template(\"US${d}\" \"${ITKT_US}, ${d}\")\n    endif()\n  endforeach()\n\n  # Wrap ITK short combination (required by: rtkLookupTableImageFilter)\n  if (NOT ITK_WRAP_signed_short)\n    itk_wrap_template(\"SS3\" \"${ITKT_SS}, 3\")\n  endif()\n\n  # Wrap ITK dimension 1 missing types\n  list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n  if (${_index} EQUAL -1 OR NOT ITK_WRAP_unsigned_char)\n    itk_wrap_template(\"UC1\" \"${ITKT_UC}, 1\")\n  endif()\n  if (${_index} EQUAL -1 OR NOT ITK_WRAP_float)\n    itk_wrap_template(\"F1\" \"${ITKT_F}, 1\")\n  endif()\n  if (${_index} EQUAL -1)\n    itk_wrap_template(\"D1\" \"${ITKT_D}, 1\")\n  endif()\n\n  # Wrap ITK dimension 4 missing types\n  list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\n  if (${_index} EQUAL -1)\n    itk_wrap_template(\"F4\" \"${ITKT_F}, 4\")\n    if (ITK_WRAP_double)\n      itk_wrap_template(\"D4\" \"${ITKT_D}, 4\")\n    endif()\n  endif()\n\n  # Force ITK_WRAP_IMAGE_DIMS to contain \"2;3;4\"\n  UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n  # Force VECTOR_COMPONENTS to contain \"2;3;4;5\"\n  set(vectorComponents 2 3 4 5)\n  foreach(component ${vectorComponents})\n    list(FIND ITK_WRAP_VECTOR_COMPONENTS \"${component}\" _index)\n    if (${_index} EQUAL -1)\n      foreach(d ${imageDimensions})\n        foreach(vt ${WRAP_ITK_VECTOR_REAL})\n          itk_wrap_template(\"${ITKM_${vt}${component}}${d}\" \"${ITKT_${vt}${component}}, ${d}\")\n        endforeach()\n        foreach(cvt ${WRAP_ITK_COV_VECTOR_REAL})\n          itk_wrap_template(\"${ITKM_${cvt}${component}}${d}\" \"${ITKT_${cvt}${component}}, ${d}\")\n        endforeach()\n      endforeach()\n    endif()\n  endforeach()\n\n  # Force ITK_WRAP_VECTOR_COMPONENTS to contain \"2;3;4;5\"\n  UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n\n  # Force ITK_WRAP_IMAGE_DIMS to contain \"2;3;4\"\n  set(imageDimensions 2 3 4)\n  foreach(d ${imageDimensions})\n    list(FIND ITK_WRAP_IMAGE_DIMS \"${d}\" _index)\n    if (${_index} EQUAL -1)\n      foreach(component ${ITK_WRAP_VECTOR_COMPONENTS})\n        foreach(vt ${WRAP_ITK_VECTOR_REAL})\n          itk_wrap_template(\"${ITKM_${vt}${component}}${d}\" \"${ITKT_${vt}${component}}, ${d}\")\n        endforeach()\n        foreach(cvt ${WRAP_ITK_COV_VECTOR_REAL})\n          itk_wrap_template(\"${ITKM_${cvt}${component}}${d}\" \"${ITKT_${cvt}${component}}, ${d}\")\n        endforeach()\n      endforeach()\n    endif()\n  endforeach()\n\n  list(FIND ITK_WRAP_VECTOR_COMPONENTS \"5\" _index)\n  if (${_index} EQUAL -1)\n    list(FIND WRAP_ITK_COV_VECTOR_REAL \"CVD\" _index)\n    if (${_index} EQUAL -1)\n      itk_wrap_template(\"${ITKM_CVD5}3\" \"itk::CovariantVector<double,5>, 3\")\n    endif()\n  endif()\n\nitk_end_wrap_class()\n\nitk_wrap_simple_type_swig_interface(\"itk::Image< float, 2 >::ConstPointer\" \"itkImageF2_ConstPointer\")\nitk_wrap_simple_type(\"itk::Image< float, 2 >::ConstPointer\" \"itkImageF2_ConstPointer\")\n\nitk_wrap_simple_type_swig_interface(\"itk::Image< float, 3 >::ConstPointer\" \"itkImageF3_ConstPointer\")\nitk_wrap_simple_type(\"itk::Image< float, 3 >::ConstPointer\" \"itkImageF3_ConstPointer\")\n\nitk_wrap_simple_type_swig_interface(\"itk::Image< float, 4 >::ConstPointer\" \"itkImageF4_ConstPointer\")\nitk_wrap_simple_type(\"itk::Image< float, 4 >::ConstPointer\" \"itkImageF4_ConstPointer\")\n\n#itk_wrap_simple_type_swig_interface(\"itk::Image< itk::CovariantVector< float, 3 >, 4 >::ConstPointer\" \"itkImageCVF34_ConstPointer\")\n#itk_wrap_simple_type(\"itk::Image< itk::CovariantVector< float, 3 >, 4 >::ConstPointer\" \"itkImageCVF34_ConstPointer\")\n\nif (ITK_WRAP_double)\n  itk_wrap_simple_type_swig_interface(\"itk::Image< double, 3 >::ConstPointer\" \"itkImageD3_ConstPointer\")\n  itk_wrap_simple_type(\"itk::Image< double, 3 >::ConstPointer\" \"itkImageD3_ConstPointer\")\n\n  itk_wrap_simple_type_swig_interface(\"itk::Image< double, 4 >::ConstPointer\" \"itkImageD4_ConstPointer\")\n  itk_wrap_simple_type(\"itk::Image< double, 4 >::ConstPointer\" \"itkImageD4_ConstPointer\")\n\n  #itk_wrap_simple_type_swig_interface(\"itk::Image< itk::CovariantVector< double, 3 >, 4 >::ConstPointer\" \"itkImageCVD34_ConstPointer\")\n  #itk_wrap_simple_type(\"itk::Image< itk::CovariantVector< double, 3 >, 4 >::ConstPointer\" \"itkImageCVD34_ConstPointer\")\nendif()\n\nset(vectorComponents 2 3 4 5)\nforeach(v ${vectorComponents})\n  foreach(cvt ${WRAP_ITK_COV_VECTOR_REAL})\n\n    itk_wrap_simple_type_swig_interface(\"itk::Image< ${ITKT_${cvt}${v}}, 4 >::ConstPointer\" \"itkImage${ITKM_${cvt}${v}}4_ConstPointer\")\n    itk_wrap_simple_type(\"itk::Image< ${ITKT_${cvt}${v}}, 4 >::ConstPointer\" \"itkImage${ITKM_${cvt}${v}}4_ConstPointer\")\n\n  endforeach()\nendforeach()\n"
  },
  {
    "path": "wrapping/itkImageRegionRTK.wrap",
    "content": "list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\nif (${_index} EQUAL -1)\n  itk_wrap_class(\"itk::ImageRegion\")\n    itk_wrap_template(1 1)\n  itk_end_wrap_class()\nendif()\n\n"
  },
  {
    "path": "wrapping/itkImageSourceRTK.wrap",
    "content": "itk_wrap_class(\"itk::ImageSource\" POINTER)\n\n  # Wrap ITK double missing types\n  if (NOT ITK_WRAP_double)\n    itk_wrap_template(\"ID1\" \"itk::Image<${ITKT_D}, 1>\")\n    itk_wrap_template(\"ID2\" \"itk::Image<${ITKT_D}, 2>\")\n    itk_wrap_template(\"ID3\" \"itk::Image<${ITKT_D}, 3>\")\n  endif()\n\n  # Wrap ITK unsigned char missing types\n  if (NOT ITK_WRAP_unsigned_char)\n    itk_wrap_template(\"IUC1\" \"itk::Image<${ITKT_UC}, 1>\")\n  endif()\n\n  # Wrap ITK unsigned short missing types\n  if (NOT ITK_WRAP_unsigned_short)\n    itk_wrap_template(\"IUS1\" \"itk::Image<${ITKT_US}, 1>\")\n    itk_wrap_template(\"IUS2\" \"itk::Image<${ITKT_US}, 2>\")\n    itk_wrap_template(\"IUS3\" \"itk::Image<${ITKT_US}, 3>\")\n  endif()\n\n  # Wrap ITK dimension 1 missing types\n  list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n  if (${_index} EQUAL -1)\n    foreach(t ${WRAP_ITK_REAL})\n      itk_wrap_template(\"I${ITKM_${t}}1\" \"itk::Image<${ITKT_${t}}, 1>\")\n    endforeach()\n\n    if (ITK_WRAP_unsigned_char)\n      itk_wrap_template(\"IUC1\" \"itk::Image<${ITKT_UC}, 1>\")\n    endif()\n    if (ITK_WRAP_unsigned_short)\n      itk_wrap_template(\"IUS1\" \"itk::Image<${ITKT_US}, 1>\")\n    endif()\n  endif()\n\n  # Wrap ITK dimension 4 missing types\n  list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\n  if (${_index} EQUAL -1)\n    itk_wrap_template(\"IF4\" \"itk::Image<${ITKT_F}, 4>\")\n    if (ITK_WRAP_double)\n      itk_wrap_template(\"ID4\" \"itk::Image<${ITKT_D}, 4>\")\n    endif()\n  endif()\n\n  # Wrap CUDA types\n  if(RTK_USE_CUDA)\n    itk_wrap_include(itkCudaImage.h)\n\n    # Wrap ITK dimension 4 missing types\n    list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\n    if (${_index} EQUAL -1)\n      itk_wrap_template(\"CIF4\" \"itk::CudaImage<${ITKT_F}, 4>\")\n    endif()\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n    UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n    foreach(c ${vectorComponents})\n      foreach(d ${imageDimensions})\n        list(FIND ITK_WRAP_IMAGE_DIMS \"${d}\" _indexd)\n        list(FIND ITK_WRAP_VECTOR_COMPONENTS \"${c}\" _indexc)\n        if (${_indexd} EQUAL -1 OR ${_indexc} EQUAL -1)\n          itk_wrap_template(\"CI${ITKM_VF${c}}${d}\" \"itk::CudaImage<${ITKT_VF${c}}, ${d}>\")\n        endif()\n      endforeach()\n    endforeach()\n\n  endif()\n\n  # Force ITK_WRAP_IMAGE_DIMS to contain \"2;3;4\"\n  UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n  set(vectorComponents \"2;3;4;5\")\n  remove(vectorComponents \"${vectorComponents}\" \"${ITK_WRAP_VECTOR_COMPONENTS}\")\n  foreach(c ${vectorComponents})\n    foreach(vt ${WRAP_ITK_VECTOR_REAL})\n      foreach(d ${imageDimensions})\n        itk_wrap_template(\"I${ITKM_${vt}${c}}${d}\" \"itk::Image<${ITKT_${vt}${c}}, ${d}>\")\n      endforeach()\n    endforeach()\n  endforeach()\n\n  # Force ITK_WRAP_IMAGE_DIMS to contain \"2;3;4\"\n  set(imageDimensions 2 3 4)\n  foreach(d ${imageDimensions})\n    list(FIND ITK_WRAP_IMAGE_DIMS \"${d}\" _index)\n    if (${_index} EQUAL -1)\n      foreach(vt ${WRAP_ITK_VECTOR_REAL})\n        foreach(c ${ITK_WRAP_VECTOR_COMPONENTS})\n          itk_wrap_template(\"I${ITKM_${vt}${c}}${d}\" \"itk::Image<${ITKT_${vt}${c}}, ${d}>\")\n        endforeach()\n      endforeach()\n    endif()\n  endforeach()\n\n  # Wrap ITK CovariantVector missing types\n  if (NOT ITK_WRAP_covariant_vector_double)\n\n    set(vectorComponents 2 4 5) # Component 3 handled in ITK\n    foreach(v ${vectorComponents})\n\n      itk_wrap_template(\"ICVD${v}3\" \"itk::Image<itk::CovariantVector<${ITKT_D}, ${v}>, 3>\")\n\n    endforeach()\n\n  endif()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/itkImageToImageFilterRTK.wrap",
    "content": "itk_wrap_class(\"itk::ImageToImageFilter\" POINTER)\n\n  # Wrap ITK double missing types\n  if (NOT ITK_WRAP_double)\n    itk_wrap_template(\"ID1ID1\" \"itk::Image<${ITKT_D}, 1>, itk::Image<${ITKT_D}, 1>\")\n    itk_wrap_template(\"ID3ID2\" \"itk::Image<${ITKT_D}, 3>, itk::Image<${ITKT_D}, 2>\")\n  endif()\n\n  # Wrap ITK dimension 1 missing types\n  list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n  if (${_index} EQUAL -1)\n    itk_wrap_template(\"IF1IF1\" \"itk::Image<${ITKT_F}, 1>, itk::Image<${ITKT_F}, 1>\")\n    if (ITK_WRAP_double)\n      itk_wrap_template(\"ID1ID1\" \"itk::Image<${ITKT_D}, 1>, itk::Image<${ITKT_D}, 1>\")\n    endif()\n  endif()\n\n  # Wrap ITK unsigned short missing types\n  if (NOT ITK_WRAP_unsigned_short)\n    itk_wrap_template(\"IUS2IUS2\" \"itk::Image<${ITKT_US}, 2>, itk::Image<${ITKT_US}, 2>\")\n    itk_wrap_template(\"IUS3IUS3\" \"itk::Image<${ITKT_US}, 3>, itk::Image<${ITKT_US}, 3>\")\n  endif()\n\n  # Wrap ITK unsigned short combination (required by : rtkLookupTableImageFilter)\n  if (NOT ITK_WRAP_unsigned_short)\n    foreach(t ${WRAP_ITK_REAL})\n      itk_wrap_template(\"IUS2I${ITKM_${t}}2\" \"itk::Image<${ITKT_US}, 2>, itk::Image<${ITKT_${t}}, 2>\")\n      itk_wrap_template(\"IUS3I${ITKM_${t}}3\" \"itk::Image<${ITKT_US}, 3>, itk::Image<${ITKT_${t}}, 3>\")\n    endforeach()\n    list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n    if (NOT ${_index} EQUAL -1)\n      itk_wrap_template(\"IUS1IF1\" \"itk::Image<${ITKT_US}, 1>, itk::Image<${ITKT_F}, 1>\")\n    endif()\n  endif()\n\n  # Wrap ITK short combination (required by : rtkLookupTableImageFilter)\n  if (NOT ITK_WRAP_signed_short)\n    itk_wrap_template(\"ISS3IF3\" \"itk::Image<${ITKT_SS}, 3>, itk::Image<${ITKT_F}, 3>\")\n  endif()\n\n  # Wrap ITK real type combination\n  itk_wrap_template(\"IF3ID2\" \"itk::Image<${ITKT_F}, 3>, itk::Image<${ITKT_D}, 2>\")\n\n  # Wrap ITK dimension 4 missing types\n  list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\n  if (${_index} EQUAL -1)\n    itk_wrap_template(\"IF4IF3\" \"itk::Image<${ITKT_F}, 4>, itk::Image<${ITKT_F}, 3>\")\n    itk_wrap_template(\"IF4IF4\" \"itk::Image<${ITKT_F}, 4>, itk::Image<${ITKT_F}, 4>\")\n    if (ITK_WRAP_double)\n      itk_wrap_template(\"ID4ID3\" \"itk::Image<${ITKT_D}, 4>, itk::Image<${ITKT_D}, 3>\")\n      itk_wrap_template(\"ID4ID4\" \"itk::Image<${ITKT_D}, 4>, itk::Image<${ITKT_D}, 4>\")\n    endif()\n  endif()\n\n  # Wrap CUDA types\n  if(RTK_USE_CUDA)\n    itk_wrap_include(itkCudaImage.h)\n\n    # Wrap ITK dimension 4 missing types\n    list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\n    if (${_index} EQUAL -1)\n      itk_wrap_template(\"CI${ITKM_F}4CI${ITKM_F}4\"\n        \"itk::CudaImage<${ITKT_F}, 4>, itk::CudaImage<${ITKT_F}, 4>\")\n    endif()\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n    UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n    foreach(c ${vectorComponents})\n      foreach(d ${imageDimensions})\n        list(FIND ITK_WRAP_IMAGE_DIMS \"${d}\" _indexd)\n        list(FIND ITK_WRAP_VECTOR_COMPONENTS \"${c}\" _indexc)\n        if (${_indexd} EQUAL -1 OR ${_indexc} EQUAL -1)\n          itk_wrap_template(\"CI${ITKM_VF${c}}${d}CI${ITKM_VF${c}}${d}\"\n          \"itk::CudaImage<${ITKT_VF${c}}, ${d}>, itk::CudaImage<${ITKT_VF${c}}, ${d}>\")\n        endif()\n      endforeach()\n    endforeach()\n\n  endif()\n\n  # Force ITK_WRAP_IMAGE_DIMS to contain \"2;3;4\"\n  UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n  set(vectorComponents \"2;3;4;5\")\n  remove(vectorComponents \"${vectorComponents}\" \"${ITK_WRAP_VECTOR_COMPONENTS}\")\n  foreach(c ${vectorComponents})\n    foreach(vt ${WRAP_ITK_VECTOR_REAL})\n      foreach(d ${imageDimensions})\n        itk_wrap_template(\"I${ITKM_${vt}${c}}${d}I${ITKM_${vt}${c}}${d}\"\n          \"itk::Image<${ITKT_${vt}${c}}, ${d}>, itk::Image<${ITKT_${vt}${c}}, ${d}>\")\n      endforeach()\n    endforeach()\n  endforeach()\n\n  # Force ITK_WRAP_VECTOR_COMPONENTS to contain \"2;3;4;5\"\n  UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n\n  # Force ITK_WRAP_IMAGE_DIMS to contain \"2;3;4\"\n  set(imageDimensions 2 3 4)\n  foreach(d ${imageDimensions})\n    list(FIND ITK_WRAP_IMAGE_DIMS \"${d}\" _index)\n    if (${_index} EQUAL -1)\n      foreach(vt ${WRAP_ITK_VECTOR_REAL})\n        foreach(c ${ITK_WRAP_VECTOR_COMPONENTS})\n          itk_wrap_template(\"I${ITKM_${vt}${c}}${d}I${ITKM_${vt}${c}}${d}\"\n            \"itk::Image<${ITKT_${vt}${c}}, ${d}>, itk::Image<${ITKT_${vt}${c}}, ${d}>\")\n        endforeach()\n      endforeach()\n    endif()\n  endforeach()\n\n  # Combination\n  set(vectorComponents 2 3 4 5)\n  foreach(c ${vectorComponents})\n    foreach(vt ${WRAP_ITK_VECTOR_REAL})\n      itk_wrap_template(\"I${ITKM_${vt}${c}}4I${ITKM_${vt}${c}}3\" \"itk::Image<${ITKT_${vt}${c}}, 4>, itk::Image<${ITKT_${vt}${c}}, 3>\")\n    endforeach()\n  endforeach()\n\n  # Wrap ITK CovariantVector missing types\n  if (NOT ITK_WRAP_covariant_vector_double)\n\n    set(vectorComponents 2 3 4 5)\n    foreach(v ${vectorComponents})\n\n      itk_wrap_template(\"ICVD${v}3ICVD${v}3\" \"itk::Image<itk::CovariantVector<${ITKT_D}, ${v}>, 3>, itk::Image<itk::CovariantVector<${ITKT_D}, ${v}>, 3>\")\n\n    endforeach()\n\n  endif()\n\n  list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n  foreach(t ${WRAP_ITK_REAL})\n    if (${_index} EQUAL -1)\n      itk_wrap_template(\"I${ITKM_${t}}2I${ITKM_${t}}1\" \"itk::Image<${ITKT_${t}}, 2>, itk::Image<${ITKT_${t}}, 1>\")\n    endif()\n    itk_wrap_template(\"I${ITKM_${t}}3VI${ITKM_${t}}2\" \"itk::Image<${ITKT_${t}}, 3>, itk::VectorImage<${ITKT_${t}}, 2>\")\n    itk_wrap_template(\"VI${ITKM_${t}}2I${ITKM_${t}}3\" \"itk::VectorImage<${ITKT_${t}}, 2>, itk::Image<${ITKT_${t}}, 3>\")\n    itk_wrap_template(\"VI${ITKM_${t}}3I${ITKM_${t}}4\" \"itk::VectorImage<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 4>\")\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/itkInPlaceImageFilterRTK.wrap",
    "content": "itk_wrap_class(\"itk::InPlaceImageFilter\" POINTER)\n\n  # Wrap ITK double missing types --\n  if (NOT ITK_WRAP_double)\n    itk_wrap_template(\"ID1ID1\" \"itk::Image<${ITKT_D}, 1>, itk::Image<${ITKT_D}, 1>\")\n    itk_wrap_template(\"ID3ID2\" \"itk::Image<${ITKT_D}, 3>, itk::Image<${ITKT_D}, 2>\")\n  endif()\n\n  # Wrap ITK dimension 1 missing types\n  list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n  if (${_index} EQUAL -1)\n    itk_wrap_template(\"IF1IF1\" \"itk::Image<${ITKT_F}, 1>, itk::Image<${ITKT_F}, 1>\")\n\tif (ITK_WRAP_double)\n      itk_wrap_template(\"ID1ID1\" \"itk::Image<${ITKT_D}, 1>, itk::Image<${ITKT_D}, 1>\")\n    endif()\n  endif()\n\n  # Wrap ITK unsigned short missing types\n  if (NOT ITK_WRAP_unsigned_short)\n    itk_wrap_template(\"IUS2IUS2\" \"itk::Image<${ITKT_US}, 2>, itk::Image<${ITKT_US}, 2>\")\n    itk_wrap_template(\"IUS3IUS3\" \"itk::Image<${ITKT_US}, 3>, itk::Image<${ITKT_US}, 3>\")\n  endif()\n\n  # Wrap ITK unsigned short combination (required by : rtkLookupTableImageFilter)\n  if (NOT ITK_WRAP_unsigned_short)\n    foreach(t ${WRAP_ITK_REAL})\n      itk_wrap_template(\"IUS2I${ITKM_${t}}2\" \"itk::Image<${ITKT_US}, 2>, itk::Image<${ITKT_${t}}, 2>\")\n      itk_wrap_template(\"IUS3I${ITKM_${t}}3\" \"itk::Image<${ITKT_US}, 3>, itk::Image<${ITKT_${t}}, 3>\")\n    endforeach()\n    list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\n    if (NOT ${_index} EQUAL -1)\n      itk_wrap_template(\"IUS1IF1\" \"itk::Image<${ITKT_US}, 1>, itk::Image<${ITKT_F}, 1>\")\n    endif()\n  endif()\n\n  # Wrap ITK unsigned int missing types\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"IUI2I${ITKM_${t}}2\" \"itk::Image<${ITKT_UI}, 2>, itk::Image<${ITKT_${t}}, 2>\")\n    itk_wrap_template(\"IUI3I${ITKM_${t}}3\" \"itk::Image<${ITKT_UI}, 3>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\n\n  # Wrap ITK short combination (required by : rtkLookupTableImageFilter)\n  if (NOT ITK_WRAP_signed_short)\n    itk_wrap_template(\"ISS3IF3\" \"itk::Image<${ITKT_SS}, 3>, itk::Image<${ITKT_F}, 3>\")\n  endif()\n\n  # Wrap ITK real type combination\n  itk_wrap_template(\"IF3ID2\" \"itk::Image<${ITKT_F}, 3>, itk::Image<${ITKT_D}, 2>\")\n\n  if(RTK_USE_CUDA)\n\n    itk_wrap_include(itkCudaImage.h)\n\n    foreach(d ${ITK_WRAP_IMAGE_DIMS})\n      itk_wrap_template(\"CI${ITKM_F}${d}\" \"itk::CudaImage<${ITKT_F}, ${d}>\")\n    endforeach()\n\n    # Wrap ITK dimension 4 CUDA missing types\n    list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\n    if (${_index} EQUAL -1)\n      itk_wrap_template(\"CIF4CIF4\" \"itk::CudaImage<${ITKT_F}, 4>, itk::CudaImage<${ITKT_F}, 4>\")\n    endif()\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n    UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n    foreach(component ${vectorComponents})\n      foreach(d ${imageDimensions})\n        itk_wrap_template(\"CI${ITKM_VF${component}}${d}\" \"itk::CudaImage<${ITKT_VF${component}}, ${d}>\")\n        itk_wrap_template(\"CI${ITKM_VF${component}}${d}CI${ITKM_VF${component}}${d}\"\n          \"itk::CudaImage<${ITKT_VF${component}}, ${d}>, itk::CudaImage<${ITKT_VF${component}}, ${d}>\")\n      endforeach()\n    endforeach()\n\n  endif()\n\n  # Force ITK_WRAP_IMAGE_DIMS to contain \"2;3;4\"\n  UNIQUE(imageDimensions \"${ITK_WRAP_IMAGE_DIMS};2;3;4\")\n  set(vectorComponents 2 3 4 5)\n  foreach(component ${vectorComponents})\n    list(FIND ITK_WRAP_VECTOR_COMPONENTS \"${component}\" _index)\n    if (${_index} EQUAL -1)\n      foreach(vt ${WRAP_ITK_VECTOR_REAL})\n        foreach(d ${imageDimensions})\n          itk_wrap_template(\"I${ITKM_${vt}${component}}${d}I${ITKM_${vt}${component}}${d}\"\n            \"itk::Image<${ITKT_${vt}${component}}, ${d}>, itk::Image<${ITKT_${vt}${component}}, ${d}>\")\n        endforeach()\n      endforeach()\n    endif()\n  endforeach()\n\n  # Force ITK_WRAP_VECTOR_COMPONENTS to contain \"2;3;4;5\"\n  UNIQUE(vectorComponents \"${ITK_WRAP_VECTOR_COMPONENTS};2;3;4;5\")\n\n  # Force ITK_WRAP_IMAGE_DIMS to contain \"2;3;4\"\n  set(imageDimensions 2 3 4)\n  foreach(d ${imageDimensions})\n    list(FIND ITK_WRAP_IMAGE_DIMS \"${d}\" _index)\n    if (${_index} EQUAL -1)\n      foreach(vt ${WRAP_ITK_VECTOR_REAL})\n        foreach(component ${ITK_WRAP_VECTOR_COMPONENTS})\n          itk_wrap_template(\"I${ITKM_${vt}${component}}${d}I${ITKM_${vt}${component}}${d}\"\n            \"itk::Image<${ITKT_${vt}${component}}, ${d}>, itk::Image<${ITKT_${vt}${component}}, ${d}>\")\n        endforeach()\n      endforeach()\n    endif()\n  endforeach()\n\n  itk_wrap_template(\"VI${ITKM_F}3VI${ITKM_F}3\"\n        \"itk::VectorImage<${ITKT_F}, 3>, itk::VectorImage<${ITKT_F}, 3>\")\n\n  if (ITK_WRAP_double)\n    itk_wrap_template(\"VI${ITKM_D}3VI${ITKM_D}3\"\n          \"itk::VectorImage<${ITKT_D}, 3>, itk::VectorImage<${ITKT_D}, 3>\")\n  endif()\nitk_end_wrap_class()\n\n"
  },
  {
    "path": "wrapping/itkMatrixRTK.wrap",
    "content": "list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\nif (${_index} EQUAL -1)\n  itk_wrap_class(\"itk::Matrix\")\n    itk_wrap_template(\"${ITKM_D}11\" \"${ITKT_D}, 1, 1\")\n  itk_end_wrap_class()\nendif()\n\n"
  },
  {
    "path": "wrapping/itkPointRTK.wrap",
    "content": "list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _index)\nif (${_index} EQUAL -1)\n  itk_wrap_class(\"itk::Point\")\n    itk_wrap_template(\"${ITKM_D}1\" \"${ITKT_D}, 1\")\n  itk_end_wrap_class()\nendif()\n\n"
  },
  {
    "path": "wrapping/itkPyBufferRTK.wrap",
    "content": "# Find PyBuffer swig files from ITKBridgeNumPy sources\nlist(GET ITKBridgeNumPy_INCLUDE_DIRS 0 ITKBridgeNumPy_INCLUDE_DIR)\nset(ITKBridgeNumpy_WRAP_DIR \"${ITKBridgeNumPy_INCLUDE_DIR}/../wrapping\")\n\nfile(READ \"${ITKBridgeNumpy_WRAP_DIR}/PyBuffer.i.init\"\n    PyBufferInit)\n\n# Append imports required by RTK. All overriden types in this class should be\n# defined in itkImageDuplicator as well.\nstring(REPLACE \"from itkImageDuplicatorPython import *\"\n  \"from itkImageDuplicatorPython import *\\nfrom itkImageDuplicatorRTKPython import *\\n\"\n  PyBufferInit \"${PyBufferInit}\")\nfile(WRITE \"${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i\" \"${PyBufferInit}\")\n\nitk_wrap_class(\"itk::PyBuffer\")\n\n  file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i)\n  UNIQUE(types \"${WRAP_ITK_SCALAR};UC;D;US;UI;UL;SC;SS;SI;SL;F\")\n  foreach(t ${types})\n    string(REGEX MATCHALL \"(V${t}|CV${t})\" VectorTypes \"${WRAP_ITK_VECTOR}\")\n    set(PixelType ${t})\n    foreach(d ${ITK_WRAP_IMAGE_DIMS})\n      # Image Vector types\n\t  set(vectorComponents 2 3 4 5)\n      foreach(vec_dim ${vectorComponents})\n\t    list(FIND ITK_WRAP_VECTOR_COMPONENTS \"${vec_dim}\" _index)\n        if (${_index} EQUAL -1)\n          foreach(vec_type ${VectorTypes})\n\n              set(PyBufferTypes I${vec_type}${vec_dim}${d})\n              configure_file( ${ITKBridgeNumpy_WRAP_DIR}/PyBuffer.i.in\n                         ${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i.temp\n                         @ONLY)\n              file(READ ${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i.temp\n                  PyBufferInterfaceTemp)\n              file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i\n                  ${PyBufferInterfaceTemp})\n              itk_wrap_template(\"I${vec_type}${vec_dim}${d}\" \"itk::Image<${ITKT_${vec_type}${vec_dim}},${d}>\")\n\n          endforeach()\n\t\tendif()\n      endforeach()\n    endforeach(d)\n  endforeach(t)\n\n  UNIQUE(types \"D;UC;US;${WRAP_ITK_REAL}\")\n  list(FIND ITK_WRAP_IMAGE_DIMS \"1\" _indexdim)\n  foreach(t ${types})\n    if (${_indexdim} EQUAL -1)\n      set(PixelType ${t})\n      set(PyBufferTypes I${t}1)\n      configure_file( ${ITKBridgeNumpy_WRAP_DIR}/PyBuffer.i.in\n                 ${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i.temp\n                 @ONLY)\n      file(READ ${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i.temp\n          PyBufferInterfaceTemp)\n      file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i\n          ${PyBufferInterfaceTemp})\n      itk_wrap_template(\"I${t}1\" \"itk::Image<${ITKT_${t}}, 1>\")\n    endif()\n  endforeach()\n\nitk_end_wrap_class()\n\n# Add library files to be included at a submodule level and copy them into\n# ITK's wrapping typedef directory.\nset(ITK_WRAP_PYTHON_SWIG_EXT\n  \"%include PyBufferRTK.i\\n${ITK_WRAP_PYTHON_SWIG_EXT}\")\n\nfile(COPY \"${CMAKE_CURRENT_BINARY_DIR}/PyBufferRTK.i\"\n  DESTINATION \"${WRAPPER_MASTER_INDEX_OUTPUT_DIR}\")\n"
  },
  {
    "path": "wrapping/itkVariableLengthVectorRTK.wrap",
    "content": "itk_wrap_class(\"itk::VariableLengthVector\")\n  itk_wrap_template(\"I\" \"int\")\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/itkVectorImageRTK.wrap",
    "content": "itk_wrap_simple_type_swig_interface(\"itk::VectorImage< float, 2 >::ConstPointer\" \"itkVectorImageF2_ConstPointer\")\nitk_wrap_simple_type(\"itk::VectorImage< float, 2 >::ConstPointer\" \"itkVectorImageF2_ConstPointer\")\n\nitk_wrap_simple_type_swig_interface(\"itk::VectorImage< float, 3 >::ConstPointer\" \"itkVectorImageF3_ConstPointer\")\nitk_wrap_simple_type(\"itk::VectorImage< float, 3 >::ConstPointer\" \"itkVectorImageF3_ConstPointer\")\n\nif (ITK_WRAP_double)\n\n  foreach(d 2 3)\n    itk_wrap_simple_type_swig_interface(\"itk::VectorImage< double, ${d} >::ConstPointer\" \"itkVectorImageD${d}_ConstPointer\")\n    itk_wrap_simple_type(\"itk::VectorImage< double, ${d} >::ConstPointer\" \"itkVectorImageD${d}_ConstPointer\")\n  endforeach()\n\nendif()\n"
  },
  {
    "path": "wrapping/itkVectorRTK.wrap",
    "content": "itk_wrap_class(\"itk::Vector\")\n    itk_wrap_template(\"i2\" \"int, 2\")\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/itkWarpImageFilterRTK.wrap",
    "content": "itk_wrap_class(\"itk::WarpImageFilter\" POINTER)\n  foreach(d ${ITK_WRAP_IMAGE_DIMS})\n    foreach(t ${WRAP_ITK_REAL})\n      itk_wrap_template(\"I${ITKM_${t}}${d}I${ITKM_${t}}${d}ICV${ITKM_${t}}${d}${d}\"\n        \"itk::Image<${ITKT_${t}}, ${d}>, itk::Image<${ITKT_${t}}, ${d}>, itk::Image< itk::CovariantVector<${ITKT_${t}}, ${d}>, ${d}>\")\n    endforeach()\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkADMMTotalVariationConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ADMMTotalVariationConeBeamReconstructionFilter\" POINTER)\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3\" \"itk::CudaImage<${ITKT_F}, 3>\")\n  endif()\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()"
  },
  {
    "path": "wrapping/rtkADMMWaveletsConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ADMMWaveletsConeBeamReconstructionFilter\" POINTER)\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3\" \"itk::CudaImage<${ITKT_F}, 3>\")\n  endif()\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkAmsterdamShroudImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::AmsterdamShroudImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkBackProjectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::BackProjectionImageFilter\" POINTER)\n\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\n\n  if(RTK_USE_CUDA)\n\n    itk_wrap_template(\"CIF3CIF3\" \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>\")\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    set(vectorComponents 2 3 4 5)\n    foreach(component ${vectorComponents})\n      itk_wrap_template(\"CI${ITKM_VF${component}}3CI${ITKM_VF${component}}3\"\n        \"itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3>\")\n    endforeach()\n\n  endif()\n\nitk_end_wrap_class()\n\nif(RTK_USE_CUDA)\n\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n\n    itk_wrap_template(\"CIF3CIF3BPCIF3CIF3\"\n      \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, rtk::BackProjectionImageFilter< itk::CudaImage<float, 3>, itk::CudaImage<float, 3> >\")\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    set(vectorComponents 2 3 4 5)\n    foreach(component ${vectorComponents})\n      itk_wrap_template(\"CI${ITKM_VF${component}}3CI${ITKM_VF${component}}3BPCI${ITKM_VF${component}}3CI${ITKM_VF${component}}3\"\n        \"itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3>, rtk::BackProjectionImageFilter< itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3> >\")\n    endforeach()\n\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n\n    itk_wrap_template(\"CIF3CIF3BPCIF3CIF3\"\n      \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, rtk::BackProjectionImageFilter< itk::CudaImage<float, 3>, itk::CudaImage<float, 3> >\")\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    set(vectorComponents 2 3 4 5)\n    foreach(component ${vectorComponents})\n      itk_wrap_template(\"CI${ITKM_VF${component}}3CI${ITKM_VF${component}}3BPCI${ITKM_VF${component}}3CI${ITKM_VF${component}}3\"\n        \"itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3>, rtk::BackProjectionImageFilter< itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3> >\")\n    endforeach()\n\n  itk_end_wrap_class()\n\nendif()\n"
  },
  {
    "path": "wrapping/rtkBioscanGeometryReader.wrap",
    "content": "itk_wrap_simple_class(\"rtk::BioscanGeometryReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkBoellaardScatterCorrectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::BoellaardScatterCorrectionImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkBoxShape.wrap",
    "content": "itk_wrap_simple_class(\"rtk::BoxShape\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkConditionalMedianImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ConditionalMedianImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkConjugateGradientConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ConjugateGradientConeBeamReconstructionFilter\" POINTER)\n\n if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3\" \"itk::CudaImage<${ITKT_F}, 3>\")\n  endif()\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkConstantImageSource.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::ConstantImageSource\" POINTER)\n\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1)\n  itk_wrap_image_filter(\"${WRAP_ITK_VECTOR_REAL}\" 1)\n\n  if(RTK_USE_CUDA)\n    foreach(d ${ITK_WRAP_IMAGE_DIMS})\n      itk_wrap_template(\"CI${ITKM_F}${d}\" \"itk::CudaImage<${ITKT_F}, ${d}>\")\n    endforeach()\n  endif()\n\nitk_end_wrap_class()\n\nif(RTK_USE_CUDA)\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3CteISrcCIF3\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::ConstantImageSource< itk::CudaImage<${ITKT_F}, 3> >\")\n  itk_end_wrap_class()\nendif()\n\n\n"
  },
  {
    "path": "wrapping/rtkConvexShape.wrap",
    "content": "itk_wrap_simple_class(\"rtk::ConvexShape\" POINTER)\n\nset(ITK_WRAP_PYTHON_SWIG_EXT\n    \"%include ConvexShape.i\\n${ITK_WRAP_PYTHON_SWIG_EXT}\")\n\nfile(COPY \"${CMAKE_CURRENT_SOURCE_DIR}/ConvexShape.i\"\n    DESTINATION \"${WRAPPER_MASTER_INDEX_OUTPUT_DIR}\")"
  },
  {
    "path": "wrapping/rtkCudaBackProjectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n\n  itk_wrap_class(\"rtk::CudaBackProjectionImageFilter\" POINTER)\n\n    itk_wrap_template(\"CIF3\" \"itk::CudaImage<float, 3>\")\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    set(vectorComponents 2 3 4 5)\n    foreach(component ${vectorComponents})\n      itk_wrap_template(\"CI${ITKM_VF${component}}3\" \"itk::CudaImage<${ITKT_VF${component}}, 3>\")\n    endforeach()\n\n  itk_end_wrap_class()\n\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaConstantVolumeSource.wrap",
    "content": "if(RTK_USE_CUDA)\n\n  itk_wrap_simple_class(\"rtk::CudaConstantVolumeSource\" POINTER)\n\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaDisplacedDetectorImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n\n  itk_wrap_simple_class(\"rtk::CudaDisplacedDetectorImageFilter\" POINTER)\n\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaFDKBackProjectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_simple_class(\"rtk::CudaFDKBackProjectionImageFilter\" POINTER)\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaFDKConeBeamReconstructionFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_simple_class(\"rtk::CudaFDKConeBeamReconstructionFilter\" POINTER)\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaFFTProjectionsConvolutionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(rtkScatterGlareCorrectionImageFilter.h)\n  itk_wrap_include(rtkFFTRampImageFilter.h)\n\n  itk_wrap_class(\"rtk::CudaFFTProjectionsConvolutionImageFilter\" POINTER)\n    itk_wrap_template(\"SGCIF3CIF3F\" \"rtk::ScatterGlareCorrectionImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>\")\n    itk_wrap_template(\"RFCIF3CIF3F\" \"rtk::FFTRampImageFilter<itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float>\")\n  itk_end_wrap_class()\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaFFTRampImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_simple_class(\"rtk::CudaFFTRampImageFilter\" POINTER)\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaForwardProjectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n\n    itk_wrap_template(\"CIF3CIF3FPCIF3CIF3\"\n      \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, rtk::ForwardProjectionImageFilter< itk::CudaImage<float, 3>, itk::CudaImage<float, 3> >\")\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    set(vectorComponents 2 3 4 5)\n    foreach(component ${vectorComponents})\n      itk_wrap_template(\"CI${ITKM_VF${component}}3CI${ITKM_VF${component}}3FPCI${ITKM_VF${component}}3CI${ITKM_VF${component}}3\"\n        \"itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3>, rtk::ForwardProjectionImageFilter< itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3> >\")\n    endforeach()\n\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n\n    itk_wrap_template(\"CIF3CIF3FPCIF3CIF3\"\n      \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, rtk::ForwardProjectionImageFilter< itk::CudaImage<float, 3>, itk::CudaImage<float, 3> >\")\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    set(vectorComponents 2 3 4 5)\n    foreach(component ${vectorComponents})\n      itk_wrap_template(\"CI${ITKM_VF${component}}3CI${ITKM_VF${component}}3FPCI${ITKM_VF${component}}3CI${ITKM_VF${component}}3\"\n        \"itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3>, rtk::ForwardProjectionImageFilter< itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3> >\")\n    endforeach()\n\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"rtk::CudaForwardProjectionImageFilter\" POINTER)\n\n    itk_wrap_template(\"CIF3\" \"itk::CudaImage<float, 3>\")\n\n    # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n    set(vectorComponents 2 3 4 5)\n    foreach(component ${vectorComponents})\n      itk_wrap_template(\"CI${ITKM_VF${component}}3\" \"itk::CudaImage<${ITKT_VF${component}}, 3>\")\n    endforeach()\n\n  itk_end_wrap_class()\n\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaIterativeFDKConeBeamReconstructionFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_simple_class(\"rtk::CudaIterativeFDKConeBeamReconstructionFilter\" POINTER)\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaParkerShortScanImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_simple_class(\"rtk::CudaParkerShortScanImageFilter\" POINTER)\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaRayCastBackProjectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_simple_class(\"rtk::CudaRayCastBackProjectionImageFilter\" POINTER)\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaScatterGlareCorrectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_simple_class(\"rtk::CudaScatterGlareCorrectionImageFilter\" POINTER)\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaSplatImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n\n  itk_wrap_simple_class(\"rtk::CudaSplatImageFilter\" POINTER)\n\nendif()\n"
  },
  {
    "path": "wrapping/rtkCudaWarpForwardProjectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_simple_class(\"rtk::CudaWarpForwardProjectionImageFilter\" POINTER)\nendif()\n"
  },
  {
    "path": "wrapping/rtkCyclicDeformationImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::CyclicDeformationImageFilter\"  POINTER)\n  set(INPUT_IMAGE_DIMS 4)\n  set(OUTPUT_IMAGE_DIMS 3)\n\n  itk_wrap_template(\"IF${INPUT_IMAGE_DIMS}IF${OUTPUT_IMAGE_DIMS}\"\n      \"itk::Image<${ITKT_F}, ${INPUT_IMAGE_DIMS}>, itk::Image<${ITKT_F}, ${OUTPUT_IMAGE_DIMS}>\")\n\n  # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n  set(vectorComponents 2 3 4 5)\n  foreach(component ${vectorComponents})\n    foreach(vt ${WRAP_ITK_VECTOR_REAL})\n\n      itk_wrap_template(\"I${ITKM_${vt}${component}}${INPUT_IMAGE_DIMS}I${ITKM_${vt}${component}}${OUTPUT_IMAGE_DIMS}\"\n        \"itk::Image<${ITKT_${vt}${component}}, ${INPUT_IMAGE_DIMS}>, itk::Image<${ITKT_${vt}${component}}, ${OUTPUT_IMAGE_DIMS}>\")\n\n    endforeach()\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDCMImagXImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::DCMImagXImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::DCMImagXImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkDPExtractShroudSignalImageFilter.notwrap",
    "content": "itk_wrap_class(\"rtk::DPExtractShroudSignalImageFilter\" POINTER)\n  foreach(t_in ${WRAP_ITK_REAL})\n    foreach(t_out ${WRAP_ITK_REAL})\n      itk_wrap_template(\"${ITKM_${t_in}}${ITKM_${t_out}}\" \"${ITKT_${t_in}}, ${ITKT_${t_out}}\")\n    endforeach()\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDaubechiesWaveletsDenoiseSequenceImageFilter.wrap",
    "content": "list(FIND ITK_WRAP_IMAGE_DIMS \"4\" _index)\nif (NOT ${_index} EQUAL -1)\n  itk_wrap_class(\"rtk::DaubechiesWaveletsDenoiseSequenceImageFilter\" POINTER)\n    itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 4)\n  itk_end_wrap_class()\nendif()\n"
  },
  {
    "path": "wrapping/rtkDeconstructSoftThresholdReconstructImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::DeconstructSoftThresholdReconstructImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDenoisingBPDQImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::DenoisingBPDQImageFilter\" POINTER)\n  foreach(d ${ITK_WRAP_IMAGE_DIMS})\n    foreach(t ${WRAP_ITK_REAL})\n      foreach(cvt ${WRAP_ITK_COV_VECTOR_REAL})\n        itk_wrap_template(\"I${ITKM_${t}}${d}I${ITKM_${cvt}${d}}${d}\"\n          \"itk::Image<${ITKT_${t}}, ${d}>, itk::Image<${ITKT_${cvt}${d}}, ${d}>\")\n      endforeach()\n    endforeach()\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDigisensGeometryReader.wrap",
    "content": "itk_wrap_simple_class(\"rtk::DigisensGeometryReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkDisplacedDetectorForOffsetFieldOfViewImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::DisplacedDetectorForOffsetFieldOfViewImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDisplacedDetectorImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::DisplacedDetectorImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3;4)\n\n  if(RTK_USE_CUDA)\n    foreach(d ${ITK_WRAP_IMAGE_DIMS})\n      itk_wrap_template(\"CI${ITKM_F}${d}\" \"itk::CudaImage<${ITKT_F}, ${d}>\")\n    endforeach()\n  endif()\n\nitk_end_wrap_class()\n\nif(RTK_USE_CUDA)\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3DDCIF3\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::DisplacedDetectorImageFilter< itk::CudaImage<${ITKT_F}, 3> >\")\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3DDCIF3\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::DisplacedDetectorImageFilter< itk::CudaImage<${ITKT_F}, 3> >\")\n  itk_end_wrap_class()\nendif()\n\n"
  },
  {
    "path": "wrapping/rtkDrawConvexImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::DrawConvexImageFilter\" POINTER)\n    itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDrawEllipsoidImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::DrawEllipsoidImageFilter\" POINTER)\n    itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDrawGeometricPhantomImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::DrawGeometricPhantomImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDrawQuadricImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::DrawQuadricImageFilter\" POINTER)\n    itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkDrawSheppLoganFilter.wrap",
    "content": "itk_wrap_class(\"rtk::DrawSheppLoganFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkEdfImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::EdfImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::EdfImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkEdfRawToAttenuationImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::EdfRawToAttenuationImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkElektaSynergyGeometryReader.wrap",
    "content": "itk_wrap_simple_class(\"rtk::ElektaSynergyGeometryReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkElektaSynergyRawLookupTableImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ElektaSynergyRawLookupTableImageFilter\" POINTER)\n  foreach(d 2 3)\n    itk_wrap_template(\"IUS${d}IUS${d}\" \"itk::Image<${ITKT_US}, ${d}>, itk::Image<${ITKT_US}, ${d}>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkElektaXVI5GeometryXMLFileReader.wrap",
    "content": "itk_wrap_simple_class(\"rtk::ElektaXVI5GeometryXMLFileReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkExtractPhaseImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ExtractPhaseImageFilter\" POINTER)\n  # WARNING: Do not use \"itk_wrap_image_filter(${WRAP_ITK_REAL} 1 1)\" macro.\n  # The \"itk_wrap_image_filter\" macro verifies that the dimension parameter\n  # exists in ITK_WRAP_IMAGE_DIMS before wrapping anything.\n  # Instead, RTK should force wrapping of dimension 1 even if it was not\n  # requested in ITK_WRAP_IMAGE_DIMS.\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}1\" \"itk::Image<${ITKT_${t}}, 1>\")\n  endforeach()\n  if (NOT ITK_WRAP_double)\n    itk_wrap_template(\"I${ITKM_D}1\" \"itk::Image<${ITKT_D}, 1>\")\n  endif()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkExtras.py",
    "content": "import itk\nfrom itk import RTK as rtk\nimport importlib\nimport shlex\n\n\n# Write a 3D circular projection geometry to a file.\ndef write_geometry(geometry, filename):\n    # Create and configure the writer\n    writer = rtk.ThreeDCircularProjectionGeometryXMLFileWriter.New()\n    writer.SetObject(geometry)\n    writer.SetFilename(filename)\n\n    # Write the geometry to file\n    writer.WriteFile()\n\n\n# Read a 3D circular projection geometry from a file.\ndef read_geometry(filename):\n    # Create and configure the reader\n    reader = rtk.ThreeDCircularProjectionGeometryXMLFileReader.New()\n    reader.SetFilename(filename)\n    reader.GenerateOutputInformation()\n\n    # Return the geometry object\n    return reader.GetOutputObject()\n\n\n# Returns the progress percentage\nclass PercentageProgressCommand:\n    def __init__(self, caller):\n        self.percentage = -1\n        self.caller = caller\n\n    def callback(self):\n        new_percentage = int(self.caller.GetProgress() * 100)\n        if new_percentage > self.percentage:\n            print(\n                f\"\\r{self.caller.GetNameOfClass()} {new_percentage}% completed.\",\n                end=\"\",\n                flush=True,\n            )\n            self.percentage = new_percentage\n\n    def End(self):\n        print()  # Print newline when execution ends\n\n\n\ndef make_application_func(app_name):\n    \"\"\"\n    Factory: returns a function that runs the RTK application `app_name`\n    with either Python-style kwargs or a single CLI-style string.\n    \"\"\"\n    def app_func(*args, **kwargs):\n        app_module = importlib.import_module(f\"itk.{app_name}\")\n        parser = app_module.build_parser()\n        # Ensure help/usage shows the logical app name in Python contexts\n        parser.prog = app_name\n\n        if kwargs:\n            if hasattr(parser, \"parse_kwargs\"):\n                args_ns = parser.parse_kwargs(func_name=app_name, **kwargs)\n            else:\n                raise TypeError(f\"Parser for {app_name} has no parse_kwargs method.\")\n        elif args and len(args) == 1 and isinstance(args[0], str):\n            # Treat single string argument as CLI\n            argv = shlex.split(args[0])\n            args_ns = parser.parse_args(argv)\n        else:\n            args_ns = parser.parse_args()\n\n        return app_module.process(args_ns)\n\n    # Metadata for help()\n    _parser = importlib.import_module(f\"itk.{app_name}\").build_parser()\n    _parser.prog = app_name\n    _parser.apply_signature(app_func)\n    app_func.__name__ = app_name\n    app_func.__module__ = \"itk.RTK\"\n    # Python-only help: version, description + examples + options header\n    description = (_parser.description or \"\").rstrip()\n    examples = _parser.build_usage_examples(app_name)\n    options = _parser.format_help()\n    idx = options.lower().find('options:')\n    opt_text = options[idx:].strip()\n    parts = [rtk.version(), description, examples, opt_text]\n    app_func.__doc__ = \"\\n\\n\".join(parts)\n\n    return app_func\n"
  },
  {
    "path": "wrapping/rtkFDKBackProjectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::FDKBackProjectionImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CI${ITKM_F}3CI${ITKM_F}3\"\n      \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>\")\n  endif()\nitk_end_wrap_class()\n\nif(RTK_USE_CUDA)\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3FDKBPCIF3CIF3\"\n      \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::FDKBackProjectionImageFilter< itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3> >\")\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3FDKBPCIF3CIF3\"\n      \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::FDKBackProjectionImageFilter< itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3> >\")\n  itk_end_wrap_class()\nendif()\n"
  },
  {
    "path": "wrapping/rtkFDKConeBeamReconstructionFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::FDKConeBeamReconstructionFilter\"  POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3\" \"itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3CIF3F\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, float\")\n  endif()\nitk_end_wrap_class()\n\nif(RTK_USE_CUDA)\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3FDKCIF3F\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::FDKConeBeamReconstructionFilter< itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, float >\")\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3FDKCIF3F\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::FDKConeBeamReconstructionFilter< itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, float >\")\n  itk_end_wrap_class()\nendif()\n"
  },
  {
    "path": "wrapping/rtkFDKVarianceReconstructionFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::FDKVarianceReconstructionFilter\"  POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3\" \"itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3CIF3F\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, float\")\n  endif()\nitk_end_wrap_class()\n\nif(RTK_USE_CUDA)\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3FDKVARCIF3F\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::FDKVarianceReconstructionFilter< itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, float >\")\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3FDKVARCIF3F\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::FDKVarianceReconstructionFilter< itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, float >\")\n  itk_end_wrap_class()\nendif()\n"
  },
  {
    "path": "wrapping/rtkFDKWarpBackProjectionImageFilter.wrap",
    "content": "itk_wrap_include(rtkCyclicDeformationImageFilter.h)\n\nitk_wrap_class(\"rtk::FDKWarpBackProjectionImageFilter\"  POINTER)\n  itk_wrap_template(\"I${ITKM_F}3I${ITKM_F}3CDFI${ITKM_VF3}4I${ITKM_VF3}3\"\n    \"itk::Image<${ITKT_F}, 3>, itk::Image<${ITKT_F}, 3>, rtk::CyclicDeformationImageFilter< itk::Image<${ITKT_VF3}, 4>, itk::Image<${ITKT_VF3}, 3> >\")\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFDKWeightProjectionFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::FDKWeightProjectionFilter\" POINTER)\n  #WARNING: Only wrapping one image template because TInputImage == TOutputImage\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1)\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3CIF3F\" \"itk::CudaImage<${ITKT_F}, 3>\" \"itk::CudaImage<${ITKT_F}, 3>\" \"${ITKT_F}\")\n  endif()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFFTHilbertImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::FFTHilbertImageFilter\"  POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3${ITKM_D}\" \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>, ${ITKT_D}\")\n  endforeach()\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CI${ITKM_F}3CI${ITKM_F}3${ITKM_F}\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, ${ITKT_F}\")\n  endif()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFFTProjectionsConvolutionImageFilter.wrap",
    "content": "itk_wrap_include( rtkFFTProjectionsConvolutionImageFilter.h )\nitk_wrap_include( itkImage.h )\nif(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_named_class(\"rtk::FFTProjectionsConvolutionImageFilter\" rtkFFTProjectionsConvolutionImageFilter POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3${ITKM_D}\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>, ${ITKT_D}\")\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3${ITKM_F}\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>, ${ITKT_F}\")\n  endforeach()\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CI${ITKM_F}3CI${ITKM_F}3${ITKM_F}\"\n      \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, ${ITKT_F}\")\n  endif()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFFTRampImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::FFTRampImageFilter\"  POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3${ITKM_D}\" \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>, ${ITKT_D}\")\n  endforeach()\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CI${ITKM_F}3CI${ITKM_F}3${ITKM_F}\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, ${ITKT_F}\")\n  endif()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFFTVarianceRampImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::FFTVarianceRampImageFilter\"  POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3${ITKM_D}\" \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>, ${ITKT_D}\")\n  endforeach()\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CI${ITKM_F}3CI${ITKM_F}3${ITKM_F}\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, ${ITKT_F}\")\n  endif()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFieldOfViewImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::FieldOfViewImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n\nset(ITK_WRAP_PYTHON_SWIG_EXT\n    \"%include FieldOfViewImageFilter.i\\n${ITK_WRAP_PYTHON_SWIG_EXT}\")\n\nfile(COPY \"${CMAKE_CURRENT_SOURCE_DIR}/FieldOfViewImageFilter.i\"\n    DESTINATION \"${WRAPPER_MASTER_INDEX_OUTPUT_DIR}\")"
  },
  {
    "path": "wrapping/rtkForwardProjectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::ForwardProjectionImageFilter\" POINTER)\n\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3CIF3\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>\")\n  endif()\n\n  # Force VECTOR_COMPONENTS to \"2;3;4;5\"\n  set(vectorComponents 2 3 4 5)\n  foreach(component ${vectorComponents})\n    foreach(vt ${WRAP_ITK_VECTOR_REAL})\n      itk_wrap_template(\"I${ITKM_${vt}${component}}3I${ITKM_${vt}${component}}3\" \"itk::Image<${ITKT_${vt}${component}},3>, itk::Image<${ITKT_${vt}${component}},3>\")\n    endforeach()\n    if(RTK_USE_CUDA)\n      itk_wrap_template(\"CI${ITKM_VF${component}}3CI${ITKM_VF${component}}3\" \"itk::CudaImage<${ITKT_VF${component}}, 3>, itk::CudaImage<${ITKT_VF${component}}, 3>\")\n    endif()\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkForwardWarpImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ForwardWarpImageFilter\" POINTER)\n  foreach(d ${ITK_WRAP_IMAGE_DIMS})\n    itk_wrap_template(\"I${ITKM_F}${d}I${ITKM_F}${d}ICV${ITKM_F}${d}${d}\"\n      \"itk::Image<${ITKT_F}, ${d}>, itk::Image<${ITKT_F}, ${d}>, itk::Image< itk::CovariantVector<${ITKT_F}, ${d}>, ${d}>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFourDConjugateGradientConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::FourDConjugateGradientConeBeamReconstructionFilter\" POINTER_WITH_SUPERCLASS)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF4CIF3\" \"itk::CudaImage<float, 4>, itk::CudaImage<float, 3>\")\n  endif()\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}4I${ITKM_${t}}3\"\n      \"itk::Image<${ITKT_${t}}, 4>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFourDROOSTERConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::FourDROOSTERConeBeamReconstructionFilter\" POINTER_WITH_SUPERCLASS)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF4CIF3\" \"itk::CudaImage<float, 4>, itk::CudaImage<float, 3>\")\n  endif()\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}4I${ITKM_${t}}3\"\n      \"itk::Image<${ITKT_${t}}, 4>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFourDSARTConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::FourDSARTConeBeamReconstructionFilter\" POINTER)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF4CIF3\" \"itk::CudaImage<float, 4>, itk::CudaImage<float, 3>\")\n  endif()\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}4I${ITKM_${t}}3\"\n      \"itk::Image<${ITKT_${t}}, 4>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkFourDToProjectionStackImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::FourDToProjectionStackImageFilter\" POINTER)\n\n  foreach(t ${WRAP_ITK_REAL})\n      itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}4\"\n        \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 4>\")\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkGeometricPhantom.wrap",
    "content": "itk_wrap_simple_class(\"rtk::GeometricPhantom\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkGlobalResourceProbe.wrap",
    "content": "itk_wrap_simple_class(\"rtk::GlobalResourceProbe\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkHilbertImageFilter.notwrap",
    "content": "itk_wrap_class(\"rtk::HilbertImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 1)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkHisImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::HisImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::HisImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkHncImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::HncImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::HncImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkHndImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::HndImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::HndImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkI0EstimationProjectionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::I0EstimationProjectionFilter\" POINTER)\n\n  foreach(bitShift 2)\n    itk_wrap_template(\"IUS3IUS3${bitShift}\" \"itk::Image<${ITKT_US}, 3>, itk::Image<${ITKT_US}, 3>, ${bitShift}\")\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkImagXImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::ImagXImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::ImagXImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkImageToVectorImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ImageToVectorImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}2VI${ITKM_${t}}2\" \"itk::Image<${ITKT_${t}}, 2>, itk::VectorImage<${ITKT_${t}}, 2>\")\n    itk_wrap_template(\"I${ITKM_${t}}3VI${ITKM_${t}}2\" \"itk::Image<${ITKT_${t}}, 3>, itk::VectorImage<${ITKT_${t}}, 2>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkIntersectionOfConvexShapes.wrap",
    "content": "itk_wrap_simple_class(\"rtk::IntersectionOfConvexShapes\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkIterativeConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::IterativeConeBeamReconstructionFilter\" POINTER)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3CIF3\" \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>\")\n    itk_wrap_template(\"CIF4CIF3\" \"itk::CudaImage<float, 4>, itk::CudaImage<float, 3>\")\n  endif()\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\n  #-------------------------------------------------------------------------\n  # Wrap template :\n  #   -rtk::IterativeConeBeamReconstructionFilter< itk::Image< float,4 >,itk::Image< float,3 > >\n  # required by :\n  #   -rtk::FourDConjugateGradientConeBeamReconstructionFilter\n  #   -rtk::FourDSARTConeBeamReconstructionFilter\n  #-------------------------------------------------------------------------\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}4I${ITKM_${t}}3\" \"itk::Image<${ITKT_${t}}, 4>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\n\n  set(vectorComponents 2 3 4 5)\n  foreach(v ${vectorComponents})\n    foreach(vt ${WRAP_ITK_VECTOR_REAL})\n      itk_wrap_template(\"I${ITKM_${vt}${v}}3I${ITKM_${vt}${v}}3\" \"itk::Image<${ITKT_${vt}${v}}, 3>, itk::Image<${ITKT_${vt}${v}}, 3>\")\n    endforeach()\n    if(RTK_USE_CUDA)\n      itk_wrap_template(\"CI${ITKM_VF${v}}3CI${ITKM_VF${v}}3\" \"itk::CudaImage<${ITKT_VF${v}}, 3>, itk::CudaImage<${ITKT_VF${v}}, 3>\")\n    endif()\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkIterativeFDKConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::IterativeFDKConeBeamReconstructionFilter\" POINTER)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3CIF3D\" \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float\")\n  endif()\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3D\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>, double\")\n  endforeach()\n\nitk_end_wrap_class()\n\nif(RTK_USE_CUDA)\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3IFDKCIF3CIF3\"\n      \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::IterativeFDKConeBeamReconstructionFilter< itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, float >\")\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n    itk_wrap_template(\"CIF3CIF3IFDKCIF3CIF3\"\n      \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, rtk::IterativeFDKConeBeamReconstructionFilter< itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>, float >\")\n  itk_end_wrap_class()\nendif()\n"
  },
  {
    "path": "wrapping/rtkJosephBackAttenuatedProjectionImageFilter.wrap",
    "content": "set(WRAPPER_AUTO_INCLUDE_HEADERS OFF)\nitk_wrap_named_class(\"rtk::Functor::InterpolationWeightMultiplicationAttenuatedBackProjection\" \"rtkFunctorInterpolationWeightMultiplicationAttenuatedBackProjection\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nitk_wrap_named_class(\"rtk::Functor::SplatWeightMultiplicationAttenuated\" \"rtkFunctorSplatWeightMultiplicationAttenuated\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}D${ITKM_${t}}\" \"${ITKT_${t}}, double, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nitk_wrap_named_class(\"rtk::Functor::ComputeAttenuationCorrectionBackProjection\" \"rtkComputeAttenuationCorrectionBackProjection\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nset(WRAPPER_AUTO_INCLUDE_HEADERS ON)\n\nitk_wrap_class(\"rtk::JosephBackProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3SWM${ITKM_${t}}D${ITKM_${t}}IS\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image< ${ITKT_${t}}, 3>, rtk::Functor::InterpolationWeightMultiplicationAttenuatedBackProjection<${ITKT_${t}}, ${ITKT_${t}}, ${ITKT_${t}}>, rtk::Functor::SplatWeightMultiplicationAttenuated<${ITKT_${t}}, double, ${ITKT_${t}}>, rtk::Functor::ComputeAttenuationCorrectionBackProjection<${ITKT_${t}}, ${ITKT_${t}}>\")\n  endforeach()\nitk_end_wrap_class()\n\nitk_wrap_class(\"rtk::JosephBackAttenuatedProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3SWM${ITKM_${t}}D${ITKM_${t}}\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image< ${ITKT_${t}}, 3>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkJosephBackProjectionImageFilter.wrap",
    "content": "set(WRAPPER_AUTO_INCLUDE_HEADERS OFF)\nitk_wrap_named_class(\"rtk::Functor::SplatWeightMultiplication\" \"rtkFunctorSplatWeightMultiplication\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}D${ITKM_${t}}\" \"${ITKT_${t}}, double, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nset(WRAPPER_AUTO_INCLUDE_HEADERS ON)\n\nitk_wrap_class(\"rtk::JosephBackProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3SWM${ITKM_${t}}D${ITKM_${t}}\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image< ${ITKT_${t}}, 3>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkJosephForwardAttenuatedProjectionImageFilter.wrap",
    "content": "set(WRAPPER_AUTO_INCLUDE_HEADERS OFF)\nitk_wrap_named_class(\"rtk::Functor::InterpolationWeightMultiplicationAttenuated\" \"rtkFunctorInterpolationWeightMultiplicationAttenuatedBackProjectionAttenuated\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nitk_wrap_named_class(\"rtk::Functor::ProjectedValueAccumulationAttenuated\" \"rtkProjectedValueAccumulationAttenuated\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nitk_wrap_named_class(\"rtk::Functor::ComputeAttenuationCorrection\" \"rtkComputeAttenuationCorrection\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nset(WRAPPER_AUTO_INCLUDE_HEADERS ON)\n\nitk_wrap_class(\"rtk::JosephForwardProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3SWM${ITKM_${t}}D${ITKM_${t}}IPC\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image< ${ITKT_${t}}, 3>, rtk::Functor::InterpolationWeightMultiplicationAttenuated<${ITKT_${t}}, ${ITKT_${t}}, ${ITKT_${t}}>, rtk::Functor::ProjectedValueAccumulationAttenuated<${ITKT_${t}}, ${ITKT_${t}}>, rtk::Functor::ComputeAttenuationCorrection<${ITKT_${t}}, ${ITKT_${t}}>\")\n  endforeach()\nitk_end_wrap_class()\n\nitk_wrap_class(\"rtk::JosephForwardAttenuatedProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3\" \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkJosephForwardProjectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::JosephForwardProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3\" \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\n\n  foreach(vt ${WRAP_ITK_VECTOR_REAL})\n    set(vectorComponents 2 3 4 5)\n    foreach(nmat ${vectorComponents})\n      itk_wrap_template(\"I${ITKM_${vt}${nmat}}3I${ITKM_${vt}${nmat}}3\" \"itk::Image<${ITKT_${vt}${nmat}},3>, itk::Image<${ITKT_${vt}${nmat}},3>\")\n    endforeach()\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkLUTbasedVariableI0RawToAttenuationImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::LUTbasedVariableI0RawToAttenuationImageFilter\" POINTER)\n\n  itk_wrap_template(\"IUS2IF2\" \"itk::Image<${ITKT_US}, 2>, itk::Image<${ITKT_F}, 2>\")\n  itk_wrap_template(\"IUS3IF3\" \"itk::Image<${ITKT_US}, 3>, itk::Image<${ITKT_F}, 3>\")\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkLagCorrectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::LagCorrectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    foreach(modelOrder 1 2 3 4)\n      itk_wrap_template(\"I${ITKM_${t}}3${modelOrder}\" \"itk::Image<${ITKT_${t}}, 3>, ${modelOrder}\")\n    endforeach()\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkLastDimensionL0GradientDenoisingImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::LastDimensionL0GradientDenoisingImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkLookupTableImageFilter.wrap",
    "content": "#-----------------------------------------------------------------------------\n# rtk::Functor< int, float >\n#-----------------------------------------------------------------------------\nset(WRAPPER_AUTO_INCLUDE_HEADERS OFF)\nset(WRAP_RTK_INT \"UI;US\")\nset(RTK_WRAP_IMAGE_DIMS 2 3)\nitk_wrap_named_class(\"rtk::Functor::LUT\" \"rtkFunctorLUT\")\n\n  foreach(i ${WRAP_RTK_INT})\n    foreach(t ${WRAP_ITK_REAL})\n      itk_wrap_template(\"${ITKM_${i}}${ITKM_${t}}\" \"${ITKT_${i}}, ${ITKT_${t}}\")\n    endforeach()\n  endforeach()\n\n  # For ElektaSynergyRawLookupTableImageFilter\n  itk_wrap_template(\"${ITKM_US}${d}${ITKM_US}${d}\" \"${ITKT_US}, ${ITKT_US}\")\nitk_end_wrap_class()\nset(WRAPPER_AUTO_INCLUDE_HEADERS ON)\n\n#-----------------------------------------------------------------------------\n# itk::UnaryFunctorImageFilter< itk::Image< int, 3 >, itk::Image< float, 3 >,\n#   rtk::Functor::LUT< int, float > >\n#-----------------------------------------------------------------------------\nitk_wrap_class(\"itk::UnaryFunctorImageFilter\" POINTER)\n\n  foreach(i ${WRAP_RTK_INT})\n    foreach(t ${WRAP_ITK_REAL})\n      foreach(d ${RTK_WRAP_IMAGE_DIMS})\n        itk_wrap_template(\"I${ITKM_${i}}${d}I${ITKM_${t}}${d}LUT${ITKM_${i}}${ITKM_${t}}\"\n                          \"itk::Image<${ITKT_${i}}, ${d}>, itk::Image<${ITKT_${t}}, ${d}>, rtk::Functor::LUT< ${ITKT_${i}}, ${ITKT_${t}} >\")\n      endforeach()\n    endforeach()\n  endforeach()\n\n  # For ElektaSynergyRawLookupTableImageFilter\n  foreach(d 2 3)\n    itk_wrap_template(\"I${ITKM_US}${d}I${ITKM_US}${d}LUT${ITKM_US}${ITKM_US}\"\n                      \"itk::Image<${ITKT_US}, ${d}>, itk::Image<${ITKT_US}, ${d}>, rtk::Functor::LUT< ${ITKT_US}, ${ITKT_US}>\")\n  endforeach()\nitk_end_wrap_class()\n\n#-----------------------------------------------------------------------------\n# rtk::LookupTableImageFilter\n#-----------------------------------------------------------------------------\nitk_wrap_class(\"rtk::LookupTableImageFilter\" POINTER)\n\n  foreach(i ${WRAP_RTK_INT})\n    foreach(t ${WRAP_ITK_REAL})\n      foreach(d ${RTK_WRAP_IMAGE_DIMS})\n        itk_wrap_template(\"I${ITKM_${i}}${d}I${ITKM_${t}}${d}\" \"itk::Image<${ITKT_${i}}, ${d}>, itk::Image<${ITKT_${t}}, ${d}>\")\n      endforeach()\n    endforeach()\n  endforeach()\n\n  # For ElektaSynergyRawLookupTableImageFilter\n  foreach(d 2 3)\n    itk_wrap_template(\"I${ITKM_US}${d}I${ITKM_US}${d}\" \"itk::Image<${ITKT_US}, ${d}>, itk::Image<${ITKT_US}, ${d}>\")\n  endforeach()\nitk_end_wrap_class()\n\n"
  },
  {
    "path": "wrapping/rtkMaskCollimationImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::MaskCollimationImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()"
  },
  {
    "path": "wrapping/rtkMaximumIntensityProjectionImageFilter.wrap",
    "content": "set(WRAPPER_AUTO_INCLUDE_HEADERS OFF)\nitk_wrap_named_class(\"rtk::Functor::InterpolationWeightMultiplication\" \"rtkInterpolationWeightMultiplication\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nitk_wrap_named_class(\"rtk::Functor::MaximumIntensityAlongRay\" \"rtkMaximumIntensityAlongRay\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nitk_wrap_named_class(\"rtk::Functor::MaximumIntensityProjectedValueAccumulation\" \"rtkMaximumIntensityProjectedValueAccumulation\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nset(WRAPPER_AUTO_INCLUDE_HEADERS ON)\n\nitk_wrap_class(\"rtk::JosephForwardProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3FWMI${ITKM_${t}}3I${ITKM_${t}}3FVAI${ITKM_${t}}3I${ITKM_${t}}3FIAI${ITKM_${t}}3I${ITKM_${t}}3\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image< ${ITKT_${t}}, 3>, rtk::Functor::InterpolationWeightMultiplication<${ITKT_${t}}, ${ITKT_${t}}>, rtk::Functor::MaximumIntensityProjectedValueAccumulation<${ITKT_${t}}, ${ITKT_${t}}>, rtk::Functor::MaximumIntensityAlongRay<${ITKT_${t}}, ${ITKT_${t}}>\")\n  endforeach()\nitk_end_wrap_class()\n\nitk_wrap_class(\"rtk::MaximumIntensityProjectionImageFilter\"  POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3\" \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkMechlemOneStepSpectralReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::MechlemOneStepSpectralReconstructionFilter\" POINTER)\n\n  # Force VECTOR_COMPONENTS to contain \"2;3;4;5\"\n  set(vectorComponents 2 3 4 5)\n\n  foreach(nmat ${vectorComponents})\n    foreach(nbin ${vectorComponents})\n      foreach(vt ${WRAP_ITK_VECTOR_REAL})\n\n        itk_wrap_template(\"I${ITKM_${vt}${nmat}}3I${ITKM_${vt}${nbin}}3I${ITKM_F}3\" \"itk::Image<${ITKT_${vt}${nmat}},3>, itk::Image<${ITKT_${vt}${nbin}},3>, itk::Image<${ITKT_F},3>\")\n\n      endforeach()\n\n      if(RTK_USE_CUDA)\n        itk_wrap_template(\"CI${ITKM_VF${nmat}}3CI${ITKM_VF${nbin}}3CI${ITKM_F}3\" \"itk::CudaImage<${ITKT_VF${nmat}},3>, itk::CudaImage<${ITKT_VF${nbin}},3>, itk::CudaImage<${ITKT_F},3>\")\n      endif()\n    endforeach()\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkMotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::MotionCompensatedFourDConjugateGradientConeBeamReconstructionFilter\" POINTER)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF4CIF3\" \"itk::CudaImage<float, 4>, itk::CudaImage<float, 3>\")\n  endif()\n  itk_wrap_template(\"I${ITKM_F}4I${ITKM_F}3\"\n    \"itk::Image<${ITKT_F}, 4>, itk::Image<${ITKT_F}, 3>\")\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkOSEMConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::OSEMConeBeamReconstructionFilter\" POINTER)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF4CIF3\" \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>\")\n  endif()\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkOraGeometryReader.wrap",
    "content": "itk_wrap_simple_class(\"rtk::OraGeometryReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkOraImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::OraImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::OraImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkParkerShortScanImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::ParkerShortScanImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1)\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3\" \"itk::CudaImage<float, 3>\")\n  endif()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkPhaseGatingImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::PhaseGatingImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkPolynomialGainCorrectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::PolynomialGainCorrectionImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkProjectGeometricPhantomImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ProjectGeometricPhantomImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkProjectionGeometry.wrap",
    "content": "itk_wrap_class(\"rtk::ProjectionGeometry\" POINTER)\n\n  foreach(d 3)\n      itk_wrap_template(\"${d}\" \"${d}\")\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkProjectionStackToFourDImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ProjectionStackToFourDImageFilter\" POINTER)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF4CIF3D\" \"itk::CudaImage<float, 4>, itk::CudaImage<float, 3>, double\")\n  endif()\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}4I${ITKM_${t}}3D\"\n      \"itk::Image<${ITKT_${t}}, 4>, itk::Image<${ITKT_${t}}, 3>, double\")\n  endforeach()\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkProjectionsReader.wrap",
    "content": "itk_wrap_class(\"rtk::ProjectionsReader\" POINTER)\n  # Force uchar image IO\n  UNIQUE(image_types \"UC;${WRAP_ITK_REAL}\")\n  itk_wrap_image_filter(\"${image_types}\" 1)\n\n  #WARNING: \"UC;${WRAP_ITK_REAL}\" is too restrictive.\n  # Types should be similar to vnl wrapped types :\n  #  \"D;F;SI;SL;LD;SC;UC;US;UI;UL\"\n  #Removing VectorImage<> (VI) and WRAP_ITK_SCALAR\nitk_end_wrap_class()"
  },
  {
    "path": "wrapping/rtkQuadricShape.wrap",
    "content": "itk_wrap_simple_class(\"rtk::QuadricShape\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkRayBoxIntersectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::RayBoxIntersectionImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkRayConvexIntersectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::RayConvexIntersectionImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkRayEllipsoidIntersectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::RayEllipsoidIntersectionImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkRayQuadricIntersectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::RayQuadricIntersectionImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkReg1DExtractShroudSignalImageFilter.notwrap",
    "content": "itk_wrap_class(\"rtk::Reg1DExtractShroudSignalImageFilter\" POINTER)\n\n  itk_wrap_template(\"${ITKM_D}${ITKM_D}\" \"double, double\")\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkRegularizedConjugateGradientConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::RegularizedConjugateGradientConeBeamReconstructionFilter\" POINTER)\n\n if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3\" \"itk::CudaImage<${ITKT_F}, 3>\")\n  endif()\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkReorderProjectionsImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::ReorderProjectionsImageFilter\" POINTER)\n    itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\n\n    if(RTK_USE_CUDA)\n        itk_wrap_template(\"CIF3CIF3\" \"itk::CudaImage<${ITKT_F}, 3>, itk::CudaImage<${ITKT_F}, 3>\")\n    endif()\n\n    # Force VECTOR_COMPONENTS to contain \"2;3;4;5\"\n    set(vectorComponents 2 3 4 5)\n    foreach(nmat ${vectorComponents})\n        foreach(vt ${WRAP_ITK_VECTOR_REAL})\n\n          itk_wrap_template(\"I${ITKM_${vt}${nmat}}3I${ITKM_${vt}${nmat}}3\" \"itk::Image<${ITKT_${vt}${nmat}},3>, itk::Image<${ITKT_${vt}${nmat}},3>\")\n\n        endforeach()\n\n        if(RTK_USE_CUDA)\n          itk_wrap_template(\"CI${ITKM_VF${nmat}}3CI${ITKM_VF${nmat}}3\" \"itk::CudaImage<${ITKT_VF${nmat}},3>, itk::CudaImage<${ITKT_VF${nmat}},3>\")\n        endif()\n    endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkSARTConeBeamReconstructionFilter.wrap",
    "content": "itk_wrap_class(\"rtk::SARTConeBeamReconstructionFilter\" POINTER)\n\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF4CIF3\" \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>\")\n  endif()\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\n\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkScatterGlareCorrectionImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n  itk_wrap_include(itkCudaImage.h)\nendif()\n\nitk_wrap_class(\"rtk::ScatterGlareCorrectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3F\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>, float\")\n  endforeach()\n  if(RTK_USE_CUDA)\n    itk_wrap_template(\"CIF3CIF3F\" \"itk::CudaImage<float, 3>, itk::CudaImage<float, 3>, float\")\n  endif()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkSelectOneProjectionPerCycleImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::SelectOneProjectionPerCycleImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkSheppLoganPhantomFilter.wrap",
    "content": "itk_wrap_class(\"rtk::SheppLoganPhantomFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkSimplexSpectralProjectionsDecompositionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::SimplexSpectralProjectionsDecompositionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"VI${ITKM_${t}}3VI${ITKM_${t}}3IF3IF2IF2\"\n        \"itk::VectorImage<${ITKT_${t}}, 3>, itk::VectorImage<${ITKT_${t}}, 3>, itk::Image<${ITKT_F}, 3>, itk::Image<${ITKT_F}, 2>, itk::Image<${ITKT_F}, 2>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkSoftThresholdImageFilter.wrap",
    "content": "#-----------------------------------------------------------------------------\n# rtk::Functor::SoftThreshold< float, float >\n#-----------------------------------------------------------------------------\nset(WRAPPER_AUTO_INCLUDE_HEADERS OFF)\nitk_wrap_named_class(\"rtk::Functor::SoftThreshold\" \"rtkFunctorSoftThreshold\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_${t}}${ITKM_${t}}\" \"${ITKT_${t}}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nset(WRAPPER_AUTO_INCLUDE_HEADERS ON)\n\n#-----------------------------------------------------------------------------\n# itk::UnaryFunctorImageFilter<itk::Image<float, 3>, itk::Image<float, 3>,\n#   rtk::Function::SoftThreshold<float, float>>\n#-----------------------------------------------------------------------------\nitk_wrap_class(\"itk::UnaryFunctorImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3ST${ITKM_${t}}${ITKM_${t}}\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>, rtk::Functor::SoftThreshold<${ITKT_${t}}, ${ITKT_${t}}>\")\n  endforeach()\nitk_end_wrap_class()\n\n#-----------------------------------------------------------------------------\n# rtk::SoftThresholdImageFilter\n#-----------------------------------------------------------------------------\nitk_wrap_class(\"rtk::SoftThresholdImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkSpectralForwardModelImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::SpectralForwardModelImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"VI${ITKM_${t}}3VI${ITKM_${t}}3IF3IF2IF2\"\n        \"itk::VectorImage<${ITKT_${t}}, 3>, itk::VectorImage<${ITKT_${t}}, 3>, itk::Image<${ITKT_F}, 3>, itk::Image<${ITKT_F}, 2>, itk::Image<${ITKT_F}, 2>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkSplatWithKnownWeightsImageFilter.wrap",
    "content": "if(RTK_USE_CUDA)\n\n  itk_wrap_include(itkCudaImage.h)\n\n  #-----------------------------------------------------------------------------\n  # rtk::SplatWithKnownWeightsImageFilter\n  #-----------------------------------------------------------------------------\n  itk_wrap_class(\"rtk::SplatWithKnownWeightsImageFilter\" POINTER)\n    itk_wrap_template(\"CIF4CIF3\" \"itk::CudaImage<float, 4>, itk::CudaImage<float, 3>\")\n  itk_end_wrap_class()\n\n  #-----------------------------------------------------------------------------\n  # Templates to be used with rtk::CudaSplatImageFilter\n  #-----------------------------------------------------------------------------\n  itk_wrap_class(\"itk::CudaImageToImageFilter\" POINTER)\n    itk_wrap_template(\"CIF4CIF4SplatCIF4CIF3\"\n      \"itk::CudaImage<${ITKT_F}, 4>, itk::CudaImage<${ITKT_F}, 4>, rtk::SplatWithKnownWeightsImageFilter< itk::CudaImage<${ITKT_F}, 4>, itk::CudaImage<${ITKT_F}, 3> >\")\n  itk_end_wrap_class()\n\n  itk_wrap_class(\"itk::CudaInPlaceImageFilter\" POINTER)\n    itk_wrap_template(\"CIF4CIF4SplatCIF4CIF3\"\n      \"itk::CudaImage<${ITKT_F}, 4>, itk::CudaImage<${ITKT_F}, 4>, rtk::SplatWithKnownWeightsImageFilter< itk::CudaImage<${ITKT_F}, 4>, itk::CudaImage<${ITKT_F}, 3> >\")\n  itk_end_wrap_class()\n\nendif()\n\n"
  },
  {
    "path": "wrapping/rtkSubSelectFromListImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::SubSelectFromListImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkSubSelectImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::SubSelectImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkThreeDCircularProjectionGeometry.wrap",
    "content": "itk_wrap_simple_class(\"rtk::ThreeDCircularProjectionGeometry\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkThreeDCircularProjectionGeometryXMLFileReader.wrap",
    "content": "itk_wrap_named_class(\"itk::XMLReader\" itkXMLReader)\n  itk_wrap_template(3DCPG \"rtk::ThreeDCircularProjectionGeometry\" )\nitk_end_wrap_class()\n\nitk_wrap_named_simple_class(\"itk::XMLReaderBase\" itkXMLFile)\n\nitk_wrap_simple_class(\"rtk::ThreeDCircularProjectionGeometryXMLFileReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkThreeDCircularProjectionGeometryXMLFileWriter.wrap",
    "content": "itk_wrap_named_class(\"itk::XMLWriterBase\" itkXMLWriterBase)\n  itk_wrap_template(3DCPG \"rtk::ThreeDCircularProjectionGeometry\" )\nitk_end_wrap_class()\n\nitk_wrap_simple_class(\"rtk::ThreeDCircularProjectionGeometryXMLFileWriter\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkTotalVariationDenoisingBPDQImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::TotalVariationDenoisingBPDQImageFilter\" POINTER)\n  foreach(d ${ITK_WRAP_IMAGE_DIMS})\n    # Do not use WRAP_ITK_COV_VECTOR_REAL types to prevent wrapping for DOUBLE\n    # as rtkMagnitudeThresholdImageFilter (contained in this class) is instantiated\n    # for TRealType=float only.\n    foreach(cvt \"CVF\")\n      itk_wrap_template(\"I${ITKM_F}${d}I${ITKM_${cvt}${d}}${d}\"\n        \"itk::Image<${ITKT_F}, ${d}>, itk::Image<${ITKT_${cvt}${d}}, ${d}>\")\n    endforeach()\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkTotalVariationImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::TotalVariationImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 1)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkVarianObiGeometryReader.wrap",
    "content": "itk_wrap_simple_class(\"rtk::VarianObiGeometryReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkVarianObiRawImageFilter.wrap",
    "content": "set(WRAPPER_AUTO_INCLUDE_HEADERS OFF)\nitk_wrap_named_class(\"rtk::Function::ObiAttenuation\" \"rtkFunctionObiAttenuation\")\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"${ITKM_UI}${ITKM_${t}}\" \"${ITKT_UI}, ${ITKT_${t}}\")\n  endforeach()\nitk_end_wrap_class()\nset(WRAPPER_AUTO_INCLUDE_HEADERS ON)\n\nitk_wrap_class(\"itk::UnaryFunctorImageFilter\" POINTER)\n  foreach(d 2 3)\n    foreach(t ${WRAP_ITK_REAL})\n      itk_wrap_template(\"I${ITKM_UI}${d}I${ITKM_${t}}${d}OA${ITKM_UI}${ITKM_${t}}\"\n                        \"itk::Image<${ITKT_UI}, ${d}>, itk::Image<${ITKT_${t}}, ${d}>, rtk::Function::ObiAttenuation< ${ITKT_UI},${ITKT_${t}} >\")\n    endforeach()\n  endforeach()\nitk_end_wrap_class()\n\nitk_wrap_class(\"rtk::VarianObiRawImageFilter\" POINTER)\n  foreach(d 2 3)\n    foreach(t ${WRAP_ITK_REAL})\n      itk_wrap_template(\"I${ITKM_UI}${d}I${ITKM_${t}}${d}\" \"itk::Image<${ITKT_UI}, ${d}>, itk::Image<${ITKT_${t}}, ${d}>\")\n    endforeach()\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkVarianProBeamGeometryReader.wrap",
    "content": "itk_wrap_simple_class(\"rtk::VarianProBeamGeometryReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkVectorImageToImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::VectorImageToImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"VI${ITKM_${t}}2I${ITKM_${t}}2\" \"itk::VectorImage<${ITKT_${t}}, 2>, itk::Image<${ITKT_${t}}, 2>\")\n    itk_wrap_template(\"VI${ITKM_${t}}2I${ITKM_${t}}3\" \"itk::VectorImage<${ITKT_${t}}, 2>, itk::Image<${ITKT_${t}}, 3>\")\n    itk_wrap_template(\"VI${ITKM_${t}}3I${ITKM_${t}}3\" \"itk::VectorImage<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>\")\n    itk_wrap_template(\"VI${ITKM_${t}}3I${ITKM_${t}}4\" \"itk::VectorImage<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 4>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkWaterPrecorrectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::WaterPrecorrectionImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkXRadGeometryReader.wrap",
    "content": "itk_wrap_simple_class(\"rtk::XRadGeometryReader\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkXRadImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::XRadImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::XRadImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkXRadRawToAttenuationImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::XRadRawToAttenuationImageFilter\" POINTER)\n  itk_wrap_image_filter(\"${WRAP_ITK_REAL}\" 2 3)\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkXimImageIO.wrap",
    "content": "itk_wrap_simple_class(\"rtk::XimImageIO\" POINTER)\nitk_wrap_simple_class(\"rtk::XimImageIOFactory\" POINTER)\n"
  },
  {
    "path": "wrapping/rtkZengBackProjectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ZengBackProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3SWM${ITKM_${t}}D${ITKM_${t}}\"\n      \"itk::Image<${ITKT_${t}}, 3>, itk::Image< ${ITKT_${t}}, 3>\")\n  endforeach()\nitk_end_wrap_class()\n"
  },
  {
    "path": "wrapping/rtkZengForwardProjectionImageFilter.wrap",
    "content": "itk_wrap_class(\"rtk::ZengForwardProjectionImageFilter\" POINTER)\n  foreach(t ${WRAP_ITK_REAL})\n    itk_wrap_template(\"I${ITKM_${t}}3I${ITKM_${t}}3\" \"itk::Image<${ITKT_${t}}, 3>, itk::Image<${ITKT_${t}}, 3>\")\n  endforeach()\nitk_end_wrap_class()\n"
  }
]